diff --git a/Content.Client/Content.Client.csproj b/Content.Client/Content.Client.csproj
index b43edd6064..5c56fa52fc 100644
--- a/Content.Client/Content.Client.csproj
+++ b/Content.Client/Content.Client.csproj
@@ -21,6 +21,17 @@
+
+
+ OptionsMenu.cs
+
+
+ OptionsMenu.cs
+
+
+ OptionsMenu.cs
+
+
diff --git a/Content.Client/EscapeMenuOwner.cs b/Content.Client/EscapeMenuOwner.cs
index 11a4ebdacb..e3d0d016db 100644
--- a/Content.Client/EscapeMenuOwner.cs
+++ b/Content.Client/EscapeMenuOwner.cs
@@ -2,29 +2,19 @@
using Content.Client.UserInterface;
using Robust.Client.Console;
using Robust.Client.Interfaces.Input;
-using Robust.Client.Interfaces.Placement;
-using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.Interfaces.State;
using Robust.Shared.Input;
using Robust.Shared.Input.Binding;
-using Robust.Shared.Interfaces.Configuration;
-using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
-using Robust.Shared.Prototypes;
namespace Content.Client
{
internal sealed class EscapeMenuOwner : IEscapeMenuOwner
{
[Dependency] private readonly IClientConsole _clientConsole = default!;
- [Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly IInputManager _inputManager = default!;
- [Dependency] private readonly IPlacementManager _placementManager = default!;
- [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- [Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IStateManager _stateManager = default!;
- [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
[Dependency] private readonly IGameHud _gameHud = default!;
[Dependency] private readonly ILocalizationManager _localizationManager = default!;
@@ -42,8 +32,7 @@ namespace Content.Client
if (obj.NewState is GameScreenBase)
{
// Switched TO GameScreen.
- _escapeMenu = new EscapeMenu(_clientConsole, _tileDefinitionManager, _placementManager,
- _prototypeManager, _resourceCache, _configurationManager, _localizationManager);
+ _escapeMenu = new EscapeMenu(_clientConsole, _localizationManager);
_escapeMenu.OnClose += () => _gameHud.EscapeButtonDown = false;
diff --git a/Content.Client/GameObjects/Components/LightBehaviourComponent.cs b/Content.Client/GameObjects/Components/LightBehaviourComponent.cs
index 83ff452c0e..4e50dd2905 100644
--- a/Content.Client/GameObjects/Components/LightBehaviourComponent.cs
+++ b/Content.Client/GameObjects/Components/LightBehaviourComponent.cs
@@ -1,5 +1,4 @@
-
-using System;
+using System;
using System.Collections.Generic;
using Robust.Client.GameObjects;
using Robust.Shared.Animations;
@@ -13,8 +12,6 @@ using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Interfaces.Serialization;
using Robust.Client.Animations;
-using Robust.Shared.Interfaces.GameObjects;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
using Robust.Client.GameObjects.Components.Animations;
using System.Linq;
@@ -43,7 +40,7 @@ namespace Content.Client.GameObjects.Components
protected IRobustRandom RobustRandom = default;
private float _maxTime = default;
-
+
public virtual void ExposeData(ObjectSerializer serializer)
{
serializer.DataField(this, x => x.ID, "id", string.Empty);
@@ -83,7 +80,7 @@ namespace Content.Client.GameObjects.Components
MaxTime = MaxDuration;
}
- owner.Length = TimeSpan.FromSeconds(MaxTime);
+ owner.Length = TimeSpan.FromSeconds(MaxTime);
}
public override (int KeyFrameIndex, float FramePlayingTime) InitPlayback()
@@ -344,7 +341,7 @@ namespace Content.Client.GameObjects.Components
/// A component which applies a specific behaviour to a PointLightComponent on its owner.
///
[RegisterComponent]
- public class LightBehaviourComponent : SharedLightBehaviourComponent
+ public class LightBehaviourComponent : SharedLightBehaviourComponent
{
private const string KeyPrefix = nameof(LightBehaviourComponent);
@@ -387,7 +384,7 @@ namespace Content.Client.GameObjects.Components
container.LightBehaviour.Initialize(_lightComponent);
}
- // we need to initialize all behaviours before starting any
+ // we need to initialize all behaviours before starting any
foreach (var container in _animations)
{
if (container.LightBehaviour.Enabled)
diff --git a/Content.Client/GameObjects/Components/Storage/ClientStorageComponent.cs b/Content.Client/GameObjects/Components/Storage/ClientStorageComponent.cs
index 4c5d5dce36..2cf1b964c4 100644
--- a/Content.Client/GameObjects/Components/Storage/ClientStorageComponent.cs
+++ b/Content.Client/GameObjects/Components/Storage/ClientStorageComponent.cs
@@ -34,7 +34,7 @@ namespace Content.Client.GameObjects.Components.Storage
base.OnAdd();
Window = new StorageWindow()
- {StorageEntity = this, Title = Owner.Name};
+ { StorageEntity = this, Title = Owner.Name };
}
public override void OnRemove()
@@ -55,7 +55,7 @@ namespace Content.Client.GameObjects.Components.Storage
break;
//Opens the UI
case OpenStorageUIMessage _:
- OpenUI();
+ ToggleUI();
break;
case CloseStorageUIMessage _:
CloseUI();
@@ -76,11 +76,14 @@ namespace Content.Client.GameObjects.Components.Storage
}
///
- /// Opens the storage UI
+ /// Opens the storage UI if closed. Closes it if opened.
///
- private void OpenUI()
+ private void ToggleUI()
{
- Window.Open();
+ if (Window.IsOpen)
+ Window.Close();
+ else
+ Window.Open();
}
private void CloseUI()
@@ -107,8 +110,8 @@ namespace Content.Client.GameObjects.Components.Storage
private Label Information;
public ClientStorageComponent StorageEntity;
- private StyleBoxFlat _HoveredBox = new StyleBoxFlat {BackgroundColor = Color.Black.WithAlpha(0.35f)};
- private StyleBoxFlat _unHoveredBox = new StyleBoxFlat {BackgroundColor = Color.Black.WithAlpha(0.0f)};
+ private StyleBoxFlat _HoveredBox = new StyleBoxFlat { BackgroundColor = Color.Black.WithAlpha(0.35f) };
+ private StyleBoxFlat _unHoveredBox = new StyleBoxFlat { BackgroundColor = Color.Black.WithAlpha(0.0f) };
protected override Vector2? CustomSize => (180, 320);
diff --git a/Content.Client/State/MainMenu.cs b/Content.Client/State/MainMenu.cs
index 06c7e46a3a..e7199e5c23 100644
--- a/Content.Client/State/MainMenu.cs
+++ b/Content.Client/State/MainMenu.cs
@@ -1,5 +1,6 @@
using System;
using System.Text.RegularExpressions;
+using Content.Client.UserInterface;
using Robust.Client;
using Robust.Client.Interfaces;
using Robust.Client.Interfaces.ResourceManagement;
@@ -7,7 +8,6 @@ using Robust.Client.Interfaces.UserInterface;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
-using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.IoC;
@@ -56,7 +56,7 @@ namespace Content.Client.State
_client.RunLevelChanged += RunLevelChanged;
- OptionsMenu = new OptionsMenu(_configurationManager);
+ OptionsMenu = new OptionsMenu();
}
///
diff --git a/Content.Client/UserInterface/EscapeMenu.cs b/Content.Client/UserInterface/EscapeMenu.cs
index 7b3ba644ce..3b58839962 100644
--- a/Content.Client/UserInterface/EscapeMenu.cs
+++ b/Content.Client/UserInterface/EscapeMenu.cs
@@ -1,24 +1,14 @@
using Robust.Client.Console;
-using Robust.Client.Interfaces.Placement;
-using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
-using Robust.Shared.Interfaces.Configuration;
-using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
-using Robust.Shared.Prototypes;
namespace Content.Client.UserInterface
{
internal sealed class EscapeMenu : SS14Window
{
private readonly IClientConsole _console;
- private readonly ITileDefinitionManager _tileDefinitionManager;
- private readonly IPlacementManager _placementManager;
- private readonly IPrototypeManager _prototypeManager;
- private readonly IResourceCache _resourceCache;
- private readonly IConfigurationManager _configSystem;
private readonly ILocalizationManager _localizationManager;
private BaseButton DisconnectButton;
@@ -26,20 +16,10 @@ namespace Content.Client.UserInterface
private BaseButton OptionsButton;
private OptionsMenu optionsMenu;
- public EscapeMenu(IClientConsole console,
- ITileDefinitionManager tileDefinitionManager,
- IPlacementManager placementManager,
- IPrototypeManager prototypeManager,
- IResourceCache resourceCache,
- IConfigurationManager configSystem, ILocalizationManager localizationManager)
+ public EscapeMenu(IClientConsole console, ILocalizationManager localizationManager)
{
- _configSystem = configSystem;
_localizationManager = localizationManager;
_console = console;
- _tileDefinitionManager = tileDefinitionManager;
- _placementManager = placementManager;
- _prototypeManager = prototypeManager;
- _resourceCache = resourceCache;
IoCManager.InjectDependencies(this);
@@ -48,7 +28,7 @@ namespace Content.Client.UserInterface
private void PerformLayout()
{
- optionsMenu = new OptionsMenu(_configSystem);
+ optionsMenu = new OptionsMenu();
Resizable = false;
@@ -95,10 +75,5 @@ namespace Content.Client.UserInterface
optionsMenu.Dispose();
}
}
-
- public override void Close()
- {
- base.Close();
- }
}
}
diff --git a/Content.Client/UserInterface/KeyRebindControl.cs b/Content.Client/UserInterface/KeyRebindControl.cs
new file mode 100644
index 0000000000..805fa26b5d
--- /dev/null
+++ b/Content.Client/UserInterface/KeyRebindControl.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using Content.Client.UserInterface.Stylesheets;
+using Content.Shared.Input;
+using Robust.Client.Input;
+using Robust.Client.Interfaces.Input;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using Robust.Shared.Input;
+using Robust.Shared.IoC;
+using Robust.Shared.Localization;
+using Robust.Shared.Timing;
+using Robust.Shared.Utility;
+
+#nullable enable
+
+namespace Content.Client.UserInterface
+{
+}
diff --git a/Content.Client/UserInterface/OptionsMenu.Audio.cs b/Content.Client/UserInterface/OptionsMenu.Audio.cs
new file mode 100644
index 0000000000..ce8a1da9b7
--- /dev/null
+++ b/Content.Client/UserInterface/OptionsMenu.Audio.cs
@@ -0,0 +1,21 @@
+using Robust.Client.Interfaces.ResourceManagement;
+using Robust.Client.UserInterface;
+using Robust.Shared.Interfaces.Configuration;
+using Robust.Shared.IoC;
+
+namespace Content.Client.UserInterface
+{
+ public sealed partial class OptionsMenu
+ {
+ private sealed class AudioControl : Control
+ {
+ public AudioControl(IConfigurationManager cfg)
+ {
+ AddChild(new Placeholder(IoCManager.Resolve())
+ {
+ PlaceholderText = "Pretend there's a bunch of volume sliders here."
+ });
+ }
+ }
+ }
+}
diff --git a/Content.Client/UserInterface/OptionsMenu.Graphics.cs b/Content.Client/UserInterface/OptionsMenu.Graphics.cs
new file mode 100644
index 0000000000..d4c655b6d2
--- /dev/null
+++ b/Content.Client/UserInterface/OptionsMenu.Graphics.cs
@@ -0,0 +1,185 @@
+using Robust.Client.Graphics;
+using Robust.Client.Interfaces.ResourceManagement;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using Robust.Shared.Interfaces.Configuration;
+using Robust.Shared.IoC;
+using Robust.Shared.Localization;
+
+namespace Content.Client.UserInterface
+{
+ public sealed partial class OptionsMenu
+ {
+ private sealed class GraphicsControl : Control
+ {
+ private readonly IConfigurationManager _cfg;
+
+ private readonly Button ApplyButton;
+ private readonly CheckBox VSyncCheckBox;
+ private readonly CheckBox FullscreenCheckBox;
+ private readonly OptionButton LightingPresetOption;
+
+
+ public GraphicsControl(IConfigurationManager cfg)
+ {
+ _cfg = cfg;
+ var vBox = new VBoxContainer();
+
+ var contents = new VBoxContainer();
+
+ VSyncCheckBox = new CheckBox {Text = Loc.GetString("VSync")};
+ contents.AddChild(VSyncCheckBox);
+ VSyncCheckBox.OnToggled += OnCheckBoxToggled;
+
+ FullscreenCheckBox = new CheckBox {Text = Loc.GetString("Fullscreen")};
+ contents.AddChild(FullscreenCheckBox);
+ FullscreenCheckBox.OnToggled += OnCheckBoxToggled;
+
+ LightingPresetOption = new OptionButton {CustomMinimumSize = (100, 0)};
+ LightingPresetOption.AddItem(Loc.GetString("Very Low"));
+ LightingPresetOption.AddItem(Loc.GetString("Low"));
+ LightingPresetOption.AddItem(Loc.GetString("Medium"));
+ LightingPresetOption.AddItem(Loc.GetString("High"));
+ LightingPresetOption.OnItemSelected += OnLightingQualityChanged;
+
+ var lightingHBox = new HBoxContainer
+ {
+ Children =
+ {
+ new Label {Text = Loc.GetString("Lighting Quality:")},
+ new Control {CustomMinimumSize = (4, 0)},
+ LightingPresetOption
+ }
+ };
+ contents.AddChild(lightingHBox);
+
+ ApplyButton = new Button
+ {
+ Text = Loc.GetString("Apply"), TextAlign = Label.AlignMode.Center,
+ SizeFlagsHorizontal = SizeFlags.ShrinkEnd
+ };
+
+ var resourceCache = IoCManager.Resolve();
+
+ contents.AddChild(new Placeholder(resourceCache)
+ {
+ SizeFlagsVertical = SizeFlags.FillExpand,
+ PlaceholderText = "UI Scaling"
+ });
+
+ contents.AddChild(new Placeholder(resourceCache)
+ {
+ SizeFlagsVertical = SizeFlags.FillExpand,
+ PlaceholderText = "Viewport settings"
+ });
+
+ vBox.AddChild(new MarginContainer
+ {
+ MarginLeftOverride = 2,
+ MarginTopOverride = 2,
+ MarginRightOverride = 2,
+ SizeFlagsVertical = SizeFlags.FillExpand,
+ Children =
+ {
+ contents
+ }
+ });
+
+ vBox.AddChild(new StripeBack
+ {
+ HasBottomEdge = false,
+ HasMargins = false,
+ Children =
+ {
+ ApplyButton
+ }
+ });
+ ApplyButton.OnPressed += OnApplyButtonPressed;
+
+ VSyncCheckBox.Pressed = _cfg.GetCVar("display.vsync");
+ FullscreenCheckBox.Pressed = ConfigIsFullscreen;
+ LightingPresetOption.SelectId(GetConfigLightingQuality());
+
+
+ AddChild(vBox);
+ }
+
+ private void OnApplyButtonPressed(BaseButton.ButtonEventArgs args)
+ {
+ _cfg.SetCVar("display.vsync", VSyncCheckBox.Pressed);
+ SetConfigLightingQuality(LightingPresetOption.SelectedId);
+ _cfg.SetCVar("display.windowmode",
+ (int) (FullscreenCheckBox.Pressed ? WindowMode.Fullscreen : WindowMode.Windowed));
+ _cfg.SaveToFile();
+ UpdateApplyButton();
+ }
+
+ private void OnCheckBoxToggled(BaseButton.ButtonToggledEventArgs args)
+ {
+ UpdateApplyButton();
+ }
+
+ private void OnLightingQualityChanged(OptionButton.ItemSelectedEventArgs args)
+ {
+ LightingPresetOption.SelectId(args.Id);
+ UpdateApplyButton();
+ }
+
+ private void UpdateApplyButton()
+ {
+ var isVSyncSame = VSyncCheckBox.Pressed == _cfg.GetCVar("display.vsync");
+ var isFullscreenSame = FullscreenCheckBox.Pressed == ConfigIsFullscreen;
+ var isLightingQualitySame = LightingPresetOption.SelectedId == GetConfigLightingQuality();
+ ApplyButton.Disabled = isVSyncSame && isFullscreenSame && isLightingQualitySame;
+ }
+
+ private bool ConfigIsFullscreen =>
+ _cfg.GetCVar("display.windowmode") == (int) WindowMode.Fullscreen;
+
+ private int GetConfigLightingQuality()
+ {
+ var val = _cfg.GetCVar("display.lightmapdivider");
+ var soft = _cfg.GetCVar("display.softshadows");
+ if (val >= 8)
+ {
+ return 0;
+ }
+ else if ((val >= 2) && !soft)
+ {
+ return 1;
+ }
+ else if (val >= 2)
+ {
+ return 2;
+ }
+ else
+ {
+ return 3;
+ }
+ }
+
+ private void SetConfigLightingQuality(int value)
+ {
+ switch (value)
+ {
+ case 0:
+ _cfg.SetCVar("display.lightmapdivider", 8);
+ _cfg.SetCVar("display.softshadows", false);
+ break;
+ case 1:
+ _cfg.SetCVar("display.lightmapdivider", 2);
+ _cfg.SetCVar("display.softshadows", false);
+ break;
+ case 2:
+ _cfg.SetCVar("display.lightmapdivider", 2);
+ _cfg.SetCVar("display.softshadows", true);
+ break;
+ case 3:
+ _cfg.SetCVar("display.lightmapdivider", 1);
+ _cfg.SetCVar("display.softshadows", true);
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/Content.Client/UserInterface/OptionsMenu.KeyRebind.cs b/Content.Client/UserInterface/OptionsMenu.KeyRebind.cs
new file mode 100644
index 0000000000..c158a48895
--- /dev/null
+++ b/Content.Client/UserInterface/OptionsMenu.KeyRebind.cs
@@ -0,0 +1,473 @@
+#nullable enable
+using System;
+using System.Collections.Generic;
+using Content.Client.UserInterface.Stylesheets;
+using Content.Shared.Input;
+using Robust.Client.Input;
+using Robust.Client.Interfaces.Input;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using Robust.Shared.Input;
+using Robust.Shared.IoC;
+using Robust.Shared.Localization;
+using Robust.Shared.Timing;
+using Robust.Shared.Utility;
+
+namespace Content.Client.UserInterface
+{
+ public sealed partial class OptionsMenu
+ {
+ private sealed class KeyRebindControl : Control
+ {
+ // List of key functions that must be registered as toggle instead.
+ private static readonly HashSet ToggleFunctions = new HashSet
+ {
+ EngineKeyFunctions.ShowDebugMonitors,
+ EngineKeyFunctions.HideUI,
+ };
+
+ [Dependency] private readonly IInputManager _inputManager = default!;
+
+ private BindButton? _currentlyRebinding;
+
+ private readonly Dictionary _keyControls =
+ new Dictionary();
+
+ private readonly List _deferCommands = new List();
+
+ public KeyRebindControl()
+ {
+ IoCManager.InjectDependencies(this);
+
+ Button resetAllButton;
+ var vBox = new VBoxContainer();
+ AddChild(new VBoxContainer
+ {
+ Children =
+ {
+ new ScrollContainer
+ {
+ SizeFlagsVertical = SizeFlags.FillExpand,
+ Children =
+ {
+ new MarginContainer
+ {
+ MarginLeftOverride = 2,
+ Children =
+ {
+ vBox
+ }
+ }
+ }
+ },
+
+ new StripeBack
+ {
+ HasBottomEdge = false,
+ HasMargins = false,
+ Children =
+ {
+ new HBoxContainer
+ {
+ Children =
+ {
+ new Control {CustomMinimumSize = (2, 0)},
+ new Label
+ {
+ StyleClasses = {StyleBase.StyleClassLabelSubText},
+ Text = "Click to change binding, right-click to clear"
+ },
+ (resetAllButton = new Button
+ {
+ Text = "Reset ALL keybinds",
+ StyleClasses = {StyleBase.ButtonCaution},
+ SizeFlagsHorizontal = SizeFlags.ShrinkEnd | SizeFlags.Expand
+ })
+ }
+ }
+ }
+ }
+ }
+ });
+
+ resetAllButton.OnPressed += args =>
+ {
+ _deferCommands.Add(() =>
+ {
+ _inputManager.ResetAllBindings();
+ _inputManager.SaveToUserData();
+ });
+ };
+
+ var first = true;
+
+ void AddHeader(string headerContents)
+ {
+ if (!first)
+ {
+ vBox.AddChild(new Control {CustomMinimumSize = (0, 8)});
+ }
+
+ first = false;
+ vBox.AddChild(new Label
+ {
+ Text = headerContents,
+ FontColorOverride = StyleNano.NanoGold,
+ StyleClasses = {StyleNano.StyleClassLabelKeyText}
+ });
+ }
+
+ void AddButton(BoundKeyFunction function, string name)
+ {
+ var control = new KeyControl(this, name, function);
+ vBox.AddChild(control);
+ _keyControls.Add(function, control);
+ }
+
+ AddHeader("Movement");
+ AddButton(EngineKeyFunctions.MoveUp, "Move up");
+ AddButton(EngineKeyFunctions.MoveLeft, "Move left");
+ AddButton(EngineKeyFunctions.MoveDown, "Move down");
+ AddButton(EngineKeyFunctions.MoveRight, "Move right");
+ AddButton(EngineKeyFunctions.Walk, "Walk");
+
+ AddHeader("Basic Interaction");
+ AddButton(EngineKeyFunctions.Use, "Use");
+ AddButton(ContentKeyFunctions.WideAttack, "Wide attack");
+ AddButton(ContentKeyFunctions.ActivateItemInHand, "Activate item in hand");
+ AddButton(ContentKeyFunctions.ActivateItemInWorld, "Activate item in world");
+ AddButton(ContentKeyFunctions.Drop, "Drop item");
+ AddButton(ContentKeyFunctions.ExamineEntity, "Examine");
+ AddButton(ContentKeyFunctions.SwapHands, "Swap hands");
+ AddButton(ContentKeyFunctions.ToggleCombatMode, "Toggle combat mode");
+
+ AddHeader("Advanced Interaction");
+ AddButton(ContentKeyFunctions.SmartEquipBackpack, "Smart-equip to backpack");
+ AddButton(ContentKeyFunctions.SmartEquipBelt, "Smart-equip to belt");
+ AddButton(ContentKeyFunctions.ThrowItemInHand, "Throw item");
+ AddButton(ContentKeyFunctions.TryPullObject, "Pull object");
+ AddButton(ContentKeyFunctions.MovePulledObject, "Move pulled object");
+ AddButton(ContentKeyFunctions.Point, "Point at location");
+
+
+ AddHeader("User Interface");
+ AddButton(ContentKeyFunctions.FocusChat, "Focus chat");
+ AddButton(ContentKeyFunctions.FocusOOC, "Focus chat (OOC)");
+ AddButton(ContentKeyFunctions.FocusAdminChat, "Focus chat (admin)");
+ AddButton(ContentKeyFunctions.OpenCharacterMenu, "Open character menu");
+ AddButton(ContentKeyFunctions.OpenContextMenu, "Open context menu");
+ AddButton(ContentKeyFunctions.OpenCraftingMenu, "Open crafting menu");
+ AddButton(ContentKeyFunctions.OpenInventoryMenu, "Open inventory");
+ AddButton(ContentKeyFunctions.OpenTutorial, "Open tutorial");
+ AddButton(ContentKeyFunctions.OpenEntitySpawnWindow, "Open entity spawn menu");
+ AddButton(ContentKeyFunctions.OpenSandboxWindow, "Open sandbox menu");
+ AddButton(ContentKeyFunctions.OpenTileSpawnWindow, "Open tile spawn menu");
+ AddButton(ContentKeyFunctions.OpenAdminMenu, "Open admin menu");
+
+ AddHeader("Miscellaneous");
+ AddButton(ContentKeyFunctions.TakeScreenshot, "Take screenshot");
+ AddButton(ContentKeyFunctions.TakeScreenshotNoUI, "Take screenshot (without UI)");
+
+ AddHeader("Map Editor");
+ AddButton(EngineKeyFunctions.EditorPlaceObject, "Place object");
+ AddButton(EngineKeyFunctions.EditorCancelPlace, "Cancel placement");
+ AddButton(EngineKeyFunctions.EditorGridPlace, "Place in grid");
+ AddButton(EngineKeyFunctions.EditorLinePlace, "Place line");
+ AddButton(EngineKeyFunctions.EditorRotateObject, "Rotate");
+
+ AddHeader("Development");
+ AddButton(EngineKeyFunctions.ShowDebugConsole, "Open Console");
+ AddButton(EngineKeyFunctions.ShowDebugMonitors, "Show Debug Monitors");
+ AddButton(EngineKeyFunctions.HideUI, "Hide UI");
+
+ foreach (var control in _keyControls.Values)
+ {
+ UpdateKeyControl(control);
+ }
+ }
+
+ private void UpdateKeyControl(KeyControl control)
+ {
+ var activeBinds = _inputManager.GetKeyBindings(control.Function);
+
+ IKeyBinding? bind1 = null;
+ IKeyBinding? bind2 = null;
+
+ if (activeBinds.Count > 0)
+ {
+ bind1 = activeBinds[0];
+
+ if (activeBinds.Count > 1)
+ {
+ bind2 = activeBinds[1];
+ }
+ }
+
+ control.BindButton1.Binding = bind1;
+ control.BindButton1.UpdateText();
+
+ control.BindButton2.Binding = bind2;
+ control.BindButton2.UpdateText();
+
+ control.BindButton2.Button.Disabled = activeBinds.Count == 0;
+ control.ResetButton.Disabled = !_inputManager.IsKeyFunctionModified(control.Function);
+ }
+
+ protected override void EnteredTree()
+ {
+ base.EnteredTree();
+
+ _inputManager.FirstChanceOnKeyEvent += InputManagerOnFirstChanceOnKeyEvent;
+ _inputManager.OnKeyBindingAdded += OnKeyBindAdded;
+ _inputManager.OnKeyBindingRemoved += OnKeyBindRemoved;
+ }
+
+ protected override void ExitedTree()
+ {
+ base.ExitedTree();
+
+ _inputManager.FirstChanceOnKeyEvent -= InputManagerOnFirstChanceOnKeyEvent;
+ _inputManager.OnKeyBindingAdded -= OnKeyBindAdded;
+ _inputManager.OnKeyBindingRemoved -= OnKeyBindRemoved;
+ }
+
+ private void OnKeyBindRemoved(IKeyBinding obj)
+ {
+ OnKeyBindModified(obj, true);
+ }
+
+ private void OnKeyBindAdded(IKeyBinding obj)
+ {
+ OnKeyBindModified(obj, false);
+ }
+
+ private void OnKeyBindModified(IKeyBinding bind, bool removal)
+ {
+ if (!_keyControls.TryGetValue(bind.Function, out var keyControl))
+ {
+ return;
+ }
+
+ if (removal && _currentlyRebinding?.KeyControl == keyControl)
+ {
+ // Don't do update if the removal was from initiating a rebind.
+ return;
+ }
+
+ UpdateKeyControl(keyControl);
+
+ if (_currentlyRebinding == keyControl.BindButton1 || _currentlyRebinding == keyControl.BindButton2)
+ {
+ _currentlyRebinding = null;
+ }
+ }
+
+ private void InputManagerOnFirstChanceOnKeyEvent(KeyEventArgs keyEvent, KeyEventType type)
+ {
+ DebugTools.Assert(IsInsideTree);
+
+ if (_currentlyRebinding == null)
+ {
+ return;
+ }
+
+ keyEvent.Handle();
+
+ if (type != KeyEventType.Up)
+ {
+ return;
+ }
+
+ var key = keyEvent.Key;
+
+ // Figure out modifiers based on key event.
+ // TODO: this won't allow for combinations with keys other than the standard modifier keys,
+ // even though the input system totally supports it.
+ var mods = new Keyboard.Key[3];
+ var i = 0;
+ if (keyEvent.Control && key != Keyboard.Key.Control)
+ {
+ mods[i] = Keyboard.Key.Control;
+ i += 1;
+ }
+
+ if (keyEvent.Shift && key != Keyboard.Key.Shift)
+ {
+ mods[i] = Keyboard.Key.Shift;
+ i += 1;
+ }
+
+ if (keyEvent.Alt && key != Keyboard.Key.Alt)
+ {
+ mods[i] = Keyboard.Key.Alt;
+ i += 1;
+ }
+
+ // The input system can only handle 3 modifier keys so if you hold all 4 of the modifier keys
+ // then system gets the shaft, I guess.
+ if (keyEvent.System && i != 3 && key != Keyboard.Key.LSystem && key != Keyboard.Key.RSystem)
+ {
+ mods[i] = Keyboard.Key.LSystem;
+ }
+
+ var function = _currentlyRebinding.KeyControl.Function;
+ var bindType = KeyBindingType.State;
+ if (ToggleFunctions.Contains(function))
+ {
+ bindType = KeyBindingType.Toggle;
+ }
+
+ var registration = new KeyBindingRegistration
+ {
+ Function = function,
+ BaseKey = key,
+ Mod1 = mods[0],
+ Mod2 = mods[1],
+ Mod3 = mods[2],
+ Priority = 0,
+ Type = bindType,
+ CanFocus = key == Keyboard.Key.MouseLeft
+ || key == Keyboard.Key.MouseRight
+ || key == Keyboard.Key.MouseMiddle,
+ CanRepeat = false
+ };
+
+ _inputManager.RegisterBinding(registration);
+ // OnKeyBindModified will cause _currentlyRebinding to be reset and the UI to update.
+ _inputManager.SaveToUserData();
+ }
+
+ private void RebindButtonPressed(BindButton button)
+ {
+ if (_currentlyRebinding != null)
+ {
+ return;
+ }
+
+ _currentlyRebinding = button;
+ _currentlyRebinding.Button.Text = Loc.GetString("Press a key...");
+
+ if (button.Binding != null)
+ {
+ _deferCommands.Add(() =>
+ {
+ // Have to do defer this or else there will be an exception in InputManager.
+ // Because this IS fired from an input event.
+ _inputManager.RemoveBinding(button.Binding);
+ });
+ }
+ }
+
+ protected override void FrameUpdate(FrameEventArgs args)
+ {
+ base.FrameUpdate(args);
+
+ if (_deferCommands.Count == 0)
+ {
+ return;
+ }
+
+ foreach (var command in _deferCommands)
+ {
+ command();
+ }
+
+ _deferCommands.Clear();
+ }
+
+ private sealed class KeyControl : Control
+ {
+ public readonly BoundKeyFunction Function;
+ public readonly BindButton BindButton1;
+ public readonly BindButton BindButton2;
+ public readonly Button ResetButton;
+
+ public KeyControl(KeyRebindControl parent, string niceName, BoundKeyFunction function)
+ {
+ Function = function;
+ var name = new Label
+ {
+ Text = Loc.GetString(niceName),
+ SizeFlagsHorizontal = SizeFlags.Expand
+ };
+
+ BindButton1 = new BindButton(parent, this, StyleBase.ButtonOpenRight);
+ BindButton2 = new BindButton(parent, this, StyleBase.ButtonOpenLeft);
+ ResetButton = new Button {Text = "Reset", StyleClasses = {StyleBase.ButtonCaution}};
+
+ var hBox = new HBoxContainer
+ {
+ Children =
+ {
+ new Control {CustomMinimumSize = (5, 0)},
+ name,
+ BindButton1,
+ BindButton2,
+ new Control {CustomMinimumSize = (10, 0)},
+ ResetButton
+ }
+ };
+
+ ResetButton.OnPressed += args =>
+ {
+ parent._deferCommands.Add(() =>
+ {
+ parent._inputManager.ResetBindingsFor(function);
+ parent._inputManager.SaveToUserData();
+ });
+ };
+
+ AddChild(hBox);
+ }
+ }
+
+ private sealed class BindButton : Control
+ {
+ private readonly KeyRebindControl _control;
+ public readonly KeyControl KeyControl;
+ public readonly Button Button;
+ public IKeyBinding? Binding;
+
+ public BindButton(KeyRebindControl control, KeyControl keyControl, string styleClass)
+ {
+ _control = control;
+ KeyControl = keyControl;
+ Button = new Button {StyleClasses = {styleClass}};
+ UpdateText();
+ AddChild(Button);
+
+ Button.OnPressed += args =>
+ {
+ control.RebindButtonPressed(this);
+ };
+
+ Button.OnKeyBindDown += ButtonOnOnKeyBindDown;
+
+ CustomMinimumSize = (200, 0);
+ }
+
+ private void ButtonOnOnKeyBindDown(GUIBoundKeyEventArgs args)
+ {
+ if (args.Function == EngineKeyFunctions.UIRightClick)
+ {
+ if (Binding != null)
+ {
+ _control._deferCommands.Add(() =>
+ {
+ _control._inputManager.RemoveBinding(Binding);
+ _control._inputManager.SaveToUserData();
+ });
+ }
+
+ args.Handle();
+ }
+ }
+
+ public void UpdateText()
+ {
+ Button.Text = Binding?.GetKeyString() ?? "Unbound";
+ }
+ }
+ }
+ }
+}
diff --git a/Content.Client/UserInterface/OptionsMenu.cs b/Content.Client/UserInterface/OptionsMenu.cs
new file mode 100644
index 0000000000..515916722d
--- /dev/null
+++ b/Content.Client/UserInterface/OptionsMenu.cs
@@ -0,0 +1,45 @@
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Shared.Interfaces.Configuration;
+using Robust.Shared.IoC;
+using Robust.Shared.Localization;
+using Robust.Shared.Maths;
+
+#nullable enable
+
+namespace Content.Client.UserInterface
+{
+ public sealed partial class OptionsMenu : SS14Window
+ {
+ [Dependency] private readonly IConfigurationManager _configManager = default!;
+
+ protected override Vector2? CustomSize => (800, 450);
+
+ public OptionsMenu()
+ {
+ IoCManager.InjectDependencies(this);
+
+ Title = Loc.GetString("Game Options");
+
+ GraphicsControl graphicsControl;
+ KeyRebindControl rebindControl;
+ AudioControl audioControl;
+
+ var tabs = new TabContainer
+ {
+ Children =
+ {
+ (graphicsControl = new GraphicsControl(_configManager)),
+ (rebindControl = new KeyRebindControl()),
+ (audioControl = new AudioControl(_configManager)),
+ }
+ };
+
+ TabContainer.SetTabTitle(graphicsControl, Loc.GetString("Graphics"));
+ TabContainer.SetTabTitle(rebindControl, Loc.GetString("Controls"));
+ TabContainer.SetTabTitle(audioControl, Loc.GetString("Audio"));
+
+ Contents.AddChild(tabs);
+ }
+ }
+}
diff --git a/Content.Client/UserInterface/StripeBack.cs b/Content.Client/UserInterface/StripeBack.cs
index 852c71deab..a43ab0c0fe 100644
--- a/Content.Client/UserInterface/StripeBack.cs
+++ b/Content.Client/UserInterface/StripeBack.cs
@@ -12,6 +12,7 @@ namespace Content.Client.UserInterface
private bool _hasTopEdge = true;
private bool _hasBottomEdge = true;
+ private bool _hasMargins = true;
public const string StylePropertyBackground = "background";
@@ -35,6 +36,16 @@ namespace Content.Client.UserInterface
}
}
+ public bool HasMargins
+ {
+ get => _hasMargins;
+ set
+ {
+ _hasMargins = value;
+ MinimumSizeChanged();
+ }
+ }
+
protected override Vector2 CalculateMinimumSize()
{
var size = Vector2.Zero;
@@ -44,14 +55,16 @@ namespace Content.Client.UserInterface
size = Vector2.ComponentMax(size, child.CombinedMinimumSize);
}
+ var padSize = HasMargins ? PadSize : 0;
+
if (HasBottomEdge)
{
- size += (0, PadSize + EdgeSize);
+ size += (0, padSize + EdgeSize);
}
if (HasTopEdge)
{
- size += (0, PadSize + EdgeSize);
+ size += (0, padSize + EdgeSize);
}
return size;
@@ -61,14 +74,16 @@ namespace Content.Client.UserInterface
{
var box = SizeBox;
+ var padSize = HasMargins ? PadSize : 0;
+
if (HasTopEdge)
{
- box += (0, PadSize + EdgeSize, 0, 0);
+ box += (0, padSize + EdgeSize, 0, 0);
}
if (HasBottomEdge)
{
- box += (0, 0, 0, -(PadSize + EdgeSize));
+ box += (0, 0, 0, -(padSize + EdgeSize));
}
foreach (var child in Children)
@@ -81,16 +96,18 @@ namespace Content.Client.UserInterface
{
UIBox2 centerBox = PixelSizeBox;
+ var padSize = HasMargins ? PadSize : 0;
+
if (HasTopEdge)
{
- centerBox += (0, (PadSize + EdgeSize) * UIScale, 0, 0);
- handle.DrawRect(new UIBox2(0, PadSize * UIScale, PixelWidth, centerBox.Top), EdgeColor);
+ centerBox += (0, (padSize + EdgeSize) * UIScale, 0, 0);
+ handle.DrawRect(new UIBox2(0, padSize * UIScale, PixelWidth, centerBox.Top), EdgeColor);
}
if (HasBottomEdge)
{
- centerBox += (0, 0, 0, -((PadSize + EdgeSize) * UIScale));
- handle.DrawRect(new UIBox2(0, centerBox.Bottom, PixelWidth, PixelHeight - PadSize * UIScale), EdgeColor);
+ centerBox += (0, 0, 0, -((padSize + EdgeSize) * UIScale));
+ handle.DrawRect(new UIBox2(0, centerBox.Bottom, PixelWidth, PixelHeight - padSize * UIScale), EdgeColor);
}
GetActualStyleBox()?.Draw(handle, centerBox);
diff --git a/Content.Client/UserInterface/Stylesheets/StyleBase.cs b/Content.Client/UserInterface/Stylesheets/StyleBase.cs
index 939c23ecb5..eaa74072ec 100644
--- a/Content.Client/UserInterface/Stylesheets/StyleBase.cs
+++ b/Content.Client/UserInterface/Stylesheets/StyleBase.cs
@@ -17,6 +17,8 @@ namespace Content.Client.UserInterface.Stylesheets
public const string ButtonOpenLeft = "OpenLeft";
public const string ButtonOpenBoth = "OpenBoth";
+ public const string ButtonCaution = "Caution";
+
public abstract Stylesheet Stylesheet { get; }
protected StyleRule[] BaseRules { get; }
diff --git a/Content.Client/UserInterface/Stylesheets/StyleNano.cs b/Content.Client/UserInterface/Stylesheets/StyleNano.cs
index 475ba6d33f..fa7329bcea 100644
--- a/Content.Client/UserInterface/Stylesheets/StyleNano.cs
+++ b/Content.Client/UserInterface/Stylesheets/StyleNano.cs
@@ -31,6 +31,11 @@ namespace Content.Client.UserInterface.Stylesheets
public static readonly Color ButtonColorPressed = Color.FromHex("#3e6c45");
public static readonly Color ButtonColorDisabled = Color.FromHex("#30313c");
+ public static readonly Color ButtonColorCautionDefault = Color.FromHex("#ab3232");
+ public static readonly Color ButtonColorCautionHovered = Color.FromHex("#cf2f2f");
+ public static readonly Color ButtonColorCautionPressed = Color.FromHex("#3e6c45");
+ public static readonly Color ButtonColorCautionDisabled = Color.FromHex("#602a2a");
+
//Used by the APC and SMES menus
public const string StyleClassPowerStateNone = "PowerStateNone";
public const string StyleClassPowerStateLow = "PowerStateLow";
@@ -70,30 +75,6 @@ namespace Content.Client.UserInterface.Stylesheets
var textureInvertedTriangle = resCache.GetTexture("/Textures/Interface/Nano/inverted_triangle.svg.png");
- static (StyleBox, StyleBox, StyleBox, StyleBox) ButtonPermutations(StyleBoxTexture @base)
- {
- var normal = new StyleBoxTexture(@base) {Modulate = ButtonColorDefault};
- var hover = new StyleBoxTexture(@base) {Modulate = ButtonColorHovered};
- var pressed = new StyleBoxTexture(@base) {Modulate = ButtonColorPressed};
- var disabled = new StyleBoxTexture(@base) {Modulate = ButtonColorDisabled};
-
- return (normal, hover, pressed, disabled);
- }
-
- // Button styles.
- var (buttonNormal, buttonHover, buttonPressed, buttonDisabled)
- = ButtonPermutations(BaseButton);
-
- var (buttonRNormal, buttonRHover, buttonRPressed, buttonRDisabled)
- = ButtonPermutations(BaseButtonOpenRight);
-
- var (buttonLNormal, buttonLHover, buttonLPressed, buttonLDisabled)
- = ButtonPermutations(BaseButtonOpenLeft);
-
- var (buttonBNormal, buttonBHover, buttonBPressed, buttonBDisabled)
- = ButtonPermutations(BaseButtonOpenBoth);
-
-
var lineEditTex = resCache.GetTexture("/Textures/Interface/Nano/lineedit.png");
var lineEdit = new StyleBoxTexture
{
@@ -297,80 +278,60 @@ namespace Content.Client.UserInterface.Stylesheets
new StyleProperty(Control.StylePropertyModulateSelf, Color.FromHex("#753131")),
}),
- // Regular buttons!
- new StyleRule(new SelectorElement(typeof(ContainerButton), new[] { ContainerButton.StyleClassButton }, null, new[] {ContainerButton.StylePseudoClassNormal}), new[]
- {
- new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonNormal),
- }),
- new StyleRule(new SelectorElement(typeof(ContainerButton), new[] { ContainerButton.StyleClassButton }, null, new[] {ContainerButton.StylePseudoClassHover}), new[]
- {
- new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonHover),
- }),
- new StyleRule(new SelectorElement(typeof(ContainerButton), new[] { ContainerButton.StyleClassButton }, null, new[] {ContainerButton.StylePseudoClassPressed}), new[]
- {
- new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonPressed),
- }),
- new StyleRule(new SelectorElement(typeof(ContainerButton), new[] { ContainerButton.StyleClassButton }, null, new[] {ContainerButton.StylePseudoClassDisabled}), new[]
- {
- new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonDisabled),
- }),
+ // Shapes for the buttons.
+ Element().Class(ContainerButton.StyleClassButton)
+ .Prop(ContainerButton.StylePropertyStyleBox, BaseButton),
+
+ Element().Class(ContainerButton.StyleClassButton)
+ .Class(ButtonOpenRight)
+ .Prop(ContainerButton.StylePropertyStyleBox, BaseButtonOpenRight),
+
+ Element().Class(ContainerButton.StyleClassButton)
+ .Class(ButtonOpenLeft)
+ .Prop(ContainerButton.StylePropertyStyleBox, BaseButtonOpenLeft),
+
+ Element().Class(ContainerButton.StyleClassButton)
+ .Class(ButtonOpenBoth)
+ .Prop(ContainerButton.StylePropertyStyleBox, BaseButtonOpenBoth),
new StyleRule(new SelectorElement(typeof(Label), new[] { Button.StyleClassButton }, null, null), new[]
{
new StyleProperty(Label.StylePropertyAlignMode, Label.AlignMode.Center),
}),
- // Right open buttons.
- Element().Class(ContainerButton.StyleClassButton).Class(ButtonOpenRight)
+ // Colors for the buttons.
+ Element().Class(ContainerButton.StyleClassButton)
.Pseudo(ContainerButton.StylePseudoClassNormal)
- .Prop(ContainerButton.StylePropertyStyleBox, buttonRNormal),
+ .Prop(Control.StylePropertyModulateSelf, ButtonColorDefault),
- Element().Class(ContainerButton.StyleClassButton).Class(ButtonOpenRight)
+ Element().Class(ContainerButton.StyleClassButton)
.Pseudo(ContainerButton.StylePseudoClassHover)
- .Prop(ContainerButton.StylePropertyStyleBox, buttonRHover),
+ .Prop(Control.StylePropertyModulateSelf, ButtonColorHovered),
- Element().Class(ContainerButton.StyleClassButton).Class(ButtonOpenRight)
+ Element().Class(ContainerButton.StyleClassButton)
.Pseudo(ContainerButton.StylePseudoClassPressed)
- .Prop(ContainerButton.StylePropertyStyleBox, buttonRPressed),
+ .Prop(Control.StylePropertyModulateSelf, ButtonColorPressed),
- Element().Class(ContainerButton.StyleClassButton).Class(ButtonOpenRight)
+ Element().Class(ContainerButton.StyleClassButton)
.Pseudo(ContainerButton.StylePseudoClassDisabled)
- .Prop(ContainerButton.StylePropertyStyleBox, buttonRDisabled),
+ .Prop(Control.StylePropertyModulateSelf, ButtonColorDisabled),
- // Left open buttons.
- Element().Class(ContainerButton.StyleClassButton).Class(ButtonOpenLeft)
+ // Colors for the caution buttons.
+ Element().Class(ContainerButton.StyleClassButton).Class(ButtonCaution)
.Pseudo(ContainerButton.StylePseudoClassNormal)
- .Prop(ContainerButton.StylePropertyStyleBox, buttonLNormal),
+ .Prop(Control.StylePropertyModulateSelf, ButtonColorCautionDefault),
- Element().Class(ContainerButton.StyleClassButton).Class(ButtonOpenLeft)
+ Element().Class(ContainerButton.StyleClassButton).Class(ButtonCaution)
.Pseudo(ContainerButton.StylePseudoClassHover)
- .Prop(ContainerButton.StylePropertyStyleBox, buttonLHover),
+ .Prop(Control.StylePropertyModulateSelf, ButtonColorCautionHovered),
- Element().Class(ContainerButton.StyleClassButton).Class(ButtonOpenLeft)
+ Element().Class(ContainerButton.StyleClassButton).Class(ButtonCaution)
.Pseudo(ContainerButton.StylePseudoClassPressed)
- .Prop(ContainerButton.StylePropertyStyleBox, buttonLPressed),
+ .Prop(Control.StylePropertyModulateSelf, ButtonColorCautionPressed),
- Element().Class(ContainerButton.StyleClassButton).Class(ButtonOpenLeft)
+ Element().Class(ContainerButton.StyleClassButton).Class(ButtonCaution)
.Pseudo(ContainerButton.StylePseudoClassDisabled)
- .Prop(ContainerButton.StylePropertyStyleBox, buttonLDisabled),
-
- // "Both" open buttons
- Element().Class(ContainerButton.StyleClassButton).Class(ButtonOpenBoth)
- .Pseudo(ContainerButton.StylePseudoClassNormal)
- .Prop(ContainerButton.StylePropertyStyleBox, buttonBNormal),
-
- Element().Class(ContainerButton.StyleClassButton).Class(ButtonOpenBoth)
- .Pseudo(ContainerButton.StylePseudoClassHover)
- .Prop(ContainerButton.StylePropertyStyleBox, buttonBHover),
-
- Element().Class(ContainerButton.StyleClassButton).Class(ButtonOpenBoth)
- .Pseudo(ContainerButton.StylePseudoClassPressed)
- .Prop(ContainerButton.StylePropertyStyleBox, buttonBPressed),
-
- Element().Class(ContainerButton.StyleClassButton).Class(ButtonOpenBoth)
- .Pseudo(ContainerButton.StylePseudoClassDisabled)
- .Prop(ContainerButton.StylePropertyStyleBox, buttonBDisabled),
-
+ .Prop(Control.StylePropertyModulateSelf, ButtonColorCautionDisabled),
new StyleRule(new SelectorChild(
new SelectorElement(typeof(Button), null, null, new[] {ContainerButton.StylePseudoClassDisabled}),
@@ -649,25 +610,28 @@ namespace Content.Client.UserInterface.Stylesheets
}),
// Those top menu buttons.
+ Element()
+ .Prop(Button.StylePropertyStyleBox, BaseButton),
+
new StyleRule(
new SelectorElement(typeof(GameHud.TopButton), null, null, new[] {Button.StylePseudoClassNormal}),
new[]
{
- new StyleProperty(Button.StylePropertyStyleBox, buttonNormal),
+ new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorDefault),
}),
new StyleRule(
new SelectorElement(typeof(GameHud.TopButton), null, null, new[] {Button.StylePseudoClassPressed}),
new[]
{
- new StyleProperty(Button.StylePropertyStyleBox, buttonPressed),
+ new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorPressed),
}),
new StyleRule(
new SelectorElement(typeof(GameHud.TopButton), null, null, new[] {Button.StylePseudoClassHover}),
new[]
{
- new StyleProperty(Button.StylePropertyStyleBox, buttonHover),
+ new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorHovered),
}),
new StyleRule(
@@ -758,21 +722,25 @@ namespace Content.Client.UserInterface.Stylesheets
}),
// OptionButton
+ new StyleRule(new SelectorElement(typeof(OptionButton), null, null, null), new[]
+ {
+ new StyleProperty(ContainerButton.StylePropertyStyleBox, BaseButton),
+ }),
new StyleRule(new SelectorElement(typeof(OptionButton), null, null, new[] {ContainerButton.StylePseudoClassNormal}), new[]
{
- new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonNormal),
+ new StyleProperty(Control.StylePropertyModulateSelf, ButtonColorDefault),
}),
new StyleRule(new SelectorElement(typeof(OptionButton), null, null, new[] {ContainerButton.StylePseudoClassHover}), new[]
{
- new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonHover),
+ new StyleProperty(Control.StylePropertyModulateSelf, ButtonColorHovered),
}),
new StyleRule(new SelectorElement(typeof(OptionButton), null, null, new[] {ContainerButton.StylePseudoClassPressed}), new[]
{
- new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonPressed),
+ new StyleProperty(Control.StylePropertyModulateSelf, ButtonColorPressed),
}),
new StyleRule(new SelectorElement(typeof(OptionButton), null, null, new[] {ContainerButton.StylePseudoClassDisabled}), new[]
{
- new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonDisabled),
+ new StyleProperty(Control.StylePropertyModulateSelf, ButtonColorDisabled),
}),
new StyleRule(new SelectorElement(typeof(TextureRect), new[] {OptionButton.StyleClassOptionTriangle}, null, null), new[]
diff --git a/Content.Client/UserInterface/Stylesheets/StyleSpace.cs b/Content.Client/UserInterface/Stylesheets/StyleSpace.cs
index 696321ab7c..3411e91032 100644
--- a/Content.Client/UserInterface/Stylesheets/StyleSpace.cs
+++ b/Content.Client/UserInterface/Stylesheets/StyleSpace.cs
@@ -18,6 +18,11 @@ namespace Content.Client.UserInterface.Stylesheets
public static readonly Color ButtonColorPressed = Color.FromHex("#3e6c45");
public static readonly Color ButtonColorDisabled = Color.FromHex("#30313c");
+ public static readonly Color ButtonColorCautionDefault = Color.FromHex("#ab3232");
+ public static readonly Color ButtonColorCautionHovered = Color.FromHex("#cf2f2f");
+ public static readonly Color ButtonColorCautionPressed = Color.FromHex("#3e6c45");
+ public static readonly Color ButtonColorCautionDisabled = Color.FromHex("#602a2a");
+
public override Stylesheet Stylesheet { get; }
public StyleSpace(IResourceCache resCache) : base(resCache)
@@ -25,29 +30,6 @@ namespace Content.Client.UserInterface.Stylesheets
var notoSans10 = resCache.GetFont("/Textures/Interface/Nano/NotoSans/NotoSans-Regular.ttf", 10);
var notoSansBold16 = resCache.GetFont("/Textures/Interface/Nano/NotoSans/NotoSans-Bold.ttf", 16);
- static (StyleBox, StyleBox, StyleBox, StyleBox) ButtonPermutations(StyleBoxTexture @base)
- {
- var normal = new StyleBoxTexture(@base) {Modulate = ButtonColorDefault};
- var hover = new StyleBoxTexture(@base) {Modulate = ButtonColorHovered};
- var pressed = new StyleBoxTexture(@base) {Modulate = ButtonColorPressed};
- var disabled = new StyleBoxTexture(@base) {Modulate = ButtonColorDisabled};
-
- return (normal, hover, pressed, disabled);
- }
-
- // Button styles.
- var (buttonNormal, buttonHover, buttonPressed, buttonDisabled)
- = ButtonPermutations(BaseButton);
-
- var (buttonRNormal, buttonRHover, buttonRPressed, buttonRDisabled)
- = ButtonPermutations(BaseButtonOpenRight);
-
- var (buttonLNormal, buttonLHover, buttonLPressed, buttonLDisabled)
- = ButtonPermutations(BaseButtonOpenLeft);
-
- var (buttonBNormal, buttonBHover, buttonBPressed, buttonBDisabled)
- = ButtonPermutations(BaseButtonOpenBoth);
-
Stylesheet = new Stylesheet(BaseRules.Concat(new StyleRule[]
{
Element