Adds colourblind mode and a colour matrix editor (#17933)

* Colourblind mode + Matrix editor

* increase that

* Protanopia filter

* Tritanopia filter

* The SQL part

* Refactor

* you saw nothing
This commit is contained in:
AffectedArc07
2022-06-10 17:52:28 -06:00
committed by GitHub
parent 0d465cdd6f
commit 7d5a7ad85d
20 changed files with 266 additions and 61 deletions
+2
View File
@@ -332,6 +332,8 @@
. = ..() //calls mob.Login()
mob.update_client_colour(0) // Activate colourblind mode if they have one set
if(ckey in GLOB.clientmessages)
for(var/message in GLOB.clientmessages[ckey])
@@ -22,7 +22,8 @@
2fa_status,
screentip_mode,
screentip_color,
ghost_darkness_level
ghost_darkness_level,
colourblind_mode
FROM player
WHERE ckey=:ckey"}, list(
"ckey" = C.ckey
@@ -875,6 +875,12 @@
else
switch(href_list["preference"])
if("cbmode")
var/cb_mode = input(user, "Select a colourblind mode\nNote this will disable special screen effects such as the cursed heart warnings!") as null|anything in list(COLOURBLIND_MODE_NONE, COLOURBLIND_MODE_DEUTER, COLOURBLIND_MODE_PROT, COLOURBLIND_MODE_TRIT)
if(cb_mode)
colourblind_mode = cb_mode
user.update_client_colour(0)
if("publicity")
if(unlock_content)
toggles ^= PREFTOGGLE_MEMBER_PUBLIC
@@ -115,6 +115,8 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
var/datum/character_save/active_character
/// How dark things are if client is a ghost, 0-255
var/ghost_darkness_level = LIGHTING_PLANE_ALPHA_VISIBLE
/// Colourblind mode
var/colourblind_mode = COLOURBLIND_MODE_NONE
/datum/preferences/New(client/C, datum/db_query/Q) // Process our query
parent = C
@@ -363,6 +365,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
dat += "<b>Attack Animations:</b> <a href='?_src_=prefs;preference=ghost_att_anim'>[(toggles2 & PREFTOGGLE_2_ITEMATTACK) ? "Yes" : "No"]</a><br>"
if(unlock_content)
dat += "<b>BYOND Membership Publicity:</b> <a href='?_src_=prefs;preference=publicity'><b>[(toggles & PREFTOGGLE_MEMBER_PUBLIC) ? "Public" : "Hidden"]</b></a><br>"
dat += "<b>Colourblind Mode:</b> <a href='?_src_=prefs;preference=cbmode'>[colourblind_mode]</a><br>"
dat += "<b>Custom UI settings:</b><br>"
dat += " - <b>Alpha (transparency):</b> <a href='?_src_=prefs;preference=UIalpha'><b>[UI_style_alpha]</b></a><br>"
dat += " - <b>Color:</b> <a href='?_src_=prefs;preference=UIcolor'><b>[UI_style_color]</b></a> <span style='border: 1px solid #161616; background-color: [UI_style_color];'>&nbsp;&nbsp;&nbsp;</span><br>"
@@ -477,7 +480,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
dat += "<a href='?_src_=prefs;preference=reset_all'>Reset Setup</a>"
dat += "</center>"
var/datum/browser/popup = new(user, "preferences", "<div align='center'>Character Setup</div>", 820, 660)
var/datum/browser/popup = new(user, "preferences", "<div align='center'>Character Setup</div>", 820, 720)
popup.set_content(dat)
popup.open(0)
@@ -24,6 +24,7 @@
screentip_mode = query.item[18]
screentip_color = query.item[19]
ghost_darkness_level = query.item[20]
colourblind_mode = query.item[21]
//Sanitize
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
@@ -43,10 +44,10 @@
screentip_mode = sanitize_integer(screentip_mode, 0, 20, initial(screentip_mode))
screentip_color = sanitize_hexcolor(screentip_color, initial(screentip_color))
ghost_darkness_level = sanitize_integer(ghost_darkness_level, 0, 255, initial(ghost_darkness_level))
colourblind_mode = sanitize_inlist(colourblind_mode, list(COLOURBLIND_MODE_NONE, COLOURBLIND_MODE_DEUTER, COLOURBLIND_MODE_PROT, COLOURBLIND_MODE_TRIT), COLOURBLIND_MODE_NONE)
return TRUE
/datum/preferences/proc/save_preferences(client/C)
// Might as well scrub out any malformed be_special list entries while we're here
for(var/role in be_special)
if(!(role in GLOB.special_roles))
@@ -58,57 +59,57 @@
deltimer(volume_mixer_saving)
volume_mixer_saving = null
var/datum/db_query/query = SSdbcore.NewQuery({"UPDATE player
SET
ooccolor=:ooccolour,
UI_style=:ui_style,
UI_style_color=:ui_colour,
UI_style_alpha=:ui_alpha,
be_role=:berole,
default_slot=:defaultslot,
toggles=:toggles,
toggles_2=:toggles2,
atklog=:atklog,
sound=:sound,
volume_mixer=:volume_mixer,
lastchangelog=:lastchangelog,
clientfps=:clientfps,
parallax=:parallax,
2fa_status=:_2fa_status,
screentip_mode=:screentip_mode,
screentip_color=:screentip_color,
ghost_darkness_level=:ghost_darkness_level
WHERE ckey=:ckey"}, list(
// OH GOD THE PARAMETERS
"ooccolour" = ooccolor,
"ui_style" = UI_style,
"ui_colour" = UI_style_color,
"ui_alpha" = UI_style_alpha,
"berole" = list2params(be_special),
"defaultslot" = default_slot,
// Even though its a number in the DB, you have to use num2text here, otherwise byond adds scientific notation to the number
"toggles" = num2text(toggles, CEILING(log(10, (TOGGLES_TOTAL)), 1)),
"toggles2" = num2text(toggles2, CEILING(log(10, (TOGGLES_2_TOTAL)), 1)),
"atklog" = atklog,
"sound" = sound,
"volume_mixer" = serialize_volume_mixer(volume_mixer),
"lastchangelog" = lastchangelog,
"clientfps" = clientfps,
"parallax" = parallax,
"_2fa_status" = _2fa_status,
"screentip_mode" = screentip_mode,
"screentip_color" = screentip_color,
"ghost_darkness_level" = ghost_darkness_level,
"ckey" = C.ckey,
)
)
var/datum/db_query/query = SSdbcore.NewQuery({"UPDATE player SET
ooccolor=:ooccolour,
UI_style=:ui_style,
UI_style_color=:ui_colour,
UI_style_alpha=:ui_alpha,
be_role=:berole,
default_slot=:defaultslot,
toggles=:toggles,
toggles_2=:toggles2,
atklog=:atklog,
sound=:sound,
volume_mixer=:volume_mixer,
lastchangelog=:lastchangelog,
clientfps=:clientfps,
parallax=:parallax,
2fa_status=:_2fa_status,
screentip_mode=:screentip_mode,
screentip_color=:screentip_color,
ghost_darkness_level=:ghost_darkness_level,
colourblind_mode=:colourblind_mode
WHERE ckey=:ckey"}, list(
// OH GOD THE PARAMETERS
"ooccolour" = ooccolor,
"ui_style" = UI_style,
"ui_colour" = UI_style_color,
"ui_alpha" = UI_style_alpha,
"berole" = list2params(be_special),
"defaultslot" = default_slot,
// Even though its a number in the DB, you have to use num2text here, otherwise byond adds scientific notation to the number
"toggles" = num2text(toggles, CEILING(log(10, (TOGGLES_TOTAL)), 1)),
"toggles2" = num2text(toggles2, CEILING(log(10, (TOGGLES_2_TOTAL)), 1)),
"atklog" = atklog,
"sound" = sound,
"volume_mixer" = serialize_volume_mixer(volume_mixer),
"lastchangelog" = lastchangelog,
"clientfps" = clientfps,
"parallax" = parallax,
"_2fa_status" = _2fa_status,
"screentip_mode" = screentip_mode,
"screentip_color" = screentip_color,
"ghost_darkness_level" = ghost_darkness_level,
"colourblind_mode" = colourblind_mode,
"ckey" = C.ckey,
))
if(!query.warn_execute())
qdel(query)
return
qdel(query)
return 1
return TRUE
/datum/preferences/proc/load_random_character_slot(client/C)
var/list/datum/character_save/valid_slots = list()
@@ -370,7 +370,9 @@
/mob/living/simple_animal/hostile/floor_cluwne/proc/Kill(mob/living/carbon/human/H)
playsound(H, 'sound/spookoween/scary_horn2.ogg', 100, 0)
var/old_color = H.client?.color
client_kill_animation(H)
if(H?.client?.prefs.colourblind_mode == COLOURBLIND_MODE_NONE)
client_kill_animation(H)
for(var/turf/T in orange(H, 4))
H.add_splatter_floor(T)
+53
View File
@@ -13,6 +13,57 @@
return 0
/mob/proc/get_screen_colour()
SHOULD_CALL_PARENT(TRUE)
// OOC Colourblind setting takes priority over everything else.
if(client?.prefs)
switch(client.prefs.colourblind_mode)
if(COLOURBLIND_MODE_NONE)
. = null
/*
Also it goes without saying
For the love of god, do NOT mess with the matricies below.
The values may look arbitrary as hell, but they follow colour filtering rules
to accent specific colours and block out others, which helps different
forms of colourblindness. Its not perfect but it helps.
If you ever want to modify these matricies, test them with someone who
suffers that form of colourblindness, and ask if its an improvement or a hinderance.
I cannot stress this enough
-aa07
*/
if(COLOURBLIND_MODE_DEUTER)
// Red-green (green weak, deuteranopia)
// Below is a colour matrix to account for that
. = list(
1.8, 0, -0.14, 0,
-1.05, 1, 0.1, 0,
0.3, 0, 1, 0,
0, 0, 0, 1
) // Time spent creating this matrix: 1 hour 32 minutes
if(COLOURBLIND_MODE_PROT)
// Red-green (red weak, protanopia)
// Below is a colour matrix to account for that
. = list(
1, 0.475, 0.594, 0,
0, 0.482, -0.68, 0,
0, 0.044, 1.087, 0,
0, 0, 0, 1
) // Time spent creating this matrix: 57 minutes
if(COLOURBLIND_MODE_TRIT)
// Blue-yellow (tritanopia)
// Below is a colour matrix to account for that
. = list(
0.74, 0.07, 0, 0,
-0.405, 0.593, 0, 0,
0.665, 0.335, 1, 0,
0, 0, 0, 1
) // Time spent creating this matrix: 34 minutes
return
/mob/proc/update_client_colour(time = 10) //Update the mob's client.color with an animation the specified time in length.
@@ -42,6 +93,8 @@
/mob/proc/flash_screen_color(flash_color, flash_time)
if(!client)
return
if(client?.prefs.colourblind_mode != COLOURBLIND_MODE_NONE)
return
client.color = flash_color
INVOKE_ASYNC(client, /client/.proc/colour_transition, get_screen_colour(), flash_time)
+2 -2
View File
@@ -102,7 +102,7 @@
if(!(NO_BLOOD in H.dna.species.species_traits))
H.blood_volume = max(H.blood_volume - blood_loss, 0)
to_chat(H, "<span class='userdanger'>You have to keep pumping your blood!</span>")
if(H.client)
if(H?.client?.prefs.colourblind_mode == COLOURBLIND_MODE_NONE)
H.client.color = "red" //bloody screen so real
else
last_pump = world.time //lets be extra fair *sigh*
@@ -133,7 +133,7 @@
if(istype(H))
if(!(NO_BLOOD in H.dna.species.species_traits))
H.blood_volume = min(H.blood_volume + cursed_heart.blood_loss * 0.5, BLOOD_VOLUME_NORMAL)
if(owner.client)
if(owner?.client?.prefs.colourblind_mode == COLOURBLIND_MODE_NONE)
owner.client.color = ""
H.adjustBruteLoss(-cursed_heart.heal_brute)
@@ -0,0 +1,43 @@
/datum/ui_module/colour_matrix_tester
name = "Colour Matrix Tester"
/// The datum we are modifying. This will almost always be an atom, but clients have colours too
var/datum/target_datum
// Target colour matrix to make applying easier
var/target_matrix = list(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
)
/datum/ui_module/colour_matrix_tester/New(datum/_host, datum/target)
..()
if(!(isatom(target) || isclient(target)))
stack_trace("Attempted to create a colour matrix tester on a non atom/client!")
qdel(src)
return
target_datum = target
/datum/ui_module/colour_matrix_tester/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.admin_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ColourMatrixTester", name, 350, 170, master_ui, state)
ui.autoupdate = TRUE
ui.open()
/datum/ui_module/colour_matrix_tester/ui_data(mob/user)
var/list/data = list()
data["colour_data"] = target_matrix
return data
/datum/ui_module/colour_matrix_tester/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
switch(action)
if("setvalue")
target_matrix[text2num(params["idx"])] = text2num(params["value"])
target_datum:color = target_matrix // Force apply
return TRUE