mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-25 21:19:44 +01:00
ports tgui color input from bubbers (#16934)
* ports tgui color input from monkeystation * . * push that real quick * . * . * cleanup * fix for 516 * port bubbers pre set selection * also this * allow 20 saved states * oups * regex replace * urg * use the update by type * . * . * highlight? * larger? * fix those * keep anyone below 516 on old style
This commit is contained in:
@@ -83,7 +83,7 @@
|
||||
active_mode = text2num(params["mode"])
|
||||
return TRUE
|
||||
if("choose_color")
|
||||
var/chosen_color = input(inserted, "Choose a color: ", "ColorMate colour picking", activecolor) as color|null
|
||||
var/chosen_color = tgui_color_picker(inserted, "Choose a color: ", "ColorMate colour picking", activecolor)
|
||||
if(chosen_color)
|
||||
activecolor = chosen_color
|
||||
return TRUE
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
active_mode = text2num(params["mode"])
|
||||
return TRUE
|
||||
if("choose_color")
|
||||
var/chosen_color = input(ui.user, "Choose a color: ", "ColorMate colour picking", activecolor) as color|null
|
||||
var/chosen_color = tgui_color_picker(ui.user, "Choose a color: ", "ColorMate colour picking", activecolor)
|
||||
if(chosen_color)
|
||||
activecolor = chosen_color
|
||||
return TRUE
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
return
|
||||
switch(option)
|
||||
if("tint")
|
||||
var/new_color = input(user, "Choose the color for the [identifier] to be:", "Statue color", tint) as color|null
|
||||
var/new_color = tgui_color_picker(user, "Choose the color for the [identifier] to be:", "Statue color", tint)
|
||||
if (new_color)
|
||||
tint = new_color
|
||||
if("material","identifier","adjective")
|
||||
|
||||
@@ -294,7 +294,7 @@
|
||||
if(istype(W,/obj/item/multitool) && state == 1)
|
||||
var/new_paint_location = tgui_input_list(user, "Please select a target zone.", "Paint Zone", list("Fore Stripe", "Aft Stripe", "CANCEL"))
|
||||
if(new_paint_location && new_paint_location != "CANCEL")
|
||||
var/new_paint_color = input(user, "Please select a paint color.", "Paint Color", null) as color|null
|
||||
var/new_paint_color = tgui_color_picker(user, "Please select a paint color.", "Paint Color", null)
|
||||
if(new_paint_color)
|
||||
switch(new_paint_location)
|
||||
if("Fore Stripe")
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
if(istype(W,/obj/item/multitool) && state == 1)
|
||||
var/new_paint_location = tgui_input_list(user, "Please select a target zone.", "Paint Zone", list("Central", "Engine", "Base", "Front", "CANCEL"))
|
||||
if(new_paint_location && new_paint_location != "CANCEL")
|
||||
var/new_paint_color = input(user, "Please select a paint color.", "Paint Color", null) as color|null
|
||||
var/new_paint_color = tgui_color_picker(user, "Please select a paint color.", "Paint Color", null)
|
||||
if(new_paint_color)
|
||||
switch(new_paint_location)
|
||||
if("Central")
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
var/new_colour = input(usr, "Choose a colour.", name, paint_colour) as color|null
|
||||
var/new_colour = tgui_color_picker(usr, "Choose a colour.", name, paint_colour)
|
||||
if(new_colour && new_colour != paint_colour)
|
||||
paint_colour = new_colour
|
||||
to_chat(usr, span_notice("You set \the [src] to paint with <font color='[paint_colour]'>a new colour</font>."))
|
||||
|
||||
@@ -318,7 +318,7 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
if(href_list["track_color"])
|
||||
var/obj/item/gps/gps = locate(href_list["track_color"])
|
||||
if(istype(gps) && !QDELETED(gps))
|
||||
var/new_colour = input(usr, "Enter a new tracking color.", "GPS Waypoint Color") as color|null
|
||||
var/new_colour = tgui_color_picker(usr, "Enter a new tracking color.", "GPS Waypoint Color")
|
||||
if(new_colour && istype(gps) && !QDELETED(gps) && holder == usr && !usr.incapacitated())
|
||||
to_chat(usr, span_notice("You adjust the colour \the [src] is using to highlight [gps.gps_tag]."))
|
||||
LAZYSET(tracking_devices, href_list["track_color"], new_colour)
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
return
|
||||
*/
|
||||
to_chat(user, "It has [uses] lights remaining.")
|
||||
var/new_color = input(user, "Choose a color to set the light to! (Default is [LIGHT_COLOR_INCANDESCENT_TUBE])", "", selected_color) as color|null
|
||||
var/new_color = tgui_color_picker(user, "Choose a color to set the light to! (Default is [LIGHT_COLOR_INCANDESCENT_TUBE])", "", selected_color)
|
||||
if(new_color)
|
||||
selected_color = new_color
|
||||
to_chat(user, "The light color has been changed.")
|
||||
|
||||
@@ -208,7 +208,7 @@
|
||||
to_chat(user, span_notice("You remove the cell from \the [src]."))
|
||||
update_icon()
|
||||
else if(istype(W,/obj/item/multitool))
|
||||
var/new_color = input(usr, "Choose a color to set the shield to!", "", effect_color) as color|null
|
||||
var/new_color = tgui_color_picker(usr, "Choose a color to set the shield to!", "", effect_color)
|
||||
if(new_color)
|
||||
effect_color = new_color
|
||||
else
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
return
|
||||
|
||||
if(tgui_alert(user, "Are you sure you want to recolor your blade?", "Confirm Recolor", list("Yes", "No")) == "Yes")
|
||||
var/energy_color_input = input(user,"","Choose Energy Color",lcolor) as color|null
|
||||
var/energy_color_input = tgui_color_picker(user,"","Choose Energy Color",lcolor)
|
||||
if(energy_color_input)
|
||||
lcolor = sanitize_hexcolor(energy_color_input)
|
||||
update_icon()
|
||||
|
||||
@@ -34,6 +34,6 @@
|
||||
|
||||
/obj/item/grenade/smokebomb/attackby(obj/item/I as obj, mob/user as mob)
|
||||
if(istype(I,/obj/item/multitool))
|
||||
var/new_smoke_color = input(user, "Choose a color for the smoke:", "Smoke Color", smoke_color) as color|null
|
||||
var/new_smoke_color = tgui_color_picker(user, "Choose a color for the smoke:", "Smoke Color", smoke_color)
|
||||
if(new_smoke_color)
|
||||
smoke_color = new_smoke_color
|
||||
|
||||
@@ -188,10 +188,12 @@
|
||||
return
|
||||
|
||||
if(tgui_alert(user, "Are you sure you want to recolor your blade?", "Confirm Recolor", list("Yes", "No")) == "Yes")
|
||||
var/energy_color_input = input(user,"","Choose Energy Color",lcolor) as color|null
|
||||
var/energy_color_input = tgui_color_picker(user,"","Choose Energy Color",lcolor)
|
||||
if(energy_color_input)
|
||||
lcolor = sanitize_hexcolor(energy_color_input)
|
||||
update_icon()
|
||||
if(active)
|
||||
set_light(lrange, lpower, lcolor)
|
||||
|
||||
/obj/item/melee/energy/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
to_chat(user, span_warning("You can't do that right now!"))
|
||||
return
|
||||
if(tgui_alert(user, "Are you sure you want to recolor your shield?", "Confirm Recolor", list("Yes", "No")) == "Yes")
|
||||
var/energy_color_input = input(user,"","Choose Energy Color",lcolor) as color|null
|
||||
var/energy_color_input = tgui_color_picker(user,"","Choose Energy Color",lcolor)
|
||||
if(energy_color_input)
|
||||
lcolor = sanitize_hexcolor(energy_color_input)
|
||||
update_icon()
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
if(usr.stat || usr.restrained() || usr.incapacitated())
|
||||
return
|
||||
|
||||
var/new_color = input(usr, "Pick a new color", "Wallet Color", color) as color|null
|
||||
var/new_color = tgui_color_picker(usr, "Pick a new color", "Wallet Color", color)
|
||||
|
||||
if(new_color && (new_color != color))
|
||||
color = new_color
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
// VOREStation Add End
|
||||
|
||||
else if(href_list["pref_runechat_color"])
|
||||
var/new_runechat_color = input(user, "Choose your character's runechat colour (#000000 for random):", "Character Preference", pref.runechat_color) as color|null
|
||||
var/new_runechat_color = tgui_color_picker(user, "Choose your character's runechat colour (#000000 for random):", "Character Preference", pref.runechat_color)
|
||||
if(new_runechat_color && CanUseTopic(user))
|
||||
pref.runechat_color = new_runechat_color
|
||||
// whenever we change this, we update our mob
|
||||
|
||||
@@ -593,7 +593,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
else if(href_list["hair_color"])
|
||||
if(!has_flag(mob_species, HAS_HAIR_COLOR))
|
||||
return TOPIC_NOACTION
|
||||
var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference", pref.read_preference(/datum/preference/color/human/hair_color)) as color|null
|
||||
var/new_hair = tgui_color_picker(user, "Choose your character's hair colour:", "Character Preference", pref.read_preference(/datum/preference/color/human/hair_color))
|
||||
if(new_hair && has_flag(mob_species, HAS_HAIR_COLOR) && CanUseTopic(user))
|
||||
pref.update_preference_by_type(/datum/preference/color/human/hair_color, new_hair)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
@@ -601,7 +601,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
else if(href_list["grad_color"])
|
||||
if(!has_flag(mob_species, HAS_HAIR_COLOR))
|
||||
return TOPIC_NOACTION
|
||||
var/new_grad = input(user, "Choose your character's secondary hair color:", "Character Preference", pref.read_preference(/datum/preference/color/human/grad_color)) as color|null
|
||||
var/new_grad = tgui_color_picker(user, "Choose your character's secondary hair color:", "Character Preference", pref.read_preference(/datum/preference/color/human/grad_color))
|
||||
if(new_grad && has_flag(mob_species, HAS_HAIR_COLOR) && CanUseTopic(user))
|
||||
pref.update_preference_by_type(/datum/preference/color/human/grad_color, new_grad)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
@@ -647,7 +647,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
else if(href_list["facial_color"])
|
||||
if(!has_flag(mob_species, HAS_HAIR_COLOR))
|
||||
return TOPIC_NOACTION
|
||||
var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference", pref.read_preference(/datum/preference/color/human/facial_color)) as color|null
|
||||
var/new_facial = tgui_color_picker(user, "Choose your character's facial-hair colour:", "Character Preference", pref.read_preference(/datum/preference/color/human/facial_color))
|
||||
if(new_facial && has_flag(mob_species, HAS_HAIR_COLOR) && CanUseTopic(user))
|
||||
pref.update_preference_by_type(/datum/preference/color/human/facial_color, new_facial)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
@@ -660,7 +660,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
else if(href_list["eye_color"])
|
||||
if(!has_flag(mob_species, HAS_EYE_COLOR))
|
||||
return TOPIC_NOACTION
|
||||
var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference", pref.read_preference(/datum/preference/color/human/eyes_color)) as color|null
|
||||
var/new_eyes = tgui_color_picker(user, "Choose your character's eye colour:", "Character Preference", pref.read_preference(/datum/preference/color/human/eyes_color))
|
||||
if(new_eyes && has_flag(mob_species, HAS_EYE_COLOR) && CanUseTopic(user))
|
||||
pref.update_preference_by_type(/datum/preference/color/human/eyes_color, new_eyes)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
@@ -676,7 +676,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
else if(href_list["skin_color"])
|
||||
if(!has_flag(mob_species, HAS_SKIN_COLOR))
|
||||
return TOPIC_NOACTION
|
||||
var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference", pref.read_preference(/datum/preference/color/human/skin_color)) as color|null
|
||||
var/new_skin = tgui_color_picker(user, "Choose your character's skin colour: ", "Character Preference", pref.read_preference(/datum/preference/color/human/skin_color))
|
||||
if(new_skin && has_flag(mob_species, HAS_SKIN_COLOR) && CanUseTopic(user))
|
||||
pref.update_preference_by_type(/datum/preference/color/human/skin_color, new_skin)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
@@ -769,7 +769,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
if (isnull(pref.body_markings[M]["color"]))
|
||||
if (tgui_alert(user, "You currently have customized marking colors. This will reset each bodypart's color. Are you sure you want to continue?","Reset Bodypart Colors",list("Yes","No")) != "Yes")
|
||||
return TOPIC_NOACTION
|
||||
var/mark_color = input(user, "Choose the [M] color: ", "Character Preference", pref.body_markings[M]["color"]) as color|null
|
||||
var/mark_color = tgui_color_picker(user, "Choose the [M] color: ", "Character Preference", pref.body_markings[M]["color"])
|
||||
if(mark_color && CanUseTopic(user))
|
||||
pref.body_markings[M] = pref.mass_edit_marking_list(M,FALSE,TRUE,pref.body_markings[M],color="[mark_color]")
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
@@ -794,7 +794,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
if (pref.body_markings.Find(marking) == 0)
|
||||
winshow(user, "prefs_markings_subwindow", FALSE)
|
||||
return TOPIC_NOACTION
|
||||
var/mark_color = input(user, "Choose the [marking] color: ", "Character Preference", pref.body_markings[marking]["color"]) as color|null
|
||||
var/mark_color = tgui_color_picker(user, "Choose the [marking] color: ", "Character Preference", pref.body_markings[marking]["color"])
|
||||
if(mark_color && CanUseTopic(user))
|
||||
pref.body_markings[marking] = pref.mass_edit_marking_list(marking,FALSE,TRUE,pref.body_markings[marking],color="[mark_color]")
|
||||
markings_subwindow(user, marking)
|
||||
@@ -807,7 +807,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
return TOPIC_NOACTION
|
||||
var/zone = href_list["zone"]
|
||||
pref.body_markings[marking]["color"] = null //turn off the color button outside the submenu
|
||||
var/mark_color = input(user, "Choose the [marking] color: ", "Character Preference", pref.body_markings[marking][zone]["color"]) as color|null
|
||||
var/mark_color = tgui_color_picker(user, "Choose the [marking] color: ", "Character Preference", pref.body_markings[marking][zone]["color"])
|
||||
if(mark_color && CanUseTopic(user))
|
||||
pref.body_markings[marking][zone]["color"] = "[mark_color]"
|
||||
markings_subwindow(user, marking)
|
||||
@@ -1036,7 +1036,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["synth2_color"])
|
||||
var/new_color = input(user, "Choose your character's synth colour: ", "Character Preference", pref.read_preference(/datum/preference/color/human/synth_color)) as color|null
|
||||
var/new_color = tgui_color_picker(user, "Choose your character's synth colour: ", "Character Preference", pref.read_preference(/datum/preference/color/human/synth_color))
|
||||
if(new_color && CanUseTopic(user))
|
||||
pref.update_preference_by_type(/datum/preference/color/human/synth_color, new_color)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
@@ -1057,22 +1057,22 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["ear_color"])
|
||||
var/new_earc = input(user, "Choose your character's ear colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/ears_color1)) as color|null
|
||||
var/new_earc = tgui_color_picker(user, "Choose your character's ear colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/ears_color1))
|
||||
if(new_earc)
|
||||
pref.update_preference_by_type(/datum/preference/color/human/ears_color1, new_earc)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["ear_color2"])
|
||||
var/new_earc2 = input(user, "Choose your character's ear colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/ears_color2)) as color|null
|
||||
var/new_earc2 = tgui_color_picker(user, "Choose your character's ear colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/ears_color2))
|
||||
if(new_earc2)
|
||||
pref.update_preference_by_type(/datum/preference/color/human/ears_color2, new_earc2)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["ear_color3"])
|
||||
var/new_earc3 = input(user, "Choose your character's tertiary ear colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/ears_color3)) as color|null
|
||||
var/new_earc3 = tgui_color_picker(user, "Choose your character's tertiary ear colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/ears_color3))
|
||||
if(new_earc3)
|
||||
pref.update_preference_by_type(/datum/preference/color/human/ears_color3, new_earc3)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
@@ -1089,12 +1089,12 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
if(channel > GLOB.fancy_sprite_accessory_color_channel_names.len)
|
||||
return TOPIC_NOACTION
|
||||
// this would say 'secondary ears' but you'd get 'choose your character's primary secondary ear colour' which sounds silly
|
||||
var/new_color = input(
|
||||
var/new_color = tgui_color_picker(
|
||||
user,
|
||||
"Choose your character's [lowertext(GLOB.fancy_sprite_accessory_color_channel_names[channel])] ear colour:",
|
||||
"Secondary Ear Coloration",
|
||||
LAZYACCESS(pref.ear_secondary_colors, channel) || "#ffffff",
|
||||
) as color | null
|
||||
)
|
||||
if(!new_color)
|
||||
return TOPIC_NOACTION
|
||||
// ensures color channel list is at least that long
|
||||
@@ -1110,22 +1110,22 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["tail_color"])
|
||||
var/new_tailc = input(user, "Choose your character's tail/taur colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/tail_color1)) as color|null
|
||||
var/new_tailc = tgui_color_picker(user, "Choose your character's tail/taur colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/tail_color1))
|
||||
if(new_tailc)
|
||||
pref.update_preference_by_type(/datum/preference/color/human/tail_color1, new_tailc)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["tail_color2"])
|
||||
var/new_tailc2 = input(user, "Choose your character's secondary tail/taur colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/tail_color2)) as color|null
|
||||
var/new_tailc2 = tgui_color_picker(user, "Choose your character's secondary tail/taur colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/tail_color2))
|
||||
if(new_tailc2)
|
||||
pref.update_preference_by_type(/datum/preference/color/human/tail_color2, new_tailc2)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["tail_color3"])
|
||||
var/new_tailc3 = input(user, "Choose your character's tertiary tail/taur colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/tail_color3)) as color|null
|
||||
var/new_tailc3 = tgui_color_picker(user, "Choose your character's tertiary tail/taur colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/tail_color3))
|
||||
if(new_tailc3)
|
||||
pref.update_preference_by_type(/datum/preference/color/human/tail_color3, new_tailc3)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
@@ -1138,22 +1138,22 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["wing_color"])
|
||||
var/new_wingc = input(user, "Choose your character's wing colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/wing_color1)) as color|null
|
||||
var/new_wingc = tgui_color_picker(user, "Choose your character's wing colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/wing_color1))
|
||||
if(new_wingc)
|
||||
pref.update_preference_by_type(/datum/preference/color/human/wing_color1, new_wingc)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["wing_color2"])
|
||||
var/new_wingc = input(user, "Choose your character's secondary wing colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/wing_color2)) as color|null
|
||||
var/new_wingc = tgui_color_picker(user, "Choose your character's secondary wing colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/wing_color2))
|
||||
if(new_wingc)
|
||||
pref.update_preference_by_type(/datum/preference/color/human/wing_color2, new_wingc)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["wing_color3"])
|
||||
var/new_wingc = input(user, "Choose your character's tertiary wing colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/wing_color3)) as color|null
|
||||
var/new_wingc = tgui_color_picker(user, "Choose your character's tertiary wing colour:", "Character Preference",
|
||||
pref.read_preference(/datum/preference/color/human/wing_color3))
|
||||
if(new_wingc)
|
||||
pref.update_preference_by_type(/datum/preference/color/human/wing_color3, new_wingc)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
/datum/gear_tweak/color/get_metadata(var/user, var/metadata, var/title = "Character Preference")
|
||||
if(valid_colors)
|
||||
return tgui_input_list(user, "Choose a color.", title, valid_colors, metadata)
|
||||
return input(user, "Choose a color.", title, metadata) as color|null
|
||||
return tgui_color_picker(user, "Choose a color.", title, metadata)
|
||||
|
||||
/datum/gear_tweak/color/tweak_item(var/obj/item/I, var/metadata)
|
||||
if(valid_colors && !(metadata in valid_colors))
|
||||
@@ -614,4 +614,4 @@ var/datum/gear_tweak/custom_desc/gear_tweak_free_desc = new()
|
||||
else
|
||||
C.initialize_tag(metadata)
|
||||
|
||||
#undef LOADOUT_BAN_STRING
|
||||
#undef LOADOUT_BAN_STRING
|
||||
|
||||
@@ -101,7 +101,7 @@ var/global/list/valid_bloodreagents = list("default",REAGENT_ID_IRON,REAGENT_ID_
|
||||
if (1) //TRAIT_PREF_TYPE_BOOLEAN
|
||||
trait_prefs[preference] = !trait_prefs[preference]
|
||||
if (2) //TRAIT_PREF_TYPE_COLOR
|
||||
var/new_color = input(user, "Choose the color for this trait preference:", "Trait Preference", trait_prefs[preference]) as color|null
|
||||
var/new_color = tgui_color_picker(user, "Choose the color for this trait preference:", "Trait Preference", trait_prefs[preference])
|
||||
if (new_color)
|
||||
trait_prefs[preference] = new_color
|
||||
if (3) //TRAIT_PREF_TYPE_STRING
|
||||
|
||||
@@ -89,3 +89,12 @@
|
||||
|
||||
/datum/preference/numeric/tgui_say_height/apply_to_client(client/client, value)
|
||||
client.tgui_say?.load()
|
||||
|
||||
/datum/preference/text/preset_colors
|
||||
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
|
||||
savefile_identifier = PREFERENCE_PLAYER
|
||||
savefile_key = "preset_colors"
|
||||
maximum_value_length = 160
|
||||
|
||||
/datum/preference/text/preset_colors/apply_to_client(client/client, value)
|
||||
return
|
||||
|
||||
@@ -92,12 +92,12 @@
|
||||
var/default_value = read_preference(requested_preference.type)
|
||||
|
||||
// Yielding
|
||||
var/new_color = input(
|
||||
var/new_color = tgui_color_picker(
|
||||
usr,
|
||||
"Select new color",
|
||||
null,
|
||||
default_value || COLOR_WHITE,
|
||||
) as color | null
|
||||
)
|
||||
|
||||
if(!new_color)
|
||||
return FALSE
|
||||
|
||||
@@ -51,7 +51,7 @@ var/global/list/all_tooltip_styles = list(
|
||||
var/UI_style_alpha_new = tgui_input_number(usr, "Select a new alpha (transparency) parameter for your UI, between 50 and 255", null, null, 255, 50)
|
||||
if(!UI_style_alpha_new || !(UI_style_alpha_new <= 255 && UI_style_alpha_new >= 50)) return
|
||||
|
||||
var/UI_style_color_new = input(usr, "Choose your UI color. Dark colors are not recommended!") as color|null
|
||||
var/UI_style_color_new = tgui_color_picker(usr, "Choose your UI color. Dark colors are not recommended!")
|
||||
if(!UI_style_color_new) return
|
||||
|
||||
//update UI
|
||||
|
||||
@@ -177,7 +177,7 @@
|
||||
if(usr.stat || usr.restrained() || usr.incapacitated())
|
||||
return
|
||||
|
||||
var/new_color = input(usr, "Pick a new color", "Color", color) as color|null
|
||||
var/new_color = tgui_color_picker(usr, "Pick a new color", "Color", color)
|
||||
|
||||
if(new_color && (new_color != color))
|
||||
color = new_color
|
||||
|
||||
@@ -69,8 +69,8 @@
|
||||
// Just uncomment this and get rid of all of the TGUI bullshit lol
|
||||
// if(!in_range(user, src))
|
||||
// return
|
||||
// var/new_color = input(user, "Pick a color", "Color Selection", detail_color) as color|null
|
||||
// var/new_color = tgui_color_picker(user, "Pick a color", "Color Selection", detail_color)
|
||||
// if(!new_color)
|
||||
// return
|
||||
// detail_color = new_color
|
||||
// update_icon()
|
||||
// update_icon()
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
power_draw_per_use = 4
|
||||
|
||||
/obj/item/integrated_circuit/input/colorpad/ask_for_input(mob/user)
|
||||
var/new_color = input(user, "Enter a color, please.", "Color pad", get_pin_data(IC_OUTPUT, 1)) as color|null
|
||||
var/new_color = tgui_color_picker(user, "Enter a color, please.", "Color pad", get_pin_data(IC_OUTPUT, 1))
|
||||
if(new_color && CanInteract(user, GLOB.tgui_physical_state))
|
||||
set_pin_data(IC_OUTPUT, 1, new_color)
|
||||
push_data()
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
for(var/channel in 1 to ear_secondary_style.get_color_channel_count())
|
||||
var/channel_name = GLOB.fancy_sprite_accessory_color_channel_names[channel]
|
||||
var/default = LAZYACCESS(ear_secondary_colors, channel) || "#ffffff"
|
||||
var/new_color = input(usr, "Pick [channel_name]", "Ear Color ([channel_name])", default) as color | null
|
||||
var/new_color = tgui_color_picker(usr, "Pick [channel_name]", "Ear Color ([channel_name])", default)
|
||||
new_colors += new_color || default
|
||||
|
||||
update_hair()
|
||||
|
||||
+1
-1
@@ -1274,7 +1274,7 @@
|
||||
return
|
||||
|
||||
if(choice == "Color") //Easy way to set color so we don't bloat up the menu with even more buttons.
|
||||
var/new_color = input(src, "Choose a color to set your appendage to!", "", appendage_color) as color|null
|
||||
var/new_color = tgui_color_picker(src, "Choose a color to set your appendage to!", "", appendage_color)
|
||||
if(new_color)
|
||||
appendage_color = new_color
|
||||
if(choice == "Functionality") //Easy way to set color so we don't bloat up the menu with even more buttons.
|
||||
|
||||
@@ -607,7 +607,7 @@ var/list/ai_verbs_default = list(
|
||||
|
||||
switch(choice)
|
||||
if("Color")
|
||||
input = input("Choose a color:", "Hologram Color", holo_color) as color|null
|
||||
input = tgui_color_picker("Choose a color:", "Hologram Color", holo_color)
|
||||
|
||||
if(input)
|
||||
holo_color = input
|
||||
|
||||
@@ -236,7 +236,7 @@
|
||||
else
|
||||
to_chat(src, span_warning("Your selected chassis eye color can not be modified. The color you pick will only apply to supporting chassis and your card screen."))
|
||||
|
||||
var/new_eye_color = input(src, "Choose your character's eye color:", "Eye Color") as color|null
|
||||
var/new_eye_color = tgui_color_picker(src, "Choose your character's eye color:", "Eye Color")
|
||||
if(new_eye_color)
|
||||
eye_color = new_eye_color
|
||||
update_icon()
|
||||
|
||||
@@ -254,7 +254,7 @@
|
||||
if(!choice)
|
||||
return
|
||||
if(choice == "Color")
|
||||
var/new_color = input(usr, "Choose a color to set the light to! (Default is [LIGHT_COLOR_INCANDESCENT_TUBE])", "", selected_color) as color|null
|
||||
var/new_color = tgui_color_picker(usr, "Choose a color to set the light to! (Default is [LIGHT_COLOR_INCANDESCENT_TUBE])", "", selected_color)
|
||||
if(new_color)
|
||||
selected_color = new_color
|
||||
to_chat(user, span_filter_notice("The light color has been changed."))
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
set category = "Abilities.Silicon"
|
||||
set src in usr
|
||||
|
||||
var/new_pupil_color = input(usr, "Select a pupil colour.", "Pupil Colour Selection") as color|null
|
||||
var/new_pupil_color = tgui_color_picker(usr, "Select a pupil colour.", "Pupil Colour Selection")
|
||||
if(usr.incapacitated() || QDELETED(usr) || QDELETED(src) || loc != usr)
|
||||
return
|
||||
|
||||
|
||||
@@ -291,7 +291,7 @@
|
||||
if(picked_color)
|
||||
to_chat(src, span_notice("You have already picked a color! If you picked the wrong color, ask an admin to change your picked_color variable to 0."))
|
||||
return
|
||||
var/newcolor = input(usr, "Choose a color.", "", color) as color|null
|
||||
var/newcolor = tgui_color_picker(usr, "Choose a color.", "", color)
|
||||
if(newcolor)
|
||||
color = newcolor
|
||||
picked_color = TRUE
|
||||
|
||||
@@ -215,7 +215,7 @@
|
||||
if(picked_color)
|
||||
to_chat(src, span_notice("You have already picked a color! If you picked the wrong color, ask an admin to change your picked_color variable to 0."))
|
||||
return
|
||||
var/newcolor = input(usr, "Choose a color.", "", color) as color|null
|
||||
var/newcolor = tgui_color_picker(usr, "Choose a color.", "", color)
|
||||
if(newcolor)
|
||||
color = newcolor
|
||||
picked_color = TRUE
|
||||
|
||||
@@ -249,7 +249,7 @@
|
||||
set name = "Pick Color"
|
||||
set category = "Abilities.Settings"
|
||||
set desc = "You can set your color!"
|
||||
var/newcolor = input(usr, "Choose a color.", "", color) as color|null
|
||||
var/newcolor = tgui_color_picker(usr, "Choose a color.", "", color)
|
||||
if(newcolor)
|
||||
color = newcolor
|
||||
chosen_color = newcolor
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
set desc = "Customize your eyes and abdomen glow color."
|
||||
set category = "Abilities.Sect Drone"
|
||||
|
||||
var/new_color = input(src, "Please select color.", "Glow Color", custom_eye_color) as color|null
|
||||
var/new_color = tgui_color_picker(src, "Please select color.", "Glow Color", custom_eye_color)
|
||||
if(new_color)
|
||||
custom_eye_color = new_color
|
||||
remove_eyes()
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
set desc = "Customize your eyes and abdomen glow color."
|
||||
set category = "Abilities.Sect Queen"
|
||||
|
||||
var/new_color = input(src, "Please select color.", "Glow Color", custom_eye_color) as color|null
|
||||
var/new_color = tgui_color_picker(src, "Please select color.", "Glow Color", custom_eye_color)
|
||||
if(new_color)
|
||||
custom_eye_color = new_color
|
||||
remove_eyes()
|
||||
|
||||
@@ -113,8 +113,8 @@ GLOBAL_LIST_EMPTY(all_waypoints)
|
||||
|
||||
var/turf/T = get_turf(linked)
|
||||
var/obj/effect/overmap/visitable/sector/current_sector = locate() in T
|
||||
|
||||
data["mapRef"] = linked?.map_name
|
||||
if(linked)
|
||||
data["mapRef"] = linked.map_name
|
||||
data["sector"] = current_sector ? current_sector.name : "Deep Space"
|
||||
data["sector_info"] = current_sector ? current_sector.desc : "Not Available"
|
||||
data["landed"] = linked.get_landed_info()
|
||||
|
||||
@@ -1114,7 +1114,7 @@ var/global/list/light_type_cache = list()
|
||||
brightness_power = new_power
|
||||
|
||||
if("Normal Color")
|
||||
var/new_color = input(usr, "Choose a color to set the light to!", "", brightness_color) as color|null
|
||||
var/new_color = tgui_color_picker(usr, "Choose a color to set the light to!", "", brightness_color)
|
||||
if(new_color)
|
||||
brightness_color = new_color
|
||||
|
||||
@@ -1129,7 +1129,7 @@ var/global/list/light_type_cache = list()
|
||||
nightshift_power = new_power
|
||||
|
||||
if("Nightshift Color")
|
||||
var/new_color = input(usr, "Choose a color to set the light to!", "", nightshift_color) as color|null
|
||||
var/new_color = tgui_color_picker(usr, "Choose a color to set the light to!", "", nightshift_color)
|
||||
if(new_color)
|
||||
nightshift_color = new_color
|
||||
|
||||
|
||||
@@ -734,7 +734,7 @@
|
||||
desc = "Causes kinetic accelerator bolts to have an adjustable-colored tracer trail and explosion. Use in-hand to change color."
|
||||
|
||||
/obj/item/borg/upgrade/modkit/tracer/adjustable/attack_self(mob/user)
|
||||
bolt_color = input(user,"","Choose Color",bolt_color) as color|null
|
||||
bolt_color = tgui_color_picker(user,"","Choose Color",bolt_color)
|
||||
|
||||
#undef KA_ENVIRO_TYPE_COLD
|
||||
#undef KA_ENVIRO_TYPE_HOT
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
return owner.change_skin_tone(new_s_tone)
|
||||
if("skin_color")
|
||||
if(can_change_skin_color(owner))
|
||||
var/new_skin = input(ui.user, "Choose your character's skin colour: ", "Skin Color", rgb(owner.r_skin, owner.g_skin, owner.b_skin)) as color|null
|
||||
var/new_skin = tgui_color_picker(ui.user, "Choose your character's skin colour: ", "Skin Color", rgb(owner.r_skin, owner.g_skin, owner.b_skin))
|
||||
if(new_skin && can_still_topic(owner, state))
|
||||
var/r_skin = hex2num(copytext(new_skin, 2, 4))
|
||||
var/g_skin = hex2num(copytext(new_skin, 4, 6))
|
||||
@@ -133,7 +133,7 @@
|
||||
return 1
|
||||
if("hair_color")
|
||||
if(can_change(owner, APPEARANCE_HAIR_COLOR))
|
||||
var/new_hair = input(ui.user, "Please select hair color.", "Hair Color", rgb(owner.r_hair, owner.g_hair, owner.b_hair)) as color|null
|
||||
var/new_hair = tgui_color_picker(ui.user, "Please select hair color.", "Hair Color", rgb(owner.r_hair, owner.g_hair, owner.b_hair))
|
||||
if(new_hair && can_still_topic(owner, state))
|
||||
var/r_hair = hex2num(copytext(new_hair, 2, 4))
|
||||
var/g_hair = hex2num(copytext(new_hair, 4, 6))
|
||||
@@ -150,7 +150,7 @@
|
||||
return 1
|
||||
if("facial_hair_color")
|
||||
if(can_change(owner, APPEARANCE_FACIAL_HAIR_COLOR))
|
||||
var/new_facial = input(ui.user, "Please select facial hair color.", "Facial Hair Color", rgb(owner.r_facial, owner.g_facial, owner.b_facial)) as color|null
|
||||
var/new_facial = tgui_color_picker(ui.user, "Please select facial hair color.", "Facial Hair Color", rgb(owner.r_facial, owner.g_facial, owner.b_facial))
|
||||
if(new_facial && can_still_topic(owner, state))
|
||||
var/r_facial = hex2num(copytext(new_facial, 2, 4))
|
||||
var/g_facial = hex2num(copytext(new_facial, 4, 6))
|
||||
@@ -161,7 +161,7 @@
|
||||
return 1
|
||||
if("eye_color")
|
||||
if(can_change(owner, APPEARANCE_EYE_COLOR))
|
||||
var/new_eyes = input(ui.user, "Please select eye color.", "Eye Color", rgb(owner.r_eyes, owner.g_eyes, owner.b_eyes)) as color|null
|
||||
var/new_eyes = tgui_color_picker(ui.user, "Please select eye color.", "Eye Color", rgb(owner.r_eyes, owner.g_eyes, owner.b_eyes))
|
||||
if(new_eyes && can_still_topic(owner, state))
|
||||
var/r_eyes = hex2num(copytext(new_eyes, 2, 4))
|
||||
var/g_eyes = hex2num(copytext(new_eyes, 4, 6))
|
||||
@@ -201,7 +201,7 @@
|
||||
return TRUE
|
||||
if("ears_color")
|
||||
if(can_change(owner, APPEARANCE_HAIR_COLOR))
|
||||
var/new_hair = input(ui.user, "Please select ear color.", "Ear Color", rgb(owner.r_ears, owner.g_ears, owner.b_ears)) as color|null
|
||||
var/new_hair = tgui_color_picker(ui.user, "Please select ear color.", "Ear Color", rgb(owner.r_ears, owner.g_ears, owner.b_ears))
|
||||
if(new_hair && can_still_topic(owner, state))
|
||||
owner.r_ears = hex2num(copytext(new_hair, 2, 4))
|
||||
owner.g_ears = hex2num(copytext(new_hair, 4, 6))
|
||||
@@ -212,7 +212,7 @@
|
||||
return 1
|
||||
if("ears2_color")
|
||||
if(can_change(owner, APPEARANCE_HAIR_COLOR))
|
||||
var/new_hair = input(ui.user, "Please select secondary ear color.", "2nd Ear Color", rgb(owner.r_ears2, owner.g_ears2, owner.b_ears2)) as color|null
|
||||
var/new_hair = tgui_color_picker(ui.user, "Please select secondary ear color.", "2nd Ear Color", rgb(owner.r_ears2, owner.g_ears2, owner.b_ears2))
|
||||
if(new_hair && can_still_topic(owner, state))
|
||||
owner.r_ears2 = hex2num(copytext(new_hair, 2, 4))
|
||||
owner.g_ears2 = hex2num(copytext(new_hair, 4, 6))
|
||||
@@ -227,7 +227,7 @@
|
||||
if(channel > length(owner.ear_secondary_colors))
|
||||
return TRUE
|
||||
var/existing = LAZYACCESS(owner.ear_secondary_colors, channel) || "#ffffff"
|
||||
var/new_color = input(ui.user, "Please select ear color.", "2nd Ear Color", existing) as color|null
|
||||
var/new_color = tgui_color_picker(ui.user, "Please select ear color.", "2nd Ear Color", existing)
|
||||
if(new_color && can_still_topic(owner, state))
|
||||
owner.ear_secondary_colors[channel] = new_color
|
||||
update_dna(owner)
|
||||
@@ -248,7 +248,7 @@
|
||||
return TRUE
|
||||
if("tail_color")
|
||||
if(can_change(owner, APPEARANCE_HAIR_COLOR))
|
||||
var/new_hair = input(ui.user, "Please select tail color.", "Tail Color", rgb(owner.r_tail, owner.g_tail, owner.b_tail)) as color|null
|
||||
var/new_hair = tgui_color_picker(ui.user, "Please select tail color.", "Tail Color", rgb(owner.r_tail, owner.g_tail, owner.b_tail))
|
||||
if(new_hair && can_still_topic(owner, state))
|
||||
owner.r_tail = hex2num(copytext(new_hair, 2, 4))
|
||||
owner.g_tail = hex2num(copytext(new_hair, 4, 6))
|
||||
@@ -259,7 +259,7 @@
|
||||
return 1
|
||||
if("tail2_color")
|
||||
if(can_change(owner, APPEARANCE_HAIR_COLOR))
|
||||
var/new_hair = input(ui.user, "Please select secondary tail color.", "2nd Tail Color", rgb(owner.r_tail2, owner.g_tail2, owner.b_tail2)) as color|null
|
||||
var/new_hair = tgui_color_picker(ui.user, "Please select secondary tail color.", "2nd Tail Color", rgb(owner.r_tail2, owner.g_tail2, owner.b_tail2))
|
||||
if(new_hair && can_still_topic(owner, state))
|
||||
owner.r_tail2 = hex2num(copytext(new_hair, 2, 4))
|
||||
owner.g_tail2 = hex2num(copytext(new_hair, 4, 6))
|
||||
@@ -270,7 +270,7 @@
|
||||
return 1
|
||||
if("tail3_color")
|
||||
if(can_change(owner, APPEARANCE_HAIR_COLOR))
|
||||
var/new_hair = input(ui.user, "Please select secondary tail color.", "3rd Tail Color", rgb(owner.r_tail3, owner.g_tail3, owner.b_tail3)) as color|null
|
||||
var/new_hair = tgui_color_picker(ui.user, "Please select secondary tail color.", "3rd Tail Color", rgb(owner.r_tail3, owner.g_tail3, owner.b_tail3))
|
||||
if(new_hair && can_still_topic(owner, state))
|
||||
owner.r_tail3 = hex2num(copytext(new_hair, 2, 4))
|
||||
owner.g_tail3 = hex2num(copytext(new_hair, 4, 6))
|
||||
@@ -293,7 +293,7 @@
|
||||
return TRUE
|
||||
if("wing_color")
|
||||
if(can_change(owner, APPEARANCE_HAIR_COLOR))
|
||||
var/new_hair = input(ui.user, "Please select wing color.", "Wing Color", rgb(owner.r_wing, owner.g_wing, owner.b_wing)) as color|null
|
||||
var/new_hair = tgui_color_picker(ui.user, "Please select wing color.", "Wing Color", rgb(owner.r_wing, owner.g_wing, owner.b_wing))
|
||||
if(new_hair && can_still_topic(owner, state))
|
||||
owner.r_wing = hex2num(copytext(new_hair, 2, 4))
|
||||
owner.g_wing = hex2num(copytext(new_hair, 4, 6))
|
||||
@@ -304,7 +304,7 @@
|
||||
return 1
|
||||
if("wing2_color")
|
||||
if(can_change(owner, APPEARANCE_HAIR_COLOR))
|
||||
var/new_hair = input(ui.user, "Please select secondary wing color.", "2nd Wing Color", rgb(owner.r_wing2, owner.g_wing2, owner.b_wing2)) as color|null
|
||||
var/new_hair = tgui_color_picker(ui.user, "Please select secondary wing color.", "2nd Wing Color", rgb(owner.r_wing2, owner.g_wing2, owner.b_wing2))
|
||||
if(new_hair && can_still_topic(owner, state))
|
||||
owner.r_wing2 = hex2num(copytext(new_hair, 2, 4))
|
||||
owner.g_wing2 = hex2num(copytext(new_hair, 4, 6))
|
||||
@@ -315,7 +315,7 @@
|
||||
return 1
|
||||
if("wing3_color")
|
||||
if(can_change(owner, APPEARANCE_HAIR_COLOR))
|
||||
var/new_hair = input(ui.user, "Please select secondary wing color.", "3rd Wing Color", rgb(owner.r_wing3, owner.g_wing3, owner.b_wing3)) as color|null
|
||||
var/new_hair = tgui_color_picker(ui.user, "Please select secondary wing color.", "3rd Wing Color", rgb(owner.r_wing3, owner.g_wing3, owner.b_wing3))
|
||||
if(new_hair && can_still_topic(owner, state))
|
||||
owner.r_wing3 = hex2num(copytext(new_hair, 2, 4))
|
||||
owner.g_wing3 = hex2num(copytext(new_hair, 4, 6))
|
||||
@@ -353,7 +353,7 @@
|
||||
return TRUE
|
||||
if (4) //color
|
||||
var/current = markings[name_marking] ? markings[name_marking] : "#000000"
|
||||
var/marking_color = input(ui.user, "Please select marking color", "Marking color", current) as color|null
|
||||
var/marking_color = tgui_color_picker(ui.user, "Please select marking color", "Marking color", current)
|
||||
if(marking_color && can_still_topic(owner, state))
|
||||
var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[name_marking]
|
||||
if (owner.change_marking_color(mark_datum, marking_color))
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
|
||||
/datum/tgui_module/ship/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||
var/list/data = ..()
|
||||
data["mapRef"] = linked?.map_name
|
||||
if(linked)
|
||||
data["mapRef"] = linked.map_name
|
||||
return data
|
||||
|
||||
/datum/tgui_module/ship/tgui_status(mob/user)
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Creates a TGUI color picker window and returns the user's response.
|
||||
*
|
||||
* This proc should be used to create a color picker that the caller will wait for a response from.
|
||||
* Arguments:
|
||||
* * user - The user to show the picker to.
|
||||
* * title - The of the picker modal, shown on the top of the TGUI window.
|
||||
* * timeout - The timeout of the picker, after which the modal will close and qdel itself. Set to zero for no timeout.
|
||||
* * autofocus - The bool that controls if this picker should grab window focus.
|
||||
*/
|
||||
/proc/tgui_color_picker(mob/user, message, title, default = "#000000", timeout = 0, autofocus = TRUE)
|
||||
if (!user)
|
||||
user = usr
|
||||
if (!istype(user))
|
||||
if (istype(user, /client))
|
||||
var/client/client = user
|
||||
user = client.mob
|
||||
else
|
||||
return
|
||||
// Client does NOT have tgui_input on: Returns regular input
|
||||
if(!user.client.prefs.read_preference(/datum/preference/toggle/tgui_input_mode) || user.client.byond_version < 516) // Todo, remove once virgo is on 516, but currently the TGUI interface is already programmed for edge
|
||||
return input(user, message, title, default) as color|null
|
||||
var/datum/tgui_color_picker/picker = new(user, message, title, default, timeout, autofocus)
|
||||
picker.tgui_interact(user)
|
||||
picker.wait()
|
||||
if (picker)
|
||||
. = picker.choice
|
||||
qdel(picker)
|
||||
|
||||
/**
|
||||
* # tgui_color_picker
|
||||
*
|
||||
* Datum used for instantiating and using a TGUI-controlled color picker.
|
||||
*/
|
||||
/datum/tgui_color_picker
|
||||
/// The title of the TGUI window
|
||||
var/title
|
||||
/// The message to show the user
|
||||
var/message
|
||||
/// The default choice, used if there is an existing value
|
||||
var/default
|
||||
/// The color the user selected, null if no selection has been made
|
||||
var/choice
|
||||
/// The time at which the tgui_color_picker was created, for displaying timeout progress.
|
||||
var/start_time
|
||||
/// The lifespan of the tgui_color_picker, after which the window will close and delete itself.
|
||||
var/timeout
|
||||
/// The bool that controls if this modal should grab window focus
|
||||
var/autofocus
|
||||
/// Boolean field describing if the tgui_color_picker was closed by the user.
|
||||
var/closed
|
||||
|
||||
/datum/tgui_color_picker/New(mob/user, message, title, default, timeout, autofocus)
|
||||
src.autofocus = autofocus
|
||||
src.title = title
|
||||
src.default = default
|
||||
src.message = message
|
||||
if (timeout)
|
||||
src.timeout = timeout
|
||||
start_time = world.time
|
||||
QDEL_IN(src, timeout)
|
||||
|
||||
/datum/tgui_color_picker/Destroy(force)
|
||||
SStgui.close_uis(src)
|
||||
. = ..()
|
||||
|
||||
/**
|
||||
* Waits for a user's response to the tgui_color_picker's prompt before returning. Returns early if
|
||||
* the window was closed by the user.
|
||||
*/
|
||||
/datum/tgui_color_picker/proc/wait()
|
||||
while (!choice && !closed && !QDELETED(src))
|
||||
stoplag(1)
|
||||
|
||||
/datum/tgui_color_picker/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "ColorPickerModal")
|
||||
ui.open()
|
||||
ui.set_autoupdate(timeout > 0)
|
||||
|
||||
/datum/tgui_color_picker/tgui_close(mob/user)
|
||||
. = ..()
|
||||
closed = TRUE
|
||||
|
||||
/datum/tgui_color_picker/tgui_state(mob/user)
|
||||
return GLOB.tgui_always_state
|
||||
|
||||
/datum/tgui_color_picker/tgui_static_data(mob/user)
|
||||
. = list()
|
||||
.["autofocus"] = autofocus
|
||||
.["large_buttons"] = !user.client?.prefs || user.client.prefs.read_preference(/datum/preference/toggle/tgui_large_buttons)
|
||||
.["swapped_buttons"] = !user.client?.prefs || user.client.prefs.read_preference(/datum/preference/toggle/tgui_swapped_buttons)
|
||||
.["title"] = title
|
||||
.["default_color"] = default
|
||||
.["message"] = message
|
||||
|
||||
/datum/tgui_color_picker/tgui_data(mob/user)
|
||||
. = list()
|
||||
if(timeout)
|
||||
.["timeout"] = CLAMP01((timeout - (world.time - start_time) - 1 SECONDS) / (timeout - 1 SECONDS))
|
||||
.["presets"] = user.read_preference(/datum/preference/text/preset_colors)
|
||||
|
||||
/datum/tgui_color_picker/tgui_act(action, list/params, datum/tgui/ui)
|
||||
. = ..()
|
||||
if (.)
|
||||
return
|
||||
switch(action)
|
||||
if("submit")
|
||||
var/raw_data = lowertext(params["entry"])
|
||||
var/hex = sanitize_hexcolor(raw_data)
|
||||
if (!hex)
|
||||
return
|
||||
set_choice(hex)
|
||||
closed = TRUE
|
||||
SStgui.close_uis(src)
|
||||
return TRUE
|
||||
if("cancel")
|
||||
closed = TRUE
|
||||
SStgui.close_uis(src)
|
||||
return TRUE
|
||||
if("null")
|
||||
set_choice(null)
|
||||
SStgui.close_uis(src)
|
||||
return TRUE
|
||||
if("preset")
|
||||
if(ui.user)
|
||||
var/raw_data = lowertext(params["color"])
|
||||
var/index = lowertext(params["index"])
|
||||
var/colors = ui.user.read_preference(/datum/preference/text/preset_colors)
|
||||
var/list/entries = splittext(colors, ";")
|
||||
while(LAZYLEN(entries) < 20)
|
||||
entries += "#FFFFFF"
|
||||
if(LAZYLEN(entries) > 20)
|
||||
entries.Cut(21)
|
||||
var/hex = sanitize_hexcolor(raw_data)
|
||||
if (!hex || !isnum(index) || entries[index] == hex)
|
||||
return
|
||||
entries[index] = hex
|
||||
ui.user.write_preference_directly(/datum/preference/text/preset_colors, entries.Join(";"))
|
||||
return TRUE
|
||||
|
||||
/datum/tgui_color_picker/proc/set_choice(choice)
|
||||
src.choice = choice
|
||||
@@ -46,9 +46,9 @@
|
||||
paint_color = rgb(rand(1,255),rand(1,255),rand(1,255))
|
||||
. = ..()
|
||||
|
||||
/obj/vehicle/bike/attackby(obj/item/W as obj, mob/user as mob)
|
||||
/obj/vehicle/bike/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/multitool) && open)
|
||||
var/new_paint = input(usr, "Please select paint color.", "Paint Color", paint_color) as color|null
|
||||
var/new_paint = tgui_color_picker(user, "Please select paint color.", "Paint Color", paint_color)
|
||||
if(new_paint)
|
||||
paint_color = new_paint
|
||||
update_icon()
|
||||
|
||||
@@ -88,9 +88,9 @@
|
||||
if(8)
|
||||
pixel_y = 0
|
||||
|
||||
/obj/vehicle/train/engine/quadbike/attackby(obj/item/W as obj, mob/user as mob)
|
||||
/obj/vehicle/train/engine/quadbike/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/multitool) && open)
|
||||
var/new_paint = input(usr, "Please select paint color.", "Paint Color", paint_color) as color|null
|
||||
var/new_paint = tgui_color_picker(user, "Please select paint color.", "Paint Color", paint_color)
|
||||
if(new_paint)
|
||||
paint_color = new_paint
|
||||
update_icon()
|
||||
@@ -276,9 +276,9 @@
|
||||
Bodypaint.color = paint_color
|
||||
add_overlay(Bodypaint)
|
||||
|
||||
/obj/vehicle/train/trolley/trailer/attackby(obj/item/W as obj, mob/user as mob)
|
||||
/obj/vehicle/train/trolley/trailer/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/multitool) && open)
|
||||
var/new_paint = input(usr, "Please select paint color.", "Paint Color", paint_color) as color|null
|
||||
var/new_paint = tgui_color_picker(user, "Please select paint color.", "Paint Color", paint_color)
|
||||
if(new_paint)
|
||||
paint_color = new_paint
|
||||
update_icon()
|
||||
|
||||
@@ -676,7 +676,7 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
|
||||
if("set_vs_color")
|
||||
var/belly_choice = tgui_input_list(ui.user, "Which vore sprite are you going to edit the color of?", "Vore Sprite Color", host.vore_icon_bellies)
|
||||
if(belly_choice)
|
||||
var/newcolor = input(ui.user, "Choose a color.", "", host.vore_sprite_color[belly_choice]) as color|null
|
||||
var/newcolor = tgui_color_picker(ui.user, "Choose a color.", "", host.vore_sprite_color[belly_choice])
|
||||
if(newcolor)
|
||||
host.vore_sprite_color[belly_choice] = newcolor
|
||||
var/multiply = tgui_input_list(ui.user, "Set the color to be applied multiplicatively or additively? Currently in [host.vore_sprite_multiply[belly_choice] ? "Multiply" : "Add"]", "Vore Sprite Color", list("Multiply", "Add"))
|
||||
@@ -1724,17 +1724,17 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
|
||||
host.vore_selected.clear_preview(host) //Clears the stomach overlay. This is a failsafe but shouldn't occur.
|
||||
. = TRUE
|
||||
if("b_fullscreen_color")
|
||||
var/newcolor = input(user, "Choose a color.", "", host.vore_selected.belly_fullscreen_color) as color|null
|
||||
var/newcolor = tgui_color_picker(user, "Choose a color.", "", host.vore_selected.belly_fullscreen_color)
|
||||
if(newcolor)
|
||||
host.vore_selected.belly_fullscreen_color = newcolor
|
||||
. = TRUE
|
||||
if("b_fullscreen_color_secondary")
|
||||
var/newcolor = input(user, "Choose a color.", "", host.vore_selected.belly_fullscreen_color_secondary) as color|null
|
||||
var/newcolor = tgui_color_picker(user, "Choose a color.", "", host.vore_selected.belly_fullscreen_color_secondary)
|
||||
if(newcolor)
|
||||
host.vore_selected.belly_fullscreen_color_secondary = newcolor
|
||||
. = TRUE
|
||||
if("b_fullscreen_color_trinary")
|
||||
var/newcolor = input(user, "Choose a color.", "", host.vore_selected.belly_fullscreen_color_trinary) as color|null
|
||||
var/newcolor = tgui_color_picker(user, "Choose a color.", "", host.vore_selected.belly_fullscreen_color_trinary)
|
||||
if(newcolor)
|
||||
host.vore_selected.belly_fullscreen_color_trinary = newcolor
|
||||
. = TRUE
|
||||
@@ -1867,7 +1867,7 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
|
||||
host.update_fullness()
|
||||
host.updateVRPanel()
|
||||
if("b_undergarment_color")
|
||||
var/newcolor = input(user, "Choose a color.", "", host.vore_selected.undergarment_color) as color|null
|
||||
var/newcolor = tgui_color_picker(user, "Choose a color.", "", host.vore_selected.undergarment_color)
|
||||
if(newcolor)
|
||||
host.vore_selected.undergarment_color = newcolor
|
||||
host.update_fullness()
|
||||
@@ -1880,17 +1880,17 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
|
||||
host.vore_selected.tail_to_change_to = tail_choice
|
||||
. = TRUE
|
||||
if("b_tail_color")
|
||||
var/newcolor = input(user, "Choose tail color.", "", host.vore_selected.tail_colouration) as color|null
|
||||
var/newcolor = tgui_color_picker(user, "Choose tail color.", "", host.vore_selected.tail_colouration)
|
||||
if(newcolor)
|
||||
host.vore_selected.tail_colouration = newcolor
|
||||
. = TRUE
|
||||
if("b_tail_color2")
|
||||
var/newcolor = input(user, "Choose tail secondary color.", "", host.vore_selected.tail_extra_overlay) as color|null
|
||||
var/newcolor = tgui_color_picker(user, "Choose tail secondary color.", "", host.vore_selected.tail_extra_overlay)
|
||||
if(newcolor)
|
||||
host.vore_selected.tail_extra_overlay = newcolor
|
||||
. = TRUE
|
||||
if("b_tail_color3")
|
||||
var/newcolor = input(user, "Choose tail tertiary color.", "", host.vore_selected.tail_extra_overlay2) as color|null
|
||||
var/newcolor = tgui_color_picker(user, "Choose tail tertiary color.", "", host.vore_selected.tail_extra_overlay2)
|
||||
if(newcolor)
|
||||
host.vore_selected.tail_extra_overlay2 = newcolor
|
||||
. = TRUE
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
set src in oview(1)
|
||||
if(ismouse(usr) || (isobserver(usr) && !CONFIG_GET(flag/ghost_interaction)))
|
||||
return
|
||||
var/new_color = input(usr, "Please select color.", "Paint Color", color) as color|null
|
||||
var/new_color = tgui_color_picker(usr, "Please select color.", "Paint Color", color)
|
||||
color = new_color
|
||||
return
|
||||
|
||||
@@ -307,7 +307,7 @@
|
||||
set src in oview(1)
|
||||
if(ismouse(usr) || (isobserver(usr) && !CONFIG_GET(flag/ghost_interaction)))
|
||||
return
|
||||
var/new_color = input(usr, "Please select color.", "Paint Color", color) as color|null
|
||||
var/new_color = tgui_color_picker(usr, "Please select color.", "Paint Color", color)
|
||||
color = new_color
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* MIT License
|
||||
* https://github.com/omgovich/react-colorful/
|
||||
*
|
||||
* Copyright (c) 2020 Vlad Shilov <omgovich@ya.ru>
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
const round = (
|
||||
number: number,
|
||||
digits = 0,
|
||||
base = Math.pow(10, digits),
|
||||
): number => {
|
||||
return Math.round(base * number) / base;
|
||||
};
|
||||
export interface RgbColor {
|
||||
r: number;
|
||||
g: number;
|
||||
b: number;
|
||||
}
|
||||
export interface RgbaColor extends RgbColor {
|
||||
a: number;
|
||||
}
|
||||
export interface HslColor {
|
||||
h: number;
|
||||
s: number;
|
||||
l: number;
|
||||
}
|
||||
export interface HslaColor extends HslColor {
|
||||
a: number;
|
||||
}
|
||||
export interface HsvColor {
|
||||
h: number;
|
||||
s: number;
|
||||
v: number;
|
||||
}
|
||||
export interface HsvaColor extends HsvColor {
|
||||
a: number;
|
||||
}
|
||||
export type ObjectColor =
|
||||
| RgbColor
|
||||
| HslColor
|
||||
| HsvColor
|
||||
| RgbaColor
|
||||
| HslaColor
|
||||
| HsvaColor;
|
||||
export type AnyColor = string | ObjectColor;
|
||||
/**
|
||||
* Valid CSS <angle> units.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/CSS/angle
|
||||
*/
|
||||
const angleUnits: Record<string, number> = {
|
||||
grad: 360 / 400,
|
||||
turn: 360,
|
||||
rad: 360 / (Math.PI * 2),
|
||||
};
|
||||
export const hexToHsva = (hex: string): HsvaColor => rgbaToHsva(hexToRgba(hex));
|
||||
export const hexToRgba = (hex: string): RgbaColor => {
|
||||
if (hex[0] === '#') hex = hex.substring(1);
|
||||
if (hex.length < 6) {
|
||||
return {
|
||||
r: parseInt(hex[0] + hex[0], 16),
|
||||
g: parseInt(hex[1] + hex[1], 16),
|
||||
b: parseInt(hex[2] + hex[2], 16),
|
||||
a: hex.length === 4 ? round(parseInt(hex[3] + hex[3], 16) / 255, 2) : 1,
|
||||
};
|
||||
}
|
||||
return {
|
||||
r: parseInt(hex.substring(0, 2), 16),
|
||||
g: parseInt(hex.substring(2, 4), 16),
|
||||
b: parseInt(hex.substring(4, 6), 16),
|
||||
a: hex.length === 8 ? round(parseInt(hex.substring(6, 8), 16) / 255, 2) : 1,
|
||||
};
|
||||
};
|
||||
export const parseHue = (value: string, unit = 'deg'): number => {
|
||||
return Number(value) * (angleUnits[unit] || 1);
|
||||
};
|
||||
export const hslaStringToHsva = (hslString: string): HsvaColor => {
|
||||
const matcher =
|
||||
/hsla?\(?\s*(-?\d*\.?\d+)(deg|rad|grad|turn)?[,\s]+(-?\d*\.?\d+)%?[,\s]+(-?\d*\.?\d+)%?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i;
|
||||
const match = matcher.exec(hslString);
|
||||
if (!match) return { h: 0, s: 0, v: 0, a: 1 };
|
||||
return hslaToHsva({
|
||||
h: parseHue(match[1], match[2]),
|
||||
s: Number(match[3]),
|
||||
l: Number(match[4]),
|
||||
a: match[5] === undefined ? 1 : Number(match[5]) / (match[6] ? 100 : 1),
|
||||
});
|
||||
};
|
||||
export const hslStringToHsva = hslaStringToHsva;
|
||||
export const hslaToHsva = ({ h, s, l, a }: HslaColor): HsvaColor => {
|
||||
s *= (l < 50 ? l : 100 - l) / 100;
|
||||
return {
|
||||
h: h,
|
||||
s: s > 0 ? ((2 * s) / (l + s)) * 100 : 0,
|
||||
v: l + s,
|
||||
a,
|
||||
};
|
||||
};
|
||||
export const hsvaToHex = (hsva: HsvaColor): string =>
|
||||
rgbaToHex(hsvaToRgba(hsva));
|
||||
export const hsvaToHsla = ({ h, s, v, a }: HsvaColor): HslaColor => {
|
||||
const hh = ((200 - s) * v) / 100;
|
||||
return {
|
||||
h: round(h),
|
||||
s: round(
|
||||
hh > 0 && hh < 200
|
||||
? ((s * v) / 100 / (hh <= 100 ? hh : 200 - hh)) * 100
|
||||
: 0,
|
||||
),
|
||||
l: round(hh / 2),
|
||||
a: round(a, 2),
|
||||
};
|
||||
};
|
||||
export const hsvaToHslString = (hsva: HsvaColor): string => {
|
||||
const { h, s, l } = hsvaToHsla(hsva);
|
||||
return `hsl(${h}, ${s}%, ${l}%)`;
|
||||
};
|
||||
export const hsvaToHsvString = (hsva: HsvaColor): string => {
|
||||
const { h, s, v } = roundHsva(hsva);
|
||||
return `hsv(${h}, ${s}%, ${v}%)`;
|
||||
};
|
||||
export const hsvaToHsvaString = (hsva: HsvaColor): string => {
|
||||
const { h, s, v, a } = roundHsva(hsva);
|
||||
return `hsva(${h}, ${s}%, ${v}%, ${a})`;
|
||||
};
|
||||
export const hsvaToHslaString = (hsva: HsvaColor): string => {
|
||||
const { h, s, l, a } = hsvaToHsla(hsva);
|
||||
return `hsla(${h}, ${s}%, ${l}%, ${a})`;
|
||||
};
|
||||
export const hsvaToRgba = ({ h, s, v, a }: HsvaColor): RgbaColor => {
|
||||
h = (h / 360) * 6;
|
||||
s = s / 100;
|
||||
v = v / 100;
|
||||
const hh = Math.floor(h),
|
||||
b = v * (1 - s),
|
||||
c = v * (1 - (h - hh) * s),
|
||||
d = v * (1 - (1 - h + hh) * s),
|
||||
module = hh % 6;
|
||||
return {
|
||||
r: [v, c, b, b, d, v][module] * 255,
|
||||
g: [d, v, v, c, b, b][module] * 255,
|
||||
b: [b, b, d, v, v, c][module] * 255,
|
||||
a: round(a, 2),
|
||||
};
|
||||
};
|
||||
export const hsvaToRgbString = (hsva: HsvaColor): string => {
|
||||
const { r, g, b } = hsvaToRgba(hsva);
|
||||
return `rgb(${round(r)}, ${round(g)}, ${round(b)})`;
|
||||
};
|
||||
export const hsvaToRgbaString = (hsva: HsvaColor): string => {
|
||||
const { r, g, b, a } = hsvaToRgba(hsva);
|
||||
return `rgba(${round(r)}, ${round(g)}, ${round(b)}, ${round(a, 2)})`;
|
||||
};
|
||||
export const hsvaStringToHsva = (hsvString: string): HsvaColor => {
|
||||
const matcher =
|
||||
/hsva?\(?\s*(-?\d*\.?\d+)(deg|rad|grad|turn)?[,\s]+(-?\d*\.?\d+)%?[,\s]+(-?\d*\.?\d+)%?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i;
|
||||
const match = matcher.exec(hsvString);
|
||||
if (!match) return { h: 0, s: 0, v: 0, a: 1 };
|
||||
return roundHsva({
|
||||
h: parseHue(match[1], match[2]),
|
||||
s: Number(match[3]),
|
||||
v: Number(match[4]),
|
||||
a: match[5] === undefined ? 1 : Number(match[5]) / (match[6] ? 100 : 1),
|
||||
});
|
||||
};
|
||||
export const hsvStringToHsva = hsvaStringToHsva;
|
||||
export const rgbaStringToHsva = (rgbaString: string): HsvaColor => {
|
||||
const matcher =
|
||||
/rgba?\(?\s*(-?\d*\.?\d+)(%)?[,\s]+(-?\d*\.?\d+)(%)?[,\s]+(-?\d*\.?\d+)(%)?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i;
|
||||
const match = matcher.exec(rgbaString);
|
||||
if (!match) return { h: 0, s: 0, v: 0, a: 1 };
|
||||
return rgbaToHsva({
|
||||
r: Number(match[1]) / (match[2] ? 100 / 255 : 1),
|
||||
g: Number(match[3]) / (match[4] ? 100 / 255 : 1),
|
||||
b: Number(match[5]) / (match[6] ? 100 / 255 : 1),
|
||||
a: match[7] === undefined ? 1 : Number(match[7]) / (match[8] ? 100 : 1),
|
||||
});
|
||||
};
|
||||
export const rgbStringToHsva = rgbaStringToHsva;
|
||||
const format = (number: number) => {
|
||||
const hex = number.toString(16);
|
||||
return hex.length < 2 ? '0' + hex : hex;
|
||||
};
|
||||
export const rgbaToHex = ({ r, g, b, a }: RgbaColor): string => {
|
||||
const alphaHex = a < 1 ? format(round(a * 255)) : '';
|
||||
return (
|
||||
'#' + format(round(r)) + format(round(g)) + format(round(b)) + alphaHex
|
||||
);
|
||||
};
|
||||
export const rgbaToHsva = ({ r, g, b, a }: RgbaColor): HsvaColor => {
|
||||
const max = Math.max(r, g, b);
|
||||
const delta = max - Math.min(r, g, b);
|
||||
// prettier-ignore
|
||||
const hh = delta
|
||||
? max === r
|
||||
? (g - b) / delta
|
||||
: max === g
|
||||
? 2 + (b - r) / delta
|
||||
: 4 + (r - g) / delta
|
||||
: 0;
|
||||
return {
|
||||
h: 60 * (hh < 0 ? hh + 6 : hh),
|
||||
s: max ? (delta / max) * 100 : 0,
|
||||
v: (max / 255) * 100,
|
||||
a,
|
||||
};
|
||||
};
|
||||
export const roundHsva = (hsva: HsvaColor): HsvaColor => ({
|
||||
h: round(hsva.h),
|
||||
s: round(hsva.s),
|
||||
v: round(hsva.v),
|
||||
a: round(hsva.a, 2),
|
||||
});
|
||||
export const rgbaToRgb = ({ r, g, b }: RgbaColor): RgbColor => ({ r, g, b });
|
||||
export const hslaToHsl = ({ h, s, l }: HslaColor): HslColor => ({ h, s, l });
|
||||
export const hsvaToHsv = (hsva: HsvaColor): HsvColor => {
|
||||
const { h, s, v } = roundHsva(hsva);
|
||||
return { h, s, v };
|
||||
};
|
||||
const hexMatcher = /^#?([0-9A-F]{3,8})$/i;
|
||||
export const validHex = (value: string, alpha?: boolean): boolean => {
|
||||
const match = hexMatcher.exec(value);
|
||||
const length = match ? match[1].length : 0;
|
||||
return (
|
||||
length === 3 || // '#rgb' format
|
||||
length === 6 || // '#rrggbb' format
|
||||
(!!alpha && length === 4) || // '#rgba' format
|
||||
(!!alpha && length === 8) // '#rrggbbaa' format
|
||||
);
|
||||
};
|
||||
// Source for the following luminance and contrast calculation code: https://blog.cristiana.tech/calculating-color-contrast-in-typescript-using-web-content-accessibility-guidelines-wcag
|
||||
export const luminance = (rgb: RgbColor): number => {
|
||||
const [r, g, b] = [rgb.r, rgb.g, rgb.b].map((v) => {
|
||||
v /= 255;
|
||||
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
||||
});
|
||||
return r * 0.2126 + g * 0.7152 + b * 0.0722;
|
||||
};
|
||||
export const contrast = (
|
||||
foreground: RgbColor,
|
||||
background: RgbColor,
|
||||
): number => {
|
||||
const foreground_luminance = luminance(foreground);
|
||||
const background_luminance = luminance(background);
|
||||
return background_luminance < foreground_luminance
|
||||
? (background_luminance + 0.05) / (foreground_luminance + 0.05)
|
||||
: (foreground_luminance + 0.05) / (background_luminance + 0.05);
|
||||
};
|
||||
|
||||
export const colorList = [
|
||||
['003366', '336699', '3366CC', '003399', '000099', '0000CC', '000066'],
|
||||
[
|
||||
'006666',
|
||||
'006699',
|
||||
'0099CC',
|
||||
'0066CC',
|
||||
'0033CC',
|
||||
'0000FF',
|
||||
'3333FF',
|
||||
'333399',
|
||||
],
|
||||
[
|
||||
'008080',
|
||||
'009999',
|
||||
'33CCCC',
|
||||
'00CCFF',
|
||||
'0099FF',
|
||||
'0066FF',
|
||||
'3366FF',
|
||||
'3333CC',
|
||||
'666699',
|
||||
],
|
||||
[
|
||||
'339966',
|
||||
'00CC99',
|
||||
'00FFCC',
|
||||
'00FFFF',
|
||||
'33CCFF',
|
||||
'3399FF',
|
||||
'6699FF',
|
||||
'6666FF',
|
||||
'6600FF',
|
||||
'6600CC',
|
||||
],
|
||||
[
|
||||
'339933',
|
||||
'00CC66',
|
||||
'00FF99',
|
||||
'66FFCC',
|
||||
'66FFFF',
|
||||
'66CCFF',
|
||||
'99CCFF',
|
||||
'9999FF',
|
||||
'9966FF',
|
||||
'9933FF',
|
||||
'9900FF',
|
||||
],
|
||||
[
|
||||
'006600',
|
||||
'00CC00',
|
||||
'00FF00',
|
||||
'66FF99',
|
||||
'99FFCC',
|
||||
'CCFFFF',
|
||||
'CCECFF',
|
||||
'CCCCFF',
|
||||
'CC99FF',
|
||||
'CC66FF',
|
||||
'CC00FF',
|
||||
'9900CC',
|
||||
],
|
||||
[
|
||||
'003300',
|
||||
'008000',
|
||||
'33CC33',
|
||||
'66FF66',
|
||||
'99FF99',
|
||||
'CCFFCC',
|
||||
'FFFFFF',
|
||||
'FFCCFF',
|
||||
'FF99FF',
|
||||
'FF66FF',
|
||||
'FF00FF',
|
||||
'CC00CC',
|
||||
'660066',
|
||||
],
|
||||
[
|
||||
'336600',
|
||||
'009900',
|
||||
'66FF33',
|
||||
'99FF66',
|
||||
'CCFF99',
|
||||
'FFFFCC',
|
||||
'FFCCCC',
|
||||
'FF99CC',
|
||||
'FF66CC',
|
||||
'FF33CC',
|
||||
'CC0099',
|
||||
'800080',
|
||||
],
|
||||
[
|
||||
'333300',
|
||||
'669900',
|
||||
'99FF33',
|
||||
'CCFF66',
|
||||
'FFFF99',
|
||||
'FFCC99',
|
||||
'FF9999',
|
||||
'FF6699',
|
||||
'FF3399',
|
||||
'CC3399',
|
||||
'990099',
|
||||
],
|
||||
[
|
||||
'666633',
|
||||
'99CC00',
|
||||
'CCFF33',
|
||||
'FFFF66',
|
||||
'FFCC66',
|
||||
'FF9966',
|
||||
'FF7C80',
|
||||
'FF0066',
|
||||
'D60093',
|
||||
'993366',
|
||||
],
|
||||
[
|
||||
'808000',
|
||||
'CCCC00',
|
||||
'FFFF00',
|
||||
'FFCC00',
|
||||
'FF9933',
|
||||
'FF6600',
|
||||
'FF5050',
|
||||
'CC0066',
|
||||
'660033',
|
||||
],
|
||||
[
|
||||
'996633',
|
||||
'CC9900',
|
||||
'FF9900',
|
||||
'CC6600',
|
||||
'FF3300',
|
||||
'FF0000',
|
||||
'CC0000',
|
||||
'990033',
|
||||
],
|
||||
['663300', '996600', 'CC3300', '993300', '990000', '800000', 'A50021'],
|
||||
[
|
||||
'F8F8F8',
|
||||
'DDDDDD',
|
||||
'B2B2B2',
|
||||
'808080',
|
||||
'5F5F5F',
|
||||
'333333',
|
||||
'1C1C1C',
|
||||
'080808',
|
||||
],
|
||||
[
|
||||
'FFFFFF',
|
||||
'EAEAEA',
|
||||
'C0C0C0',
|
||||
'969696',
|
||||
'777777',
|
||||
'4D4D4D',
|
||||
'292929',
|
||||
'111111',
|
||||
'000000',
|
||||
],
|
||||
];
|
||||
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* MIT License
|
||||
* https://github.com/omgovich/react-colorful/
|
||||
*
|
||||
* Copyright (c) 2020 Vlad Shilov <omgovich@ya.ru>
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
import { KEY } from 'common/keys';
|
||||
import { clamp } from 'common/math';
|
||||
import React, { Component, createRef, ReactNode, RefObject } from 'react';
|
||||
|
||||
export interface Interaction {
|
||||
left: number;
|
||||
top: number;
|
||||
}
|
||||
|
||||
// Finds the proper window object to fix iframe embedding issues
|
||||
const getParentWindow = (node?: HTMLDivElement | null): Window => {
|
||||
return (node && node.ownerDocument.defaultView) || window;
|
||||
};
|
||||
|
||||
// Returns a relative position of the pointer inside the node's bounding box
|
||||
const getRelativePosition = (
|
||||
node: HTMLDivElement,
|
||||
event: MouseEvent,
|
||||
): Interaction => {
|
||||
const rect = node.getBoundingClientRect();
|
||||
const parentWindow = getParentWindow(node);
|
||||
|
||||
const offsetX = event.pageX - (rect.left + parentWindow.scrollX);
|
||||
const offsetY = event.pageY - (rect.top + parentWindow.scrollY);
|
||||
|
||||
return {
|
||||
left: clamp(offsetX / rect.width, 0, 1),
|
||||
top: clamp(offsetY / rect.height, 0, 1),
|
||||
};
|
||||
};
|
||||
|
||||
export interface InteractiveProps {
|
||||
onMove: (interaction: Interaction) => void;
|
||||
onKey: (offset: Interaction) => void;
|
||||
children: ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export class Interactive extends Component<InteractiveProps> {
|
||||
containerRef: RefObject<HTMLDivElement>;
|
||||
|
||||
constructor(props: InteractiveProps) {
|
||||
super(props);
|
||||
this.containerRef = createRef();
|
||||
}
|
||||
|
||||
handleMoveStart = (event: React.MouseEvent<HTMLDivElement>) => {
|
||||
const el = this.containerRef?.current;
|
||||
if (!el) return;
|
||||
|
||||
// Prevent text selection
|
||||
event.preventDefault();
|
||||
el.focus();
|
||||
this.props.onMove(getRelativePosition(el, event.nativeEvent));
|
||||
this.toggleDocumentEvents(true);
|
||||
};
|
||||
|
||||
handleMove = (event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
const isDown = event.buttons > 0;
|
||||
|
||||
if (isDown && this.containerRef?.current) {
|
||||
this.props.onMove(getRelativePosition(this.containerRef.current, event));
|
||||
} else {
|
||||
this.toggleDocumentEvents(false);
|
||||
}
|
||||
};
|
||||
|
||||
handleMoveEnd = () => {
|
||||
this.toggleDocumentEvents(false);
|
||||
};
|
||||
|
||||
handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
const pressedKey = event.key;
|
||||
|
||||
if (
|
||||
pressedKey !== KEY.Left &&
|
||||
pressedKey !== KEY.Right &&
|
||||
pressedKey !== KEY.Up &&
|
||||
pressedKey !== KEY.Down
|
||||
) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
this.props.onKey({
|
||||
left:
|
||||
pressedKey === KEY.Right ? 0.05 : pressedKey === KEY.Left ? -0.05 : 0,
|
||||
top: pressedKey === KEY.Down ? 0.05 : pressedKey === KEY.Up ? -0.05 : 0,
|
||||
});
|
||||
};
|
||||
|
||||
toggleDocumentEvents(state?: boolean) {
|
||||
const el = this.containerRef?.current;
|
||||
const parentWindow = getParentWindow(el);
|
||||
|
||||
const toggleEvent = state
|
||||
? parentWindow.addEventListener
|
||||
: parentWindow.removeEventListener;
|
||||
toggleEvent('mousemove', this.handleMove);
|
||||
toggleEvent('mouseup', this.handleMoveEnd);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.toggleDocumentEvents(true);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.toggleDocumentEvents(false);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { style, children, ...rest } = this.props;
|
||||
return (
|
||||
<div
|
||||
{...rest}
|
||||
style={style}
|
||||
ref={this.containerRef}
|
||||
onMouseDown={this.handleMoveStart}
|
||||
className="react-colorful__interactive"
|
||||
onKeyDown={this.handleKeyDown}
|
||||
tabIndex={0}
|
||||
role="slider"
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* MIT License
|
||||
* https://github.com/omgovich/react-colorful/
|
||||
*
|
||||
* Copyright (c) 2020 Vlad Shilov <omgovich@ya.ru>
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
import { classes } from 'common/react';
|
||||
import React from 'react';
|
||||
|
||||
interface PointerProps {
|
||||
className?: string;
|
||||
top?: number;
|
||||
left: number;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export const Pointer: React.FC<PointerProps> = ({
|
||||
className,
|
||||
color,
|
||||
left,
|
||||
top = 0.5,
|
||||
}) => {
|
||||
const nodeClassName = classes(['react-colorful__pointer', className]);
|
||||
|
||||
const style = {
|
||||
top: `${top * 100}%`,
|
||||
left: `${left * 100}%`,
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={nodeClassName} style={style}>
|
||||
<div
|
||||
className="react-colorful__pointer-fill"
|
||||
style={{ backgroundColor: color }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -21,6 +21,7 @@ export { Icon } from './Icon';
|
||||
export { Image } from './Image';
|
||||
export { InfinitePlane } from './InfinitePlane';
|
||||
export { Input } from './Input';
|
||||
export { Interactive } from './Interactive';
|
||||
export { Knob } from './Knob';
|
||||
export { LabeledControls } from './LabeledControls';
|
||||
export { LabeledList } from './LabeledList';
|
||||
@@ -28,6 +29,7 @@ export { Modal } from './Modal';
|
||||
export { NanoMap } from './NanoMap';
|
||||
export { NoticeBox } from './NoticeBox';
|
||||
export { NumberInput } from './NumberInput';
|
||||
export { Pointer } from './Pointer';
|
||||
export { Popper } from './Popper';
|
||||
export { ProgressBar } from './ProgressBar';
|
||||
export { RestrictedInput } from './RestrictedInput';
|
||||
|
||||
@@ -0,0 +1,888 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2023 itsmeow
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import {
|
||||
colorList,
|
||||
hexToHsva,
|
||||
HsvaColor,
|
||||
hsvaToHex,
|
||||
hsvaToHslString,
|
||||
hsvaToRgba,
|
||||
rgbaToHsva,
|
||||
validHex,
|
||||
} from 'common/colorpicker';
|
||||
import { clamp } from 'common/math';
|
||||
import { classes } from 'common/react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Pointer } from 'tgui/components';
|
||||
import { Interaction, Interactive } from 'tgui/components/Interactive';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Flex,
|
||||
NumberInput,
|
||||
Section,
|
||||
Stack,
|
||||
Tooltip,
|
||||
} from 'tgui-core/components';
|
||||
|
||||
import { useBackend } from '../backend';
|
||||
import { Autofocus } from '../components/Autofocus';
|
||||
import { Window } from '../layouts';
|
||||
import { InputButtons } from './common/InputButtons';
|
||||
import { Loader } from './common/Loader';
|
||||
|
||||
interface ColorPickerData {
|
||||
autofocus: boolean;
|
||||
buttons: string[];
|
||||
message: string;
|
||||
large_buttons: boolean;
|
||||
swapped_buttons: boolean;
|
||||
timeout: number;
|
||||
title: string;
|
||||
default_color: string;
|
||||
presets: string;
|
||||
}
|
||||
|
||||
interface ColorPickerModalProps {}
|
||||
|
||||
export const ColorPickerModal: React.FC<ColorPickerModalProps> = () => {
|
||||
const { act, data } = useBackend<ColorPickerData>();
|
||||
const {
|
||||
timeout,
|
||||
message,
|
||||
autofocus,
|
||||
default_color = '#000000',
|
||||
presets = '',
|
||||
} = data;
|
||||
let { title } = data;
|
||||
|
||||
const [selectedColor, setSelectedColor] = useState<HsvaColor>(
|
||||
hexToHsva(default_color),
|
||||
);
|
||||
|
||||
const [lastSelectedColor, setLastSelectedColor] = useState<string>('');
|
||||
const [allowEditing, setAllowEditing] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedColor(hexToHsva(default_color));
|
||||
}, [default_color]);
|
||||
|
||||
useEffect(() => {
|
||||
const hexCol = hsvaToHex(selectedColor);
|
||||
if (
|
||||
selectedPreset !== undefined &&
|
||||
lastSelectedColor !== hexCol &&
|
||||
allowEditing
|
||||
) {
|
||||
setLastSelectedColor(hexCol);
|
||||
act('preset', { color: hexCol, index: selectedPreset + 1 });
|
||||
}
|
||||
}, [selectedColor]);
|
||||
|
||||
if (!title) {
|
||||
title = 'Color';
|
||||
}
|
||||
|
||||
const [selectedPreset, setSelectedPreset] = useState<number | undefined>(
|
||||
undefined,
|
||||
);
|
||||
|
||||
const ourPresets = presets
|
||||
.replaceAll('#', '')
|
||||
.replace(/(^;)|(;$)/g, '')
|
||||
.split(';');
|
||||
while (ourPresets.length < 20) {
|
||||
ourPresets.push('FFFFFF');
|
||||
}
|
||||
const presetList = ourPresets.reduce(
|
||||
(input, entry, index) => {
|
||||
if (index < 10) {
|
||||
return [[...input[0], entry], input[1]];
|
||||
} else {
|
||||
return [input[0], [...input[1], entry]];
|
||||
}
|
||||
},
|
||||
[[], []],
|
||||
);
|
||||
return (
|
||||
<Window
|
||||
height={message ? 460 : 420}
|
||||
title={title}
|
||||
width={600}
|
||||
theme="generic"
|
||||
>
|
||||
{!!timeout && <Loader value={timeout} />}
|
||||
<Window.Content>
|
||||
<Stack fill vertical>
|
||||
{!!autofocus && <Autofocus />}
|
||||
{message && (
|
||||
<Stack.Item m={1}>
|
||||
<Section fill>
|
||||
<Box color="label" overflow="hidden">
|
||||
{message}
|
||||
</Box>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
)}
|
||||
<Stack.Item grow>
|
||||
<Section fill>
|
||||
<ColorSelector
|
||||
color={selectedColor}
|
||||
setColor={setSelectedColor}
|
||||
defaultColor={default_color}
|
||||
presetList={presetList}
|
||||
selectedPreset={selectedPreset}
|
||||
onSelectedPreset={setSelectedPreset}
|
||||
allowEditing={allowEditing}
|
||||
onAllowEditing={setAllowEditing}
|
||||
/>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<InputButtons input={hsvaToHex(selectedColor)} />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
interface ColorPresetsProps {
|
||||
setColor: (color: HsvaColor) => void;
|
||||
setShowPresets: (show: boolean) => void;
|
||||
presetList: string[][];
|
||||
selectedPreset: number | undefined;
|
||||
onSelectedPreset: React.Dispatch<React.SetStateAction<number | undefined>>;
|
||||
allowEditing: boolean;
|
||||
onAllowEditing: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
const ColorPresets: React.FC<ColorPresetsProps> = React.memo(
|
||||
({
|
||||
setColor,
|
||||
setShowPresets,
|
||||
presetList,
|
||||
selectedPreset,
|
||||
onSelectedPreset,
|
||||
allowEditing,
|
||||
onAllowEditing,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
onClick={() => setShowPresets(false)}
|
||||
position="absolute"
|
||||
right="4px"
|
||||
icon="arrow-left"
|
||||
/>
|
||||
<Stack justify="center" vertical>
|
||||
<Stack.Item>
|
||||
{colorList.map((row, index) => (
|
||||
<Stack.Item key={index} width="100%">
|
||||
<Stack justify="center">
|
||||
{row.map((entry) => (
|
||||
<Box key={entry} p="1px" backgroundColor="black">
|
||||
<Box
|
||||
p="1px"
|
||||
backgroundColor="#AAAAAA"
|
||||
onClick={() => {
|
||||
setColor(hexToHsva(entry));
|
||||
onSelectedPreset(undefined);
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
backgroundColor={'#' + entry}
|
||||
width="21px"
|
||||
height="14px"
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
))}
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
{presetList.map((row, index) => (
|
||||
<Stack.Item key={index} grow>
|
||||
<Stack justify="center">
|
||||
{row.map((entry, i) => (
|
||||
<Box key={i} p="1px" backgroundColor="black">
|
||||
<Box
|
||||
p="1px"
|
||||
backgroundColor={
|
||||
selectedPreset === 10 * index + i
|
||||
? '#FF0000'
|
||||
: '#AAAAAA'
|
||||
}
|
||||
onClick={() => {
|
||||
setColor(hexToHsva(entry));
|
||||
onSelectedPreset(10 * index + i);
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
backgroundColor={'#' + entry}
|
||||
width="21px"
|
||||
height="14px"
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
))}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
<Button
|
||||
color={allowEditing ? 'green' : 'red'}
|
||||
position="absolute"
|
||||
right="4px"
|
||||
bottom="4px"
|
||||
icon="lock"
|
||||
onClick={() => onAllowEditing(!allowEditing)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
interface ColorSelectorProps {
|
||||
color: HsvaColor;
|
||||
setColor: React.Dispatch<React.SetStateAction<HsvaColor>>;
|
||||
defaultColor: string;
|
||||
presetList: string[][];
|
||||
selectedPreset: number | undefined;
|
||||
onSelectedPreset: React.Dispatch<React.SetStateAction<number | undefined>>;
|
||||
allowEditing: boolean;
|
||||
onAllowEditing: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
const ColorSelector: React.FC<ColorSelectorProps> = React.memo(
|
||||
({
|
||||
color,
|
||||
setColor,
|
||||
defaultColor,
|
||||
presetList,
|
||||
selectedPreset,
|
||||
onSelectedPreset,
|
||||
allowEditing,
|
||||
onAllowEditing,
|
||||
}) => {
|
||||
const handleChange = useCallback(
|
||||
(params: Partial<HsvaColor>) => {
|
||||
setColor((current) => ({ ...current, ...params }));
|
||||
},
|
||||
[setColor],
|
||||
);
|
||||
|
||||
const [showPresets, setShowPresets] = useState<boolean>(false);
|
||||
const rgb = hsvaToRgba(color);
|
||||
const hexColor = hsvaToHex(color);
|
||||
|
||||
return (
|
||||
<Flex direction="row">
|
||||
<Flex.Item mr={2}>
|
||||
<Stack vertical>
|
||||
<Stack.Item>
|
||||
<div className="react-colorful">
|
||||
<SaturationValue hsva={color} onChange={handleChange} />
|
||||
<Hue
|
||||
hue={color.h}
|
||||
onChange={handleChange}
|
||||
className="react-colorful__last-control"
|
||||
/>
|
||||
</div>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Box inline width="100px" height="20px" textAlign="center">
|
||||
Current
|
||||
</Box>
|
||||
<Box inline width="100px" height="20px" textAlign="center">
|
||||
Previous
|
||||
</Box>
|
||||
<br />
|
||||
<Tooltip content={hexColor} position="bottom">
|
||||
<Box
|
||||
inline
|
||||
width="100px"
|
||||
height="30px"
|
||||
backgroundColor={hexColor}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip content={defaultColor} position="bottom">
|
||||
<Box
|
||||
inline
|
||||
width="100px"
|
||||
height="30px"
|
||||
backgroundColor={defaultColor}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Flex.Item>
|
||||
<Flex.Item grow fontSize="15px" lineHeight="24px">
|
||||
{showPresets ? (
|
||||
<ColorPresets
|
||||
setColor={(c) => handleChange(c)}
|
||||
setShowPresets={setShowPresets}
|
||||
presetList={presetList}
|
||||
selectedPreset={selectedPreset}
|
||||
onSelectedPreset={onSelectedPreset}
|
||||
allowEditing={allowEditing}
|
||||
onAllowEditing={onAllowEditing}
|
||||
/>
|
||||
) : (
|
||||
<Stack vertical>
|
||||
<Stack.Item>
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<Box textColor="label">Hex:</Box>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow height="24px">
|
||||
<HexColorInput
|
||||
fluid
|
||||
color={hsvaToHex(color).substring(1)}
|
||||
onChange={(value) => {
|
||||
setColor(hexToHsva(value));
|
||||
}}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="eye-dropper"
|
||||
onClick={() => setShowPresets(true)}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Divider />
|
||||
<HueRow color={color} handleChange={handleChange} />
|
||||
<SaturationRow color={color} handleChange={handleChange} />
|
||||
<ValueRow color={color} handleChange={handleChange} />
|
||||
<Stack.Divider />
|
||||
<RedRow color={color} handleChange={handleChange} />
|
||||
<GreenRow color={color} handleChange={handleChange} />
|
||||
<BlueRow color={color} handleChange={handleChange} />
|
||||
</Stack>
|
||||
)}
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
interface RowProps {
|
||||
color: HsvaColor;
|
||||
handleChange: (c: Partial<HsvaColor>) => void;
|
||||
}
|
||||
|
||||
const HueRow: React.FC<RowProps> = React.memo(({ color, handleChange }) => (
|
||||
<Stack.Item>
|
||||
<Stack>
|
||||
<Stack.Item width="25px">
|
||||
<Box textColor="label">H:</Box>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Hue hue={color.h} onChange={handleChange} />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<TextSetter
|
||||
value={color.h}
|
||||
callback={(v) => handleChange({ h: v })}
|
||||
max={360}
|
||||
unit="°"
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
));
|
||||
|
||||
const SaturationRow: React.FC<RowProps> = React.memo(
|
||||
({ color, handleChange }) => (
|
||||
<Stack.Item>
|
||||
<Stack>
|
||||
<Stack.Item width="25px">
|
||||
<Box textColor="label">S:</Box>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Saturation color={color} onChange={handleChange} />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<TextSetter
|
||||
value={color.s}
|
||||
callback={(v) => handleChange({ s: v })}
|
||||
unit="%"
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
),
|
||||
);
|
||||
|
||||
const ValueRow: React.FC<RowProps> = React.memo(({ color, handleChange }) => (
|
||||
<Stack.Item>
|
||||
<Stack>
|
||||
<Stack.Item width="25px">
|
||||
<Box textColor="label">V:</Box>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Value color={color} onChange={handleChange} />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<TextSetter
|
||||
value={color.v}
|
||||
callback={(v) => handleChange({ v })}
|
||||
unit="%"
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
));
|
||||
|
||||
interface RGBRowProps {
|
||||
color: HsvaColor;
|
||||
handleChange: (c: HsvaColor) => void;
|
||||
}
|
||||
|
||||
const RedRow: React.FC<RGBRowProps> = React.memo(({ color, handleChange }) => {
|
||||
const rgb = hsvaToRgba(color);
|
||||
return (
|
||||
<Stack.Item>
|
||||
<Stack>
|
||||
<Stack.Item width="25px">
|
||||
<Box textColor="label">R:</Box>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<RGBSlider color={color} onChange={handleChange} target="r" />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<TextSetter
|
||||
value={rgb.r}
|
||||
callback={(v) => {
|
||||
handleChange(rgbaToHsva({ ...rgb, r: v }));
|
||||
}}
|
||||
max={255}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
);
|
||||
});
|
||||
|
||||
const GreenRow: React.FC<RGBRowProps> = React.memo(
|
||||
({ color, handleChange }) => {
|
||||
const rgb = hsvaToRgba(color);
|
||||
return (
|
||||
<Stack.Item>
|
||||
<Stack>
|
||||
<Stack.Item width="25px">
|
||||
<Box textColor="label">G:</Box>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<RGBSlider color={color} onChange={handleChange} target="g" />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<TextSetter
|
||||
value={rgb.g}
|
||||
callback={(v) => {
|
||||
handleChange(rgbaToHsva({ ...rgb, g: v }));
|
||||
}}
|
||||
max={255}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
const BlueRow: React.FC<RGBRowProps> = React.memo(({ color, handleChange }) => {
|
||||
const rgb = hsvaToRgba(color);
|
||||
return (
|
||||
<Stack.Item>
|
||||
<Stack>
|
||||
<Stack.Item width="25px">
|
||||
<Box textColor="label">B:</Box>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<RGBSlider color={color} onChange={handleChange} target="b" />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<TextSetter
|
||||
value={rgb.b}
|
||||
callback={(v) => {
|
||||
handleChange(rgbaToHsva({ ...rgb, b: v }));
|
||||
}}
|
||||
max={255}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
);
|
||||
});
|
||||
|
||||
interface TextSetterProps {
|
||||
value: number;
|
||||
callback: (value: number) => void;
|
||||
min?: number;
|
||||
max?: number;
|
||||
unit?: string;
|
||||
}
|
||||
|
||||
const TextSetter: React.FC<TextSetterProps> = React.memo(
|
||||
({ value, callback, min = 0, max = 100, unit }) => {
|
||||
return (
|
||||
<NumberInput
|
||||
width="70px"
|
||||
value={Math.round(value)}
|
||||
step={1}
|
||||
minValue={min}
|
||||
maxValue={max}
|
||||
onChange={callback}
|
||||
unit={unit}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
interface HexColorInputProps {
|
||||
prefixed?: boolean;
|
||||
alpha?: boolean;
|
||||
color: string;
|
||||
fluid?: boolean;
|
||||
onChange: (newColor: string) => void;
|
||||
}
|
||||
|
||||
const HexColorInput: React.FC<HexColorInputProps> = React.memo(
|
||||
({ alpha, color, fluid, onChange, ...rest }) => {
|
||||
const initialColor = useMemo(() => {
|
||||
const stripped = color
|
||||
.replace(/[^0-9A-Fa-f]/g, '')
|
||||
.substring(0, 6)
|
||||
.toUpperCase();
|
||||
return stripped;
|
||||
}, [color]);
|
||||
|
||||
const [localValue, setLocalValue] = useState(initialColor);
|
||||
|
||||
useEffect(() => {
|
||||
setLocalValue(initialColor);
|
||||
}, [initialColor]);
|
||||
|
||||
const isValidFullHex = useCallback(
|
||||
(val: string) => {
|
||||
return validHex(val, alpha) && val.length === 6;
|
||||
},
|
||||
[alpha],
|
||||
);
|
||||
|
||||
const handleChangeEvent = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const inputValue = e.currentTarget.value;
|
||||
const strippedValue = inputValue
|
||||
.replace(/[^0-9A-Fa-f]/g, '')
|
||||
.substring(0, 6)
|
||||
.toUpperCase();
|
||||
|
||||
setLocalValue(strippedValue);
|
||||
|
||||
if (isValidFullHex(strippedValue)) {
|
||||
onChange(strippedValue);
|
||||
}
|
||||
};
|
||||
|
||||
const commitOrRevert = useCallback(() => {
|
||||
if (isValidFullHex(localValue)) {
|
||||
onChange(localValue);
|
||||
} else {
|
||||
setLocalValue(initialColor);
|
||||
}
|
||||
}, [initialColor, isValidFullHex, localValue, onChange]);
|
||||
|
||||
const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
||||
commitOrRevert();
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === 'Enter') {
|
||||
commitOrRevert();
|
||||
(e.currentTarget as HTMLInputElement).blur();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box className={classes(['Input', fluid && 'Input--fluid'])}>
|
||||
<div className="Input__baseline">.</div>
|
||||
<input
|
||||
className="Input__input"
|
||||
value={localValue}
|
||||
spellCheck={false}
|
||||
onChange={handleChangeEvent}
|
||||
onBlur={handleBlur}
|
||||
onKeyDown={handleKeyDown}
|
||||
{...rest}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
interface SaturationValueProps {
|
||||
hsva: HsvaColor;
|
||||
onChange: (newColor: Partial<HsvaColor>) => void;
|
||||
}
|
||||
|
||||
const SaturationValue: React.FC<SaturationValueProps> = React.memo(
|
||||
({ hsva, onChange }) => {
|
||||
const handleMove = (interaction: Interaction) => {
|
||||
onChange({
|
||||
s: interaction.left * 100,
|
||||
v: 100 - interaction.top * 100,
|
||||
});
|
||||
};
|
||||
|
||||
const handleKey = (offset: Interaction) => {
|
||||
onChange({
|
||||
s: clamp(hsva.s + offset.left * 100, 0, 100),
|
||||
v: clamp(hsva.v - offset.top * 100, 0, 100),
|
||||
});
|
||||
};
|
||||
|
||||
const containerStyle = useMemo(
|
||||
() => ({
|
||||
backgroundColor: hsvaToHslString({
|
||||
h: hsva.h,
|
||||
s: 100,
|
||||
v: 100,
|
||||
a: 1,
|
||||
}),
|
||||
}),
|
||||
[hsva.h],
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="react-colorful__saturation_value" style={containerStyle}>
|
||||
<Interactive
|
||||
onMove={handleMove}
|
||||
onKey={handleKey}
|
||||
aria-label="Color"
|
||||
aria-valuetext={`Saturation ${Math.round(
|
||||
hsva.s,
|
||||
)}%, Brightness ${Math.round(hsva.v)}%`}
|
||||
>
|
||||
<Pointer
|
||||
className="react-colorful__saturation_value-pointer"
|
||||
top={1 - hsva.v / 100}
|
||||
left={hsva.s / 100}
|
||||
color={hsvaToHslString(hsva)}
|
||||
/>
|
||||
</Interactive>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
interface HueProps {
|
||||
className?: string;
|
||||
hue: number;
|
||||
onChange: (newHue: Partial<HsvaColor>) => void;
|
||||
}
|
||||
|
||||
const Hue: React.FC<HueProps> = React.memo(({ className, hue, onChange }) => {
|
||||
const handleMove = (interaction: Interaction) => {
|
||||
onChange({ h: 360 * interaction.left });
|
||||
};
|
||||
|
||||
const handleKey = (offset: Interaction) => {
|
||||
onChange({ h: clamp(hue + offset.left * 360, 0, 360) });
|
||||
};
|
||||
|
||||
const nodeClassName = classes(['react-colorful__hue', className]);
|
||||
|
||||
return (
|
||||
<div className={nodeClassName}>
|
||||
<Interactive
|
||||
onMove={handleMove}
|
||||
onKey={handleKey}
|
||||
aria-label="Hue"
|
||||
aria-valuenow={Math.round(hue)}
|
||||
aria-valuemax={360}
|
||||
aria-valuemin={0}
|
||||
>
|
||||
<Pointer
|
||||
className="react-colorful__hue-pointer"
|
||||
left={hue / 360}
|
||||
color={hsvaToHslString({ h: hue, s: 100, v: 100, a: 1 })}
|
||||
/>
|
||||
</Interactive>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
interface SaturationProps {
|
||||
className?: string;
|
||||
color: HsvaColor;
|
||||
onChange: (newSaturation: Partial<HsvaColor>) => void;
|
||||
}
|
||||
|
||||
const Saturation: React.FC<SaturationProps> = React.memo(
|
||||
({ className, color, onChange }) => {
|
||||
const handleMove = (interaction: Interaction) => {
|
||||
onChange({ s: 100 * interaction.left });
|
||||
};
|
||||
|
||||
const handleKey = (offset: Interaction) => {
|
||||
onChange({ s: clamp(color.s + offset.left * 100, 0, 100) });
|
||||
};
|
||||
|
||||
const nodeClassName = classes(['react-colorful__saturation', className]);
|
||||
|
||||
const background = useMemo(
|
||||
() =>
|
||||
`linear-gradient(to right, ${hsvaToHslString({
|
||||
h: color.h,
|
||||
s: 0,
|
||||
v: color.v,
|
||||
a: 1,
|
||||
})}, ${hsvaToHslString({ h: color.h, s: 100, v: color.v, a: 1 })})`,
|
||||
[color],
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={nodeClassName}>
|
||||
<Interactive
|
||||
style={{ background }}
|
||||
onMove={handleMove}
|
||||
onKey={handleKey}
|
||||
aria-label="Saturation"
|
||||
aria-valuenow={Math.round(color.s)}
|
||||
aria-valuemax={100}
|
||||
aria-valuemin={0}
|
||||
>
|
||||
<Pointer
|
||||
className="react-colorful__saturation-pointer"
|
||||
left={color.s / 100}
|
||||
color={hsvaToHslString({
|
||||
h: color.h,
|
||||
s: color.s,
|
||||
v: color.v,
|
||||
a: 1,
|
||||
})}
|
||||
/>
|
||||
</Interactive>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
interface ValueProps {
|
||||
className?: string;
|
||||
color: HsvaColor;
|
||||
onChange: (newValue: Partial<HsvaColor>) => void;
|
||||
}
|
||||
|
||||
const Value: React.FC<ValueProps> = React.memo(
|
||||
({ className, color, onChange }) => {
|
||||
const handleMove = (interaction: Interaction) => {
|
||||
onChange({ v: 100 * interaction.left });
|
||||
};
|
||||
|
||||
const handleKey = (offset: Interaction) => {
|
||||
onChange({
|
||||
v: clamp(color.v + offset.left * 100, 0, 100),
|
||||
});
|
||||
};
|
||||
|
||||
const nodeClassName = classes(['react-colorful__value', className]);
|
||||
|
||||
const background = useMemo(
|
||||
() =>
|
||||
`linear-gradient(to right, ${hsvaToHslString({
|
||||
h: color.h,
|
||||
s: color.s,
|
||||
v: 0,
|
||||
a: 1,
|
||||
})}, ${hsvaToHslString({ h: color.h, s: color.s, v: 100, a: 1 })})`,
|
||||
[color],
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={nodeClassName}>
|
||||
<Interactive
|
||||
style={{
|
||||
background,
|
||||
}}
|
||||
onMove={handleMove}
|
||||
onKey={handleKey}
|
||||
aria-label="Value"
|
||||
aria-valuenow={Math.round(color.v)}
|
||||
aria-valuemax={100}
|
||||
aria-valuemin={0}
|
||||
>
|
||||
<Pointer
|
||||
className="react-colorful__value-pointer"
|
||||
left={color.v / 100}
|
||||
color={hsvaToHslString(color)}
|
||||
/>
|
||||
</Interactive>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
interface RGBSliderProps {
|
||||
className?: string;
|
||||
color: HsvaColor;
|
||||
onChange: (newValue: HsvaColor) => void;
|
||||
target: 'r' | 'g' | 'b';
|
||||
}
|
||||
|
||||
const RGBSlider: React.FC<RGBSliderProps> = React.memo(
|
||||
({ className, color, onChange, target }) => {
|
||||
const rgb = hsvaToRgba(color);
|
||||
|
||||
const setNewTarget = (value: number) => {
|
||||
const newRgb = { ...rgb, [target]: value };
|
||||
onChange(rgbaToHsva(newRgb));
|
||||
};
|
||||
|
||||
const handleMove = (interaction: Interaction) => {
|
||||
setNewTarget(255 * interaction.left);
|
||||
};
|
||||
|
||||
const handleKey = (offset: Interaction) => {
|
||||
setNewTarget(clamp(rgb[target] + offset.left * 255, 0, 255));
|
||||
};
|
||||
|
||||
const nodeClassName = classes([`react-colorful__${target}`, className]);
|
||||
|
||||
const channels = {
|
||||
r: `rgb(${Math.round(rgb.r)},0,0)`,
|
||||
g: `rgb(0,${Math.round(rgb.g)},0)`,
|
||||
b: `rgb(0,0,${Math.round(rgb.b)})`,
|
||||
};
|
||||
|
||||
const selected = channels[target];
|
||||
|
||||
return (
|
||||
<div className={nodeClassName}>
|
||||
<Interactive
|
||||
onMove={handleMove}
|
||||
onKey={handleKey}
|
||||
aria-valuenow={rgb[target]}
|
||||
aria-valuemax={255}
|
||||
aria-valuemin={0}
|
||||
>
|
||||
<Pointer
|
||||
className={`react-colorful__${target}-pointer`}
|
||||
left={rgb[target] / 255}
|
||||
color={selected}
|
||||
/>
|
||||
</Interactive>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -7,7 +7,7 @@ import { Window } from '../layouts';
|
||||
import { OvermapFlightData, OvermapPanControls } from './common/Overmap';
|
||||
|
||||
type Data = {
|
||||
mapRef: string | null;
|
||||
mapRef: string | undefined;
|
||||
sector: string;
|
||||
sector_info: string;
|
||||
landed: string;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-popper": "^2.3.0",
|
||||
"tgui-core": "^1.2.0",
|
||||
"tgui-core": "^1.7.4",
|
||||
"tgui-dev-server": "workspace:*",
|
||||
"tgui-polyfill": "workspace:*"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* MIT License
|
||||
* https://github.com/omgovich/react-colorful/
|
||||
*
|
||||
* Copyright (c) 2020 Vlad Shilov <omgovich@ya.ru>
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
@use '../colors.scss';
|
||||
@use '../base.scss';
|
||||
|
||||
.react-colorful {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.react-colorful__saturation_value {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
border-color: transparent; /* Fixes https://github.com/omgovich/react-colorful/issues/139 */
|
||||
border-bottom: 12px solid #000;
|
||||
border-radius: 8px 8px 0 0;
|
||||
background-image: linear-gradient(
|
||||
to top,
|
||||
rgba(0, 0, 0, 255),
|
||||
rgba(0, 0, 0, 0)
|
||||
),
|
||||
linear-gradient(to right, rgba(255, 255, 255, 255), rgba(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
.react-colorful__pointer-fill,
|
||||
.react-colorful__alpha-gradient {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
pointer-events: none;
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
||||
/* Improve elements rendering on light backgrounds */
|
||||
.react-colorful__alpha-gradient,
|
||||
.react-colorful__saturation_value {
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.react-colorful__hue,
|
||||
.react-colorful__r,
|
||||
.react-colorful__g,
|
||||
.react-colorful__b,
|
||||
.react-colorful__alpha,
|
||||
.react-colorful__saturation,
|
||||
.react-colorful__value {
|
||||
position: relative;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.react-colorful__hue {
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
#f00 0%,
|
||||
#ff0 17%,
|
||||
#0f0 33%,
|
||||
#0ff 50%,
|
||||
#00f 67%,
|
||||
#f0f 83%,
|
||||
#f00 100%
|
||||
);
|
||||
}
|
||||
|
||||
.react-colorful__r {
|
||||
background: linear-gradient(to right, #000, #f00);
|
||||
}
|
||||
|
||||
.react-colorful__g {
|
||||
background: linear-gradient(to right, #000, #0f0);
|
||||
}
|
||||
|
||||
.react-colorful__b {
|
||||
background: linear-gradient(to right, #000, #00f);
|
||||
}
|
||||
|
||||
/* Round bottom corners of the last element: `Hue` for `ColorPicker` or `Alpha` for `AlphaColorPicker` */
|
||||
.react-colorful__last-control {
|
||||
border-radius: 0 0 8px 8px;
|
||||
}
|
||||
|
||||
.react-colorful__interactive {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border-radius: inherit;
|
||||
outline: none;
|
||||
/* Don't trigger the default scrolling behavior when the event is originating from this element */
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
.react-colorful__pointer {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
transform: translate(-50%, -50%);
|
||||
background-color: #cfcfcf;
|
||||
border: 2px solid #cfcfcf;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.react-colorful__interactive:focus .react-colorful__pointer {
|
||||
transform: translate(-50%, -50%) scale(1.1);
|
||||
background-color: #fff;
|
||||
border-color: #fff;
|
||||
}
|
||||
|
||||
/* Chessboard-like pattern for alpha related elements */
|
||||
.react-colorful__alpha,
|
||||
.react-colorful__alpha-pointer {
|
||||
background-color: #fff;
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill-opacity=".05"><rect x="8" width="8" height="8"/><rect y="8" width="8" height="8"/></svg>');
|
||||
}
|
||||
|
||||
.react-colorful__saturation-pointer,
|
||||
.react-colorful__value-pointer,
|
||||
.react-colorful__hue-pointer,
|
||||
.react-colorful__r-pointer,
|
||||
.react-colorful__g-pointer,
|
||||
.react-colorful__b-pointer {
|
||||
z-index: 1;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* Display the saturation value pointer over the hue one */
|
||||
.react-colorful__saturation_value-pointer {
|
||||
z-index: 3;
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
@include meta.load-css('./interfaces/AlertModal.scss');
|
||||
@include meta.load-css('./interfaces/CameraConsole.scss');
|
||||
@include meta.load-css('./interfaces/Changelog.scss');
|
||||
@include meta.load-css('./interfaces/ColorPicker.scss');
|
||||
@include meta.load-css('./interfaces/CrewManifest.scss');
|
||||
@include meta.load-css('./interfaces/ExperimentConfigure.scss');
|
||||
@include meta.load-css('./interfaces/FishingMinigame.scss');
|
||||
|
||||
+5
-5
@@ -8236,13 +8236,13 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"tgui-core@npm:^1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "tgui-core@npm:1.2.0"
|
||||
"tgui-core@npm:^1.7.4":
|
||||
version: 1.7.4
|
||||
resolution: "tgui-core@npm:1.7.4"
|
||||
peerDependencies:
|
||||
react: ^18.2.0
|
||||
react-dom: ^18.2.0
|
||||
checksum: 10c0/1eead0edbe0df5c49bfa88f0d2caa5df743057be75e9c526d0afd838b8def072c67fe60435c66cba52551c4ef70749d60d68094fa103542187008998002714f7
|
||||
checksum: 10c0/06b9d8702d6ae170383b28725bf6308cd320499367ea8ea1f9dd5039ab371cfe34419a7d3d1e0e2b86884326e8d4ab116e5601208d2f85d215b7c464fd32fdbf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8354,7 +8354,7 @@ __metadata:
|
||||
react: "npm:^18.2.0"
|
||||
react-dom: "npm:^18.2.0"
|
||||
react-popper: "npm:^2.3.0"
|
||||
tgui-core: "npm:^1.2.0"
|
||||
tgui-core: "npm:^1.7.4"
|
||||
tgui-dev-server: "workspace:*"
|
||||
tgui-polyfill: "workspace:*"
|
||||
languageName: unknown
|
||||
|
||||
@@ -4251,6 +4251,7 @@
|
||||
#include "code\modules\tgui\states\zlevel.dm"
|
||||
#include "code\modules\tgui_input\alert.dm"
|
||||
#include "code\modules\tgui_input\checkboxes.dm"
|
||||
#include "code\modules\tgui_input\color.dm"
|
||||
#include "code\modules\tgui_input\list.dm"
|
||||
#include "code\modules\tgui_input\number.dm"
|
||||
#include "code\modules\tgui_input\text.dm"
|
||||
|
||||
Reference in New Issue
Block a user