ProgressColorSystem.cs 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. using Content.Shared.CCVar;
  2. using Robust.Shared.Configuration;
  3. namespace Content.Client.UserInterface.Systems;
  4. /// <summary>
  5. /// This system handles getting an interpolated color based on the value of a cvar.
  6. /// </summary>
  7. public sealed class ProgressColorSystem : EntitySystem
  8. {
  9. [Dependency] private readonly IConfigurationManager _configuration = default!;
  10. private bool _colorBlindFriendly;
  11. private static readonly Color[] Plasma =
  12. {
  13. new(240, 249, 33),
  14. new(248, 149, 64),
  15. new(204, 71, 120),
  16. new(126, 3, 168),
  17. new(13, 8, 135)
  18. };
  19. /// <inheritdoc/>
  20. public override void Initialize()
  21. {
  22. Subs.CVar(_configuration, CCVars.AccessibilityColorblindFriendly, OnColorBlindFriendlyChanged, true);
  23. }
  24. private void OnColorBlindFriendlyChanged(bool value, in CVarChangeInfo info)
  25. {
  26. _colorBlindFriendly = value;
  27. }
  28. public Color GetProgressColor(float progress)
  29. {
  30. if (!_colorBlindFriendly)
  31. {
  32. if (progress >= 1.0f)
  33. {
  34. return new Color(0f, 1f, 0f);
  35. }
  36. // lerp
  37. var hue = 5f / 18f * progress;
  38. return Color.FromHsv((hue, 1f, 0.75f, 1f));
  39. }
  40. return InterpolateColorGaussian(Plasma, progress);
  41. }
  42. /// <summary>
  43. /// Interpolates between multiple colors based on a gaussian distribution.
  44. /// Taken from https://stackoverflow.com/a/26103117
  45. /// </summary>
  46. public static Color InterpolateColorGaussian(Color[] colors, double x)
  47. {
  48. double r = 0.0, g = 0.0, b = 0.0;
  49. var total = 0f;
  50. var step = 1.0 / (colors.Length - 1);
  51. var mu = 0.0;
  52. const double sigma2 = 0.035;
  53. foreach(var color in colors)
  54. {
  55. var percent = Math.Exp(-(x - mu) * (x - mu) / (2.0 * sigma2)) / Math.Sqrt(2.0 * Math.PI * sigma2);
  56. total += (float) percent;
  57. mu += step;
  58. r += color.R * percent;
  59. g += color.G * percent;
  60. b += color.B * percent;
  61. }
  62. return new Color((float) r / total, (float) g / total, (float) b / total);
  63. }
  64. }