* 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
147 lines
4.4 KiB
C#
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;
|
|
}
|
|
} |