Add a toggle for colorblind friendly progress bar colors (#25318)
* Add a toggle for progress bar colors * yeah this thing * PJB review * optimization
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
using System.Numerics;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Client.UserInterface.Systems;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
@@ -18,6 +18,7 @@ public sealed class DoAfterOverlay : Overlay
|
||||
private readonly IPlayerManager _player;
|
||||
private readonly SharedTransformSystem _transform;
|
||||
private readonly MetaDataSystem _meta;
|
||||
private readonly ProgressColorSystem _progressColor;
|
||||
|
||||
private readonly Texture _barTexture;
|
||||
private readonly ShaderInstance _shader;
|
||||
@@ -40,6 +41,7 @@ public sealed class DoAfterOverlay : Overlay
|
||||
_player = player;
|
||||
_transform = _entManager.EntitySysManager.GetEntitySystem<SharedTransformSystem>();
|
||||
_meta = _entManager.EntitySysManager.GetEntitySystem<MetaDataSystem>();
|
||||
_progressColor = _entManager.System<ProgressColorSystem>();
|
||||
var sprite = new SpriteSpecifier.Rsi(new("/Textures/Interface/Misc/progress_bar.rsi"), "icon");
|
||||
_barTexture = _entManager.EntitySysManager.GetEntitySystem<SpriteSystem>().Frame0(sprite);
|
||||
|
||||
@@ -125,7 +127,7 @@ public sealed class DoAfterOverlay : Overlay
|
||||
elapsedRatio = (float) Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
|
||||
var cancelElapsed = (time - doAfter.CancelledTime.Value).TotalSeconds;
|
||||
var flash = Math.Floor(cancelElapsed / FlashTime) % 2 == 0;
|
||||
color = new Color(1f, 0f, 0f, flash ? alpha : 0f);
|
||||
color = GetProgressColor(0, flash ? alpha : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -146,14 +148,8 @@ public sealed class DoAfterOverlay : Overlay
|
||||
handle.SetTransform(Matrix3.Identity);
|
||||
}
|
||||
|
||||
public static Color GetProgressColor(float progress, float alpha = 1f)
|
||||
public Color GetProgressColor(float progress, float alpha = 1f)
|
||||
{
|
||||
if (progress >= 1.0f)
|
||||
{
|
||||
return new Color(0f, 1f, 0f, alpha);
|
||||
}
|
||||
// lerp
|
||||
var hue = (5f / 18f) * progress;
|
||||
return Color.FromHsv((hue, 1f, 0.75f, alpha));
|
||||
return _progressColor.GetProgressColor(progress).WithAlpha(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
xmlns:xNamespace="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="clr-namespace:Content.Client.Stylesheets">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<ScrollContainer VerticalExpand="True" HorizontalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" Margin="8 8 8 8" VerticalExpand="True">
|
||||
<Label Text="{Loc 'ui-options-general-ui-style'}"
|
||||
FontColorOverride="{xNamespace:Static s:StyleNano.NanoGold}"
|
||||
@@ -23,6 +24,7 @@
|
||||
StyleClasses="LabelKeyText"/>
|
||||
<CheckBox Name="ReducedMotionCheckBox" Text="{Loc 'ui-options-reduced-motion'}" />
|
||||
<CheckBox Name="EnableColorNameCheckBox" Text="{Loc 'ui-options-enable-color-name'}" />
|
||||
<CheckBox Name="ColorblindFriendlyCheckBox" Text="{Loc 'ui-options-colorblind-friendly'}" />
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Label Text="{Loc 'ui-options-screen-shake-intensity'}" Margin="8 0" />
|
||||
<Slider Name="ScreenShakeIntensitySlider"
|
||||
@@ -53,8 +55,8 @@
|
||||
<CheckBox Name="OpaqueStorageWindowCheckBox" Text="{Loc 'ui-options-opaque-storage-window'}" />
|
||||
<CheckBox Name="StaticStorageUI" Text="{Loc 'ui-options-static-storage-ui'}" />
|
||||
<!-- <CheckBox Name="ToggleWalk" Text="{Loc 'ui-options-hotkey-toggle-walk'}" /> -->
|
||||
|
||||
</BoxContainer>
|
||||
</ScrollContainer>
|
||||
<controls:StripeBack HasBottomEdge="False" HasMargins="False">
|
||||
<Button Name="ApplyButton"
|
||||
Text="{Loc 'ui-options-apply'}"
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace Content.Client.Options.UI.Tabs
|
||||
FancySpeechBubblesCheckBox.OnToggled += OnCheckBoxToggled;
|
||||
FancyNameBackgroundsCheckBox.OnToggled += OnCheckBoxToggled;
|
||||
EnableColorNameCheckBox.OnToggled += OnCheckBoxToggled;
|
||||
ColorblindFriendlyCheckBox.OnToggled += OnCheckBoxToggled;
|
||||
ReducedMotionCheckBox.OnToggled += OnCheckBoxToggled;
|
||||
ScreenShakeIntensitySlider.OnValueChanged += OnScreenShakeIntensitySliderChanged;
|
||||
// ToggleWalk.OnToggled += OnCheckBoxToggled;
|
||||
@@ -78,6 +79,7 @@ namespace Content.Client.Options.UI.Tabs
|
||||
FancySpeechBubblesCheckBox.Pressed = _cfg.GetCVar(CCVars.ChatEnableFancyBubbles);
|
||||
FancyNameBackgroundsCheckBox.Pressed = _cfg.GetCVar(CCVars.ChatFancyNameBackground);
|
||||
EnableColorNameCheckBox.Pressed = _cfg.GetCVar(CCVars.ChatEnableColorName);
|
||||
ColorblindFriendlyCheckBox.Pressed = _cfg.GetCVar(CCVars.AccessibilityColorblindFriendly);
|
||||
ReducedMotionCheckBox.Pressed = _cfg.GetCVar(CCVars.ReducedMotion);
|
||||
ScreenShakeIntensitySlider.Value = _cfg.GetCVar(CCVars.ScreenShakeIntensity) * 100f;
|
||||
// ToggleWalk.Pressed = _cfg.GetCVar(CCVars.ToggleWalk);
|
||||
@@ -123,6 +125,7 @@ namespace Content.Client.Options.UI.Tabs
|
||||
_cfg.SetCVar(CCVars.ChatEnableFancyBubbles, FancySpeechBubblesCheckBox.Pressed);
|
||||
_cfg.SetCVar(CCVars.ChatFancyNameBackground, FancyNameBackgroundsCheckBox.Pressed);
|
||||
_cfg.SetCVar(CCVars.ChatEnableColorName, EnableColorNameCheckBox.Pressed);
|
||||
_cfg.SetCVar(CCVars.AccessibilityColorblindFriendly, ColorblindFriendlyCheckBox.Pressed);
|
||||
_cfg.SetCVar(CCVars.ReducedMotion, ReducedMotionCheckBox.Pressed);
|
||||
_cfg.SetCVar(CCVars.ScreenShakeIntensity, ScreenShakeIntensitySlider.Value / 100f);
|
||||
// _cfg.SetCVar(CCVars.ToggleWalk, ToggleWalk.Pressed);
|
||||
@@ -149,6 +152,7 @@ namespace Content.Client.Options.UI.Tabs
|
||||
var isFancyChatSame = FancySpeechBubblesCheckBox.Pressed == _cfg.GetCVar(CCVars.ChatEnableFancyBubbles);
|
||||
var isFancyBackgroundSame = FancyNameBackgroundsCheckBox.Pressed == _cfg.GetCVar(CCVars.ChatFancyNameBackground);
|
||||
var isEnableColorNameSame = EnableColorNameCheckBox.Pressed == _cfg.GetCVar(CCVars.ChatEnableColorName);
|
||||
var isColorblindFriendly = ColorblindFriendlyCheckBox.Pressed == _cfg.GetCVar(CCVars.AccessibilityColorblindFriendly);
|
||||
var isReducedMotionSame = ReducedMotionCheckBox.Pressed == _cfg.GetCVar(CCVars.ReducedMotion);
|
||||
var isScreenShakeIntensitySame = Math.Abs(ScreenShakeIntensitySlider.Value / 100f - _cfg.GetCVar(CCVars.ScreenShakeIntensity)) < 0.01f;
|
||||
// var isToggleWalkSame = ToggleWalk.Pressed == _cfg.GetCVar(CCVars.ToggleWalk);
|
||||
@@ -164,6 +168,7 @@ namespace Content.Client.Options.UI.Tabs
|
||||
isFancyChatSame &&
|
||||
isFancyBackgroundSame &&
|
||||
isEnableColorNameSame &&
|
||||
isColorblindFriendly &&
|
||||
isReducedMotionSame &&
|
||||
isScreenShakeIntensitySame &&
|
||||
// isToggleWalkSame &&
|
||||
|
||||
@@ -8,6 +8,8 @@ using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using System.Numerics;
|
||||
using Content.Shared.StatusIcon.Components;
|
||||
using Content.Client.UserInterface.Systems;
|
||||
using Robust.Shared.Prototypes;
|
||||
using static Robust.Shared.Maths.Color;
|
||||
|
||||
namespace Content.Client.Overlays;
|
||||
@@ -17,19 +19,25 @@ namespace Content.Client.Overlays;
|
||||
/// </summary>
|
||||
public sealed class EntityHealthBarOverlay : Overlay
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
private readonly IEntityManager _entManager;
|
||||
private readonly SharedTransformSystem _transform;
|
||||
private readonly MobStateSystem _mobStateSystem;
|
||||
private readonly MobThresholdSystem _mobThresholdSystem;
|
||||
private readonly ProgressColorSystem _progressColor;
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
|
||||
public HashSet<string> DamageContainers = new();
|
||||
private readonly ShaderInstance _shader;
|
||||
|
||||
public EntityHealthBarOverlay(IEntityManager entManager)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_entManager = entManager;
|
||||
_transform = _entManager.EntitySysManager.GetEntitySystem<SharedTransformSystem>();
|
||||
_mobStateSystem = _entManager.EntitySysManager.GetEntitySystem<MobStateSystem>();
|
||||
_mobThresholdSystem = _entManager.EntitySysManager.GetEntitySystem<MobThresholdSystem>();
|
||||
_transform = _entManager.System<SharedTransformSystem>();
|
||||
_mobStateSystem = _entManager.System<MobStateSystem>();
|
||||
_mobThresholdSystem = _entManager.System<MobThresholdSystem>();
|
||||
_progressColor = _entManager.System<ProgressColorSystem>();
|
||||
_shader = _prototype.Index<ShaderPrototype>("unshaded").Instance();
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
@@ -42,6 +50,8 @@ public sealed class EntityHealthBarOverlay : Overlay
|
||||
var scaleMatrix = Matrix3.CreateScale(new Vector2(scale, scale));
|
||||
var rotationMatrix = Matrix3.CreateRotation(-rotation);
|
||||
|
||||
handle.UseShader(_shader);
|
||||
|
||||
var query = _entManager.AllEntityQueryEnumerator<MobThresholdsComponent, MobStateComponent, DamageableComponent, SpriteComponent>();
|
||||
while (query.MoveNext(out var uid,
|
||||
out var mobThresholdsComponent,
|
||||
@@ -147,26 +157,11 @@ public sealed class EntityHealthBarOverlay : Overlay
|
||||
return (0, true);
|
||||
}
|
||||
|
||||
public static Color GetProgressColor(float progress, bool crit)
|
||||
public Color GetProgressColor(float progress, bool crit)
|
||||
{
|
||||
if (progress >= 1.0f)
|
||||
{
|
||||
return SeaBlue;
|
||||
}
|
||||
if (crit)
|
||||
progress = 0;
|
||||
|
||||
if (!crit)
|
||||
{
|
||||
switch (progress)
|
||||
{
|
||||
case > 0.90F:
|
||||
return SeaBlue;
|
||||
case > 0.50F:
|
||||
return Violet;
|
||||
case > 0.15F:
|
||||
return Ruber;
|
||||
}
|
||||
}
|
||||
|
||||
return VividGamboge;
|
||||
return _progressColor.GetProgressColor(progress);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Numerics;
|
||||
using Content.Client.DoAfter;
|
||||
using Content.Client.UserInterface.Systems;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
@@ -9,11 +9,13 @@ namespace Content.Client.UserInterface.Controls
|
||||
{
|
||||
public float Progress;
|
||||
|
||||
private readonly ProgressColorSystem _progressColor = IoCManager.Resolve<IEntityManager>().System<ProgressColorSystem>();
|
||||
|
||||
protected override void Draw(DrawingHandleScreen handle)
|
||||
{
|
||||
var dims = Texture != null ? GetDrawDimensions(Texture) : UIBox2.FromDimensions(Vector2.Zero, PixelSize);
|
||||
dims.Top = Math.Max(dims.Bottom - dims.Bottom * Progress,0);
|
||||
handle.DrawRect(dims, DoAfterOverlay.GetProgressColor(Progress));
|
||||
handle.DrawRect(dims, _progressColor.GetProgressColor(Progress));
|
||||
|
||||
base.Draw(handle);
|
||||
}
|
||||
|
||||
77
Content.Client/UserInterface/Systems/ProgressColorSystem.cs
Normal file
77
Content.Client/UserInterface/Systems/ProgressColorSystem.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Client.UserInterface.Systems;
|
||||
|
||||
/// <summary>
|
||||
/// This system handles getting an interpolated color based on the value of a cvar.
|
||||
/// </summary>
|
||||
public sealed class ProgressColorSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _configuration = default!;
|
||||
|
||||
private bool _colorBlindFriendly;
|
||||
|
||||
private static readonly Color[] Plasma =
|
||||
{
|
||||
new(240, 249, 33),
|
||||
new(248, 149, 64),
|
||||
new(204, 71, 120),
|
||||
new(126, 3, 168),
|
||||
new(13, 8, 135)
|
||||
};
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
Subs.CVar(_configuration, CCVars.AccessibilityColorblindFriendly, OnColorBlindFriendlyChanged, true);
|
||||
}
|
||||
|
||||
private void OnColorBlindFriendlyChanged(bool value, in CVarChangeInfo info)
|
||||
{
|
||||
_colorBlindFriendly = value;
|
||||
}
|
||||
|
||||
public Color GetProgressColor(float progress)
|
||||
{
|
||||
if (!_colorBlindFriendly)
|
||||
{
|
||||
if (progress >= 1.0f)
|
||||
{
|
||||
return new Color(0f, 1f, 0f);
|
||||
}
|
||||
|
||||
// lerp
|
||||
var hue = 5f / 18f * progress;
|
||||
return Color.FromHsv((hue, 1f, 0.75f, 1f));
|
||||
}
|
||||
|
||||
return InterpolateColorGaussian(Plasma, progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interpolates between multiple colors based on a gaussian distribution.
|
||||
/// Taken from https://stackoverflow.com/a/26103117
|
||||
/// </summary>
|
||||
public static Color InterpolateColorGaussian(Color[] colors, double x)
|
||||
{
|
||||
double r = 0.0, g = 0.0, b = 0.0;
|
||||
var total = 0f;
|
||||
var step = 1.0 / (colors.Length - 1);
|
||||
var mu = 0.0;
|
||||
const double sigma2 = 0.035;
|
||||
|
||||
foreach(var color in colors)
|
||||
{
|
||||
var percent = Math.Exp(-(x - mu) * (x - mu) / (2.0 * sigma2)) / Math.Sqrt(2.0 * Math.PI * sigma2);
|
||||
total += (float) percent;
|
||||
mu += step;
|
||||
|
||||
r += color.R * percent;
|
||||
g += color.G * percent;
|
||||
b += color.B * percent;
|
||||
}
|
||||
|
||||
return new Color((float) r / total, (float) g / total, (float) b / total);
|
||||
}
|
||||
}
|
||||
@@ -1578,6 +1578,13 @@ namespace Content.Shared.CCVar
|
||||
public static readonly CVarDef<float> ScreenShakeIntensity =
|
||||
CVarDef.Create("accessibility.screen_shake_intensity", 1f, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
/// <summary>
|
||||
/// A generic toggle for various visual effects that are color sensitive.
|
||||
/// As of 2/16/24, only applies to progress bar colors.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<bool> AccessibilityColorblindFriendly =
|
||||
CVarDef.Create("accessibility.colorblind_friendly", false, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
/*
|
||||
* CHAT
|
||||
*/
|
||||
|
||||
@@ -46,6 +46,7 @@ ui-options-show-looc-on-head = Show LOOC chat above characters head
|
||||
ui-options-fancy-speech = Show names in speech bubbles
|
||||
ui-options-fancy-name-background = Add background to speech bubble names
|
||||
ui-options-enable-color-name = Add colors to character names
|
||||
ui-options-colorblind-friendly = Colorblind friendly mode
|
||||
ui-options-reduced-motion = Reduce motion of visual effects
|
||||
ui-options-screen-shake-intensity = Screen shake intensity
|
||||
ui-options-screen-shake-percent = { TOSTRING($intensity, "P0") }
|
||||
|
||||
Reference in New Issue
Block a user