[MIRROR] Painting improvement: Added a palette component for spraycans and palette items. [MDB IGNORE] (#12219)

* Painting improvement: Added a palette component for spraycans and palette items. (#65577)

* Painting improvement: Added a palette component for spraycans and palettes.

* Painting improvement: Added a palette component for spraycans and palette items.

Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
SkyratBot
2022-03-22 22:03:57 +01:00
committed by GitHub
parent 59084d96d4
commit 42f1c5e8ec
11 changed files with 263 additions and 54 deletions

View File

@@ -0,0 +1,7 @@
// signals for painting canvases, tools and the /datum/component/palette component
///from base of /item/proc/set_painting_tool_color(): (chosen_color)
#define COMSIG_PAINTING_TOOL_SET_COLOR "painting_tool_set_color"
/// from base of /item/canvas/ui_data(): (data)
#define COMSIG_PAINTING_TOOL_GET_ADDITIONAL_DATA "painting_tool_get_data"

View File

@@ -25,15 +25,26 @@ GLOBAL_LIST_EMPTY(radial_menus)
var/next_page = FALSE var/next_page = FALSE
var/tooltips = FALSE var/tooltips = FALSE
/atom/movable/screen/radial/slice/set_parent(new_value)
. = ..()
if(parent)
icon_state = parent.radial_slice_icon
/atom/movable/screen/radial/slice/MouseEntered(location, control, params) /atom/movable/screen/radial/slice/MouseEntered(location, control, params)
. = ..() . = ..()
icon_state = "radial_slice_focus" if(next_page || !parent)
icon_state = "radial_slice_focus"
else
icon_state = "[parent.radial_slice_icon]_focus"
if(tooltips) if(tooltips)
openToolTip(usr, src, params, title = name) openToolTip(usr, src, params, title = name)
/atom/movable/screen/radial/slice/MouseExited(location, control, params) /atom/movable/screen/radial/slice/MouseExited(location, control, params)
. = ..() . = ..()
icon_state = "radial_slice" if(next_page || !parent)
icon_state = "radial_slice"
else
icon_state = parent.radial_slice_icon
if(tooltips) if(tooltips)
closeToolTip(usr) closeToolTip(usr)
@@ -42,7 +53,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
if(next_page) if(next_page)
parent.next_page() parent.next_page()
else else
parent.element_chosen(choice,usr) parent.element_chosen(choice, usr, params)
/atom/movable/screen/radial/center /atom/movable/screen/radial/center
name = "Close Menu" name = "Close Menu"
@@ -101,6 +112,9 @@ GLOBAL_LIST_EMPTY(radial_menus)
var/entry_animation = TRUE var/entry_animation = TRUE
var/icon_path = 'icons/hud/radial.dmi' //SKYRAT EDIT ADDITION - GUNPOINT var/icon_path = 'icons/hud/radial.dmi' //SKYRAT EDIT ADDITION - GUNPOINT
///A replacement icon state for the generic radial slice bg icon. Doesn't affect the next page nor the center buttons
var/radial_slice_icon
//If we swap to vis_contens inventory these will need a redo //If we swap to vis_contens inventory these will need a redo
/datum/radial_menu/proc/check_screen_border(mob/user) /datum/radial_menu/proc/check_screen_border(mob/user)
var/atom/movable/AM = anchor var/atom/movable/AM = anchor
@@ -132,7 +146,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
starting_angle = 180 starting_angle = 180
ending_angle = 45 ending_angle = 45
/datum/radial_menu/proc/setup_menu(use_tooltips) /datum/radial_menu/proc/setup_menu(use_tooltips, set_page = 1)
if(ending_angle > starting_angle) if(ending_angle > starting_angle)
zone = ending_angle - starting_angle zone = ending_angle - starting_angle
else else
@@ -169,7 +183,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
page_data[page] = current page_data[page] = current
pages = page pages = page
current_page = 1 current_page = clamp(set_page, 1, pages)
update_screen_objects(anim = entry_animation) update_screen_objects(anim = entry_animation)
/datum/radial_menu/proc/update_screen_objects(anim = FALSE) /datum/radial_menu/proc/update_screen_objects(anim = FALSE)
@@ -215,9 +229,14 @@ GLOBAL_LIST_EMPTY(radial_menus)
if(choice_id == NEXT_PAGE_ID) if(choice_id == NEXT_PAGE_ID)
E.name = "Next Page" E.name = "Next Page"
E.next_page = TRUE E.next_page = TRUE
E.icon_state = "radial_slice" // Resets the bg icon state to the default for next page buttons.
E.add_overlay("radial_next") E.add_overlay("radial_next")
else else
if(istext(choices_values[choice_id])) //This isn't granted to exist, so use the ?. operator for conditionals that use it.
var/datum/radial_menu_choice/choice_datum = choice_datums[choice_id]
if(choice_datum?.name)
E.name = choice_datum.name
else if(istext(choices_values[choice_id]))
E.name = choices_values[choice_id] E.name = choices_values[choice_id]
else if(ispath(choices_values[choice_id],/atom)) else if(ispath(choices_values[choice_id],/atom))
var/atom/A = choices_values[choice_id] var/atom/A = choices_values[choice_id]
@@ -230,13 +249,11 @@ GLOBAL_LIST_EMPTY(radial_menus)
E.next_page = FALSE E.next_page = FALSE
if(choices_icons[choice_id]) if(choices_icons[choice_id])
E.add_overlay(choices_icons[choice_id]) E.add_overlay(choices_icons[choice_id])
if (choice_datums[choice_id]) if (choice_datum?.info)
var/datum/radial_menu_choice/choice_datum = choice_datums[choice_id] var/obj/effect/abstract/info/info_button = new(E, choice_datum.info)
if (choice_datum.info) info_button.plane = ABOVE_HUD_PLANE
var/obj/effect/abstract/info/info_button = new(E, choice_datum.info) info_button.layer = RADIAL_CONTENT_LAYER
info_button.plane = ABOVE_HUD_PLANE E.vis_contents += info_button
info_button.layer = RADIAL_CONTENT_LAYER
E.vis_contents += info_button
/datum/radial_menu/New() /datum/radial_menu/New()
close_button = new close_button = new
@@ -246,6 +263,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
choices.Cut() choices.Cut()
choices_icons.Cut() choices_icons.Cut()
choices_values.Cut() choices_values.Cut()
choice_datums.Cut()
current_page = 1 current_page = 1
/datum/radial_menu/proc/element_chosen(choice_id,mob/user) /datum/radial_menu/proc/element_chosen(choice_id,mob/user)
@@ -254,7 +272,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
/datum/radial_menu/proc/get_next_id() /datum/radial_menu/proc/get_next_id()
return "c_[choices.len]" return "c_[choices.len]"
/datum/radial_menu/proc/set_choices(list/new_choices, use_tooltips) /datum/radial_menu/proc/set_choices(list/new_choices, use_tooltips, set_page = 1)
if(choices.len) if(choices.len)
Reset() Reset()
for(var/E in new_choices) for(var/E in new_choices)
@@ -268,7 +286,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
if (istype(new_choices[E], /datum/radial_menu_choice)) if (istype(new_choices[E], /datum/radial_menu_choice))
choice_datums[id] = new_choices[E] choice_datums[id] = new_choices[E]
setup_menu(use_tooltips) setup_menu(use_tooltips, set_page)
/datum/radial_menu/proc/extract_image(to_extract_from) /datum/radial_menu/proc/extract_image(to_extract_from)
if (istype(to_extract_from, /datum/radial_menu_choice)) if (istype(to_extract_from, /datum/radial_menu_choice))
@@ -327,7 +345,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
Choices should be a list where list keys are movables or text used for element names and return value Choices should be a list where list keys are movables or text used for element names and return value
and list values are movables/icons/images used for element icons and list values are movables/icons/images used for element icons
*/ */
/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE, no_repeat_close = FALSE) /proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE, no_repeat_close = FALSE, radial_slice_icon = "radial_slice")
if(!user || !anchor || !length(choices)) if(!user || !anchor || !length(choices))
return return
if(!uniqueid) if(!uniqueid)
@@ -346,6 +364,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
if(istype(custom_check)) if(istype(custom_check))
menu.custom_check_callback = custom_check menu.custom_check_callback = custom_check
menu.anchor = anchor menu.anchor = anchor
menu.radial_slice_icon = radial_slice_icon
menu.check_screen_border(user) //Do what's needed to make it look good near borders or on hud menu.check_screen_border(user) //Do what's needed to make it look good near borders or on hud
menu.set_choices(choices, tooltips) menu.set_choices(choices, tooltips)
menu.show_to(user) menu.show_to(user)
@@ -365,6 +384,9 @@ GLOBAL_LIST_EMPTY(radial_menus)
/// Required -- what to display for this button /// Required -- what to display for this button
var/image var/image
/// If provided, this will be the name the radial slice hud button. This has priority over everything else.
var/name
/// If provided, will display an info button that will put this text in your chat /// If provided, will display an info button that will put this text in your chat
var/info var/info

View File

@@ -8,7 +8,7 @@
/atom/movable/screen/radial/persistent/center/Click(location, control, params) /atom/movable/screen/radial/persistent/center/Click(location, control, params)
if(usr.client == parent.current_user) if(usr.client == parent.current_user)
parent.element_chosen(null,usr) parent.element_chosen(null, usr, params)
/atom/movable/screen/radial/persistent/center/MouseEntered(location, control, params) /atom/movable/screen/radial/persistent/center/MouseEntered(location, control, params)
. = ..() . = ..()
@@ -29,15 +29,17 @@
close_button.set_parent(src) close_button.set_parent(src)
/datum/radial_menu/persistent/element_chosen(choice_id,mob/user) /datum/radial_menu/persistent/element_chosen(choice_id, mob/user, params)
select_proc_callback.Invoke(choices_values[choice_id]) select_proc_callback.Invoke(choices_values[choice_id], params)
/datum/radial_menu/persistent/proc/change_choices(list/newchoices, tooltips) /datum/radial_menu/persistent/proc/change_choices(list/newchoices, tooltips = FALSE, animate = FALSE, keep_same_page = FALSE)
if(!newchoices.len) if(!newchoices.len)
return return
entry_animation = FALSE
var/target_page = keep_same_page ? current_page : 1 //Stores the current_page value before it's set back to 1 on Reset()
Reset() Reset()
set_choices(newchoices,tooltips) set_choices(newchoices,tooltips, set_page = target_page)
/datum/radial_menu/persistent/Destroy() /datum/radial_menu/persistent/Destroy()
QDEL_NULL(select_proc_callback) QDEL_NULL(select_proc_callback)
@@ -53,7 +55,7 @@
Select_proc is the proc to be called each time an element on the menu is clicked, and should accept the chosen element as its final argument Select_proc is the proc to be called each time an element on the menu is clicked, and should accept the chosen element as its final argument
Clicking the center button will return a choice of null Clicking the center button will return a choice of null
*/ */
/proc/show_radial_menu_persistent(mob/user, atom/anchor, list/choices, datum/callback/select_proc, uniqueid, radius, tooltips = FALSE) /proc/show_radial_menu_persistent(mob/user, atom/anchor, list/choices, datum/callback/select_proc, uniqueid, radius, tooltips = FALSE, radial_slice_icon = "radial_slice")
if(!user || !anchor || !length(choices) || !select_proc) if(!user || !anchor || !length(choices) || !select_proc)
return return
if(!uniqueid) if(!uniqueid)
@@ -67,6 +69,7 @@
GLOB.radial_menus[uniqueid] = menu GLOB.radial_menus[uniqueid] = menu
if(radius) if(radius)
menu.radius = radius menu.radius = radius
menu.radial_slice_icon = radial_slice_icon
menu.select_proc_callback = select_proc menu.select_proc_callback = select_proc
menu.anchor = anchor menu.anchor = anchor
menu.check_screen_border(user) //Do what's needed to make it look good near borders or on hud menu.check_screen_border(user) //Do what's needed to make it look good near borders or on hud

View File

@@ -0,0 +1,130 @@
/**
* A component that stores colors for use by painting-related items like spraycans or palettes
* which can be accessed through a radial menu by right clicking the item while it's held by the user mob.
* Right-clicking a color will open a color input prompt to edit it. Left clicking will instead select it
* and call set_painting_tool_color() on the parent for more specific object behavior.
*/
/datum/component/palette
/*
* A list that stores a selection of colors.
* The number of available spaces is defined by the available_space arg of Initialize()
*/
var/list/colors = list()
/*
* The currently selected color. This should be synced with that of the parent item, so please
* use the item/proc/painting_tool_pick_color proc for color
*/
var/selected_color
/// The persistent radial menu for this component.
var/datum/radial_menu/persistent/color_picker_menu
/// The radial menu choice datums are stored here as a microop to avoid generating new ones every time the menu is opened or updated.
var/list/datum/radial_menu_choice/menu_choices
/datum/component/palette/Initialize(available_space, selected_color)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
if(!isnum(available_space) || available_space < 1) /// This component means nothing if there's no space for colors
stack_trace("palette component initialized without a proper value for the available_space arg")
return COMPONENT_INCOMPATIBLE
for(var/index in 1 to available_space)
colors += "#ffffff"
src.colors = colors
src.selected_color = selected_color || "#ffffff"
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF_SECONDARY, .proc/on_attack_self_secondary)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
RegisterSignal(parent, COMSIG_PAINTING_TOOL_SET_COLOR, .proc/on_painting_tool_set_color)
RegisterSignal(parent, COMSIG_PAINTING_TOOL_GET_ADDITIONAL_DATA, .proc/get_palette_data)
/datum/component/palette/Destroy()
QDEL_NULL(color_picker_menu)
QDEL_LIST(menu_choices)
UnregisterSignal(parent, list(COMSIG_ITEM_ATTACK_SELF_SECONDARY, COMSIG_PARENT_EXAMINE,
COMSIG_ITEM_DROPPED, COMSIG_PAINTING_TOOL_SET_COLOR, COMSIG_PAINTING_TOOL_GET_ADDITIONAL_DATA))
return ..()
/datum/component/palette/proc/on_examine(datum/source, mob/user, list/examine_list)
SIGNAL_HANDLER
examine_list += span_notice("<b>Right-Click</b> this item while it's in your active hand to open/close its color picker menu.")
examine_list += span_notice("In the color picker, <b>Left-Click</b> a color button to pick it or <b>Right-Click</b> to edit it.")
/datum/component/palette/proc/on_attack_self_secondary(datum/source, mob/user)
SIGNAL_HANDLER
if(!color_picker_menu)
INVOKE_ASYNC(src, .proc/open_radial_menu, user)
else
close_radial_menu()
return COMPONENT_CANCEL_ATTACK_CHAIN
/datum/component/palette/proc/open_radial_menu(mob/user)
var/list/choices = build_radial_list()
color_picker_menu = show_radial_menu_persistent(user, parent, choices, select_proc = CALLBACK(src, .proc/choice_selected, user), tooltips = TRUE, radial_slice_icon = "palette_bg")
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/close_radial_menu)
/datum/component/palette/proc/build_radial_list()
var/radial_list = list()
LAZYSETLEN(menu_choices, length(colors))
for(var/index in 1 to length(colors))
var/hexcolor = colors[index]
var/datum/radial_menu_choice/option = menu_choices[index]
if(!option)
option = new
var/icon_state_to_use = hexcolor == selected_color ? "palette_selected" : "palette_element"
var/image/element = image(icon = 'icons/hud/radial.dmi', icon_state = icon_state_to_use)
element.color = hexcolor
option.image = element
// We want only the name/tooltip to show the hexcolor to avoid having multiple choices with same ids (identical colors).
option.name = hexcolor
radial_list["[index]"] = option
return radial_list
/datum/component/palette/proc/close_radial_menu()
SIGNAL_HANDLER
QDEL_NULL(color_picker_menu)
UnregisterSignal(parent, COMSIG_ITEM_DROPPED)
/datum/component/palette/proc/update_radial_list()
if(QDELETED(color_picker_menu))
return
var/list/choices = build_radial_list()
color_picker_menu.change_choices(choices, tooltips = TRUE, keep_same_page = TRUE)
/datum/component/palette/proc/choice_selected(mob/user, choice, params)
if(!choice || IS_DEAD_OR_INCAP(user)) // center button or incapacitated but still holding on the item.
close_radial_menu()
return
var/is_right_clicking = LAZYACCESS(params2list(params), RIGHT_CLICK)
var/index = text2num(choice)
if(is_right_clicking)
var/chosen_color = input(user, "Pick new color", "[parent]", colors[index]) as color|null
if(chosen_color && !QDELETED(src) && !IS_DEAD_OR_INCAP(user) && user.is_holding(parent))
colors[index] = chosen_color
update_radial_list()
else
var/obj/item/parent_item = parent
parent_item.set_painting_tool_color(colors[index]) // This will send a signal back to us. See below.
/datum/component/palette/proc/on_painting_tool_set_color(datum/source, chosen_color)
SIGNAL_HANDLER
selected_color = chosen_color
update_radial_list()
/datum/component/palette/proc/get_palette_data(datum/source, data)
SIGNAL_HANDLER
var/list/painting_data = list()
for(var/hexcolor in colors)
painting_data += list(list(
"color" = hexcolor,
"is_selected" = hexcolor == selected_color
))
data["paint_tool_palette"] = painting_data

View File

@@ -1476,3 +1476,13 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
animate(attack_image, alpha = 175, transform = copy_transform.Scale(0.75), pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3) animate(attack_image, alpha = 175, transform = copy_transform.Scale(0.75), pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3)
animate(time = 1) animate(time = 1)
animate(alpha = 0, time = 3, easing = CIRCULAR_EASING|EASE_OUT) animate(alpha = 0, time = 3, easing = CIRCULAR_EASING|EASE_OUT)
/// Common proc used by painting tools like spraycans and palettes that can access the entire 24 bits color space.
/obj/item/proc/pick_painting_tool_color(mob/user, default_color)
var/chosen_color = input(user,"Pick new color", "[src]", default_color) as color|null
if(!chosen_color || QDELETED(src) || IS_DEAD_OR_INCAP(user) || !user.is_holding(src))
return
set_painting_tool_color(chosen_color)
/obj/item/proc/set_painting_tool_color(chosen_color)
SEND_SIGNAL(src, COMSIG_PAINTING_TOOL_SET_COLOR, chosen_color)

View File

@@ -265,7 +265,6 @@
if(!wiring_gui_menu) if(!wiring_gui_menu)
return return
wiring_gui_menu.entry_animation = FALSE //stop the open anim from playing each time we update
var/list/choices = wiringGuiGenerateChoices(user) var/list/choices = wiringGuiGenerateChoices(user)
wiring_gui_menu.change_choices(choices,FALSE) wiring_gui_menu.change_choices(choices,FALSE)

View File

@@ -12,6 +12,8 @@
#define PAINT_LARGE_HORIZONTAL 2 #define PAINT_LARGE_HORIZONTAL 2
#define PAINT_LARGE_HORIZONTAL_ICON 'icons/effects/96x32.dmi' #define PAINT_LARGE_HORIZONTAL_ICON 'icons/effects/96x32.dmi'
#define AVAILABLE_SPRAYCAN_SPACE 8 // enough to fill one radial menu page
/* /*
* Crayons * Crayons
*/ */
@@ -87,13 +89,15 @@
drawtype = pick(all_drawables) drawtype = pick(all_drawables)
AddElement(/datum/element/venue_price, FOOD_PRICE_EXOTIC) AddElement(/datum/element/venue_price, FOOD_PRICE_EXOTIC)
if(can_change_colour)
AddComponent(/datum/component/palette, AVAILABLE_SPRAYCAN_SPACE, paint_color)
refill() refill()
/obj/item/toy/crayon/examine(mob/user) /obj/item/toy/crayon/set_painting_tool_color(chosen_color)
. = ..() . = ..()
if(can_change_colour) paint_color = chosen_color
. += span_notice("Ctrl-click [src] while it's on your person to quickly recolour it.") update_appearance()
/obj/item/toy/crayon/proc/refill() /obj/item/toy/crayon/proc/refill()
if(charges == -1) if(charges == -1)
@@ -163,12 +167,6 @@
to_chat(user, span_notice("The cap on [src] is now [is_capped ? "on" : "off"].")) to_chat(user, span_notice("The cap on [src] is now [is_capped ? "on" : "off"]."))
update_appearance() update_appearance()
/obj/item/toy/crayon/CtrlClick(mob/user)
if(can_change_colour && !isturf(loc) && user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
select_colour(user)
else
return ..()
/obj/item/toy/crayon/proc/staticDrawables() /obj/item/toy/crayon/proc/staticDrawables()
. = list() . = list()
@@ -248,7 +246,7 @@
else else
paint_mode = PAINT_NORMAL paint_mode = PAINT_NORMAL
if("select_colour") if("select_colour")
. = can_change_colour && select_colour(usr) . = can_change_colour && pick_painting_tool_color(usr, paint_color)
if("enter_text") if("enter_text")
var/txt = tgui_input_text(usr, "Choose what to write", "Scribbles", text_buffer) var/txt = tgui_input_text(usr, "Choose what to write", "Scribbles", text_buffer)
if(isnull(txt)) if(isnull(txt))
@@ -263,13 +261,6 @@
drawtype = "a" drawtype = "a"
update_appearance() update_appearance()
/obj/item/toy/crayon/proc/select_colour(mob/user)
var/chosen_colour = input(user, "", "Choose Color", paint_color) as color|null
if (!isnull(chosen_colour) && user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
paint_color = chosen_colour
return TRUE
return FALSE
/obj/item/toy/crayon/proc/crayon_text_strip(text) /obj/item/toy/crayon/proc/crayon_text_strip(text)
text = copytext(text, 1, MAX_MESSAGE_LEN) text = copytext(text, 1, MAX_MESSAGE_LEN)
var/static/regex/crayon_regex = new /regex(@"[^\w!?,.=&%#+/\-]", "ig") var/static/regex/crayon_regex = new /regex(@"[^\w!?,.=&%#+/\-]", "ig")
@@ -591,7 +582,7 @@
dye_color = DYE_RAINBOW dye_color = DYE_RAINBOW
/obj/item/toy/crayon/rainbow/afterattack(atom/target, mob/user, proximity, params) /obj/item/toy/crayon/rainbow/afterattack(atom/target, mob/user, proximity, params)
paint_color = rgb(rand(0,255), rand(0,255), rand(0,255)) set_painting_tool_color(rgb(rand(0,255), rand(0,255), rand(0,255)))
. = ..() . = ..()
/* /*
@@ -700,7 +691,7 @@
if(pre_noise || post_noise) if(pre_noise || post_noise)
playsound(src, 'sound/effects/spray.ogg', 5, TRUE, 5) playsound(src, 'sound/effects/spray.ogg', 5, TRUE, 5)
if(can_change_colour) if(can_change_colour)
paint_color = "#C0C0C0" set_painting_tool_color("#C0C0C0")
update_appearance() update_appearance()
if(actually_paints) if(actually_paints)
H.update_lips("spray_face", paint_color) H.update_lips("spray_face", paint_color)
@@ -713,11 +704,8 @@
. = ..() . = ..()
// If default crayon red colour, pick a more fun spraycan colour // If default crayon red colour, pick a more fun spraycan colour
if(!paint_color) if(!paint_color)
paint_color = pick("#DA0000","#FF9300","#FFF200","#A8E61D","#00B7EF", set_painting_tool_color(pick("#DA0000", "#FF9300", "#FFF200", "#A8E61D", "#00B7EF", "#DA00FF"))
"#DA00FF")
refill() refill()
update_appearance()
/obj/item/toy/crayon/spraycan/examine(mob/user) /obj/item/toy/crayon/spraycan/examine(mob/user)
. = ..() . = ..()
@@ -914,3 +902,5 @@
#undef RANDOM_ORIENTED #undef RANDOM_ORIENTED
#undef RANDOM_RUNE #undef RANDOM_RUNE
#undef RANDOM_ANY #undef RANDOM_ANY
#undef AVAILABLE_SPRAYCAN_SPACE

View File

@@ -113,7 +113,13 @@
.["finalized"] = finalized .["finalized"] = finalized
.["editable"] = !finalized //Ideally you should be able to draw moustaches on existing paintings in the gallery but that's not implemented yet .["editable"] = !finalized //Ideally you should be able to draw moustaches on existing paintings in the gallery but that's not implemented yet
.["show_plaque"] = istype(loc,/obj/structure/sign/painting) .["show_plaque"] = istype(loc,/obj/structure/sign/painting)
.["paint_tool_color"] = get_paint_tool_color(user.get_active_held_item()) var/obj/item/painting_implement = user.get_active_held_item()
.["paint_tool_color"] = get_paint_tool_color(painting_implement)
// Clearing additional data so that it doesn't linger around if the painting tool is dropped.
.["paint_tool_palette"] = null
if(!painting_implement)
return
SEND_SIGNAL(painting_implement, COMSIG_PAINTING_TOOL_GET_ADDITIONAL_DATA, .)
/obj/item/canvas/examine(mob/user) /obj/item/canvas/examine(mob/user)
. = ..() . = ..()
@@ -146,6 +152,9 @@
used = TRUE used = TRUE
update_appearance() update_appearance()
. = TRUE . = TRUE
if("select_color")
var/obj/item/painting_implement = user.get_active_held_item()
painting_implement?.set_painting_tool_color(params["selected_color"])
if("finalize") if("finalize")
. = TRUE . = TRUE
finalize(user) finalize(user)
@@ -504,6 +513,8 @@
desc_with_canvas = "A painting hung away from lesser minds." desc_with_canvas = "A painting hung away from lesser minds."
persistence_id = "library_private" persistence_id = "library_private"
#define AVAILABLE_PALETTE_SPACE 14 // Enough to fill two radial menu pages
/// Simple painting utility. /// Simple painting utility.
/obj/item/paint_palette /obj/item/paint_palette
name = "paint palette" name = "paint palette"
@@ -514,10 +525,18 @@
righthand_file = 'icons/mob/inhands/equipment/palette_righthand.dmi' righthand_file = 'icons/mob/inhands/equipment/palette_righthand.dmi'
w_class = WEIGHT_CLASS_TINY w_class = WEIGHT_CLASS_TINY
///Chosen paint color ///Chosen paint color
var/current_color var/current_color = "#000000"
/obj/item/paint_palette/Initialize()
. = ..()
AddComponent(/datum/component/palette, AVAILABLE_PALETTE_SPACE, current_color)
/obj/item/paint_palette/attack_self(mob/user, modifiers) /obj/item/paint_palette/attack_self(mob/user, modifiers)
. = ..() . = ..()
var/chosen_color = input(user,"Pick new color","Palette") as color|null pick_painting_tool_color(user, current_color)
if(chosen_color)
current_color = chosen_color /obj/item/paint_palette/set_painting_tool_color(chosen_color)
. = ..()
current_color = chosen_color
#undef AVAILABLE_PALETTE_SPACE

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -223,6 +223,7 @@
#include "code\__DEFINES\dcs\signals\signals_NTNet.dm" #include "code\__DEFINES\dcs\signals\signals_NTNet.dm"
#include "code\__DEFINES\dcs\signals\signals_object.dm" #include "code\__DEFINES\dcs\signals\signals_object.dm"
#include "code\__DEFINES\dcs\signals\signals_operating_computer.dm" #include "code\__DEFINES\dcs\signals\signals_operating_computer.dm"
#include "code\__DEFINES\dcs\signals\signals_painting.dm"
#include "code\__DEFINES\dcs\signals\signals_radiation.dm" #include "code\__DEFINES\dcs\signals\signals_radiation.dm"
#include "code\__DEFINES\dcs\signals\signals_reagent.dm" #include "code\__DEFINES\dcs\signals\signals_reagent.dm"
#include "code\__DEFINES\dcs\signals\signals_restaurant.dm" #include "code\__DEFINES\dcs\signals\signals_restaurant.dm"
@@ -787,6 +788,7 @@
#include "code\datums\components\omen.dm" #include "code\datums\components\omen.dm"
#include "code\datums\components\orbiter.dm" #include "code\datums\components\orbiter.dm"
#include "code\datums\components\overlay_lighting.dm" #include "code\datums\components\overlay_lighting.dm"
#include "code\datums\components\palette.dm"
#include "code\datums\components\payment.dm" #include "code\datums\components\payment.dm"
#include "code\datums\components\pellet_cloud.dm" #include "code\datums\components\pellet_cloud.dm"
#include "code\datums\components\phylactery.dm" #include "code\datums\components\phylactery.dm"

View File

@@ -182,12 +182,18 @@ const getImageSize = value => {
return [width, height]; return [width, height];
}; };
type PaletteColor = {
color: string;
is_selected: boolean;
}
type CanvasData = { type CanvasData = {
grid: string[][], grid: string[][],
finalized: boolean, finalized: boolean,
name: string, name: string,
editable: boolean, editable: boolean,
paint_tool_color: string | null, paint_tool_color: string | null,
paint_tool_palette: PaletteColor[] | null,
author: string | null, author: string | null,
medium: string | null, medium: string | null,
patron: string | null, patron: string | null,
@@ -201,11 +207,13 @@ export const Canvas = (props, context) => {
const scaled_width = width * PX_PER_UNIT; const scaled_width = width * PX_PER_UNIT;
const scaled_height = height * PX_PER_UNIT; const scaled_height = height * PX_PER_UNIT;
const average_plaque_height = 90; const average_plaque_height = 90;
const palette_height = 36;
return ( return (
<Window <Window
width={scaled_width + 72} width={scaled_width + 72}
height={scaled_height + 70 height={scaled_height + 75
+ (data.show_plaque ? average_plaque_height : 0)}> + (data.show_plaque ? average_plaque_height : 0)
+ (data.editable && data.paint_tool_palette ? palette_height : 0)}>
<Window.Content> <Window.Content>
<Box textAlign="center"> <Box textAlign="center">
<PaintCanvas <PaintCanvas
@@ -218,7 +226,26 @@ export const Canvas = (props, context) => {
onCanvasModifiedHandler={(changed) => act("paint", { data: toMassPaintFormat(changed) })} onCanvasModifiedHandler={(changed) => act("paint", { data: toMassPaintFormat(changed) })}
editable={data.editable} editable={data.editable}
/> />
<Flex align="center" justify="center"> <Flex align="center" justify="center" direction="column">
{!!data.editable && !!data.paint_tool_palette && (
<Flex.Item>
{data.paint_tool_palette.map((element, index) => (
<Button
key={`${index}`}
backgroundColor={element.color}
style={{
"width": "24px",
"height": "24px",
"border-style": "solid",
"border-color": element.is_selected ? "lightblue" : "black",
"border-width": "2px",
}}
onClick={() => act('select_color', {
selected_color: element.color,
})} />
))}
</Flex.Item>
)}
{!data.finalized && ( {!data.finalized && (
<Flex.Item> <Flex.Item>
<Button.Confirm <Button.Confirm