using Robust.Shared.Utility; namespace Content.Shared.Humanoid.Markings; /// /// Default colors for marking /// [DataDefinition] public sealed partial class MarkingColors { /// /// Coloring properties that will be used on any unspecified layer /// [DataField("default", true)] public LayerColoringDefinition Default = new LayerColoringDefinition(); /// /// Layers with their own coloring type and properties /// [DataField("layers", true)] public Dictionary? Layers; } public static class MarkingColoring { /// /// Returns list of colors for marking layers /// public static List GetMarkingLayerColors( MarkingPrototype prototype, Color? skinColor, Color? eyeColor, MarkingSet markingSet, List? ignores = null // Floof ) { var colors = new List(); // Coloring from default properties var defaultColor = prototype.Coloring.Default.GetColor(skinColor, eyeColor, markingSet); if (prototype.Coloring.Layers == null) { // If layers is not specified, then every layer must be default for (var i = 0; i < prototype.Sprites.Count; i++) { colors.Add(defaultColor); } return colors; } else { // If some layers are specified. for (var i = 0; i < prototype.Sprites.Count; i++) { // Getting layer name string? name = prototype.Sprites[i] switch { SpriteSpecifier.Rsi rsi => rsi.RsiState, SpriteSpecifier.Texture texture => texture.TexturePath.Filename, _ => null }; if (name == null) { colors.Add(defaultColor); continue; } // All specified layers must be colored separately, all unspecified must depend on default coloring if (prototype.Coloring.Layers.TryGetValue(name, out var layerColoring)) { var marking_color = layerColoring.GetColor(skinColor, eyeColor, markingSet); colors.Add(marking_color); } else { colors.Add(defaultColor); } } return colors; } } } /// /// A class that defines coloring type and fallback for markings /// [DataDefinition] public sealed partial class LayerColoringDefinition { [DataField("type")] public LayerColoringType? Type = new SkinColoring(); /// /// Coloring types that will be used if main coloring type will return nil /// [DataField("fallbackTypes")] public List FallbackTypes = new() {}; /// /// Color that will be used if coloring type and fallback type will return nil /// [DataField("fallbackColor")] public Color FallbackColor = Color.White; public Color GetColor(Color? skin, Color? eyes, MarkingSet markingSet) { Color? color = null; if (Type != null) color = Type.GetColor(skin, eyes, markingSet); if (color == null) { foreach (var type in FallbackTypes) { color = type.GetColor(skin, eyes, markingSet); if (color != null) break; } } return color ?? FallbackColor; } } /// /// An abstract class for coloring types /// [ImplicitDataDefinitionForInheritors] public abstract partial class LayerColoringType { /// /// Makes output color negative /// [DataField("negative")] public bool Negative { get; private set; } = false; public abstract Color? GetCleanColor(Color? skin, Color? eyes, MarkingSet markingSet); public Color? GetColor(Color? skin, Color? eyes, MarkingSet markingSet) { var color = GetCleanColor(skin, eyes, markingSet); // Negative color if (color != null && Negative) { var rcolor = color.Value; rcolor.R = 1f-rcolor.R; rcolor.G = 1f-rcolor.G; rcolor.B = 1f-rcolor.B; return rcolor; } return color; } }