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
This commit is contained in:
147
Content.Shared/Humanoid/Markings/MarkingColoring.cs
Normal file
147
Content.Shared/Humanoid/Markings/MarkingColoring.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user