Adds a color matrix layer to GAGS (#63957)

* Adds a color matrix layer to GAGS

* Fixes default row value

* Passes along the last viable icon for color matrix use

* Removes stray nocache reference
This commit is contained in:
Emmett Gaines
2022-01-13 15:44:57 -05:00
committed by GitHub
parent dd5622ad68
commit fdeca47f6d
3 changed files with 52 additions and 16 deletions
+7 -7
View File
@@ -231,20 +231,20 @@
fcopy(icon_output, "tmp/gags_debug_output.dmi")
/// Actually create the icon and color it in, handles caching
/datum/greyscale_config/proc/Generate(color_string)
/datum/greyscale_config/proc/Generate(color_string, icon/last_external_icon)
var/key = color_string
var/icon/new_icon = icon_cache[key]
if(new_icon)
return icon(new_icon)
var/icon/icon_bundle = GenerateBundle(color_string)
var/icon/icon_bundle = GenerateBundle(color_string, last_external_icon=last_external_icon)
icon_bundle = fcopy_rsc(icon_bundle)
icon_cache[key] = icon_bundle
var/icon/output = icon(icon_bundle)
return output
/// Handles the actual icon manipulation to create the spritesheet
/datum/greyscale_config/proc/GenerateBundle(list/colors, list/render_steps)
/datum/greyscale_config/proc/GenerateBundle(list/colors, list/render_steps, icon/last_external_icon)
if(!istype(colors))
colors = SSgreyscale.ParseColorString(colors)
if(length(colors) != expected_colors)
@@ -255,7 +255,7 @@
var/list/icon_state_steps
if(render_steps)
icon_state_steps = render_steps[icon_state] = list()
var/icon/generated_icon = GenerateLayerGroup(colors, icon_states[icon_state], icon_state_steps)
var/icon/generated_icon = GenerateLayerGroup(colors, icon_states[icon_state], icon_state_steps, last_external_icon)
// We read a pixel to force the icon to be fully generated before we let it loose into the world
// I hate this
generated_icon.GetPixel(1, 1)
@@ -271,15 +271,15 @@
return icon_bundle
/// Internal recursive proc to handle nested layer groups
/datum/greyscale_config/proc/GenerateLayerGroup(list/colors, list/group, list/render_steps)
/datum/greyscale_config/proc/GenerateLayerGroup(list/colors, list/group, list/render_steps, icon/last_external_icon)
var/icon/new_icon
for(var/datum/greyscale_layer/layer as anything in group)
var/icon/layer_icon
if(islist(layer))
layer_icon = GenerateLayerGroup(colors, layer, render_steps)
layer_icon = GenerateLayerGroup(colors, layer, render_steps, new_icon || last_external_icon)
layer = layer[1] // When there are multiple layers in a group like this we use the first one's blend mode
else
layer_icon = layer.Generate(colors, render_steps)
layer_icon = layer.Generate(colors, render_steps, new_icon || last_external_icon)
if(!new_icon)
new_icon = layer_icon
+21
View File
@@ -31,6 +31,27 @@
new_values += new_value
return new_values
/datum/json_reader/color_matrix/ReadJson(list/value)
if(!istype(value))
CRASH("Expected a list but got [value]")
if(length(value) > 5 || length(value) < 4)
CRASH("Color matrix must contain 4 or 5 rows")
var/list/new_values = list()
for(var/list/row in value)
var/list/interpreted_row = list()
if(!istype(row) || length(row) != 4)
stack_trace("Expected list to contain further row lists with exactly 4 entries")
interpreted_row = list(0, 0, 0, 0)
continue
for(var/number in row)
if(!isnum(number))
stack_trace("Each color matrix row must only contain numbers")
interpreted_row += 0
else
interpreted_row += number
new_values += interpreted_row
return new_values
/datum/json_reader/blend_mode
var/static/list/blend_modes = list(
"add" = ICON_ADD,
+24 -9
View File
@@ -66,18 +66,19 @@
/// Used to actualy create the layer using the given colors
/// Do not override, use InternalGenerate instead
/datum/greyscale_layer/proc/Generate(list/colors, list/render_steps)
/datum/greyscale_layer/proc/Generate(list/colors, list/render_steps, icon/new_icon)
var/list/processed_colors = list()
for(var/i in color_ids)
if(isnum(i))
processed_colors += colors[i]
else
processed_colors += i
return InternalGenerate(processed_colors, render_steps)
var/icon/copy_of_new_icon = icon(new_icon) // Layers shouldn't be modifying it directly, this is just for them to reference
return InternalGenerate(processed_colors, render_steps, copy_of_new_icon)
/// Override this to implement layers.
/// The colors var will only contain colors that this layer is configured to use.
/datum/greyscale_layer/proc/InternalGenerate(list/colors, list/render_steps)
/datum/greyscale_layer/proc/InternalGenerate(list/colors, list/render_steps, icon/new_icon)
////////////////////////////////////////////////////////
// Subtypes
@@ -103,11 +104,25 @@
. = ..()
required_values[NAMEOF(src, icon_state)] = /datum/json_reader/text
/datum/greyscale_layer/icon_state/InternalGenerate(list/colors, list/render_steps)
/datum/greyscale_layer/icon_state/InternalGenerate(list/colors, list/render_steps, icon/new_icon)
. = ..()
var/icon/new_icon = icon(icon)
var/icon/generated_icon = icon(icon)
if(length(colors))
new_icon.Blend(colors[1], ICON_MULTIPLY)
generated_icon.Blend(colors[1], ICON_MULTIPLY)
return generated_icon
/// A layer to modify the previous layer's colors with a color matrix
/datum/greyscale_layer/color_matrix
layer_type = "color_matrix"
var/list/color_matrix
/datum/greyscale_layer/color_matrix/GetExpectedValues(list/required_values, list/optional_values)
. = ..()
required_values[NAMEOF(src, color_matrix)] = /datum/json_reader/color_matrix
/datum/greyscale_layer/color_matrix/InternalGenerate(list/colors, list/render_steps, icon/new_icon)
. = ..()
new_icon.MapColors(arglist(color_matrix))
return new_icon
/// A layer created by using another greyscale icon's configuration
@@ -130,12 +145,12 @@
if(!reference_type.icon_states[icon_state])
CRASH("[src] expects icon_state '[icon_state]' but referenced configuration '[reference_type]' does not have it.")
/datum/greyscale_layer/reference/InternalGenerate(list/colors, list/render_steps)
/datum/greyscale_layer/reference/InternalGenerate(list/colors, list/render_steps, icon/new_icon)
var/icon/generated_icon
if(render_steps)
var/list/reference_data = list()
generated_icon = reference_type.GenerateBundle(colors, reference_data)
generated_icon = reference_type.GenerateBundle(colors, reference_data, new_icon)
render_steps += reference_data[icon_state]
else
generated_icon = reference_type.Generate(colors.Join())
generated_icon = reference_type.Generate(colors.Join(), new_icon)
return icon(generated_icon, icon_state)