mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-31 00:58:26 +01:00
Adds icon state configuration to GAS (#58487)
Relatively simple change that allows you to specify icon states in greyscale config so as to allow generating icon files with multiple states. This is a requisite for GAS to work with icon smoothing. Also a couple bits of additional warnings and documentation.
This commit is contained in:
@@ -29,7 +29,7 @@ The json is made up of some metadata and a list of layers used while creating th
|
||||
|
||||
```json
|
||||
{
|
||||
"layers": [
|
||||
"icon_state_name": [
|
||||
{
|
||||
"type": "reference",
|
||||
"reference_type": "/datum/greyscale_config/some_other_config",
|
||||
@@ -61,6 +61,8 @@ The last layer is another reference type. Note that you don't need to give color
|
||||
|
||||
"blend_mode" and "color_ids" are special, all layer types have them. The blend mode is what controls how that layer's finished product gets merged together with the rest of the sprite. The color ids control what colors are passed in to the layer.
|
||||
|
||||
Once it is done generating it will be placed in an icon file with the icon state of "icon_state_name". You can use any name you like here.
|
||||
|
||||
## Dmi File
|
||||
|
||||
There are no special requirements from the dmi file to work with this system. You just need to specify the icon file in code and the icon_state in the json configuration.
|
||||
@@ -88,4 +90,4 @@ More configurations can be found in [code/datums/greyscale/greyscale_configs.dm]
|
||||
|
||||
## Debugging
|
||||
|
||||
If you're making a new greyscale sprite you sometimes want to be able to see how layers got generated or maybe you're just tweaking some colors. Rather than rebooting the server with every change there is a greyscale modification menu that can be found in the vv dropdown menu for the greyscale object. Here you can change colors and preview the results.
|
||||
If you're making a new greyscale sprite you sometimes want to be able to see how layers got generated or maybe you're just tweaking some colors. Rather than rebooting the server with every change there is a greyscale modification menu that can be found in the vv dropdown menu for the greyscale object. Here you can change colors, preview the results, and reload everything from their files.
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
/// String path to the icon file, used for reloading
|
||||
var/string_icon_file
|
||||
|
||||
/// Layer objects that the sprite is made up of
|
||||
var/list/layers
|
||||
/// A list of icon states and their layers
|
||||
var/list/icon_states
|
||||
|
||||
/// How many colors are expected to be given when building the sprite
|
||||
var/expected_colors = 0
|
||||
@@ -40,10 +40,13 @@
|
||||
json_config = file(string_json_config)
|
||||
icon_file = file(string_icon_file)
|
||||
|
||||
icon_states = list()
|
||||
|
||||
var/list/raw = json_decode(file2text(json_config))
|
||||
layers = ReadLayersFromJson(raw["layers"])
|
||||
if(!length(layers))
|
||||
CRASH("The json configuration [DebugName()] is missing any layers.")
|
||||
ReadIconStateConfiguration(raw)
|
||||
|
||||
if(!length(icon_states))
|
||||
CRASH("The json configuration [DebugName()] is missing any icon_states.")
|
||||
|
||||
icon_cache = list()
|
||||
|
||||
@@ -53,6 +56,17 @@
|
||||
/datum/greyscale_config/proc/DebugName()
|
||||
return "([icon_file]|[json_config])"
|
||||
|
||||
/// Takes the json icon state configuration and puts it into a more processed format
|
||||
/datum/greyscale_config/proc/ReadIconStateConfiguration(list/data)
|
||||
for(var/state in data)
|
||||
var/list/raw_layers = data[state]
|
||||
if(!length(raw_layers))
|
||||
stack_trace("The json configuration [DebugName()] for icon state '[state]' is missing any layers.")
|
||||
continue
|
||||
if(icon_states[state])
|
||||
stack_trace("The json configuration [DebugName()] has a duplicate icon state '[state]' and is being overriden.")
|
||||
icon_states[state] = ReadLayersFromJson(raw_layers)
|
||||
|
||||
/// Takes the json layers configuration and puts it into a more processed format
|
||||
/datum/greyscale_config/proc/ReadLayersFromJson(list/data)
|
||||
var/list/output = ReadLayerGroup(data)
|
||||
@@ -74,7 +88,9 @@
|
||||
/// Reads layer configurations to take out some useful overall information
|
||||
/datum/greyscale_config/proc/ReadMetadata()
|
||||
var/list/datum/greyscale_layer/all_layers = list()
|
||||
var/list/to_process = list(layers)
|
||||
var/list/to_process = list()
|
||||
for(var/state in icon_states)
|
||||
to_process += icon_states[state]
|
||||
while(length(to_process))
|
||||
var/current = to_process[length(to_process)]
|
||||
to_process.len--
|
||||
@@ -91,21 +107,24 @@
|
||||
expected_colors = length(color_groups)
|
||||
|
||||
/// Actually create the icon and color it in, handles caching
|
||||
/datum/greyscale_config/proc/Generate(color_string)
|
||||
/datum/greyscale_config/proc/Generate(color_string, list/render_steps)
|
||||
var/key = color_string
|
||||
var/icon/new_icon = icon_cache[key]
|
||||
if(new_icon)
|
||||
if(new_icon && !render_steps)
|
||||
return icon(new_icon)
|
||||
var/list/colors = ParseColorString(color_string)
|
||||
if(length(colors) != expected_colors)
|
||||
CRASH("[DebugName()] expected [expected_colors] color arguments but only received [length(colors)]")
|
||||
new_icon = GenerateLayerGroup(colors, layers)
|
||||
// We read a pixel to force the icon to be fully generated before we let it loose into the world
|
||||
// I hate this
|
||||
new_icon.GetPixel(1, 1)
|
||||
new_icon = fcopy_rsc(new_icon)
|
||||
icon_cache[key] = new_icon
|
||||
return icon(new_icon)
|
||||
var/icon/icon_bundle = new
|
||||
for(var/icon_state in icon_states)
|
||||
var/icon/generated_icon = GenerateLayerGroup(colors, icon_states[icon_state], render_steps)
|
||||
// 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)
|
||||
icon_bundle.Insert(generated_icon, icon_state)
|
||||
icon_bundle = fcopy_rsc(icon_bundle)
|
||||
icon_cache[key] = icon_bundle
|
||||
return icon(icon_bundle)
|
||||
|
||||
/// Internal recursive proc to handle nested layer groups
|
||||
/datum/greyscale_config/proc/GenerateLayerGroup(list/colors, list/group, list/render_steps)
|
||||
@@ -125,20 +144,15 @@
|
||||
|
||||
// These are so we can see the result of every step of the process in the preview ui
|
||||
if(render_steps)
|
||||
var/icon/new_icon_copy = new(new_icon)
|
||||
var/icon/layer_icon_copy = new(layer_icon)
|
||||
render_steps[layer_icon_copy] = icon(new_icon_copy)
|
||||
render_steps[image(new_icon)] = image(layer_icon)
|
||||
return new_icon
|
||||
|
||||
/datum/greyscale_config/proc/GenerateDebug(list/colors)
|
||||
if(length(colors) != expected_colors)
|
||||
CRASH("[DebugName()] expected [expected_colors] color arguments but only received [length(colors)]")
|
||||
|
||||
/datum/greyscale_config/proc/GenerateDebug(colors)
|
||||
var/list/output = list()
|
||||
var/list/debug_steps = list()
|
||||
output["steps"] = debug_steps
|
||||
|
||||
output["icon"] = GenerateLayerGroup(colors, layers, debug_steps)
|
||||
output["icon"] = Generate(colors, debug_steps)
|
||||
return output
|
||||
|
||||
/datum/greyscale_config/proc/ParseColorString(color_string)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"layers": [
|
||||
"": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "base",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"layers": [
|
||||
"": [
|
||||
{
|
||||
"type": "reference",
|
||||
"reference_type": "/datum/greyscale_config/canister/base",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"layers": [
|
||||
"": [
|
||||
{
|
||||
"type": "reference",
|
||||
"reference_type": "/datum/greyscale_config/canister/base",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"layers": [
|
||||
"": [
|
||||
{
|
||||
"type": "reference",
|
||||
"reference_type": "/datum/greyscale_config/canister/base",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"layers": [
|
||||
"": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "outline",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"layers": [
|
||||
"": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "can_base",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"layers": [
|
||||
"": [
|
||||
{
|
||||
"type": "reference",
|
||||
"reference_type": "/datum/greyscale_config/canister/base",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"layers": [
|
||||
"": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "cutters",
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
|
||||
/datum/greyscale_layer/New(icon_file, list/json_data)
|
||||
color_ids = json_data["color_ids"]
|
||||
for(var/i in color_ids)
|
||||
if(!isnum(i))
|
||||
CRASH("Color ids must be a positive integer starting from 1, '[i]' is not valid. Make sure it is not quoted in the json configuration.")
|
||||
blend_mode = blend_modes[lowertext(json_data["blend_mode"])]
|
||||
if(isnull(blend_mode))
|
||||
CRASH("Greyscale config for [icon_file] is missing a blend mode on a layer.")
|
||||
@@ -26,7 +29,7 @@
|
||||
processed_colors += colors[i]
|
||||
return InternalGenerate(processed_colors, render_steps)
|
||||
|
||||
/datum/greyscale_layer/proc/InternalGenerate(list/colors)
|
||||
/datum/greyscale_layer/proc/InternalGenerate(list/colors, list/render_steps)
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Subtypes
|
||||
@@ -66,9 +69,4 @@
|
||||
CRASH("An unknown greyscale configuration was given to a reference layer: [json_data["reference_type"]]")
|
||||
|
||||
/datum/greyscale_layer/reference/InternalGenerate(list/colors, list/render_steps)
|
||||
if(render_steps)
|
||||
// We're debugging
|
||||
var/list/debug_data = reference_config.GenerateDebug(colors)
|
||||
render_steps += debug_data["steps"]
|
||||
return debug_data["icon"]
|
||||
return reference_config.Generate(colors.Join())
|
||||
return reference_config.Generate(colors.Join(), render_steps)
|
||||
|
||||
@@ -83,10 +83,11 @@
|
||||
split_colors += "#[raw_colors[i]]"
|
||||
|
||||
/datum/greyscale_modify_menu/proc/refresh_preview()
|
||||
var/list/data = SSgreyscale.configurations["[target.greyscale_config]"].GenerateDebug(split_colors)
|
||||
var/list/data = SSgreyscale.configurations["[target.greyscale_config]"].GenerateDebug(split_colors.Join())
|
||||
|
||||
sprite_data = list()
|
||||
var/list/steps = list()
|
||||
sprite_data["steps"] = steps
|
||||
for(var/step in data["steps"])
|
||||
CHECK_TICK
|
||||
steps += list(list("layer"=icon2html(data["steps"][step], user, sourceonly=TRUE), "result"=icon2html(step, user, sourceonly=TRUE)))
|
||||
|
||||
Reference in New Issue
Block a user