MarkingColoring.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. using Robust.Shared.Utility;
  2. namespace Content.Shared.Humanoid.Markings;
  3. /// <summary>
  4. /// Default colors for marking
  5. /// </summary>
  6. [DataDefinition]
  7. public sealed partial class MarkingColors
  8. {
  9. /// <summary>
  10. /// Coloring properties that will be used on any unspecified layer
  11. /// </summary>
  12. [DataField("default", true)]
  13. public LayerColoringDefinition Default = new LayerColoringDefinition();
  14. /// <summary>
  15. /// Layers with their own coloring type and properties
  16. /// </summary>
  17. [DataField("layers", true)]
  18. public Dictionary<string, LayerColoringDefinition>? Layers;
  19. }
  20. public static class MarkingColoring
  21. {
  22. /// <summary>
  23. /// Returns list of colors for marking layers
  24. /// </summary>
  25. public static List<Color> GetMarkingLayerColors
  26. (
  27. MarkingPrototype prototype,
  28. Color? skinColor,
  29. Color? eyeColor,
  30. MarkingSet markingSet
  31. )
  32. {
  33. var colors = new List<Color>();
  34. // Coloring from default properties
  35. var defaultColor = prototype.Coloring.Default.GetColor(skinColor, eyeColor, markingSet);
  36. if (prototype.Coloring.Layers == null)
  37. {
  38. // If layers is not specified, then every layer must be default
  39. for (var i = 0; i < prototype.Sprites.Count; i++)
  40. {
  41. colors.Add(defaultColor);
  42. }
  43. return colors;
  44. }
  45. else
  46. {
  47. // If some layers are specified.
  48. for (var i = 0; i < prototype.Sprites.Count; i++)
  49. {
  50. // Getting layer name
  51. string? name = prototype.Sprites[i] switch
  52. {
  53. SpriteSpecifier.Rsi rsi => rsi.RsiState,
  54. SpriteSpecifier.Texture texture => texture.TexturePath.Filename,
  55. _ => null
  56. };
  57. if (name == null)
  58. {
  59. colors.Add(defaultColor);
  60. continue;
  61. }
  62. // All specified layers must be colored separately, all unspecified must depend on default coloring
  63. if (prototype.Coloring.Layers.TryGetValue(name, out var layerColoring))
  64. {
  65. var marking_color = layerColoring.GetColor(skinColor, eyeColor, markingSet);
  66. colors.Add(marking_color);
  67. }
  68. else
  69. {
  70. colors.Add(defaultColor);
  71. }
  72. }
  73. return colors;
  74. }
  75. }
  76. }
  77. /// <summary>
  78. /// A class that defines coloring type and fallback for markings
  79. /// </summary>
  80. [DataDefinition]
  81. public sealed partial class LayerColoringDefinition
  82. {
  83. [DataField("type")]
  84. public LayerColoringType? Type = new SkinColoring();
  85. /// <summary>
  86. /// Coloring types that will be used if main coloring type will return nil
  87. /// </summary>
  88. [DataField("fallbackTypes")]
  89. public List<LayerColoringType> FallbackTypes = new() {};
  90. /// <summary>
  91. /// Color that will be used if coloring type and fallback type will return nil
  92. /// </summary>
  93. [DataField("fallbackColor")]
  94. public Color FallbackColor = Color.White;
  95. public Color GetColor(Color? skin, Color? eyes, MarkingSet markingSet)
  96. {
  97. Color? color = null;
  98. if (Type != null)
  99. color = Type.GetColor(skin, eyes, markingSet);
  100. if (color == null)
  101. {
  102. foreach (var type in FallbackTypes)
  103. {
  104. color = type.GetColor(skin, eyes, markingSet);
  105. if (color != null) break;
  106. }
  107. }
  108. return color ?? FallbackColor;
  109. }
  110. }
  111. /// <summary>
  112. /// An abstract class for coloring types
  113. /// </summary>
  114. [ImplicitDataDefinitionForInheritors]
  115. public abstract partial class LayerColoringType
  116. {
  117. /// <summary>
  118. /// Makes output color negative
  119. /// </summary>
  120. [DataField("negative")]
  121. public bool Negative { get; private set; } = false;
  122. public abstract Color? GetCleanColor(Color? skin, Color? eyes, MarkingSet markingSet);
  123. public Color? GetColor(Color? skin, Color? eyes, MarkingSet markingSet)
  124. {
  125. var color = GetCleanColor(skin, eyes, markingSet);
  126. // Negative color
  127. if (color != null && Negative)
  128. {
  129. var rcolor = color.Value;
  130. rcolor.R = 1f-rcolor.R;
  131. rcolor.G = 1f-rcolor.G;
  132. rcolor.B = 1f-rcolor.B;
  133. return rcolor;
  134. }
  135. return color;
  136. }
  137. }