Files
tbd-station-14/Content.Shared/Humanoid/Markings/MarkingColoring.cs
csqrb 8b3d7728d7 Marking default coloring (#13039)
* Marking coloring WIP

* EnsureDefault now supports coloring!

* Now markings have coloring when they get added

* Many things

* yml files

* cleanup

* Some requested changes

* Nullable type and WIP caching

* Time to resolve that thing with deprecated hair fields

* Latest reviews + im still trying to use these hair markings

* FirstOrDefault thing and Tattoo docs

* IDK

* It's now works a bit more properly in preferences GUI

* THEY SYNCING! However preferences GUI still broken and doesn't work properly

* Markings now updating when changing in GUI. However they still don't work properly with bald humanoids

* Forgor...

* Default hair-colored markings will not color to hair if there is no hair

* Fixed default colors for customizable markings

* Fixed bug in prefs GUI that set current hair to null

* Now markings that must match skin color because of limb (e.x. Slimes) - will match skin color

* final tweaks: if hair uses skin color then markings will use skin color as hair color (slimes)

* fix

* fixed dirty. no more funni invis bug

* Mirrors and client profile loading

* default colors soon TM

* review + better coloring

* Hardcode is gone

* diona markings

* oh my god

* fixed CategoryColoring

* cool fallback, clean up and some other tweaks

* code style

* more style

* a
2023-03-04 18:59:07 -08:00

147 lines
4.4 KiB
C#

using Robust.Shared.Utility;
namespace Content.Shared.Humanoid.Markings;
/// <summary>
/// Default colors for marking
/// </summary>
[DataDefinition]
public sealed class MarkingColors
{
/// <summary>
/// Coloring properties that will be used on any unspecified layer
/// </summary>
[DataField("default", true)]
public LayerColoringDefinition Default = new LayerColoringDefinition();
/// <summary>
/// Layers with their own coloring type and properties
/// </summary>
[DataField("layers", true)]
public Dictionary<string, LayerColoringDefinition>? Layers;
}
public static class MarkingColoring
{
/// <summary>
/// Returns list of colors for marking layers
/// </summary>
public static List<Color> GetMarkingLayerColors
(
MarkingPrototype prototype,
Color? skinColor,
Color? eyeColor,
MarkingSet markingSet
)
{
var colors = new List<Color>();
// 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;
}
}
}
/// <summary>
/// A class that defines coloring type and fallback for markings
/// </summary>
[DataDefinition]
public sealed class LayerColoringDefinition
{
[DataField("type")]
public LayerColoringType Type = new SkinColoring();
/// <summary>
/// Coloring types that will be used if main coloring type will return nil
/// </summary>
[DataField("fallbackTypes")]
public List<LayerColoringType> FallbackTypes = new() {};
/// <summary>
/// Color that will be used if coloring type and fallback type will return nil
/// </summary>
[DataField("fallbackColor")]
public Color FallbackColor = Color.White;
public Color GetColor(Color? skin, Color? eyes, MarkingSet markingSet)
{
var 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;
}
}
/// <summary>
/// An abstract class for coloring types
/// </summary>
[ImplicitDataDefinitionForInheritors]
public abstract class LayerColoringType
{
/// <summary>
/// Makes output color negative
/// </summary>
[DataField("negative")]
public bool Negative { get; } = 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;
}
}