mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
[MIRROR] View Variables Dark Mode (#10987)
Co-authored-by: ShadowLarkens <shadowlarkens@gmail.com>
This commit is contained in:
committed by
GitHub
parent
064422fbc3
commit
3118b7aad8
@@ -3,6 +3,10 @@
|
||||
#define isweakref(A) istype(A, /datum/weakref)
|
||||
|
||||
//#define islist(D) istype(D, /list) //Built in
|
||||
#define isimage(thing) (istype(thing, /image))
|
||||
|
||||
GLOBAL_VAR_INIT(magic_appearance_detecting_image, new /image) // appearances are awful to detect safely, but this seems to be the best way ~ninjanomnom
|
||||
#define isappearance(thing) (!isimage(thing) && !ispath(thing) && istype(GLOB.magic_appearance_detecting_image, thing))
|
||||
|
||||
//---------------
|
||||
#define isatom(D) istype(D, /atom)
|
||||
|
||||
@@ -757,3 +757,25 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
|
||||
|
||||
var/icon/I = getFlatIcon(thing, force_south = force_south)
|
||||
return icon2html(I, target, sourceonly = sourceonly)
|
||||
|
||||
/// Checks whether a given icon state exists in a given icon file. If `file` and `state` both exist,
|
||||
/// this will return `TRUE` - otherwise, it will return `FALSE`.
|
||||
///
|
||||
/// If you want a stack trace to be output when the given state/file doesn't exist, use
|
||||
/// `/proc/icon_exists_or_scream()`.
|
||||
/proc/icon_exists(file, state)
|
||||
var/static/list/icon_states_cache = list()
|
||||
if(isnull(file) || isnull(state))
|
||||
return FALSE //This is common enough that it shouldn't panic, imo.
|
||||
|
||||
if(isnull(icon_states_cache[file]))
|
||||
icon_states_cache[file] = list()
|
||||
var/file_string = "[file]"
|
||||
if(isfile(file) && length(file_string)) // ensure that it's actually a file, and not a runtime icon
|
||||
for(var/istate in json_decode(rustg_dmi_icon_states(file_string)))
|
||||
icon_states_cache[file][istate] = TRUE
|
||||
else // Otherwise, we have to use the slower BYOND proc
|
||||
for(var/istate in icon_states(file))
|
||||
icon_states_cache[file][istate] = TRUE
|
||||
|
||||
return !isnull(icon_states_cache[file][state])
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
name = data_list[name] //name is really the index until this line
|
||||
else
|
||||
value = data_list[name]
|
||||
header = "<li style='backgroundColor:white'>(<a href='byond://?_src_=vars;[HrefToken()];[VV_HK_LIST_EDIT]=1;target=\ref[DA];index=[index]'>E</a>) (<a href='byond://?_src_=vars;[HrefToken()];[VV_HK_LIST_CHANGE]=1;target=\ref[DA];index=[index]'>C</a>) (<a href='byond://?_src_=vars;[HrefToken()];[VV_HK_LIST_REMOVE]=1;target=\ref[DA];index=[index]'>-</a>) "
|
||||
header = "<li>(<a href='byond://?_src_=vars;[HrefToken()];[VV_HK_LIST_EDIT]=1;target=\ref[DA];index=[index]'>E</a>) (<a href='byond://?_src_=vars;[HrefToken()];[VV_HK_LIST_CHANGE]=1;target=\ref[DA];index=[index]'>C</a>) (<a href='byond://?_src_=vars;[HrefToken()];[VV_HK_LIST_REMOVE]=1;target=\ref[DA];index=[index]'>-</a>) "
|
||||
else
|
||||
header = "<li style='backgroundColor:white'>(<a href='byond://?_src_=vars;[HrefToken()];datumedit=\ref[DA];varnameedit=[name]'>E</a>) (<a href='byond://?_src_=vars;[HrefToken()];datumchange=\ref[DA];varnamechange=[name]'>C</a>) (<a href='byond://?_src_=vars;[HrefToken()];datummass=\ref[DA];varnamemass=[name]'>M</a>) "
|
||||
header = "<li>(<a href='byond://?_src_=vars;[HrefToken()];datumedit=\ref[DA];varnameedit=[name]'>E</a>) (<a href='byond://?_src_=vars;[HrefToken()];datumchange=\ref[DA];varnamechange=[name]'>C</a>) (<a href='byond://?_src_=vars;[HrefToken()];datummass=\ref[DA];varnamemass=[name]'>M</a>) "
|
||||
else
|
||||
header = "<li>"
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#define ICON_STATE_CHECKED 1 /// this dmi is checked. We don't check this one anymore.
|
||||
#define ICON_STATE_NULL 2 /// this dmi has null-named icon_state, allowing it to show a sprite on vv editor.
|
||||
|
||||
/client/proc/debug_variables(datum/D in world)
|
||||
set category = "Debug.Investigate"
|
||||
set name = "View Variables"
|
||||
@@ -11,8 +14,14 @@
|
||||
if(!D)
|
||||
return
|
||||
|
||||
var/islist = islist(D)
|
||||
if (!islist && !istype(D))
|
||||
var/dark = usr.client.prefs ? usr.client.prefs.read_preference(/datum/preference/toggle/holder/vv_dark) : TRUE
|
||||
var/use_gfi = usr.client.prefs ? usr.client.prefs.read_preference(/datum/preference/toggle/holder/vv_gfi) : TRUE
|
||||
|
||||
var/datum/asset/asset_cache_datum = get_asset_datum(/datum/asset/simple/vv)
|
||||
asset_cache_datum.send(usr)
|
||||
|
||||
var/islist = islist(D) || (!isdatum(D) && hascall(D, "Cut")) // Some special lists don't count as lists, but can be detected by if they have list procs
|
||||
if(!islist && !isdatum(D))
|
||||
return
|
||||
|
||||
//VOREStation Edit Start - the rest of this proc in a spawn
|
||||
@@ -22,29 +31,57 @@
|
||||
var/icon/sprite
|
||||
var/hash
|
||||
|
||||
var/type = /list
|
||||
if (!islist)
|
||||
type = D.type
|
||||
var/type = islist ? /list : D.type
|
||||
var/no_icon = FALSE
|
||||
|
||||
if(istype(D, /atom))
|
||||
if(isatom(D))
|
||||
var/atom/AT = D
|
||||
if(AT.icon && AT.icon_state)
|
||||
if(use_gfi)
|
||||
sprite = getFlatIcon(D)
|
||||
if(!sprite)
|
||||
no_icon = TRUE
|
||||
else if(AT.icon && AT.icon_state)
|
||||
sprite = new /icon(AT.icon, AT.icon_state)
|
||||
hash = md5(AT.icon)
|
||||
hash = md5(hash + AT.icon_state)
|
||||
src << browse_rsc(sprite, "vv[hash].png")
|
||||
else
|
||||
no_icon = TRUE
|
||||
|
||||
else if(isimage(D))
|
||||
// icon_state=null shows first image even if dmi has no icon_state for null name.
|
||||
// This list remembers which dmi has null icon_state, to determine if icon_state=null should display a sprite
|
||||
// (NOTE: icon_state="" is correct, but saying null is obvious)
|
||||
var/static/list/dmi_nullstate_checklist = list()
|
||||
var/image/image_object = D
|
||||
var/icon_filename_text = "[image_object.icon]" // "icon(null)" type can exist. textifying filters it.
|
||||
if(icon_filename_text)
|
||||
if(image_object.icon_state)
|
||||
sprite = icon(image_object.icon, image_object.icon_state)
|
||||
|
||||
else // it means: icon_state=""
|
||||
if(!dmi_nullstate_checklist[icon_filename_text])
|
||||
dmi_nullstate_checklist[icon_filename_text] = ICON_STATE_CHECKED
|
||||
if(icon_exists(image_object.icon, ""))
|
||||
// this dmi has nullstate. We'll allow "icon_state=null" to show image.
|
||||
dmi_nullstate_checklist[icon_filename_text] = ICON_STATE_NULL
|
||||
|
||||
if(dmi_nullstate_checklist[icon_filename_text] == ICON_STATE_NULL)
|
||||
sprite = icon(image_object.icon, image_object.icon_state)
|
||||
|
||||
var/sprite_text
|
||||
if(sprite)
|
||||
hash = md5(sprite)
|
||||
src << browse_rsc(sprite, "vv[hash].png")
|
||||
sprite_text = no_icon ? "\[NO ICON\]" : "<img src='vv[hash].png'></td><td>"
|
||||
|
||||
title = "[D] (\ref[D]) = [type]"
|
||||
var/formatted_type = replacetext("[type]", "/", "<wbr>/")
|
||||
|
||||
var/sprite_text
|
||||
if(sprite)
|
||||
sprite_text = "<img src='vv[hash].png'></td><td>"
|
||||
var/list/header = islist(D)? list(span_bold("/list")) : D.vv_get_header()
|
||||
|
||||
var/marked
|
||||
var/ref_line = "@[copytext(refid, 2, -1)]" // get rid of the brackets, add a @ prefix for copy pasting in asay
|
||||
|
||||
var/marked_line
|
||||
if(holder && holder.marked_datum && holder.marked_datum == D)
|
||||
marked = VV_MSG_MARKED
|
||||
marked_line = VV_MSG_MARKED
|
||||
var/varedited_line = ""
|
||||
if(!islist && (D.datum_flags & DF_VAR_EDITED))
|
||||
varedited_line = VV_MSG_EDITED
|
||||
@@ -86,35 +123,28 @@
|
||||
var/ui_scale = prefs?.read_preference(/datum/preference/toggle/ui_scale)
|
||||
|
||||
var/list/variable_html = list()
|
||||
if (islist)
|
||||
if(islist)
|
||||
var/list/L = D
|
||||
for (var/i in 1 to L.len)
|
||||
var/key = L[i]
|
||||
var/value
|
||||
if (IS_NORMAL_LIST(L) && IS_VALID_ASSOC_KEY(key))
|
||||
if(IS_NORMAL_LIST(L) && IS_VALID_ASSOC_KEY(key))
|
||||
value = L[key]
|
||||
variable_html += debug_variable(i, value, 0, D)
|
||||
else
|
||||
|
||||
names = sortList(names)
|
||||
for (var/V in names)
|
||||
if(D.can_vv_get(V))
|
||||
variable_html += D.vv_get_var(V)
|
||||
|
||||
var/html = {"
|
||||
<html>
|
||||
<!DOCTYPE html>
|
||||
<html class="[dark ? "dark" : ""]">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta charset="utf-8" />
|
||||
<title>[title]</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Verdana, sans-serif;
|
||||
font-size: 9pt;
|
||||
}
|
||||
.value {
|
||||
font-family: "Courier New", monospace;
|
||||
font-size: 8pt;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="[SSassets.transport.get_asset_url("view_variables.css")]">
|
||||
[!ui_scale && window_scaling ? "<style>body {zoom: [100 / window_scaling]%;}</style>" : ""]
|
||||
</head>
|
||||
<body onload='selectTextField()' onkeydown='return handle_keydown()' onkeyup='handle_keyup()'>
|
||||
@@ -228,8 +258,9 @@
|
||||
</tr>
|
||||
</table>
|
||||
<div align='center'>
|
||||
"} + span_bold(span_small("[formatted_type]")) + {"
|
||||
<span id='marked'>[marked]</span>
|
||||
<b><font size='1'>[formatted_type]</font></b>
|
||||
<br><b><font size='1'>[ref_line]</font></b>
|
||||
<span id='marked'>[marked_line]</span>
|
||||
<span id='varedited'>[varedited_line]</span>
|
||||
<span id='deleted'>[deleted_line]</span>
|
||||
</div>
|
||||
@@ -252,9 +283,9 @@
|
||||
</table>
|
||||
</div>
|
||||
<hr>
|
||||
"} + span_small(span_bold("E") + " - Edit, tries to determine the variable type by itself.<br>") + {"
|
||||
"} + span_small(span_bold("C") + " - Change, asks you for the var type first.<br>") + {"
|
||||
"} + span_small(span_bold("M") + " - Mass modify: changes this variable for all objects of this type.<br>") + {"
|
||||
<b>E</b> - Edit, tries to determine the variable type by itself.<br>
|
||||
<b>C</b> - Change, asks you for the var type first.<br>
|
||||
<b>M</b> - Mass modify: changes this variable for all objects of this type.<br>
|
||||
<hr>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
@@ -288,3 +319,6 @@
|
||||
|
||||
/client/proc/vv_update_display(datum/D, span, content)
|
||||
src << output("[span]:[content]", "variables\ref[D].browser:replace_span")
|
||||
|
||||
#undef ICON_STATE_CHECKED
|
||||
#undef ICON_STATE_NULL
|
||||
|
||||
4
code/modules/asset_cache/assets/vv.dm
Normal file
4
code/modules/asset_cache/assets/vv.dm
Normal file
@@ -0,0 +1,4 @@
|
||||
/datum/asset/simple/vv
|
||||
assets = list(
|
||||
"view_variables.css" = 'html/admin/view_variables.css'
|
||||
)
|
||||
@@ -72,6 +72,18 @@
|
||||
default_value = TRUE
|
||||
savefile_identifier = PREFERENCE_PLAYER
|
||||
|
||||
/datum/preference/toggle/holder/vv_dark
|
||||
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
|
||||
savefile_key = "vvdark"
|
||||
default_value = TRUE
|
||||
savefile_identifier = PREFERENCE_PLAYER
|
||||
|
||||
/datum/preference/toggle/holder/vv_gfi
|
||||
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
|
||||
savefile_key = "vvgfi"
|
||||
default_value = TRUE
|
||||
savefile_identifier = PREFERENCE_PLAYER
|
||||
|
||||
/// The color admins will speak in for OOC.
|
||||
/datum/preference/color/ooc_color
|
||||
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
|
||||
|
||||
61
html/admin/view_variables.css
Normal file
61
html/admin/view_variables.css
Normal file
@@ -0,0 +1,61 @@
|
||||
body {
|
||||
font-family: Verdana, sans-serif;
|
||||
font-size: 9pt;
|
||||
}
|
||||
.value {
|
||||
font-family: "Courier New", monospace;
|
||||
font-size: 8pt;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
table.matrix {
|
||||
border-collapse: collapse; border-spacing: 0;
|
||||
font-size: 7pt;
|
||||
}
|
||||
|
||||
.matrix td{
|
||||
text-align: center;
|
||||
padding: 0 1ex 0ex 1ex;
|
||||
}
|
||||
|
||||
table.matrixbrak {
|
||||
border-collapse: collapse; border-spacing: 0;
|
||||
}
|
||||
|
||||
table.matrixbrak td.lbrak {
|
||||
width: 0.8ex;
|
||||
font-size: 50%;
|
||||
border-top: solid 0.25ex black;
|
||||
border-bottom: solid 0.25ex black;
|
||||
border-left: solid 0.5ex black;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
table.matrixbrak td.rbrak {
|
||||
width: 0.8ex;
|
||||
font-size: 50%;
|
||||
border-top: solid 0.25ex black;
|
||||
border-bottom: solid 0.25ex black;
|
||||
border-right: solid 0.5ex black;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
/* Dark Mode */
|
||||
.dark body {
|
||||
background-color: #0d1117;
|
||||
color: #f0f6fc;
|
||||
}
|
||||
|
||||
.dark a {
|
||||
color: rgb(68, 147, 248);
|
||||
}
|
||||
|
||||
.dark select {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dark input {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
@@ -54,6 +54,21 @@ export const CHAT_ADSAY: FeatureToggle = {
|
||||
component: CheckboxInput,
|
||||
};
|
||||
|
||||
export const vvdark: FeatureToggle = {
|
||||
name: 'VV: Dark Theme',
|
||||
category: 'ADMIN',
|
||||
description: 'When enabled, View Variables will use a dark theme',
|
||||
component: CheckboxInput,
|
||||
};
|
||||
|
||||
export const vvgfi: FeatureToggle = {
|
||||
name: 'VV: Use getFlatIcon',
|
||||
category: 'ADMIN',
|
||||
description:
|
||||
'When enabled, View Variables will use getFlatIcon for icon previews. Warning: Increases load time.',
|
||||
component: CheckboxInput,
|
||||
};
|
||||
|
||||
export const ooccolor: Feature<string> = {
|
||||
name: 'OOC Color',
|
||||
category: 'ADMIN',
|
||||
|
||||
@@ -2166,6 +2166,7 @@
|
||||
#include "code\modules\asset_cache\assets\preferences.dm"
|
||||
#include "code\modules\asset_cache\assets\tgfont.dm"
|
||||
#include "code\modules\asset_cache\assets\tgui.dm"
|
||||
#include "code\modules\asset_cache\assets\vv.dm"
|
||||
#include "code\modules\asset_cache\assets\spritesheets\chat.dm"
|
||||
#include "code\modules\asset_cache\assets\spritesheets\chem_master.dm"
|
||||
#include "code\modules\asset_cache\assets\spritesheets\kitchen_recipes.dm"
|
||||
|
||||
Reference in New Issue
Block a user