Smarter pipes (#58296)
Smart pipe improvements Co-authored-by: tralezab <spamqetuo2@gmail.com>
@@ -577,16 +577,20 @@ GLOBAL_LIST_EMPTY(colored_images)
|
||||
CHECK_TICK
|
||||
|
||||
|
||||
/datum/controller/subsystem/air/proc/get_init_dirs(type, dir)
|
||||
/datum/controller/subsystem/air/proc/get_init_dirs(type, dir, init_dir)
|
||||
|
||||
if(!pipe_init_dirs_cache[type])
|
||||
pipe_init_dirs_cache[type] = list()
|
||||
|
||||
if(!pipe_init_dirs_cache[type]["[dir]"])
|
||||
var/obj/machinery/atmospherics/temp = new type(null, FALSE, dir)
|
||||
pipe_init_dirs_cache[type]["[dir]"] = temp.GetInitDirections()
|
||||
if(!pipe_init_dirs_cache[type]["[init_dir]"])
|
||||
pipe_init_dirs_cache[type]["[init_dir]"] = list()
|
||||
|
||||
if(!pipe_init_dirs_cache[type]["[init_dir]"]["[dir]"])
|
||||
var/obj/machinery/atmospherics/temp = new type(null, FALSE, dir, init_dir)
|
||||
pipe_init_dirs_cache[type]["[init_dir]"]["[dir]"] = temp.GetInitDirections()
|
||||
qdel(temp)
|
||||
|
||||
return pipe_init_dirs_cache[type]["[dir]"]
|
||||
return pipe_init_dirs_cache[type]["[init_dir]"]["[dir]"]
|
||||
|
||||
/datum/controller/subsystem/air/proc/generate_atmos()
|
||||
atmos_gen = list()
|
||||
|
||||
@@ -18,11 +18,16 @@ Buildable meters
|
||||
icon_state = "simple"
|
||||
inhand_icon_state = "buildpipe"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
///Piping layer that we are going to be on
|
||||
var/piping_layer = PIPING_LAYER_DEFAULT
|
||||
///Type of pipe-object made, selected from the RPD
|
||||
var/RPD_type
|
||||
/// Whether it can be painted
|
||||
///Whether it can be painted
|
||||
var/paintable = FALSE
|
||||
///Color of the pipe is going to be made from this pipe-object
|
||||
var/pipe_color
|
||||
///Initial direction of the created pipe (either made from the RPD or after unwrenching the pipe)
|
||||
var/p_init_dir = SOUTH
|
||||
|
||||
/obj/item/pipe/directional
|
||||
RPD_type = PIPE_UNARY
|
||||
@@ -42,10 +47,11 @@ Buildable meters
|
||||
//Flipping handled manually due to custom handling for trinary pipes
|
||||
AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE)
|
||||
|
||||
/obj/item/pipe/Initialize(mapload, _pipe_type, _dir, obj/machinery/atmospherics/make_from, device_color)
|
||||
/obj/item/pipe/Initialize(mapload, _pipe_type, _dir, obj/machinery/atmospherics/make_from, device_color, device_init_dir = SOUTH)
|
||||
if(make_from)
|
||||
make_from_existing(make_from)
|
||||
else
|
||||
p_init_dir = device_init_dir
|
||||
pipe_type = _pipe_type
|
||||
pipe_color = device_color
|
||||
setDir(_dir)
|
||||
@@ -56,6 +62,7 @@ Buildable meters
|
||||
return ..()
|
||||
|
||||
/obj/item/pipe/proc/make_from_existing(obj/machinery/atmospherics/make_from)
|
||||
p_init_dir = make_from.initialize_directions
|
||||
setDir(make_from.dir)
|
||||
pipename = make_from.name
|
||||
add_atom_colour(make_from.color, FIXED_COLOUR_PRIORITY)
|
||||
@@ -176,12 +183,12 @@ Buildable meters
|
||||
if((machine.piping_layer != piping_layer) && !((machine.pipe_flags | flags) & PIPING_ALL_LAYER)) //don't continue if either pipe goes across all layers
|
||||
continue
|
||||
|
||||
if(machine.GetInitDirections() & SSair.get_init_dirs(pipe_type, fixed_dir())) // matches at least one direction on either type of pipe
|
||||
if(machine.GetInitDirections() & SSair.get_init_dirs(pipe_type, fixed_dir(), p_init_dir)) // matches at least one direction on either type of pipe
|
||||
to_chat(user, "<span class='warning'>There is already a pipe at that location!</span>")
|
||||
return TRUE
|
||||
// no conflicts found
|
||||
|
||||
var/obj/machinery/atmospherics/built_machine = new pipe_type(loc)
|
||||
var/obj/machinery/atmospherics/built_machine = new pipe_type(loc, , , p_init_dir)
|
||||
build_pipe(built_machine)
|
||||
built_machine.on_construction(pipe_color, piping_layer)
|
||||
transfer_fingerprints_to(built_machine)
|
||||
@@ -196,7 +203,7 @@ Buildable meters
|
||||
|
||||
/obj/item/pipe/proc/build_pipe(obj/machinery/atmospherics/A)
|
||||
A.setDir(fixed_dir())
|
||||
A.SetInitDirections()
|
||||
A.SetInitDirections(p_init_dir)
|
||||
|
||||
if(pipename)
|
||||
A.name = pipename
|
||||
|
||||
@@ -196,23 +196,39 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
custom_materials = list(/datum/material/iron=75000, /datum/material/glass=37500)
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 50)
|
||||
resistance_flags = FIRE_PROOF
|
||||
///Sparks system used when changing device in the UI
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
var/working = 0
|
||||
///Direction of the device we are going to spawn, set up in the UI
|
||||
var/p_dir = NORTH
|
||||
///Initial direction of the smart pipe we are going to spawn, set up in the UI
|
||||
var/p_init_dir = ALL_CARDINALS
|
||||
///Is the device of the flipped type?
|
||||
var/p_flipped = FALSE
|
||||
///Color of the device we are going to spawn
|
||||
var/paint_color = "grey"
|
||||
var/atmos_build_speed = 5 //deciseconds (500ms)
|
||||
var/disposal_build_speed = 5
|
||||
var/transit_build_speed = 5
|
||||
var/destroy_speed = 5
|
||||
var/paint_speed = 5
|
||||
///Speed of building atmos devices
|
||||
var/atmos_build_speed = 0.5 SECONDS
|
||||
///Speed of building disposal devices
|
||||
var/disposal_build_speed = 0.5 SECONDS
|
||||
///Speed of building transit devices
|
||||
var/transit_build_speed = 0.5 SECONDS
|
||||
///Speed of removal of unwrenched devices
|
||||
var/destroy_speed = 0.5 SECONDS
|
||||
///Category currently active (Atmos, disposal, transit)
|
||||
var/category = ATMOS_CATEGORY
|
||||
///Piping layer we are going to spawn the atmos device in
|
||||
var/piping_layer = PIPING_LAYER_DEFAULT
|
||||
///Layer for disposal ducts
|
||||
var/ducting_layer = DUCT_LAYER_DEFAULT
|
||||
///Stores the current device to spawn
|
||||
var/datum/pipe_info/recipe
|
||||
///Stores the first atmos device
|
||||
var/static/datum/pipe_info/first_atmos
|
||||
///Stores the first disposal device
|
||||
var/static/datum/pipe_info/first_disposal
|
||||
///Stores the first transit device
|
||||
var/static/datum/pipe_info/first_transit
|
||||
///The modes that are allowed for the RPD
|
||||
var/mode = BUILD_MODE | DESTROY_MODE | WRENCH_MODE
|
||||
/// Bitflags for upgrades
|
||||
var/upgrade_flags
|
||||
@@ -344,6 +360,11 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
r += list(list("pipe_name" = info.name, "pipe_index" = i, "selected" = (info == recipe), "all_layers" = info.all_layers))
|
||||
data["categories"] += list(list("cat_name" = c, "recipes" = r))
|
||||
|
||||
var/list/init_directions = list("north" = FALSE, "south" = FALSE, "east" = FALSE, "west" = FALSE)
|
||||
for(var/direction in GLOB.cardinals)
|
||||
if(p_init_dir & direction)
|
||||
init_directions[dir2text(direction)] = TRUE
|
||||
data["init_directions"] = init_directions
|
||||
return data
|
||||
|
||||
/obj/item/pipe_dispenser/ui_act(action, params)
|
||||
@@ -390,6 +411,10 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
mode &= ~n
|
||||
else
|
||||
mode |= n
|
||||
if("init_dir_setting")
|
||||
p_init_dir ^= text2dir(params["dir_flag"])
|
||||
if("init_reset")
|
||||
p_init_dir = ALL_CARDINALS
|
||||
if(playeffect)
|
||||
spark_system.start()
|
||||
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, FALSE)
|
||||
@@ -456,19 +481,25 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
activate()
|
||||
var/obj/machinery/atmospherics/path = queued_p_type
|
||||
var/pipe_item_type = initial(path.construction_type) || /obj/item/pipe
|
||||
var/obj/item/pipe/P = new pipe_item_type(get_turf(attack_target), queued_p_type, queued_p_dir, null, GLOB.pipe_paint_colors[paint_color])
|
||||
|
||||
if(queued_p_flipped && istype(P, /obj/item/pipe/trinary/flippable))
|
||||
var/obj/item/pipe/trinary/flippable/F = P
|
||||
var/obj/item/pipe/pipe_type = new pipe_item_type(
|
||||
get_turf(attack_target),
|
||||
queued_p_type,
|
||||
queued_p_dir,
|
||||
null,
|
||||
GLOB.pipe_paint_colors[paint_color],
|
||||
ispath(queued_p_type, /obj/machinery/atmospherics/pipe/smart) ? p_init_dir : null,
|
||||
)
|
||||
if(queued_p_flipped && istype(pipe_type, /obj/item/pipe/trinary/flippable))
|
||||
var/obj/item/pipe/trinary/flippable/F = pipe_type
|
||||
F.flipped = queued_p_flipped
|
||||
|
||||
P.update()
|
||||
P.add_fingerprint(usr)
|
||||
P.setPipingLayer(piping_layer)
|
||||
pipe_type.update()
|
||||
pipe_type.add_fingerprint(usr)
|
||||
pipe_type.setPipingLayer(piping_layer)
|
||||
if(ispath(queued_p_type, /obj/machinery/atmospherics) && !ispath(queued_p_type, /obj/machinery/atmospherics/pipe/color_adapter))
|
||||
P.add_atom_colour(GLOB.pipe_paint_colors[paint_color], FIXED_COLOUR_PRIORITY)
|
||||
pipe_type.add_atom_colour(GLOB.pipe_paint_colors[paint_color], FIXED_COLOUR_PRIORITY)
|
||||
if(mode & WRENCH_MODE)
|
||||
P.wrench_act(user, src)
|
||||
pipe_type.wrench_act(user, src)
|
||||
|
||||
if(DISPOSALS_CATEGORY) //Making disposals pipes
|
||||
if(!can_make_pipe)
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
if(HAS_TRAIT(L, TRAIT_VENTCRAWLER_NUDE) || HAS_TRAIT(L, TRAIT_VENTCRAWLER_ALWAYS))
|
||||
. += "<span class='notice'>Alt-click to crawl through it.</span>"
|
||||
|
||||
/obj/machinery/atmospherics/New(loc, process = TRUE, setdir)
|
||||
/obj/machinery/atmospherics/New(loc, process = TRUE, setdir, init_dir = ALL_CARDINALS)
|
||||
if(!isnull(setdir))
|
||||
setDir(setdir)
|
||||
if(pipe_flags & PIPING_CARDINAL_AUTONORMALIZE)
|
||||
@@ -88,7 +88,7 @@
|
||||
..()
|
||||
if(process)
|
||||
SSair.start_processing_machine(src)
|
||||
SetInitDirections()
|
||||
SetInitDirections(init_dir)
|
||||
|
||||
/obj/machinery/atmospherics/Destroy()
|
||||
for(var/i in 1 to device_type)
|
||||
@@ -223,7 +223,18 @@
|
||||
* * given_layer - the piping_layer we are checking
|
||||
*/
|
||||
/obj/machinery/atmospherics/proc/connection_check(obj/machinery/atmospherics/target, given_layer)
|
||||
if(isConnectable(target, given_layer) && target.isConnectable(src, given_layer) && (target.initialize_directions & get_dir(target,src) || istype(target, /obj/machinery/atmospherics/pipe/multiz)))
|
||||
if(isConnectable(target, given_layer) && target.isConnectable(src, given_layer) && check_init_directions(target))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* check if the initialized direction are the same on both sides (or if is a multiz adapter)
|
||||
* returns TRUE or FALSE if the connection is possible or not
|
||||
* Arguments:
|
||||
* * obj/machinery/atmospherics/target - the machinery we want to connect to
|
||||
*/
|
||||
/obj/machinery/atmospherics/proc/check_init_directions(obj/machinery/atmospherics/target)
|
||||
if((initialize_directions & get_dir(src, target) && target.initialize_directions & get_dir(target,src)) || istype(target, /obj/machinery/atmospherics/pipe/multiz))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -274,7 +285,7 @@
|
||||
/**
|
||||
* Set the initial directions of the device (NORTH || SOUTH || EAST || WEST), called on New()
|
||||
*/
|
||||
/obj/machinery/atmospherics/proc/SetInitDirections()
|
||||
/obj/machinery/atmospherics/proc/SetInitDirections(init_dir)
|
||||
return
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GLOBAL_LIST_INIT(atmos_components, typecacheof(list(/obj/machinery/atmospherics)))
|
||||
|
||||
//Smart pipes... or are they?
|
||||
/obj/machinery/atmospherics/pipe/smart
|
||||
icon = 'icons/obj/atmospherics/pipes/simple.dmi'
|
||||
icon_state = "pipe11-3"
|
||||
@@ -24,8 +24,11 @@ GLOBAL_LIST_INIT(atmos_components, typecacheof(list(/obj/machinery/atmospherics)
|
||||
icon_state = ""
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/atmospherics/pipe/smart/SetInitDirections()
|
||||
initialize_directions = ALL_CARDINALS
|
||||
/obj/machinery/atmospherics/pipe/smart/SetInitDirections(init_dir)
|
||||
if(init_dir)
|
||||
initialize_directions = init_dir
|
||||
else
|
||||
initialize_directions = ALL_CARDINALS
|
||||
|
||||
/obj/machinery/atmospherics/pipe/smart/proc/check_connections()
|
||||
var/mutable_appearance/center
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#define MODE_TRAY "t-ray"
|
||||
#define MODE_RAD "radiation"
|
||||
#define MODE_SHUTTLE "shuttle"
|
||||
#define MODE_PIPE_CONNECTABLE "connectable"
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine
|
||||
name = "engineering scanner goggles"
|
||||
@@ -21,6 +22,7 @@
|
||||
var/list/modes = list(MODE_NONE = MODE_MESON, MODE_MESON = MODE_TRAY, MODE_TRAY = MODE_RAD, MODE_RAD = MODE_NONE)
|
||||
var/mode = MODE_NONE
|
||||
var/range = 1
|
||||
var/list/connection_images = list()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/Initialize()
|
||||
. = ..()
|
||||
@@ -38,7 +40,8 @@
|
||||
/obj/item/clothing/glasses/meson/engine/proc/toggle_mode(mob/user, voluntary)
|
||||
mode = modes[mode]
|
||||
to_chat(user, "<span class='[voluntary ? "notice":"warning"]'>[voluntary ? "You turn the goggles":"The goggles turn"] [mode ? "to [mode] mode":"off"][voluntary ? ".":"!"]</span>")
|
||||
|
||||
if(connection_images.len)
|
||||
connection_images.Cut()
|
||||
switch(mode)
|
||||
if(MODE_MESON)
|
||||
vision_flags = SEE_TURFS
|
||||
@@ -52,6 +55,9 @@
|
||||
lighting_alpha = null
|
||||
change_glass_color(user, /datum/client_colour/glass_colour/lightblue)
|
||||
|
||||
if(MODE_PIPE_CONNECTABLE)
|
||||
change_glass_color(user, /datum/client_colour/glass_colour/lightblue)
|
||||
|
||||
if(MODE_RAD)
|
||||
change_glass_color(user, /datum/client_colour/glass_colour/lightgreen)
|
||||
|
||||
@@ -87,6 +93,8 @@
|
||||
show_rads()
|
||||
if(MODE_SHUTTLE)
|
||||
show_shuttle()
|
||||
if(MODE_PIPE_CONNECTABLE)
|
||||
show_connections()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/proc/show_rads()
|
||||
var/mob/living/carbon/human/user = loc
|
||||
@@ -130,6 +138,30 @@
|
||||
pic = new('icons/turf/overlays.dmi', place, "redOverlay", AREA_LAYER)
|
||||
flick_overlay(pic, list(user.client), 8)
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/proc/show_connections()
|
||||
var/mob/living/carbon/human/user = loc
|
||||
|
||||
for(var/obj/machinery/atmospherics/pipe/smart/smart in connection_images)
|
||||
if(get_dist(loc, smart.loc) > range)
|
||||
connection_images -= smart
|
||||
|
||||
for(var/obj/machinery/atmospherics/pipe/smart/smart in orange(range, user))
|
||||
if(!connection_images[smart])
|
||||
connection_images[smart] = list()
|
||||
for(var/direction in GLOB.cardinals)
|
||||
if(!(smart.GetInitDirections() & direction))
|
||||
continue
|
||||
if(!connection_images[smart][dir2text(direction)])
|
||||
var/image/arrow
|
||||
arrow = new('icons/obj/atmospherics/pipes/simple.dmi', get_turf(smart), "connection_overlay")
|
||||
arrow.dir = direction
|
||||
arrow.layer = smart.layer
|
||||
arrow.color = smart.pipe_color
|
||||
PIPING_LAYER_DOUBLE_SHIFT(arrow, smart.piping_layer)
|
||||
connection_images[smart][dir2text(direction)] = arrow
|
||||
if(connection_images.len)
|
||||
flick_overlay(connection_images[smart][dir2text(direction)], list(user.client), 1.5 SECONDS)
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/update_icon_state()
|
||||
icon_state = inhand_icon_state = "trayson-[mode]"
|
||||
return ..()
|
||||
@@ -141,7 +173,12 @@
|
||||
desc = "Used by engineering staff to see underfloor objects such as cables and pipes."
|
||||
range = 2
|
||||
|
||||
modes = list(MODE_NONE = MODE_TRAY, MODE_TRAY = MODE_NONE)
|
||||
modes = list(MODE_NONE = MODE_TRAY, MODE_TRAY = MODE_PIPE_CONNECTABLE, MODE_PIPE_CONNECTABLE = MODE_NONE)
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/tray/dropped(mob/user)
|
||||
. = ..()
|
||||
if(connection_images.len)
|
||||
connection_images.Cut()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/shuttle
|
||||
name = "shuttle region scanner"
|
||||
@@ -156,3 +193,4 @@
|
||||
#undef MODE_TRAY
|
||||
#undef MODE_RAD
|
||||
#undef MODE_SHUTTLE
|
||||
#undef MODE_PIPE_CONNECTABLE
|
||||
|
||||
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
@@ -1,6 +1,7 @@
|
||||
import { classes } from 'common/react';
|
||||
import { multiline } from 'common/string';
|
||||
import { useBackend, useLocalState } from '../backend';
|
||||
import { Box, Button, ColorBox, Flex, LabeledList, Section, Tabs } from '../components';
|
||||
import { Box, Button, ColorBox, Dimmer, LabeledList, Section, Stack, Tabs } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
const ROOT_CATEGORIES = [
|
||||
@@ -35,16 +36,127 @@ const TOOLS = [
|
||||
},
|
||||
];
|
||||
|
||||
export const RapidPipeDispenser = (props, context) => {
|
||||
const SelectionSection = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
category: rootCategoryIndex,
|
||||
categories = [],
|
||||
selected_color,
|
||||
piping_layer,
|
||||
mode,
|
||||
} = data;
|
||||
return (
|
||||
<Section>
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Category">
|
||||
{ROOT_CATEGORIES.map((categoryName, i) => (
|
||||
<Button
|
||||
key={categoryName}
|
||||
selected={rootCategoryIndex === i}
|
||||
icon={ICON_BY_CATEGORY_NAME[categoryName]}
|
||||
color="transparent"
|
||||
onClick={() => act('category', { category: i })} >
|
||||
{categoryName}
|
||||
</Button>
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Modes">
|
||||
<Stack fill>
|
||||
{TOOLS.map(tool => (
|
||||
<Stack.Item grow key={tool.bitmask}>
|
||||
<Button.Checkbox
|
||||
checked={mode & tool.bitmask}
|
||||
fluid
|
||||
content={tool.name}
|
||||
onClick={() => act('mode', {
|
||||
mode: tool.bitmask,
|
||||
})} />
|
||||
</Stack.Item>
|
||||
))}
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Color">
|
||||
<Box
|
||||
inline
|
||||
width="64px"
|
||||
color={data.paint_colors[selected_color]}>
|
||||
{selected_color}
|
||||
</Box>
|
||||
{Object.keys(data.paint_colors)
|
||||
.map(colorName => (
|
||||
<ColorBox
|
||||
key={colorName}
|
||||
ml={1}
|
||||
color={data.paint_colors[colorName]}
|
||||
onClick={() => act('color', {
|
||||
paint_color: colorName,
|
||||
})} />
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const LayerSection = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
category: rootCategoryIndex,
|
||||
piping_layer,
|
||||
} = data;
|
||||
const previews = data.preview_rows.flatMap(row => row.previews);
|
||||
return (
|
||||
<Section fill width={7.5}>
|
||||
{rootCategoryIndex === 0 && (
|
||||
<Stack vertical mb={1}>
|
||||
{[1, 2, 3, 4, 5].map(layer => (
|
||||
<Stack.Item my={0} key={layer}>
|
||||
<Button.Checkbox
|
||||
checked={layer === piping_layer}
|
||||
content={'Layer ' + layer}
|
||||
onClick={() => act('piping_layer', {
|
||||
piping_layer: layer,
|
||||
})} />
|
||||
</Stack.Item>
|
||||
))}
|
||||
</Stack>
|
||||
)}
|
||||
<Box width="120px">
|
||||
{previews.map(preview => (
|
||||
<Button
|
||||
ml={0}
|
||||
key={preview.dir}
|
||||
title={preview.dir_name}
|
||||
selected={preview.selected}
|
||||
style={{
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
padding: 0,
|
||||
}}
|
||||
onClick={() => act('setdir', {
|
||||
dir: preview.dir,
|
||||
flipped: preview.flipped,
|
||||
})}>
|
||||
<Box
|
||||
className={classes([
|
||||
'pipes32x32',
|
||||
preview.dir + '-' + preview.icon_state,
|
||||
])}
|
||||
style={{
|
||||
transform: 'scale(1.5) translate(9.5%, 9.5%)',
|
||||
}} />
|
||||
</Button>
|
||||
))}
|
||||
</Box>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const PipeTypeSection = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
categories = [],
|
||||
} = data;
|
||||
const [
|
||||
categoryName,
|
||||
setCategoryName,
|
||||
@@ -52,132 +164,138 @@ export const RapidPipeDispenser = (props, context) => {
|
||||
const shownCategory = categories
|
||||
.find(category => category.cat_name === categoryName)
|
||||
|| categories[0];
|
||||
return (
|
||||
<Section fill scrollable>
|
||||
<Tabs>
|
||||
{categories.map((category, i) => (
|
||||
<Tabs.Tab
|
||||
fluid
|
||||
key={category.cat_name}
|
||||
icon={ICON_BY_CATEGORY_NAME[category.cat_name]}
|
||||
selected={category.cat_name === shownCategory.cat_name}
|
||||
onClick={() => setCategoryName(category.cat_name)}>
|
||||
{category.cat_name}
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
{shownCategory?.recipes.map(recipe => (
|
||||
<Button.Checkbox
|
||||
key={recipe.pipe_index}
|
||||
fluid
|
||||
ellipsis
|
||||
checked={recipe.selected}
|
||||
content={recipe.pipe_name}
|
||||
title={recipe.pipe_name}
|
||||
onClick={() => act('pipe_type', {
|
||||
pipe_type: recipe.pipe_index,
|
||||
category: shownCategory.cat_name,
|
||||
})} />
|
||||
))}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const SmartPipeBlockSection = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const init_directions = data.init_directions || [];
|
||||
const {
|
||||
category: rootCategoryIndex,
|
||||
} = data;
|
||||
return (
|
||||
<Section>
|
||||
<Stack fill vertical textAlign="center">
|
||||
<Stack.Item basis={1.5}>
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
color="transparent"
|
||||
icon="info"
|
||||
tooltipPosition="right"
|
||||
tooltip={multiline`
|
||||
This is a panel for blocking certain connection
|
||||
directions for the smart pipes.
|
||||
The button in the center resets to
|
||||
default (all directions can connect)`} />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button iconRotation={-90} icon="arrow-right"
|
||||
disabled={!!data.smart_pipe}
|
||||
selected={init_directions["north"]}
|
||||
onClick={() => act('init_dir_setting', {
|
||||
dir_flag: "north",
|
||||
})} />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Item basis={1.5}>
|
||||
<Stack fill>
|
||||
<Stack.Item>
|
||||
<Button icon="arrow-left"
|
||||
selected={init_directions["west"]}
|
||||
onClick={() => act('init_dir_setting', {
|
||||
dir_flag: "west",
|
||||
})} />
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Button icon="circle"
|
||||
onClick={() => act('init_reset', {
|
||||
})} />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button icon="arrow-right"
|
||||
selected={init_directions["east"]}
|
||||
onClick={() => act('init_dir_setting', {
|
||||
dir_flag: "east",
|
||||
})} />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Button iconRotation={90} icon="arrow-right"
|
||||
selected={init_directions["south"]}
|
||||
onClick={() => act('init_dir_setting', {
|
||||
dir_flag: "south",
|
||||
})} />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
export const RapidPipeDispenser = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
category: rootCategoryIndex,
|
||||
} = data;
|
||||
return (
|
||||
<Window
|
||||
width={425}
|
||||
height={515}>
|
||||
<Window.Content scrollable>
|
||||
<Section>
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Category">
|
||||
{ROOT_CATEGORIES.map((categoryName, i) => (
|
||||
<Button
|
||||
key={categoryName}
|
||||
selected={rootCategoryIndex === i}
|
||||
icon={ICON_BY_CATEGORY_NAME[categoryName]}
|
||||
color="transparent"
|
||||
content={categoryName}
|
||||
onClick={() => act('category', { category: i })} />
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Modes">
|
||||
{TOOLS.map(tool => (
|
||||
<Button.Checkbox
|
||||
key={tool.bitmask}
|
||||
checked={mode & tool.bitmask}
|
||||
content={tool.name}
|
||||
onClick={() => act('mode', {
|
||||
mode: tool.bitmask,
|
||||
})} />
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Color">
|
||||
<Box
|
||||
inline
|
||||
width="64px"
|
||||
color={data.paint_colors[selected_color]}>
|
||||
{selected_color}
|
||||
</Box>
|
||||
{Object.keys(data.paint_colors)
|
||||
.map(colorName => (
|
||||
<ColorBox
|
||||
key={colorName}
|
||||
ml={1}
|
||||
color={data.paint_colors[colorName]}
|
||||
onClick={() => act('color', {
|
||||
paint_color: colorName,
|
||||
})} />
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Flex m={-0.5}>
|
||||
<Flex.Item m={0.5}>
|
||||
<Section>
|
||||
{rootCategoryIndex === 0 && (
|
||||
<Box mb={1}>
|
||||
{[1, 2, 3, 4, 5].map(layer => (
|
||||
<Button.Checkbox
|
||||
key={layer}
|
||||
fluid
|
||||
checked={layer === piping_layer}
|
||||
content={'Layer ' + layer}
|
||||
onClick={() => act('piping_layer', {
|
||||
piping_layer: layer,
|
||||
})} />
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
<Box width="108px">
|
||||
{previews.map(preview => (
|
||||
<Button
|
||||
key={preview.dir}
|
||||
title={preview.dir_name}
|
||||
selected={preview.selected}
|
||||
style={{
|
||||
width: '48px',
|
||||
height: '48px',
|
||||
padding: 0,
|
||||
}}
|
||||
onClick={() => act('setdir', {
|
||||
dir: preview.dir,
|
||||
flipped: preview.flipped,
|
||||
})}>
|
||||
<Box
|
||||
className={classes([
|
||||
'pipes32x32',
|
||||
preview.dir + '-' + preview.icon_state,
|
||||
])}
|
||||
style={{
|
||||
transform: 'scale(1.5) translate(17%, 17%)',
|
||||
}} />
|
||||
</Button>
|
||||
))}
|
||||
</Box>
|
||||
</Section>
|
||||
</Flex.Item>
|
||||
<Flex.Item m={0.5} grow={1}>
|
||||
<Section>
|
||||
<Tabs>
|
||||
{categories.map((category, i) => (
|
||||
<Tabs.Tab
|
||||
fluid
|
||||
key={category.cat_name}
|
||||
icon={ICON_BY_CATEGORY_NAME[category.cat_name]}
|
||||
selected={category.cat_name === shownCategory.cat_name}
|
||||
onClick={() => setCategoryName(category.cat_name)}>
|
||||
{category.cat_name}
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
{shownCategory?.recipes.map(recipe => (
|
||||
<Button.Checkbox
|
||||
key={recipe.pipe_index}
|
||||
fluid
|
||||
ellipsis
|
||||
checked={recipe.selected}
|
||||
content={recipe.pipe_name}
|
||||
title={recipe.pipe_name}
|
||||
onClick={() => act('pipe_type', {
|
||||
pipe_type: recipe.pipe_index,
|
||||
category: shownCategory.cat_name,
|
||||
})} />
|
||||
))}
|
||||
</Section>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
width={450}
|
||||
height={575}>
|
||||
<Window.Content>
|
||||
<Stack fill vertical>
|
||||
<Stack.Item>
|
||||
<SelectionSection />
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Stack fill>
|
||||
<Stack.Item>
|
||||
<Stack vertical fill>
|
||||
{rootCategoryIndex === 0 && (
|
||||
<Stack.Item>
|
||||
<SmartPipeBlockSection />
|
||||
</Stack.Item>
|
||||
)}
|
||||
<Stack.Item grow>
|
||||
<LayerSection />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<PipeTypeSection />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
|
||||