mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 17:52:36 +00:00
[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:
7
code/__DEFINES/dcs/signals/signals_painting.dm
Normal file
7
code/__DEFINES/dcs/signals/signals_painting.dm
Normal 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"
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
130
code/datums/components/palette.dm
Normal file
130
code/datums/components/palette.dm
Normal 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
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 |
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user