diff --git a/Content.Client/AI/ClientAiDebugSystem.cs b/Content.Client/AI/ClientAiDebugSystem.cs
index e60014f48f..fb3a657c4b 100644
--- a/Content.Client/AI/ClientAiDebugSystem.cs
+++ b/Content.Client/AI/ClientAiDebugSystem.cs
@@ -8,6 +8,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.AI
{
@@ -169,8 +170,9 @@ namespace Content.Client.AI
MouseFilter = Control.MouseFilterMode.Ignore,
};
- var vBox = new VBoxContainer()
+ var vBox = new BoxContainer()
{
+ Orientation = LayoutOrientation.Vertical,
SeparationOverride = 15,
Children = {actionLabel, pathfindingLabel},
};
diff --git a/Content.Client/AME/UI/AMEWindow.cs b/Content.Client/AME/UI/AMEWindow.cs
index 0b56471431..e9104e6f67 100644
--- a/Content.Client/AME/UI/AMEWindow.cs
+++ b/Content.Client/AME/UI/AMEWindow.cs
@@ -6,6 +6,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using static Content.Shared.AME.SharedAMEControllerComponent;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.AME.UI
{
@@ -30,58 +31,66 @@ namespace Content.Client.AME.UI
MinSize = SetSize = (250, 250);
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = Loc.GetString("ame-window-engine-status-label") + " "},
(InjectionStatus = new Label {Text = Loc.GetString("ame-window-engine-injection-status-not-injecting-label")})
}
},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
(ToggleInjection = new Button {Text = Loc.GetString("ame-window-toggle-injection-button"), StyleClasses = {StyleBase.ButtonOpenBoth}, Disabled = true}),
}
},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = Loc.GetString("ame-window-fuel-status-label") + " "},
(FuelAmount = new Label {Text = Loc.GetString("ame-window-fuel-not-inserted-text")})
}
},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
(EjectButton = new Button {Text = Loc.GetString("ame-window-eject-button"), StyleClasses = {StyleBase.ButtonOpenBoth}, Disabled = true}),
}
},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = Loc.GetString("ame-window-injection-amount-label") + " "},
(InjectionAmount = new Label {Text = "0"})
}
},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
(IncreaseFuelButton = new Button {Text = Loc.GetString("ame-window-increase-fuel-button"), StyleClasses = {StyleBase.ButtonOpenRight}}),
(DecreaseFuelButton = new Button {Text = Loc.GetString("ame-window-decrease-fuel-button"), StyleClasses = {StyleBase.ButtonOpenLeft}}),
}
},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label { Text = Loc.GetString("ame-window-core-count-label") + " "},
diff --git a/Content.Client/Access/UI/IdCardConsoleWindow.cs b/Content.Client/Access/UI/IdCardConsoleWindow.cs
index 450aa0ebdd..4c3093baa2 100644
--- a/Content.Client/Access/UI/IdCardConsoleWindow.cs
+++ b/Content.Client/Access/UI/IdCardConsoleWindow.cs
@@ -8,6 +8,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using static Content.Shared.Access.SharedIdCardConsoleComponent;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Access.UI
{
@@ -38,7 +39,10 @@ namespace Content.Client.Access.UI
{
MinSize = SetSize = (650, 290);
_owner = owner;
- var vBox = new VBoxContainer();
+ var vBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
vBox.AddChild(new GridContainer
{
diff --git a/Content.Client/Actions/UI/ActionAlertTooltip.cs b/Content.Client/Actions/UI/ActionAlertTooltip.cs
index 8ebb9c8642..b64faa56b1 100644
--- a/Content.Client/Actions/UI/ActionAlertTooltip.cs
+++ b/Content.Client/Actions/UI/ActionAlertTooltip.cs
@@ -4,6 +4,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Shared.IoC;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Actions.UI
{
@@ -28,8 +29,12 @@ namespace Content.Client.Actions.UI
SetOnlyStyleClass(StyleNano.StyleClassTooltipPanel);
- VBoxContainer vbox;
- AddChild(vbox = new VBoxContainer {RectClipContent = true});
+ BoxContainer vbox;
+ AddChild(vbox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical,
+ RectClipContent = true
+ });
var nameLabel = new RichTextLabel
{
MaxWidth = TooltipTextMaxWidth,
diff --git a/Content.Client/Actions/UI/ActionMenu.cs b/Content.Client/Actions/UI/ActionMenu.cs
index f935adfd3c..bb7f996ad0 100644
--- a/Content.Client/Actions/UI/ActionMenu.cs
+++ b/Content.Client/Actions/UI/ActionMenu.cs
@@ -19,6 +19,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Timing;
using static Robust.Client.UserInterface.Controls.BaseButton;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Actions.UI
{
@@ -71,12 +72,14 @@ namespace Content.Client.Actions.UI
Title = Loc.GetString("ui-actionmenu-title");
MinSize = (300, 300);
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
(_searchBar = new LineEdit
diff --git a/Content.Client/Actions/UI/ActionSlot.cs b/Content.Client/Actions/UI/ActionSlot.cs
index 29b4b48b82..36702eddd9 100644
--- a/Content.Client/Actions/UI/ActionSlot.cs
+++ b/Content.Client/Actions/UI/ActionSlot.cs
@@ -16,6 +16,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Actions.UI
{
@@ -174,8 +175,9 @@ namespace Content.Client.Actions.UI
_cooldownGraphic = new CooldownGraphic {Progress = 0, Visible = false};
// padding to the left of the number to shift it right
- var paddingBox = new HBoxContainer()
+ var paddingBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
VerticalExpand = true,
MinSize = (64, 64)
@@ -187,8 +189,9 @@ namespace Content.Client.Actions.UI
paddingBox.AddChild(_number);
// padding to the left of the small icon
- var paddingBoxItemIcon = new HBoxContainer()
+ var paddingBoxItemIcon = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
VerticalExpand = true,
MinSize = (64, 64)
diff --git a/Content.Client/Actions/UI/ActionsUI.cs b/Content.Client/Actions/UI/ActionsUI.cs
index 7c9b5ca86b..7544bece52 100644
--- a/Content.Client/Actions/UI/ActionsUI.cs
+++ b/Content.Client/Actions/UI/ActionsUI.cs
@@ -18,6 +18,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Timing;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Actions.UI
{
@@ -42,7 +43,7 @@ namespace Content.Client.Actions.UI
private readonly Label _loadoutNumber;
private readonly Texture _lockTexture;
private readonly Texture _unlockTexture;
- private readonly HBoxContainer _loadoutContainer;
+ private readonly BoxContainer _loadoutContainer;
private readonly TextureRect _dragShadow;
@@ -108,15 +109,17 @@ namespace Content.Client.Actions.UI
};
AddChild(panelContainer);
- var hotbarContainer = new VBoxContainer
+ var hotbarContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
SeparationOverride = 3,
HorizontalAlignment = HAlignment.Left
};
panelContainer.AddChild(hotbarContainer);
- var settingsContainer = new HBoxContainer
+ var settingsContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true
};
hotbarContainer.AddChild(settingsContainer);
@@ -156,8 +159,9 @@ namespace Content.Client.Actions.UI
};
hotbarContainer.AddChild(_slotContainer);
- _loadoutContainer = new HBoxContainer
+ _loadoutContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
MouseFilter = MouseFilterMode.Stop
};
diff --git a/Content.Client/Administration/UI/AdminAddReagentUI.cs b/Content.Client/Administration/UI/AdminAddReagentUI.cs
index 397b899369..425fb16746 100644
--- a/Content.Client/Administration/UI/AdminAddReagentUI.cs
+++ b/Content.Client/Administration/UI/AdminAddReagentUI.cs
@@ -8,6 +8,7 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Prototypes;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Administration.UI
{
@@ -65,8 +66,9 @@ namespace Content.Client.Administration.UI
Title = Loc.GetString("admin-add-reagent-eui-title");
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
new GridContainer
@@ -88,8 +90,9 @@ namespace Content.Client.Administration.UI
HorizontalExpand = true,
VerticalExpand = true
},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
(_errorLabel = new Label
diff --git a/Content.Client/Administration/UI/AdminMenuWindow.xaml.cs b/Content.Client/Administration/UI/AdminMenuWindow.xaml.cs
index f527a28c8d..bb431027b0 100644
--- a/Content.Client/Administration/UI/AdminMenuWindow.xaml.cs
+++ b/Content.Client/Administration/UI/AdminMenuWindow.xaml.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System.Collections.Generic;
using Content.Client.Administration.UI.Tabs;
using Content.Client.HUD;
diff --git a/Content.Client/Administration/UI/CustomControls/CommandButton.cs b/Content.Client/Administration/UI/CustomControls/CommandButton.cs
index c4dce7e05d..9986eac3c1 100644
--- a/Content.Client/Administration/UI/CustomControls/CommandButton.cs
+++ b/Content.Client/Administration/UI/CustomControls/CommandButton.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using Robust.Client.Console;
+using Robust.Client.Console;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.IoC;
diff --git a/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml b/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml
index 33d5d6d535..4f64435d42 100644
--- a/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml
+++ b/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml
@@ -1,13 +1,13 @@
-
-
+
-
+
-
+
diff --git a/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs b/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs
index c582b234c0..fa1dfeb613 100644
--- a/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs
+++ b/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using Robust.Client.AutoGenerated;
diff --git a/Content.Client/Administration/UI/CustomControls/UICommandButton.cs b/Content.Client/Administration/UI/CustomControls/UICommandButton.cs
index dd38f32479..eeeb214397 100644
--- a/Content.Client/Administration/UI/CustomControls/UICommandButton.cs
+++ b/Content.Client/Administration/UI/CustomControls/UICommandButton.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System;
+using System;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC;
diff --git a/Content.Client/Administration/UI/PermissionsEui.cs b/Content.Client/Administration/UI/PermissionsEui.cs
index feaa2b751d..8aa8b32a6f 100644
--- a/Content.Client/Administration/UI/PermissionsEui.cs
+++ b/Content.Client/Administration/UI/PermissionsEui.cs
@@ -14,6 +14,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
using static Content.Shared.Administration.PermissionsEuiMsg;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Administration.UI
{
@@ -316,15 +317,17 @@ namespace Content.Client.Administration.UI
};
AdminsList = new GridContainer {Columns = 5, VerticalExpand = true};
- var adminVBox = new VBoxContainer
+ var adminVBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children = {AdminsList, AddAdminButton},
};
TabContainer.SetTabTitle(adminVBox, Loc.GetString("permissions-eui-menu-admins-tab-title"));
AdminRanksList = new GridContainer {Columns = 3};
- var rankVBox = new VBoxContainer
+ var rankVBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children = { AdminRanksList, AddAdminRankButton}
};
TabContainer.SetTabTitle(rankVBox, Loc.GetString("permissions-eui-menu-admin-ranks-tab-title"));
@@ -451,7 +454,10 @@ namespace Content.Client.Administration.UI
FlagButtons.Add(flag, (inherit, sub, plus));
}
- var bottomButtons = new HBoxContainer();
+ var bottomButtons = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
if (data != null)
{
// show remove button.
@@ -461,17 +467,20 @@ namespace Content.Client.Administration.UI
bottomButtons.AddChild(SaveButton);
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 2,
Children =
{
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true,
Children =
{
@@ -541,7 +550,10 @@ namespace Content.Client.Administration.UI
HorizontalAlignment = HAlignment.Right,
HorizontalExpand = true
};
- var flagsBox = new VBoxContainer();
+ var flagsBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
foreach (var flag in AdminFlagsHelper.AllFlags)
{
@@ -565,7 +577,10 @@ namespace Content.Client.Administration.UI
flagsBox.AddChild(checkBox);
}
- var bottomButtons = new HBoxContainer();
+ var bottomButtons = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
if (data != null)
{
// show remove button.
@@ -575,8 +590,9 @@ namespace Content.Client.Administration.UI
bottomButtons.AddChild(SaveButton);
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
NameEdit,
diff --git a/Content.Client/Administration/UI/SetOutfit/SetOutfitMenu.xaml b/Content.Client/Administration/UI/SetOutfit/SetOutfitMenu.xaml
index 6cdafeb1c8..efb831cd1b 100644
--- a/Content.Client/Administration/UI/SetOutfit/SetOutfitMenu.xaml
+++ b/Content.Client/Administration/UI/SetOutfit/SetOutfitMenu.xaml
@@ -1,15 +1,15 @@
-
-
-
+
+
-
+
-
-
+
+
diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml b/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml
index 30a1cb64bf..98167d55c8 100644
--- a/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml
+++ b/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml
@@ -5,7 +5,7 @@
xmlns:at="clr-namespace:Content.Client.Administration.UI.Tabs.AdminTab"
Margin="4"
MinSize="50 50">
-
+
@@ -13,5 +13,5 @@
-
+
diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml.cs b/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml.cs
index aa9fc7307c..02dad6cbd2 100644
--- a/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using Robust.Client.AutoGenerated;
+using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
namespace Content.Client.Administration.UI.Tabs.AdminTab
diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/BanWindow.xaml b/Content.Client/Administration/UI/Tabs/AdminTab/BanWindow.xaml
index 18b82ca927..d81942655a 100644
--- a/Content.Client/Administration/UI/Tabs/AdminTab/BanWindow.xaml
+++ b/Content.Client/Administration/UI/Tabs/AdminTab/BanWindow.xaml
@@ -1,23 +1,23 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
+
diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/BanWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AdminTab/BanWindow.xaml.cs
index f45c3c3250..834348c66e 100644
--- a/Content.Client/Administration/UI/Tabs/AdminTab/BanWindow.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/AdminTab/BanWindow.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using JetBrains.Annotations;
+using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
using Robust.Client.Console;
using Robust.Client.UserInterface.Controls;
diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/KickWindow.xaml b/Content.Client/Administration/UI/Tabs/AdminTab/KickWindow.xaml
index 72d79c8a53..c1ee96cfe6 100644
--- a/Content.Client/Administration/UI/Tabs/AdminTab/KickWindow.xaml
+++ b/Content.Client/Administration/UI/Tabs/AdminTab/KickWindow.xaml
@@ -2,13 +2,13 @@
xmlns="https://spacestation14.io"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc Kick}" MinSize="425 272">
-
-
+
+
-
+
-
+
diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/KickWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AdminTab/KickWindow.xaml.cs
index 761be3d836..786123fab2 100644
--- a/Content.Client/Administration/UI/Tabs/AdminTab/KickWindow.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/AdminTab/KickWindow.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using JetBrains.Annotations;
+using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
using Robust.Client.Console;
using Robust.Client.UserInterface.Controls;
diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml b/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml
index ef7635c599..380ee75ed4 100644
--- a/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml
+++ b/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml
@@ -2,8 +2,8 @@
xmlns="https://spacestation14.io"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc Teleport}" MinSize="425 230">
-
+
-
+
diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml.cs
index 5c8c5fc43b..f0b044c500 100644
--- a/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using JetBrains.Annotations;
+using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
using Robust.Client.Console;
using Robust.Client.UserInterface.Controls;
diff --git a/Content.Client/Administration/UI/Tabs/AdminbusTab/AdminbusTab.xaml.cs b/Content.Client/Administration/UI/Tabs/AdminbusTab/AdminbusTab.xaml.cs
index 20d22ceb0e..698880b754 100644
--- a/Content.Client/Administration/UI/Tabs/AdminbusTab/AdminbusTab.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/AdminbusTab/AdminbusTab.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using Content.Client.Administration.Managers;
+using Content.Client.Administration.Managers;
using Robust.Client.AutoGenerated;
using Robust.Client.Placement;
using Robust.Client.ResourceManagement;
@@ -15,6 +14,9 @@ namespace Content.Client.Administration.UI.Tabs.AdminbusTab
[GenerateTypedNameReferences]
public partial class AdminbusTab : Control
{
+ private EntitySpawnWindow? _entitySpawnWindow;
+ private TileSpawnWindow? _tileSpawnWindow;
+
protected override void EnteredTree()
{
// For the SpawnEntitiesButton and SpawnTilesButton we need to do the press manually
@@ -23,22 +25,22 @@ namespace Content.Client.Administration.UI.Tabs.AdminbusTab
SpawnTilesButton.OnPressed += SpawnTilesButtonOnOnPressed;
}
- private static void SpawnEntitiesButtonOnOnPressed(BaseButton.ButtonEventArgs obj)
+ private void SpawnEntitiesButtonOnOnPressed(BaseButton.ButtonEventArgs obj)
{
var manager = IoCManager.Resolve();
- var window = new EntitySpawnWindow(IoCManager.Resolve(),
+ _entitySpawnWindow ??= new EntitySpawnWindow(IoCManager.Resolve(),
IoCManager.Resolve(),
IoCManager.Resolve());
- manager.OpenCommand(window);
+ manager.OpenCommand(_entitySpawnWindow);
}
- private static void SpawnTilesButtonOnOnPressed(BaseButton.ButtonEventArgs obj)
+ private void SpawnTilesButtonOnOnPressed(BaseButton.ButtonEventArgs obj)
{
var manager = IoCManager.Resolve();
- var window = new TileSpawnWindow(IoCManager.Resolve(),
+ _tileSpawnWindow ??= new TileSpawnWindow(IoCManager.Resolve(),
IoCManager.Resolve(),
IoCManager.Resolve());
- manager.OpenCommand(window);
+ manager.OpenCommand(_tileSpawnWindow);
}
}
}
diff --git a/Content.Client/Administration/UI/Tabs/AdminbusTab/StationEventsWindow.xaml b/Content.Client/Administration/UI/Tabs/AdminbusTab/StationEventsWindow.xaml
index 097eb0f150..709d665fb6 100644
--- a/Content.Client/Administration/UI/Tabs/AdminbusTab/StationEventsWindow.xaml
+++ b/Content.Client/Administration/UI/Tabs/AdminbusTab/StationEventsWindow.xaml
@@ -1,13 +1,13 @@
-
-
+
+
-
+
-
+
diff --git a/Content.Client/Administration/UI/Tabs/AdminbusTab/StationEventsWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AdminbusTab/StationEventsWindow.xaml.cs
index f500ece192..a26d41934c 100644
--- a/Content.Client/Administration/UI/Tabs/AdminbusTab/StationEventsWindow.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/AdminbusTab/StationEventsWindow.xaml.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System.Collections.Generic;
using System.Linq;
using Content.Client.StationEvents.Managers;
diff --git a/Content.Client/Administration/UI/Tabs/AtmosTab/AddAtmosWindow.xaml b/Content.Client/Administration/UI/Tabs/AtmosTab/AddAtmosWindow.xaml
index bdc9528ba8..c2857cc733 100644
--- a/Content.Client/Administration/UI/Tabs/AtmosTab/AddAtmosWindow.xaml
+++ b/Content.Client/Administration/UI/Tabs/AtmosTab/AddAtmosWindow.xaml
@@ -1,11 +1,11 @@
-
-
+
+
-
+
-
+
diff --git a/Content.Client/Administration/UI/Tabs/AtmosTab/AddAtmosWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AtmosTab/AddAtmosWindow.xaml.cs
index 6867a1bc8f..11390ea3b8 100644
--- a/Content.Client/Administration/UI/Tabs/AtmosTab/AddAtmosWindow.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/AtmosTab/AddAtmosWindow.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
diff --git a/Content.Client/Administration/UI/Tabs/AtmosTab/AddGasWindow.xaml b/Content.Client/Administration/UI/Tabs/AtmosTab/AddGasWindow.xaml
index d31d48dd8c..4b5f9d46e0 100644
--- a/Content.Client/Administration/UI/Tabs/AtmosTab/AddGasWindow.xaml
+++ b/Content.Client/Administration/UI/Tabs/AtmosTab/AddGasWindow.xaml
@@ -1,31 +1,31 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
+
diff --git a/Content.Client/Administration/UI/Tabs/AtmosTab/AddGasWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AtmosTab/AddGasWindow.xaml.cs
index 273d194196..1d43aeeb23 100644
--- a/Content.Client/Administration/UI/Tabs/AtmosTab/AddGasWindow.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/AtmosTab/AddGasWindow.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using Content.Client.Atmos.EntitySystems;
using Content.Shared.Atmos;
diff --git a/Content.Client/Administration/UI/Tabs/AtmosTab/AtmosTab.xaml.cs b/Content.Client/Administration/UI/Tabs/AtmosTab/AtmosTab.xaml.cs
index a27a42c07e..b7d682e12a 100644
--- a/Content.Client/Administration/UI/Tabs/AtmosTab/AtmosTab.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/AtmosTab/AtmosTab.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using Robust.Client.AutoGenerated;
+using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
namespace Content.Client.Administration.UI.Tabs.AtmosTab
diff --git a/Content.Client/Administration/UI/Tabs/AtmosTab/FillGasWindow.xaml b/Content.Client/Administration/UI/Tabs/AtmosTab/FillGasWindow.xaml
index e06e390ba8..715653236d 100644
--- a/Content.Client/Administration/UI/Tabs/AtmosTab/FillGasWindow.xaml
+++ b/Content.Client/Administration/UI/Tabs/AtmosTab/FillGasWindow.xaml
@@ -1,21 +1,21 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
+
diff --git a/Content.Client/Administration/UI/Tabs/AtmosTab/FillGasWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AtmosTab/FillGasWindow.xaml.cs
index 2465d8c61d..6c51f34357 100644
--- a/Content.Client/Administration/UI/Tabs/AtmosTab/FillGasWindow.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/AtmosTab/FillGasWindow.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using Content.Client.Atmos.EntitySystems;
using Content.Shared.Atmos;
diff --git a/Content.Client/Administration/UI/Tabs/AtmosTab/SetTemperatureWindow.xaml b/Content.Client/Administration/UI/Tabs/AtmosTab/SetTemperatureWindow.xaml
index 97abb3ecb7..da471f500e 100644
--- a/Content.Client/Administration/UI/Tabs/AtmosTab/SetTemperatureWindow.xaml
+++ b/Content.Client/Administration/UI/Tabs/AtmosTab/SetTemperatureWindow.xaml
@@ -1,26 +1,26 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
+
diff --git a/Content.Client/Administration/UI/Tabs/AtmosTab/SetTemperatureWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AtmosTab/SetTemperatureWindow.xaml.cs
index 234dde6a84..a5be641a21 100644
--- a/Content.Client/Administration/UI/Tabs/AtmosTab/SetTemperatureWindow.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/AtmosTab/SetTemperatureWindow.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
diff --git a/Content.Client/Administration/UI/Tabs/PlayerTab.xaml b/Content.Client/Administration/UI/Tabs/PlayerTab.xaml
index 4cca89fb11..6c17639df7 100644
--- a/Content.Client/Administration/UI/Tabs/PlayerTab.xaml
+++ b/Content.Client/Administration/UI/Tabs/PlayerTab.xaml
@@ -1,14 +1,14 @@
-
-
+
+
-
+
-
+
-
+
diff --git a/Content.Client/Administration/UI/Tabs/PlayerTab.xaml.cs b/Content.Client/Administration/UI/Tabs/PlayerTab.xaml.cs
index 020f64ade0..a128c9ad1b 100644
--- a/Content.Client/Administration/UI/Tabs/PlayerTab.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/PlayerTab.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-
+
using System.Collections.Generic;
using Content.Shared.Administration.Menu;
using Robust.Client.AutoGenerated;
@@ -10,6 +9,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Administration.UI.Tabs
{
@@ -41,8 +41,9 @@ namespace Content.Client.Administration.UI.Tabs
var altColor = Color.FromHex("#292B38");
var defaultColor = Color.FromHex("#2F2F3B");
- var header = new HBoxContainer
+ var header = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
SeparationOverride = 4,
Children =
@@ -85,8 +86,9 @@ namespace Content.Client.Administration.UI.Tabs
var useAltColor = false;
foreach (var player in players)
{
- var hBox = new HBoxContainer
+ var hBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
SeparationOverride = 4,
Children =
diff --git a/Content.Client/Administration/UI/Tabs/RoundTab.xaml.cs b/Content.Client/Administration/UI/Tabs/RoundTab.xaml.cs
index bfe1dfe3af..0e897bd376 100644
--- a/Content.Client/Administration/UI/Tabs/RoundTab.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/RoundTab.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using Robust.Client.AutoGenerated;
+using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
namespace Content.Client.Administration.UI.Tabs
diff --git a/Content.Client/Administration/UI/Tabs/ServerTab.xaml.cs b/Content.Client/Administration/UI/Tabs/ServerTab.xaml.cs
index fbb52bf7b0..9f7d6a0e40 100644
--- a/Content.Client/Administration/UI/Tabs/ServerTab.xaml.cs
+++ b/Content.Client/Administration/UI/Tabs/ServerTab.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using Robust.Client.AutoGenerated;
+using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
namespace Content.Client.Administration.UI.Tabs
diff --git a/Content.Client/Alerts/UI/AlertsUI.cs b/Content.Client/Alerts/UI/AlertsUI.cs
index f5064438ee..46e6721acd 100644
--- a/Content.Client/Alerts/UI/AlertsUI.cs
+++ b/Content.Client/Alerts/UI/AlertsUI.cs
@@ -48,7 +48,7 @@ namespace Content.Client.Alerts.UI
base.EnteredTree();
var _chatManager = IoCManager.Resolve();
_chatManager.OnChatBoxResized += OnChatResized;
- OnChatResized(new ChatResizedEventArgs(ChatBox.InitialChatBottom));
+ OnChatResized(new ChatResizedEventArgs(HudChatBox.InitialChatBottom));
}
protected override void ExitedTree()
diff --git a/Content.Client/Arcade/BlockGameMenu.cs b/Content.Client/Arcade/BlockGameMenu.cs
index 0ac7329a71..ce11b1a6e4 100644
--- a/Content.Client/Arcade/BlockGameMenu.cs
+++ b/Content.Client/Arcade/BlockGameMenu.cs
@@ -14,6 +14,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Arcade
{
@@ -28,7 +29,7 @@ namespace Content.Client.Arcade
private readonly PanelContainer _mainPanel;
- private VBoxContainer _gameRootContainer;
+ private BoxContainer _gameRootContainer;
private GridContainer _gameGrid = default!;
private GridContainer _nextBlockGrid = default!;
private GridContainer _holdBlockGrid = default!;
@@ -68,7 +69,10 @@ namespace Content.Client.Arcade
#region Game Menu
// building the game container
- _gameRootContainer = new VBoxContainer();
+ _gameRootContainer = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
_levelLabel = new Label
{
@@ -92,7 +96,10 @@ namespace Content.Client.Arcade
MinSize = new Vector2(1,10)
});
- var gameBox = new HBoxContainer();
+ var gameBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
gameBox.AddChild(SetupHoldBox(backgroundTexture));
gameBox.AddChild(new Control
{
@@ -152,8 +159,9 @@ namespace Content.Client.Arcade
_menuRootContainer.AddChild(pauseMenuInnerPanel);
- var pauseMenuContainer = new VBoxContainer
+ var pauseMenuContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center
};
@@ -224,8 +232,9 @@ namespace Content.Client.Arcade
_gameOverRootContainer.AddChild(gameOverMenuInnerPanel);
- var gameOverMenuContainer = new VBoxContainer
+ var gameOverMenuContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center
};
@@ -282,8 +291,9 @@ namespace Content.Client.Arcade
_highscoresRootContainer.AddChild(menuInnerPanel);
- var menuContainer = new VBoxContainer()
+ var menuContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center
};
@@ -291,7 +301,10 @@ namespace Content.Client.Arcade
menuContainer.AddChild(new Label{Text = Loc.GetString("blockgame-menu-label-highscores")});
menuContainer.AddChild(new Control{MinSize = new Vector2(1,10)});
- var highScoreBox = new HBoxContainer();
+ var highScoreBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
_localHighscoresLabel = new Label
{
diff --git a/Content.Client/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs b/Content.Client/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs
index d714789aa0..72fa97c32a 100644
--- a/Content.Client/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs
+++ b/Content.Client/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System.Collections.Generic;
using Content.Client.Atmos.Overlays;
using Content.Shared.Atmos;
diff --git a/Content.Client/Atmos/EntitySystems/GasTileOverlaySystem.cs b/Content.Client/Atmos/EntitySystems/GasTileOverlaySystem.cs
index 470c4cae0c..9beb61a3c9 100644
--- a/Content.Client/Atmos/EntitySystems/GasTileOverlaySystem.cs
+++ b/Content.Client/Atmos/EntitySystems/GasTileOverlaySystem.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System;
using System.Collections.Generic;
using Content.Client.Atmos.Overlays;
diff --git a/Content.Client/Atmos/UI/GasAnalyzerMenu.cs b/Content.Client/Atmos/UI/GasAnalyzerMenu.cs
index 3c114f7d7c..86122932a4 100644
--- a/Content.Client/Atmos/UI/GasAnalyzerMenu.cs
+++ b/Content.Client/Atmos/UI/GasAnalyzerMenu.cs
@@ -10,6 +10,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using static Content.Shared.Atmos.Components.SharedGasAnalyzerComponent;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Atmos.UI
{
@@ -61,11 +62,15 @@ namespace Content.Client.Atmos.UI
LayoutContainer.SetAnchorPreset(bottomWrap, LayoutContainer.LayoutPreset.VerticalCenterWide);
LayoutContainer.SetGrowHorizontal(bottomWrap, LayoutContainer.GrowDirection.Both);
- var topContainerWrap = new VBoxContainer
+ var topContainerWrap = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
- (_topContainer = new VBoxContainer()),
+ (_topContainer = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ }),
new Control {MinSize = (0, 110)}
}
};
@@ -78,8 +83,9 @@ namespace Content.Client.Atmos.UI
var fontSmall = resourceCache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 10);
Button refreshButton;
- var topRow = new HBoxContainer
+ var topRow = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Margin = new Thickness(4, 4, 12, 2),
Children =
{
@@ -118,8 +124,9 @@ namespace Content.Client.Atmos.UI
PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#202025") },
Children =
{
- (_statusContainer = new VBoxContainer
+ (_statusContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(8, 8, 4, 4)
})
}
@@ -178,10 +185,17 @@ namespace Content.Client.Atmos.UI
});
// Add a table with all the gases
- var tableKey = new VBoxContainer();
- var tableVal = new VBoxContainer();
- _statusContainer.AddChild(new HBoxContainer
+ var tableKey = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical
+ };
+ var tableVal = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
+ _statusContainer.AddChild(new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
tableKey,
@@ -195,8 +209,9 @@ namespace Content.Client.Atmos.UI
// This is the gas bar thingy
var height = 30;
var minSize = 24; // This basically allows gases which are too small, to be shown properly
- var gasBar = new HBoxContainer
+ var gasBar = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
MinSize = new Vector2(0, height)
};
diff --git a/Content.Client/Atmos/UI/GasCanisterWindow.xaml b/Content.Client/Atmos/UI/GasCanisterWindow.xaml
index 6bddc2ced3..69e2599523 100644
--- a/Content.Client/Atmos/UI/GasCanisterWindow.xaml
+++ b/Content.Client/Atmos/UI/GasCanisterWindow.xaml
@@ -2,51 +2,51 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:Content.Client.Stylesheets"
MinSize="480 400" Title="Canister">
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
diff --git a/Content.Client/Atmos/Visualizers/PipeConnectorVisualizer.cs b/Content.Client/Atmos/Visualizers/PipeConnectorVisualizer.cs
index 1e6d3c05a7..9f7e58d31b 100644
--- a/Content.Client/Atmos/Visualizers/PipeConnectorVisualizer.cs
+++ b/Content.Client/Atmos/Visualizers/PipeConnectorVisualizer.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Piping;
diff --git a/Content.Client/Audio/BackgroundAudioSystem.cs b/Content.Client/Audio/BackgroundAudioSystem.cs
index 9aa00712cd..4d79891649 100644
--- a/Content.Client/Audio/BackgroundAudioSystem.cs
+++ b/Content.Client/Audio/BackgroundAudioSystem.cs
@@ -1,4 +1,3 @@
-#nullable enable
using Content.Client.GameTicking.Managers;
using Content.Client.Lobby;
using Content.Client.Viewport;
diff --git a/Content.Client/Body/UI/BodyScannerDisplay.cs b/Content.Client/Body/UI/BodyScannerDisplay.cs
index 90b3436582..428a2b4516 100644
--- a/Content.Client/Body/UI/BodyScannerDisplay.cs
+++ b/Content.Client/Body/UI/BodyScannerDisplay.cs
@@ -8,6 +8,7 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
using static Robust.Client.UserInterface.Controls.ItemList;
namespace Content.Client.Body.UI
@@ -25,8 +26,9 @@ namespace Content.Client.Body.UI
Owner = owner;
Title = Loc.GetString("body-scanner-display-title");
- var hSplit = new HBoxContainer
+ var hSplit = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
// Left half
@@ -39,20 +41,23 @@ namespace Content.Client.Body.UI
}
},
// Right half
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true,
Children =
{
// Top half of the right half
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
VerticalExpand = true,
Children =
{
(BodyPartLabel = new Label()),
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label
diff --git a/Content.Client/Body/UI/SurgeryWindow.cs b/Content.Client/Body/UI/SurgeryWindow.cs
index ef771bab1e..9f8b18c5e0 100644
--- a/Content.Client/Body/UI/SurgeryWindow.cs
+++ b/Content.Client/Body/UI/SurgeryWindow.cs
@@ -5,6 +5,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Body.UI
{
@@ -12,7 +13,7 @@ namespace Content.Client.Body.UI
{
public delegate void OptionSelectedCallback(int selectedOptionData);
- private readonly VBoxContainer _optionsBox;
+ private readonly BoxContainer _optionsBox;
private OptionSelectedCallback? _optionSelectedCallback;
public SurgeryWindow()
@@ -21,8 +22,9 @@ namespace Content.Client.Body.UI
Title = Loc.GetString("surgery-window-title");
RectClipContent = true;
- var vSplitContainer = new VBoxContainer
+ var vSplitContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
new ScrollContainer
@@ -33,8 +35,9 @@ namespace Content.Client.Body.UI
VScrollEnabled = true,
Children =
{
- (_optionsBox = new VBoxContainer
+ (_optionsBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true
})
}
@@ -94,8 +97,9 @@ namespace Content.Client.Body.UI
AddChild(Button);
- AddChild(new HBoxContainer
+ AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
(SpriteView = new SpriteView
diff --git a/Content.Client/Buckle/BuckleComponent.cs b/Content.Client/Buckle/BuckleComponent.cs
index 542fb4e3ef..2e342aa203 100644
--- a/Content.Client/Buckle/BuckleComponent.cs
+++ b/Content.Client/Buckle/BuckleComponent.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using Content.Shared.Buckle.Components;
+using Content.Shared.Buckle.Components;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
diff --git a/Content.Client/Cargo/UI/CargoConsoleMenu.cs b/Content.Client/Cargo/UI/CargoConsoleMenu.cs
index 36eb189c4b..69a3e1a03b 100644
--- a/Content.Client/Cargo/UI/CargoConsoleMenu.cs
+++ b/Content.Client/Cargo/UI/CargoConsoleMenu.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System;
using System.Collections.Generic;
using Content.Client.Stylesheets;
@@ -11,6 +10,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using static Robust.Client.UserInterface.Controls.BaseButton;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Cargo.UI
{
@@ -28,12 +28,12 @@ namespace Content.Client.Cargo.UI
private Label _pointsLabel { get; set; }
private Label _shuttleStatusLabel { get; set; }
private Label _shuttleCapacityLabel { get; set; }
- private VBoxContainer _requests { get; set; }
- private VBoxContainer _orders { get; set; }
+ private BoxContainer _requests { get; set; }
+ private BoxContainer _orders { get; set; }
private OptionButton _categories { get; set; }
private LineEdit _searchBar { get; set; }
- public VBoxContainer Products { get; set; }
+ public BoxContainer Products { get; set; }
public Button CallShuttleButton { get; set; }
public Button PermissionsButton { get; set; }
@@ -50,9 +50,15 @@ namespace Content.Client.Cargo.UI
else
Title = Loc.GetString("cargo-console-menu-title");
- var rows = new VBoxContainer();
+ var rows = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
- var accountName = new HBoxContainer();
+ var accountName = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
var accountNameLabel = new Label {
Text = Loc.GetString("cargo-console-menu-account-name-label") + " ",
StyleClasses = { StyleNano.StyleClassLabelKeyText }
@@ -64,7 +70,10 @@ namespace Content.Client.Cargo.UI
accountName.AddChild(_accountNameLabel);
rows.AddChild(accountName);
- var points = new HBoxContainer();
+ var points = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
var pointsLabel = new Label
{
Text = Loc.GetString("cargo-console-menu-points-label") + " ",
@@ -78,7 +87,10 @@ namespace Content.Client.Cargo.UI
points.AddChild(_pointsLabel);
rows.AddChild(points);
- var shuttleStatus = new HBoxContainer();
+ var shuttleStatus = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
var shuttleStatusLabel = new Label
{
Text = Loc.GetString("cargo-console-menu-shuttle-status-label") + " ",
@@ -92,7 +104,10 @@ namespace Content.Client.Cargo.UI
shuttleStatus.AddChild(_shuttleStatusLabel);
rows.AddChild(shuttleStatus);
- var shuttleCapacity = new HBoxContainer();
+ var shuttleCapacity = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
var shuttleCapacityLabel = new Label
{
Text = Loc.GetString("cargo-console-menu-order-capacity-label") + " ",
@@ -106,7 +121,10 @@ namespace Content.Client.Cargo.UI
shuttleCapacity.AddChild(_shuttleCapacityLabel);
rows.AddChild(shuttleCapacity);
- var buttons = new HBoxContainer();
+ var buttons = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
CallShuttleButton = new Button()
{
//Text = Loc.GetString("Call Shuttle"),
@@ -123,7 +141,10 @@ namespace Content.Client.Cargo.UI
buttons.AddChild(PermissionsButton);
rows.AddChild(buttons);
- var category = new HBoxContainer();
+ var category = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
_categories = new OptionButton
{
Prefix = Loc.GetString("cargo-console-menu-categories-label") + " ",
@@ -146,8 +167,9 @@ namespace Content.Client.Cargo.UI
VerticalExpand = true,
SizeFlagsStretchRatio = 6
};
- Products = new VBoxContainer()
+ Products = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true,
VerticalExpand = true
};
@@ -164,17 +186,22 @@ namespace Content.Client.Cargo.UI
{
VerticalExpand = true
};
- var rAndOVBox = new VBoxContainer();
- var requestsLabel = new Label { Text = Loc.GetString("cargo-console-menu-requests-label") };
- _requests = new VBoxContainer // replace with scroll box so that approval buttons can be added
+ var rAndOVBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical
+ };
+ var requestsLabel = new Label { Text = Loc.GetString("cargo-console-menu-requests-label") };
+ _requests = new BoxContainer // replace with scroll box so that approval buttons can be added
+ {
+ Orientation = LayoutOrientation.Vertical,
StyleClasses = { "transparentItemList" },
VerticalExpand = true,
SizeFlagsStretchRatio = 1,
};
var ordersLabel = new Label { Text = Loc.GetString("cargo-console-menu-orders-label") };
- _orders = new VBoxContainer
+ _orders = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
StyleClasses = { "transparentItemList" },
VerticalExpand = true,
SizeFlagsStretchRatio = 1,
@@ -386,8 +413,9 @@ namespace Content.Client.Cargo.UI
};
AddChild(MainButton);
- var hBox = new HBoxContainer
+ var hBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true
};
@@ -433,8 +461,9 @@ namespace Content.Client.Cargo.UI
{
HorizontalExpand = true;
- var hBox = new HBoxContainer
+ var hBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
};
@@ -445,8 +474,9 @@ namespace Content.Client.Cargo.UI
};
hBox.AddChild(Icon);
- var vBox = new VBoxContainer
+ var vBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true,
VerticalExpand = true
};
diff --git a/Content.Client/Cargo/UI/CargoConsoleOrderMenu.cs b/Content.Client/Cargo/UI/CargoConsoleOrderMenu.cs
index d368abe666..f5daf8d4f1 100644
--- a/Content.Client/Cargo/UI/CargoConsoleOrderMenu.cs
+++ b/Content.Client/Cargo/UI/CargoConsoleOrderMenu.cs
@@ -3,6 +3,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Cargo.UI
{
@@ -19,7 +20,10 @@ namespace Content.Client.Cargo.UI
Title = Loc.GetString("cargo-console-order-menu-title");
- var vBox = new VBoxContainer();
+ var vBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
var gridContainer = new GridContainer { Columns = 2 };
var requesterLabel = new Label { Text = Loc.GetString("cargo-console-order-menu-requester-label") };
diff --git a/Content.Client/Changelog/ChangelogManager.cs b/Content.Client/Changelog/ChangelogManager.cs
index d0a34a5e23..48854ba45b 100644
--- a/Content.Client/Changelog/ChangelogManager.cs
+++ b/Content.Client/Changelog/ChangelogManager.cs
@@ -13,7 +13,6 @@ using Robust.Shared.Serialization.Markdown;
using Robust.Shared.Serialization.Markdown.Mapping;
using Robust.Shared.Utility;
-#nullable enable
namespace Content.Client.Changelog
{
diff --git a/Content.Client/Changelog/ChangelogWindow.xaml b/Content.Client/Changelog/ChangelogWindow.xaml
index c763c4ad2e..41ac1c70ee 100644
--- a/Content.Client/Changelog/ChangelogWindow.xaml
+++ b/Content.Client/Changelog/ChangelogWindow.xaml
@@ -3,20 +3,20 @@
xmlns:ui="clr-namespace:Content.Client.HUD.UI"
MinSize="500 400" MouseFilter="Stop">
-
-
+
+
-
+
-
+
-
+
diff --git a/Content.Client/Changelog/ChangelogWindow.xaml.cs b/Content.Client/Changelog/ChangelogWindow.xaml.cs
index f5e4360f1c..c6117128f9 100644
--- a/Content.Client/Changelog/ChangelogWindow.xaml.cs
+++ b/Content.Client/Changelog/ChangelogWindow.xaml.cs
@@ -15,6 +15,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
using static Content.Client.Changelog.ChangelogManager;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Changelog
{
@@ -94,10 +95,14 @@ namespace Content.Client.Changelog
var upArrow =
_resourceCache.GetTexture("/Textures/Interface/Changelog/up_arrow.svg.192dpi.png");
- var readDivider = new VBoxContainer();
-
- var hBox = new HBoxContainer
+ var readDivider = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical
+ };
+
+ var hBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal,
HorizontalAlignment = HAlignment.Center,
Children =
{
@@ -148,8 +153,9 @@ namespace Content.Client.Changelog
{
var text = new RichTextLabel();
text.SetMessage(FormattedMessage.FromMarkup(change.Message));
- ChangelogBody.AddChild(new HBoxContainer
+ ChangelogBody.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Margin = new Thickness(14, 1, 10, 2),
Children =
{
diff --git a/Content.Client/CharacterAppearance/MagicMirrorBoundUserInterface.cs b/Content.Client/CharacterAppearance/MagicMirrorBoundUserInterface.cs
index 34ef6f1900..1749ec46b8 100644
--- a/Content.Client/CharacterAppearance/MagicMirrorBoundUserInterface.cs
+++ b/Content.Client/CharacterAppearance/MagicMirrorBoundUserInterface.cs
@@ -13,6 +13,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using static Content.Shared.CharacterAppearance.Components.SharedMagicMirrorComponent;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.CharacterAppearance
{
@@ -107,8 +108,9 @@ namespace Content.Client.CharacterAppearance
MinSize = (50, 0)
};
- AddChild(new HBoxContainer
+ AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
_slider,
@@ -204,10 +206,16 @@ namespace Content.Client.CharacterAppearance
{
IoCManager.InjectDependencies(this);
- var vBox = new VBoxContainer();
+ var vBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
AddChild(vBox);
- _colorContainer = new VBoxContainer();
+ _colorContainer = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
vBox.AddChild(_colorContainer);
_colorContainer.AddChild(_colorSliderR = new ColorSlider(StyleNano.StyleClassSliderRed));
_colorContainer.AddChild(_colorSliderG = new ColorSlider(StyleNano.StyleClassSliderGreen));
@@ -289,7 +297,10 @@ namespace Content.Client.CharacterAppearance
public EyeColorPicker()
{
- var vBox = new VBoxContainer();
+ var vBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
AddChild(vBox);
vBox.AddChild(_colorSliderR = new ColorSlider(StyleNano.StyleClassSliderRed));
@@ -340,8 +351,9 @@ namespace Content.Client.CharacterAppearance
_eyeColorPicker = new EyeColorPicker {SizeFlagsHorizontal = SizeFlags.FillExpand};
_eyeColorPicker.OnEyeColorPicked += newColor => owner.EyeColorSelected(newColor);
- Contents.AddChild(new HBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 8,
Children = {_hairStylePicker, _facialHairStylePicker, _eyeColorPicker}
});
diff --git a/Content.Client/CharacterInfo/Components/CharacterInfoComponent.cs b/Content.Client/CharacterInfo/Components/CharacterInfoComponent.cs
index 7161808649..ce4f536335 100644
--- a/Content.Client/CharacterInfo/Components/CharacterInfoComponent.cs
+++ b/Content.Client/CharacterInfo/Components/CharacterInfoComponent.cs
@@ -62,19 +62,21 @@ namespace Content.Client.CharacterInfo.Components
public Label NameLabel { get; }
public Label SubText { get; }
- public VBoxContainer ObjectivesContainer { get; }
+ public BoxContainer ObjectivesContainer { get; }
public CharacterInfoControl(IResourceCache resourceCache)
{
IoCManager.InjectDependencies(this);
- AddChild(new HBoxContainer
+ AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
(SpriteView = new SpriteView { Scale = (2, 2)}),
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
VerticalAlignment = VAlignment.Top,
Children =
{
@@ -100,7 +102,10 @@ namespace Content.Client.CharacterInfo.Components
Text = Loc.GetString("character-info-objectives-label"),
HorizontalAlignment = HAlignment.Center
});
- ObjectivesContainer = new VBoxContainer();
+ ObjectivesContainer = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
AddChild(ObjectivesContainer);
AddChild(new Placeholder()
@@ -116,8 +121,9 @@ namespace Content.Client.CharacterInfo.Components
ObjectivesContainer.RemoveAllChildren();
foreach (var (groupId, objectiveConditions) in characterInfoMessage.Objectives)
{
- var vbox = new VBoxContainer
+ var vbox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Modulate = Color.Gray
};
@@ -129,7 +135,10 @@ namespace Content.Client.CharacterInfo.Components
foreach (var objectiveCondition in objectiveConditions)
{
- var hbox = new HBoxContainer();
+ var hbox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
hbox.AddChild(new ProgressTextureRect
{
Texture = objectiveCondition.SpriteSpecifier.Frame0(),
@@ -140,8 +149,9 @@ namespace Content.Client.CharacterInfo.Components
{
MinSize = (10,0)
});
- hbox.AddChild(new VBoxContainer
+ hbox.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
new Label{Text = objectiveCondition.Title},
diff --git a/Content.Client/CharacterInterface/CharacterInterfaceComponent.cs b/Content.Client/CharacterInterface/CharacterInterfaceComponent.cs
index 95f769e126..f071c03269 100644
--- a/Content.Client/CharacterInterface/CharacterInterfaceComponent.cs
+++ b/Content.Client/CharacterInterface/CharacterInterfaceComponent.cs
@@ -9,6 +9,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.CharacterInterface
{
@@ -110,14 +111,17 @@ namespace Content.Client.CharacterInterface
///
public class CharacterWindow : SS14Window
{
- private readonly VBoxContainer _contentsVBox;
+ private readonly BoxContainer _contentsVBox;
private readonly List _windowComponents;
public CharacterWindow(List windowComponents)
{
Title = "Character";
- _contentsVBox = new VBoxContainer();
+ _contentsVBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
Contents.AddChild(_contentsVBox);
windowComponents.Sort((a, b) => ((int) a.Priority).CompareTo((int) b.Priority));
diff --git a/Content.Client/Chat/ChatHelper.cs b/Content.Client/Chat/ChatHelper.cs
index 076a6995cf..350ab6aa1c 100644
--- a/Content.Client/Chat/ChatHelper.cs
+++ b/Content.Client/Chat/ChatHelper.cs
@@ -12,7 +12,7 @@ namespace Content.Client.Chat
ChatChannel.Radio => Color.Green,
ChatChannel.OOC => Color.LightSkyBlue,
ChatChannel.Dead => Color.MediumPurple,
- ChatChannel.AdminChat => Color.Red,
+ ChatChannel.Admin => Color.Red,
_ => Color.DarkGray
};
}
diff --git a/Content.Client/Chat/ChatInput.cs b/Content.Client/Chat/ChatInput.cs
new file mode 100644
index 0000000000..541cd8dc9f
--- /dev/null
+++ b/Content.Client/Chat/ChatInput.cs
@@ -0,0 +1,42 @@
+using Content.Client.Chat.UI;
+using Content.Client.Viewport;
+using Content.Shared.Chat;
+using Content.Shared.Input;
+using Robust.Client.Input;
+using Robust.Shared.Input.Binding;
+
+namespace Content.Client.Chat
+{
+ public static class ChatInput
+ {
+ public static void SetupChatInputHandlers(IInputManager inputManager, ChatBox chatBox)
+ {
+ inputManager.SetInputCommand(ContentKeyFunctions.FocusChat,
+ InputCmdHandler.FromDelegate(_ => GameScreen.FocusChat(chatBox)));
+
+ inputManager.SetInputCommand(ContentKeyFunctions.FocusLocalChat,
+ InputCmdHandler.FromDelegate(_ => GameScreen.FocusChannel(chatBox, ChatSelectChannel.Local)));
+
+ inputManager.SetInputCommand(ContentKeyFunctions.FocusOOC,
+ InputCmdHandler.FromDelegate(_ => GameScreen.FocusChannel(chatBox, ChatSelectChannel.OOC)));
+
+ inputManager.SetInputCommand(ContentKeyFunctions.FocusAdminChat,
+ InputCmdHandler.FromDelegate(_ => GameScreen.FocusChannel(chatBox, ChatSelectChannel.Admin)));
+
+ inputManager.SetInputCommand(ContentKeyFunctions.FocusRadio,
+ InputCmdHandler.FromDelegate(_ => GameScreen.FocusChannel(chatBox, ChatSelectChannel.Radio)));
+
+ inputManager.SetInputCommand(ContentKeyFunctions.FocusDeadChat,
+ InputCmdHandler.FromDelegate(_ => GameScreen.FocusChannel(chatBox, ChatSelectChannel.Dead)));
+
+ inputManager.SetInputCommand(ContentKeyFunctions.FocusConsoleChat,
+ InputCmdHandler.FromDelegate(_ => GameScreen.FocusChannel(chatBox, ChatSelectChannel.Console)));
+
+ inputManager.SetInputCommand(ContentKeyFunctions.CycleChatChannelForward,
+ InputCmdHandler.FromDelegate(_ => chatBox.CycleChatChannel(true)));
+
+ inputManager.SetInputCommand(ContentKeyFunctions.CycleChatChannelBackward,
+ InputCmdHandler.FromDelegate(_ => chatBox.CycleChatChannel(false)));
+ }
+ }
+}
diff --git a/Content.Client/Chat/Managers/ChatManager.cs b/Content.Client/Chat/Managers/ChatManager.cs
index 4af4b111e4..78f3fd9269 100644
--- a/Content.Client/Chat/Managers/ChatManager.cs
+++ b/Content.Client/Chat/Managers/ChatManager.cs
@@ -1,20 +1,21 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using Content.Client.Administration.Managers;
using Content.Client.Chat.UI;
using Content.Client.Ghost;
using Content.Shared.Administration;
+using Content.Shared.CCVar;
using Content.Shared.Chat;
using Robust.Client.Console;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
+using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
-using Robust.Shared.Localization;
using Robust.Shared.Log;
-using Robust.Shared.Maths;
using Robust.Shared.Network;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
@@ -52,23 +53,17 @@ namespace Content.Client.Chat.Managers
///
/// The max amount of characters an entity can send in one message
///
- private int _maxMessageLength = 1000;
+ public int MaxMessageLength => _cfg.GetCVar(CCVars.ChatMaxMessageLength);
- public const char ConCmdSlash = '/';
- public const char OOCAlias = '[';
- public const char MeAlias = '@';
- public const char AdminChatAlias = ']';
- public const char RadioAlias = ';';
+ private readonly List _history = new();
+ public IReadOnlyList History => _history;
- private readonly List _filteredHistory = new();
-
- // currently enabled channel filters set by the user. If an entry is not in this
- // list it has not been explicitly set yet, thus will default to enabled when it first
- // becomes filterable (added to _filterableChannels)
+ // currently enabled channel filters set by the user.
+ // All values default to on, even if they aren't a filterable chat channel currently.
// Note that these are persisted here, at the manager,
// rather than the chatbox so that these settings persist between instances of different
// chatboxes.
- public readonly Dictionary _channelFilters = new();
+ public ChatChannel ChannelFilters { get; private set; } = (ChatChannel) ushort.MaxValue;
// Maintains which channels a client should be able to filter (for showing in the chatbox)
// and select (for attempting to send on).
@@ -80,18 +75,16 @@ namespace Content.Client.Chat.Managers
//
// Note that Command is an available selection in the chatbox channel selector,
// which is not actually a chat channel but is always available.
- private readonly HashSet _filterableChannels = new();
- private readonly List _selectableChannels = new();
-
- // Flag Enums for holding filtered channels
- private ChatChannel _filteredChannels;
+ public ChatSelectChannel SelectableChannels { get; private set; }
+ public ChatChannel FilterableChannels { get; private set; }
///
/// For currently disabled chat filters,
- /// unread messages (messages received since the channel has been filtered
- /// out). Never goes above 10 (9+ should be shown when at 10)
+ /// unread messages (messages received since the channel has been filtered out).
///
- private readonly Dictionary _unreadMessages = new();
+ private readonly Dictionary _unreadMessages = new();
+
+ public IReadOnlyDictionary UnreadMessages => _unreadMessages;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IClientNetManager _netManager = default!;
@@ -100,16 +93,23 @@ namespace Content.Client.Chat.Managers
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
[Dependency] private readonly IClientAdminManager _adminMgr = default!;
+ [Dependency] private readonly IConfigurationManager _cfg = default!;
///
/// Current chat box control. This can be modified, so do not depend on saving a reference to this.
///
public ChatBox? CurrentChatBox { get; private set; }
+
///
/// Invoked when CurrentChatBox is resized (including after setting initial default size)
///
public event Action? OnChatBoxResized;
+ public event Action? ChatPermissionsUpdated;
+ public event Action? UnreadMessageCountsUpdated;
+ public event Action? MessageAdded;
+ public event Action? FiltersUpdated;
+
private Control _speechBubbleRoot = null!;
///
@@ -128,15 +128,11 @@ namespace Content.Client.Chat.Managers
public void Initialize()
{
_netManager.RegisterNetMessage(OnChatMessage);
- _netManager.RegisterNetMessage(OnMaxLengthReceived);
_speechBubbleRoot = new LayoutContainer();
LayoutContainer.SetAnchorPreset(_speechBubbleRoot, LayoutContainer.LayoutPreset.Wide);
_userInterfaceManager.StateRoot.AddChild(_speechBubbleRoot);
_speechBubbleRoot.SetPositionFirst();
-
- // When connexion is achieved, request the max chat message length
- _netManager.Connected += RequestMaxLength;
}
public void PostInject()
@@ -178,83 +174,58 @@ namespace Content.Client.Chat.Managers
// for any newly-granted channels
private void UpdateChannelPermissions()
{
+ var oldSelectable = SelectableChannels;
+ SelectableChannels = default;
+ FilterableChannels = default;
+
+ // Can always send console stuff.
+ SelectableChannels |= ChatSelectChannel.Console;
+
// can always send/recieve OOC
- if (!_selectableChannels.Contains(ChatChannel.OOC))
- {
- _selectableChannels.Add(ChatChannel.OOC);
- }
- AddFilterableChannel(ChatChannel.OOC);
+ SelectableChannels |= ChatSelectChannel.OOC;
+ FilterableChannels |= ChatChannel.OOC;
// can always hear server (nobody can actually send server messages).
- AddFilterableChannel(ChatChannel.Server);
+ FilterableChannels |= ChatChannel.Server;
// can always hear local / radio / emote
- AddFilterableChannel(ChatChannel.Local);
- AddFilterableChannel(ChatChannel.Radio);
- AddFilterableChannel(ChatChannel.Emotes);
+ // todo: this makes no sense the lobby exists fix this.
+ FilterableChannels |= ChatChannel.Local;
+ FilterableChannels |= ChatChannel.Radio;
+ FilterableChannels |= ChatChannel.Emotes;
// Can only send local / radio / emote when attached to a non-ghost entity.
// TODO: this logic is iffy (checking if controlling something that's NOT a ghost), is there a better way to check this?
- if (!_playerManager.LocalPlayer?.ControlledEntity?.HasComponent() ?? false)
+ if (!IsGhost)
{
- _selectableChannels.Add(ChatChannel.Local);
- _selectableChannels.Add(ChatChannel.Radio);
- _selectableChannels.Add(ChatChannel.Emotes);
- }
- else
- {
- _selectableChannels.Remove(ChatChannel.Local);
- _selectableChannels.Remove(ChatChannel.Radio);
- _selectableChannels.Remove(ChatChannel.Emotes);
+ SelectableChannels |= ChatSelectChannel.Local;
+ SelectableChannels |= ChatSelectChannel.Radio;
+ SelectableChannels |= ChatSelectChannel.Emotes;
}
// Only ghosts and admins can send / see deadchat.
- // TODO: Should spectators also be able to see deadchat?
- if (_adminMgr.HasFlag(AdminFlags.Admin) ||
- (_playerManager?.LocalPlayer?.ControlledEntity?.HasComponent() ?? false))
+ if (_adminMgr.HasFlag(AdminFlags.Admin) || IsGhost)
{
- AddFilterableChannel(ChatChannel.Dead);
- if (!_selectableChannels.Contains(ChatChannel.Dead))
- {
- _selectableChannels.Add(ChatChannel.Dead);
- }
- }
- else
- {
- _filterableChannels.Remove(ChatChannel.Dead);
- _selectableChannels.Remove(ChatChannel.Dead);
+ FilterableChannels |= ChatChannel.Dead;
+ SelectableChannels |= ChatSelectChannel.Dead;
}
// only admins can see / filter asay
if (_adminMgr.HasFlag(AdminFlags.Admin))
{
- AddFilterableChannel(ChatChannel.AdminChat);
- if (!_selectableChannels.Contains(ChatChannel.AdminChat))
- {
- _selectableChannels.Add(ChatChannel.AdminChat);
- }
- }
- else
- {
- _selectableChannels.Remove(ChatChannel.AdminChat);
- _filterableChannels.Remove(ChatChannel.AdminChat);
+ FilterableChannels |= ChatChannel.Admin;
+ SelectableChannels |= ChatSelectChannel.Admin;
}
+ // Necessary so that we always have a channel to fall back to.
+ DebugTools.Assert((SelectableChannels & ChatSelectChannel.OOC) != 0, "OOC must always be available");
+ DebugTools.Assert((FilterableChannels & ChatChannel.OOC) != 0, "OOC must always be available");
+
// let our chatbox know all the new settings
- CurrentChatBox?.SetChannelPermissions(_selectableChannels, _filterableChannels, _channelFilters, _unreadMessages, true);
- }
-
- ///
- /// Adds the channel to the set of filterable channels, defaulting it as enabled
- /// if it doesn't currently have an explicit enable/disable setting
- ///
- private void AddFilterableChannel(ChatChannel channel)
- {
- if (!_channelFilters.ContainsKey(channel))
- _channelFilters[channel] = true;
- _filterableChannels.Add(channel);
+ ChatPermissionsUpdated?.Invoke(new ChatPermissionsUpdatedEventArgs {OldSelectableChannels = oldSelectable});
}
+ public bool IsGhost => _playerManager.LocalPlayer?.ControlledEntity?.HasComponent() ?? false;
public void FrameUpdate(FrameEventArgs delta)
{
@@ -296,27 +267,19 @@ namespace Content.Client.Chat.Managers
public void SetChatBox(ChatBox chatBox)
{
- if (CurrentChatBox != null)
- {
- CurrentChatBox.TextSubmitted -= OnChatBoxTextSubmitted;
- CurrentChatBox.FilterToggled -= OnFilterButtonToggled;
- CurrentChatBox.OnResized -= ChatBoxOnResized;
- }
-
CurrentChatBox = chatBox;
- if (CurrentChatBox != null)
- {
- CurrentChatBox.TextSubmitted += OnChatBoxTextSubmitted;
- CurrentChatBox.FilterToggled += OnFilterButtonToggled;
- CurrentChatBox.OnResized += ChatBoxOnResized;
-
- CurrentChatBox.SetChannelPermissions(_selectableChannels, _filterableChannels, _channelFilters, _unreadMessages, false);
- }
-
- RepopulateChat(_filteredHistory);
}
- private void ChatBoxOnResized(ChatResizedEventArgs chatResizedEventArgs)
+ public void ClearUnfilteredUnreads()
+ {
+ foreach (var channel in _unreadMessages.Keys.ToArray())
+ {
+ if ((ChannelFilters & channel) != 0)
+ _unreadMessages.Remove(channel);
+ }
+ }
+
+ public void ChatBoxOnResized(ChatResizedEventArgs chatResizedEventArgs)
{
OnChatBoxResized?.Invoke(chatResizedEventArgs);
}
@@ -334,158 +297,86 @@ namespace Content.Client.Chat.Managers
}
}
- private void WriteChatMessage(StoredChatMessage message)
- {
- Logger.Debug($"{message.Channel}: {message.Message}");
-
- if (IsFiltered(message.Channel))
- {
- Logger.Debug($"Message filtered: {message.Channel}: {message.Message}");
- // accumulate unread
- if (message.Read) return;
- if (!_unreadMessages.TryGetValue(message.Channel, out var count))
- {
- count = 0;
- }
- count = (byte) Math.Min(count + 1, 10);
- _unreadMessages[message.Channel] = count;
- CurrentChatBox?.UpdateUnreadMessageCounts(_unreadMessages);
- return;
- }
-
- var color = Color.DarkGray;
- var messageText = FormattedMessage.EscapeText(message.Message);
- if (!string.IsNullOrEmpty(message.MessageWrap))
- {
- messageText = string.Format(message.MessageWrap, messageText);
- }
-
- if (message.MessageColorOverride != Color.Transparent)
- {
- color = message.MessageColorOverride;
- }
- else
- {
- color = ChatHelper.ChatColor(message.Channel);
- }
-
- if (CurrentChatBox == null) return;
- CurrentChatBox.AddLine(messageText, message.Channel, color);
- // TODO: Can make this "smarter" later by only setting it false when the message has been scrolled to
- message.Read = true;
- }
-
- private void OnChatBoxTextSubmitted(ChatBox chatBox, string text)
+ public void OnChatBoxTextSubmitted(ChatBox chatBox, ReadOnlyMemory text, ChatSelectChannel channel)
{
DebugTools.Assert(chatBox == CurrentChatBox);
- if (string.IsNullOrWhiteSpace(text))
- return;
+ var str = text.ToString();
- // Check if message is longer than the character limit
- if (text.Length > _maxMessageLength)
+ switch (channel)
{
- if (CurrentChatBox != null)
- {
- string locWarning = Loc.GetString("chat-manager-max-message-length",
- ("maxMessageLength", _maxMessageLength));
- CurrentChatBox.AddLine(locWarning, ChatChannel.Server, Color.Orange);
- CurrentChatBox.ClearOnEnter = false; // The text shouldn't be cleared if it hasn't been sent
- }
- return;
- }
-
- switch (text[0])
- {
- case ConCmdSlash:
- {
+ case ChatSelectChannel.Console:
// run locally
- var conInput = text.Substring(1);
- _consoleHost.ExecuteCommand(conInput);
+ _consoleHost.ExecuteCommand(text.ToString());
break;
- }
- case OOCAlias:
- {
- var conInput = text.Substring(1);
- if (string.IsNullOrWhiteSpace(conInput))
- return;
- _consoleHost.ExecuteCommand($"ooc \"{CommandParsing.Escape(conInput)}\"");
- break;
- }
- case AdminChatAlias:
- {
- var conInput = text.Substring(1);
- if (string.IsNullOrWhiteSpace(conInput))
- return;
- if (_adminMgr.HasFlag(AdminFlags.Admin))
- {
- _consoleHost.ExecuteCommand($"asay \"{CommandParsing.Escape(conInput)}\"");
- }
- else
- {
- _consoleHost.ExecuteCommand($"ooc \"{CommandParsing.Escape(conInput)}\"");
- }
+ case ChatSelectChannel.OOC:
+ _consoleHost.ExecuteCommand($"ooc \"{CommandParsing.Escape(str)}\"");
break;
- }
- case MeAlias:
- {
- var conInput = text.Substring(1);
- if (string.IsNullOrWhiteSpace(conInput))
- return;
- _consoleHost.ExecuteCommand($"me \"{CommandParsing.Escape(conInput)}\"");
+
+ case ChatSelectChannel.Admin:
+ _consoleHost.ExecuteCommand($"asay \"{CommandParsing.Escape(str)}\"");
break;
- }
+
+ case ChatSelectChannel.Emotes:
+ _consoleHost.ExecuteCommand($"me \"{CommandParsing.Escape(str)}\"");
+ break;
+
+ case ChatSelectChannel.Dead:
+ if (IsGhost)
+ goto case ChatSelectChannel.Local;
+ else if (_adminMgr.HasFlag(AdminFlags.Admin))
+ _consoleHost.ExecuteCommand($"dsay \"{CommandParsing.Escape(str)}\"");
+ else
+ Logger.WarningS("chat", "Tried to speak on deadchat without being ghost or admin.");
+ break;
+
+ case ChatSelectChannel.Radio:
+ _consoleHost.ExecuteCommand($"say \";{CommandParsing.Escape(str)}\"");
+ break;
+
+ case ChatSelectChannel.Local:
+ _consoleHost.ExecuteCommand($"say \"{CommandParsing.Escape(str)}\"");
+ break;
+
default:
- {
- var conInput = CurrentChatBox?.DefaultChatFormat != null
- ? string.Format(CurrentChatBox.DefaultChatFormat, CommandParsing.Escape(text))
- : text;
- _consoleHost.ExecuteCommand(conInput);
- break;
- }
+ throw new ArgumentOutOfRangeException(nameof(channel), channel, null);
}
}
- private void OnFilterButtonToggled(ChatChannel channel, bool enabled)
+ public void OnFilterButtonToggled(ChatChannel channel, bool enabled)
{
if (enabled)
{
- _channelFilters[channel] = true;
- _filteredChannels &= ~channel;
+ ChannelFilters |= channel;
_unreadMessages.Remove(channel);
- CurrentChatBox?.UpdateUnreadMessageCounts(_unreadMessages);
+ UnreadMessageCountsUpdated?.Invoke();
}
else
{
- _channelFilters[channel] = false;
- _filteredChannels |= channel;
+ ChannelFilters &= ~channel;
}
- RepopulateChat(_filteredHistory);
- }
-
- private void RepopulateChat(IEnumerable filteredMessages)
- {
- if (CurrentChatBox == null)
- {
- return;
- }
-
- CurrentChatBox.Contents.Clear();
-
- foreach (var msg in filteredMessages)
- {
- WriteChatMessage(msg);
- }
+ FiltersUpdated?.Invoke();
}
private void OnChatMessage(MsgChatMessage msg)
{
// Log all incoming chat to repopulate when filter is un-toggled
var storedMessage = new StoredChatMessage(msg);
- _filteredHistory.Add(storedMessage);
- WriteChatMessage(storedMessage);
+ _history.Add(storedMessage);
+ MessageAdded?.Invoke(storedMessage);
+
+ if (!storedMessage.Read)
+ {
+ Logger.Debug($"Message filtered: {storedMessage.Channel}: {storedMessage.Message}");
+ if (!_unreadMessages.TryGetValue(msg.Channel, out var count))
+ count = 0;
+
+ count += 1;
+ _unreadMessages[msg.Channel] = count;
+ UnreadMessageCountsUpdated?.Invoke();
+ }
// Local messages that have an entity attached get a speech bubble.
if (msg.SenderEntity == default)
@@ -498,7 +389,7 @@ namespace Content.Client.Chat.Managers
break;
case ChatChannel.Dead:
- if (!_playerManager.LocalPlayer?.ControlledEntity?.HasComponent() ?? true)
+ if (!IsGhost)
break;
AddSpeechBubble(msg, SpeechBubble.SpeechType.Say);
@@ -510,17 +401,6 @@ namespace Content.Client.Chat.Managers
}
}
- private void OnMaxLengthReceived(ChatMaxMsgLengthMessage msg)
- {
- _maxMessageLength = msg.MaxMessageLength;
- }
-
- private void RequestMaxLength(object? sender, NetChannelArgs args)
- {
- ChatMaxMsgLengthMessage msg = _netManager.CreateNetMessage();
- _netManager.ClientSendMessage(msg);
- }
-
private void AddSpeechBubble(MsgChatMessage msg, SpeechBubble.SpeechType speechType)
{
if (!_entityManager.TryGetEntity(msg.SenderEntity, out var entity))
@@ -604,7 +484,8 @@ namespace Content.Client.Chat.Managers
private void CreateSpeechBubble(IEntity entity, SpeechBubbleData speechData)
{
- var bubble = SpeechBubble.CreateSpeechBubble(speechData.Type, speechData.Message, entity, _eyeManager, this);
+ var bubble =
+ SpeechBubble.CreateSpeechBubble(speechData.Type, speechData.Message, entity, _eyeManager, this);
if (_activeSpeechBubbles.TryGetValue(entity.Uid, out var existing))
{
@@ -631,11 +512,6 @@ namespace Content.Client.Chat.Managers
}
}
- private bool IsFiltered(ChatChannel channel)
- {
- return _filteredChannels.HasFlag(channel);
- }
-
private sealed class SpeechBubbleQueueData
{
///
diff --git a/Content.Client/Chat/Managers/IChatManager.cs b/Content.Client/Chat/Managers/IChatManager.cs
index 64367365f2..2c25b1b7ee 100644
--- a/Content.Client/Chat/Managers/IChatManager.cs
+++ b/Content.Client/Chat/Managers/IChatManager.cs
@@ -1,5 +1,7 @@
using System;
+using System.Collections.Generic;
using Content.Client.Chat.UI;
+using Content.Shared.Chat;
using Robust.Shared.GameObjects;
using Robust.Shared.Timing;
@@ -7,6 +9,10 @@ namespace Content.Client.Chat.Managers
{
public interface IChatManager
{
+ ChatChannel ChannelFilters { get; }
+ ChatSelectChannel SelectableChannels { get; }
+ ChatChannel FilterableChannels { get; }
+
void Initialize();
void FrameUpdate(FrameEventArgs delta);
@@ -20,9 +26,29 @@ namespace Content.Client.Chat.Managers
///
ChatBox? CurrentChatBox { get; }
+ IReadOnlyDictionary UnreadMessages { get; }
+ IReadOnlyList History { get; }
+ int MaxMessageLength { get; }
+ bool IsGhost { get; }
+
///
/// Invoked when CurrentChatBox is resized (including after setting initial default size)
///
event Action? OnChatBoxResized;
+
+ event Action? ChatPermissionsUpdated;
+ event Action? UnreadMessageCountsUpdated;
+ event Action? MessageAdded;
+ event Action? FiltersUpdated;
+
+ void ClearUnfilteredUnreads();
+ void ChatBoxOnResized(ChatResizedEventArgs chatResizedEventArgs);
+ void OnChatBoxTextSubmitted(ChatBox chatBox, ReadOnlyMemory text, ChatSelectChannel channel);
+ void OnFilterButtonToggled(ChatChannel channel, bool enabled);
+ }
+
+ public struct ChatPermissionsUpdatedEventArgs
+ {
+ public ChatSelectChannel OldSelectableChannels;
}
}
diff --git a/Content.Client/Chat/UI/ChatBox.cs b/Content.Client/Chat/UI/ChatBox.cs
deleted file mode 100644
index 1052f499c2..0000000000
--- a/Content.Client/Chat/UI/ChatBox.cs
+++ /dev/null
@@ -1,973 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Content.Client.Alerts.UI;
-using Content.Client.Chat.Managers;
-using Content.Client.Lobby;
-using Content.Client.Resources;
-using Content.Client.Stylesheets;
-using Content.Shared.Chat;
-using Content.Shared.Input;
-using Robust.Client.Graphics;
-using Robust.Client.ResourceManagement;
-using Robust.Client.State;
-using Robust.Client.UserInterface;
-using Robust.Client.UserInterface.Controls;
-using Robust.Shared.Input;
-using Robust.Shared.IoC;
-using Robust.Shared.Localization;
-using Robust.Shared.Maths;
-using Robust.Shared.Timing;
-using Robust.Shared.Utility;
-
-namespace Content.Client.Chat.UI
-{
- public class ChatBox : Control
- {
- public const float InitialChatBottom = 235;
-
- public delegate void TextSubmitHandler(ChatBox chatBox, string text);
-
- public delegate void FilterToggledHandler(ChatChannel toggled, bool enabled);
-
- public event TextSubmitHandler? TextSubmitted;
-
- public event FilterToggledHandler? FilterToggled;
-
- public HistoryLineEdit Input { get; private set; }
- public OutputPanel Contents { get; }
-
- public event Action? OnResized;
-
- // order in which the available channel filters show up when available
- public static readonly IReadOnlyList ChannelFilterOrder = new List
- {
- ChatChannel.Local, ChatChannel.Emotes, ChatChannel.Radio, ChatChannel.OOC, ChatChannel.Dead, ChatChannel.AdminChat,
- ChatChannel.Server
- };
-
- // order in which the channels show up in the channel selector
- private static readonly IReadOnlyList ChannelSelectorOrder = new List
- {
- ChatChannel.Local, ChatChannel.Emotes, ChatChannel.Radio, ChatChannel.OOC, ChatChannel.Dead, ChatChannel.AdminChat
- };
-
- private const float FilterPopupWidth = 110;
- private const int DragMarginSize = 7;
- private const int MinDistanceFromBottom = 255;
- private const int MinLeft = 500;
-
- ///
- /// Will be Unspecified if set to Console
- ///
- public ChatChannel SelectedChannel = ChatChannel.Unspecified;
-
- ///
- /// Default formatting string for the ClientChatConsole.
- ///
- public string DefaultChatFormat { get; set; } = string.Empty;
-
- public bool ReleaseFocusOnEnter { get; set; } = true;
-
- public bool ClearOnEnter { get; set; } = true;
-
- // when channel is changed temporarily due to typing an alias
- // prefix, we save the current channel selection here to restore it when
- // the message is sent
- private ChatChannel? _savedSelectedChannel;
-
- private readonly Popup _channelSelectorPopup;
- private readonly Button _channelSelector;
- private readonly HBoxContainer _channelSelectorHBox;
- private readonly FilterButton _filterButton;
- private readonly Popup _filterPopup;
- private readonly PanelContainer _filterPopupPanel;
- private readonly VBoxContainer _filterVBox;
- private DragMode _currentDrag = DragMode.None;
- private Vector2 _dragOffsetTopLeft;
- private Vector2 _dragOffsetBottomRight;
- private readonly IClyde _clyde;
- private readonly bool _lobbyMode;
- private byte _clampIn;
- // currently known selectable channels as provided by ChatManager,
- // never contains Unspecified (which corresponds to Console which is always available)
- public List SelectableChannels = new();
-
- ///
- /// When lobbyMode is false, will position / add to correct location in StateRoot and
- /// be resizable.
- /// wWen true, will leave layout up to parent and not be resizable.
- ///
- public ChatBox()
- {
- //TODO Paul needs to fix xaml ctor args so we can pass this instead of resolving it.
- var stateManager = IoCManager.Resolve();
- _lobbyMode = stateManager.CurrentState is LobbyState;
-
- // TODO: Revisit the resizing stuff after https://github.com/space-wizards/RobustToolbox/issues/1392 is done,
- // Probably not "supposed" to inject IClyde, but I give up.
- // I can't find any other way to allow this control to properly resize when the
- // window is resized. Resized() isn't reliably called when resizing the window,
- // and layoutcontainer anchor / margin don't seem to adjust how we need
- // them to when the window is resized. We need it to be able to resize
- // within some bounds so that it doesn't overlap other UI elements, while still
- // being freely resizable within those bounds.
- _clyde = IoCManager.Resolve();
- MouseFilter = MouseFilterMode.Stop;
- LayoutContainer.SetMarginLeft(this, 4);
- LayoutContainer.SetMarginRight(this, 4);
- MinHeight = 128;
- MinWidth = 200;
-
- AddChild(new PanelContainer
- {
- PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#25252aaa")},
- VerticalExpand = true,
- HorizontalExpand = true,
- Children =
- {
- new VBoxContainer
- {
- Children =
- {
- (Contents = new OutputPanel
- {
- VerticalExpand = true,
- }),
- new PanelContainer
- {
- StyleClasses = { StyleNano.StyleClassChatSubPanel },
- HorizontalExpand = true,
- Children =
- {
- new HBoxContainer
- {
- HorizontalExpand = true,
- SeparationOverride = 4,
- Children =
- {
- (_channelSelector = new ChannelSelectorButton
- {
- StyleClasses = { StyleNano.StyleClassChatChannelSelectorButton },
- MinWidth = 75,
- Text = Loc.GetString("hud-chatbox-ooc"),
- ToggleMode = true
- }),
- (Input = new HistoryLineEdit
- {
- PlaceHolder = Loc.GetString("hud-chatbox-info"),
- HorizontalExpand = true,
- StyleClasses = { StyleNano.StyleClassChatLineEdit }
- }),
- (_filterButton = new FilterButton
- {
- StyleClasses = { StyleNano.StyleClassChatFilterOptionButton }
- })
- }
- }
- }
- }
- }
- }
- }
- });
-
- _filterPopup = new Popup
- {
- Children =
- {
- (_filterPopupPanel = new PanelContainer
- {
- StyleClasses = {StyleNano.StyleClassBorderedWindowPanel},
- Children =
- {
- new HBoxContainer
- {
- Children =
- {
- new Control{MinSize = (4,0)},
- (_filterVBox = new VBoxContainer
- {
- SeparationOverride = 4
- })
- }
- }
- }
- })
- }
- };
-
- _channelSelectorPopup = new Popup
- {
- Children =
- {
- (_channelSelectorHBox = new HBoxContainer
- {
- SeparationOverride = 1
- })
- }
- };
-
- if (!_lobbyMode)
- {
- UserInterfaceManager.StateRoot.AddChild(this);
- LayoutContainer.SetAnchorAndMarginPreset(this, LayoutContainer.LayoutPreset.TopRight, margin: 10);
- LayoutContainer.SetAnchorAndMarginPreset(this, LayoutContainer.LayoutPreset.TopRight, margin: 10);
- LayoutContainer.SetMarginLeft(this, -475);
- LayoutContainer.SetMarginBottom(this, InitialChatBottom);
- OnResized?.Invoke(new ChatResizedEventArgs(InitialChatBottom));
- }
- }
-
- protected override void EnteredTree()
- {
- base.EnteredTree();
- _channelSelector.OnToggled += OnChannelSelectorToggled;
- _filterButton.OnToggled += OnFilterButtonToggled;
- Input.OnKeyBindDown += InputKeyBindDown;
- Input.OnTextEntered += Input_OnTextEntered;
- Input.OnTextChanged += InputOnTextChanged;
- Input.OnFocusExit += InputOnFocusExit;
- _channelSelectorPopup.OnPopupHide += OnChannelSelectorPopupHide;
- _filterPopup.OnPopupHide += OnFilterPopupHide;
- _clyde.OnWindowResized += ClydeOnOnWindowResized;
- }
-
- protected override void ExitedTree()
- {
- base.ExitedTree();
- _channelSelector.OnToggled -= OnChannelSelectorToggled;
- _filterButton.OnToggled -= OnFilterButtonToggled;
- Input.OnKeyBindDown -= InputKeyBindDown;
- Input.OnTextEntered -= Input_OnTextEntered;
- Input.OnTextChanged -= InputOnTextChanged;
- Input.OnFocusExit -= InputOnFocusExit;
- _channelSelectorPopup.OnPopupHide -= OnChannelSelectorPopupHide;
- _filterPopup.OnPopupHide -= OnFilterPopupHide;
- _clyde.OnWindowResized -= ClydeOnOnWindowResized;
- UnsubFilterItems();
- UnsubChannelItems();
-
- }
-
- private void UnsubFilterItems()
- {
- foreach (var child in _filterVBox.Children)
- {
- if (child is not ChannelFilterCheckbox checkbox) continue;
- checkbox.OnToggled -= OnFilterCheckboxToggled;
- }
- }
-
- private void UnsubChannelItems()
- {
- foreach (var child in _channelSelectorHBox.Children)
- {
- if (child is not ChannelItemButton button) continue;
- button.OnPressed -= OnChannelSelectorItemPressed;
- }
- }
-
-
- ///
- /// Update the available filters / selectable channels and the current filter settings using the provided
- /// data.
- ///
- /// channels currently selectable to send on
- /// channels currently able ot filter on
- /// current settings for the channel filters, this SHOULD always have an entry if
- /// there is a corresponding entry in filterableChannels, but it may also have additional
- /// entries (which should not be presented to the user)
- /// unread message counts for each disabled channel, values 10 or higher will show as 9+
- public void SetChannelPermissions(List selectableChannels, IReadOnlySet filterableChannels,
- IReadOnlyDictionary channelFilters, IReadOnlyDictionary unreadMessages, bool switchIfConsole)
- {
- SelectableChannels = selectableChannels;
- // update the channel selector
- UnsubChannelItems();
- _channelSelectorHBox.RemoveAllChildren();
- foreach (var selectableChannel in ChannelSelectorOrder)
- {
- if (!selectableChannels.Contains(selectableChannel)) continue;
- var newButton = new ChannelItemButton(selectableChannel);
- newButton.OnPressed += OnChannelSelectorItemPressed;
- _channelSelectorHBox.AddChild(newButton);
- }
- // console channel is always selectable and represented via Unspecified
- var consoleButton = new ChannelItemButton(ChatChannel.Unspecified);
- consoleButton.OnPressed += OnChannelSelectorItemPressed;
- _channelSelectorHBox.AddChild(consoleButton);
-
-
- if (_savedSelectedChannel.HasValue && _savedSelectedChannel.Value != ChatChannel.Unspecified &&
- !selectableChannels.Contains(_savedSelectedChannel.Value))
- {
- // we just lost our saved selected channel, the current one will become permanent
- _savedSelectedChannel = null;
- }
-
- if (!selectableChannels.Contains(SelectedChannel) && (switchIfConsole || SelectedChannel != ChatChannel.Unspecified))
- {
- // our previously selected channel no longer exists or we are still on console channel because we just joined
- if ((SelectedChannel & ChatChannel.IC) != 0 || SelectedChannel == ChatChannel.Unspecified)
- {
- if (!SafelySelectChannel(ChatChannel.Local))
- SafelySelectChannel(ChatChannel.Dead);
- }
- else if (selectableChannels.Contains(ChatChannel.OOC))
- {
- SafelySelectChannel(ChatChannel.OOC);
- }
- else //This shouldn't happen but better to be safe than sorry
- {
- SafelySelectChannel(selectableChannels.First());
- }
- }
- else
- {
- SafelySelectChannel(SelectedChannel);
- }
-
- // update the channel filters
- UnsubFilterItems();
- _filterVBox.Children.Clear();
- _filterVBox.AddChild(new Control {CustomMinimumSize = (10, 0)});
- foreach (var channelFilter in ChannelFilterOrder)
- {
- if (!filterableChannels.Contains(channelFilter)) continue;
- byte? unreadCount = null;
- if (unreadMessages.TryGetValue(channelFilter, out var unread))
- {
- unreadCount = unread;
- }
- var newCheckBox = new ChannelFilterCheckbox(channelFilter, unreadCount)
- {
- // shouldn't happen, but if there's no explicit enable setting provided, default to enabled
- Pressed = !channelFilters.TryGetValue(channelFilter, out var enabled) || enabled
- };
- newCheckBox.OnToggled += OnFilterCheckboxToggled;
- _filterVBox.AddChild(newCheckBox);
- }
- _filterVBox.AddChild(new Control {CustomMinimumSize = (10, 0)});
- }
-
- ///
- /// Update the unread message counts in the filters based on the provided data.
- ///
- /// counts for each channel, any values above 9 will show as 9+
- public void UpdateUnreadMessageCounts(IReadOnlyDictionary unreadMessages)
- {
- foreach (var channelFilter in _filterVBox.Children)
- {
- if (channelFilter is not ChannelFilterCheckbox filterCheckbox) continue;
- if (unreadMessages.TryGetValue(filterCheckbox.Channel, out var unread))
- {
- filterCheckbox.UpdateUnreadCount(unread);
- }
- else
- {
- filterCheckbox.UpdateUnreadCount(null);
- }
- }
- }
-
- private void OnFilterCheckboxToggled(BaseButton.ButtonToggledEventArgs args)
- {
- if (args.Button is not ChannelFilterCheckbox checkbox) return;
- FilterToggled?.Invoke(checkbox.Channel, checkbox.Pressed);
- }
-
-
- private void OnFilterButtonToggled(BaseButton.ButtonToggledEventArgs args)
- {
- if (args.Pressed)
- {
- var globalPos = _filterButton.GlobalPosition;
- var (minX, minY) = _filterPopupPanel.CombinedMinimumSize;
- var box = UIBox2.FromDimensions(globalPos - (FilterPopupWidth, 0), (Math.Max(minX, FilterPopupWidth), minY));
- UserInterfaceManager.ModalRoot.AddChild(_filterPopup);
- _filterPopup.Open(box);
- }
- else
- {
- _filterPopup.Close();
- }
- }
-
- private void OnChannelSelectorToggled(BaseButton.ButtonToggledEventArgs args)
- {
- if (args.Pressed)
- {
- var globalLeft = GlobalPosition.X;
- var globalBot = GlobalPosition.Y + Height;
- var box = UIBox2.FromDimensions((globalLeft, globalBot), (SizeBox.Width, AlertsUI.ChatSeparation));
- UserInterfaceManager.ModalRoot.AddChild(_channelSelectorPopup);
- _channelSelectorPopup.Open(box);
- }
- else
- {
- _channelSelectorPopup.Close();
- }
- }
-
- private void OnFilterPopupHide()
- {
- OnPopupHide(_filterPopup, _filterButton);
- }
-
- private void OnChannelSelectorPopupHide()
- {
- OnPopupHide(_channelSelectorPopup, _channelSelector);
- }
-
- private void OnPopupHide(Control popup, BaseButton button)
- {
- UserInterfaceManager.ModalRoot.RemoveChild(popup);
- // this weird check here is because the hiding of the popup happens prior to the button
- // receiving the keydown, which would cause it to then become unpressed
- // and reopen immediately. To avoid this, if the popup was hidden due to clicking on the button,
- // we will not auto-unpress the button, instead leaving it up to the button toggle logic
- // (and this requires the button to be set to EnableAllKeybinds = true)
- if (UserInterfaceManager.CurrentlyHovered != button)
- {
- button.Pressed = false;
- }
- }
-
- private void OnChannelSelectorItemPressed(BaseButton.ButtonEventArgs obj)
- {
- if (obj.Button is not ChannelItemButton button) return;
- SafelySelectChannel(button.Channel);
- _channelSelectorPopup.Close();
- }
-
-
- ///
- /// Selects the indicated channel, clearing out any temporarily-selected channel
- /// (any currently entered text is preserved). If the specified channel is not selectable,
- /// will just maintain current selection.
- ///
- public void SelectChannel(ChatChannel toSelect)
- {
- _savedSelectedChannel = null;
- SafelySelectChannel(toSelect);
- }
-
- private bool SafelySelectChannel(ChatChannel toSelect)
- {
- if (toSelect == ChatChannel.Unspecified ||
- SelectableChannels.Contains(toSelect))
- {
- SelectedChannel = toSelect;
- _channelSelector.Text = ChannelSelectorName(toSelect);
- _channelSelector.Modulate = ChatHelper.ChatColor(toSelect);
- return true;
- }
- // keep current setting
- return false;
- }
-
- protected override void KeyBindDown(GUIBoundKeyEventArgs args)
- {
- base.KeyBindDown(args);
-
- if (args.Function == EngineKeyFunctions.UIClick && !_lobbyMode)
- {
- _currentDrag = GetDragModeFor(args.RelativePosition);
-
- if (_currentDrag != DragMode.None)
- {
- _dragOffsetTopLeft = args.PointerLocation.Position / UIScale - Position;
- _dragOffsetBottomRight = Position + Size - args.PointerLocation.Position / UIScale;
- }
- }
-
- if (args.CanFocus)
- {
- Input.GrabKeyboardFocus();
- }
- }
-
- protected override void KeyBindUp(GUIBoundKeyEventArgs args)
- {
- base.KeyBindUp(args);
-
- if (args.Function != EngineKeyFunctions.UIClick || _lobbyMode)
- {
- return;
- }
-
- _dragOffsetTopLeft = _dragOffsetBottomRight = Vector2.Zero;
- _currentDrag = DragMode.None;
-
- // If this is done in MouseDown, Godot won't fire MouseUp as you need focus to receive MouseUps.
- UserInterfaceManager.KeyboardFocused?.ReleaseKeyboardFocus();
- }
-
- public void CycleChatChannel(bool forward)
- {
- Input.IgnoreNext = true;
- var channels = SelectableChannels;
- var idx = channels.IndexOf(SelectedChannel);
- if (forward)
- {
- idx++;
- }
- else
- {
- idx--;
- }
- idx = MathHelper.Mod(idx, channels.Count);
-
- SelectChannel(channels[idx]);
- }
-
- private void InputKeyBindDown(GUIBoundKeyEventArgs args)
- {
- if (args.Function == EngineKeyFunctions.TextReleaseFocus)
- {
- Input.ReleaseKeyboardFocus();
- args.Handle();
- return;
- }
-
- if (args.Function == ContentKeyFunctions.CycleChatChannelForward)
- {
- CycleChatChannel(true);
- args.Handle();
- return;
- }
-
- if (args.Function == ContentKeyFunctions.CycleChatChannelBackward)
- {
- CycleChatChannel(false);
- args.Handle();
- return;
- }
-
- // if we temporarily selected another channel via a prefx, undo that when we backspace on an empty input
- if (args.Function == EngineKeyFunctions.TextBackspace && Input.Text.Length == 0 && _savedSelectedChannel.HasValue)
- {
- SafelySelectChannel(_savedSelectedChannel.Value);
- _savedSelectedChannel = null;
- }
- }
-
- // TODO: this drag and drop stuff is somewhat duplicated from Robust BaseWindow but also modified
- [Flags]
- private enum DragMode : byte
- {
- None = 0,
- Bottom = 1 << 1,
- Left = 1 << 2
- }
-
- private DragMode GetDragModeFor(Vector2 relativeMousePos)
- {
- var mode = DragMode.None;
-
- if (relativeMousePos.Y > Size.Y - DragMarginSize)
- {
- mode = DragMode.Bottom;
- }
-
- if (relativeMousePos.X < DragMarginSize)
- {
- mode |= DragMode.Left;
- }
-
- return mode;
- }
-
- protected override void MouseMove(GUIMouseMoveEventArgs args)
- {
- base.MouseMove(args);
-
- if (Parent == null || _lobbyMode)
- {
- return;
- }
-
- if (_currentDrag == DragMode.None)
- {
- var cursor = CursorShape.Arrow;
- var previewDragMode = GetDragModeFor(args.RelativePosition);
- switch (previewDragMode)
- {
- case DragMode.Bottom:
- cursor = CursorShape.VResize;
- break;
-
- case DragMode.Left:
- cursor = CursorShape.HResize;
- break;
-
- case DragMode.Bottom | DragMode.Left:
- cursor = CursorShape.Crosshair;
- break;
- }
-
- DefaultCursorShape = cursor;
- }
- else
- {
- var top = Rect.Top;
- var bottom = Rect.Bottom;
- var left = Rect.Left;
- var right = Rect.Right;
- var (minSizeX, minSizeY) = CombinedMinimumSize;
- if ((_currentDrag & DragMode.Bottom) == DragMode.Bottom)
- {
- bottom = Math.Max(args.GlobalPosition.Y + _dragOffsetBottomRight.Y, top + minSizeY);
- }
-
- if ((_currentDrag & DragMode.Left) == DragMode.Left)
- {
- var maxX = right - minSizeX;
- left = Math.Min(args.GlobalPosition.X - _dragOffsetTopLeft.X, maxX);
- }
-
- ClampSize(left, bottom);
- }
- }
-
- protected override void UIScaleChanged()
- {
- base.UIScaleChanged();
- ClampAfterDelay();
- }
-
- private void ClydeOnOnWindowResized(WindowResizedEventArgs obj)
- {
- ClampAfterDelay();
- }
-
- private void ClampAfterDelay()
- {
- if (!_lobbyMode)
- _clampIn = 2;
- }
-
- protected override void FrameUpdate(FrameEventArgs args)
- {
- base.FrameUpdate(args);
- if (_lobbyMode) return;
- // we do the clamping after a delay (after UI scale / window resize)
- // because we need to wait for our parent container to properly resize
- // first, so we can calculate where we should go. If we do it right away,
- // we won't have the correct values from the parent to know how to adjust our margins.
- if (_clampIn <= 0) return;
- _clampIn -= 1;
- if (_clampIn == 0) ClampSize();
- }
-
- private void ClampSize(float? desiredLeft = null, float? desiredBottom = null)
- {
- if (Parent == null || _lobbyMode) return;
- var top = Rect.Top;
- var right = Rect.Right;
- var left = desiredLeft ?? Rect.Left;
- var bottom = desiredBottom ?? Rect.Bottom;
-
- // clamp so it doesn't go too high or low (leave space for alerts UI)
- var maxBottom = Parent.Size.Y - MinDistanceFromBottom;
- if (maxBottom <= MinHeight)
- {
- // we can't fit in our given space (window made awkwardly small), so give up
- // and overlap at our min height
- bottom = MinHeight;
- }
- else
- {
- bottom = Math.Clamp(bottom, MinHeight, maxBottom);
- }
-
- var maxLeft = Parent.Size.X - MinWidth;
- if (maxLeft <= MinLeft)
- {
- // window too narrow, give up and overlap at our max left
- left = maxLeft;
- }
- else
- {
- left = Math.Clamp(left, MinLeft, maxLeft);
- }
-
- LayoutContainer.SetMarginLeft(this, -((right + 10) - left));
- LayoutContainer.SetMarginBottom(this, bottom);
- OnResized?.Invoke(new ChatResizedEventArgs(bottom));
- }
-
- protected override void MouseExited()
- {
- base.MouseExited();
-
- if (_currentDrag == DragMode.None && !_lobbyMode)
- {
- DefaultCursorShape = CursorShape.Arrow;
- }
- }
-
-
- private void InputOnTextChanged(LineEdit.LineEditEventArgs obj)
- {
- // switch temporarily to a different channel if an alias prefix has been entered.
-
- // are we already temporarily switching to a channel?
- if (_savedSelectedChannel.HasValue) return;
-
- var trimmed = obj.Text.Trim();
- if (trimmed.Length == 0 || trimmed.Length > 1) return;
-
- var channel = GetChannelFromPrefix(trimmed[0]);
- var prevChannel = SelectedChannel;
- if (channel == null || !SafelySelectChannel(channel.Value)) return;
- // we ate the prefix and auto-switched (temporarily) to the channel with that prefix
- _savedSelectedChannel = prevChannel;
- Input.Text = "";
- }
-
- private static ChatChannel? GetChannelFromPrefix(char prefix)
- {
- return prefix switch
- {
- ChatManager.MeAlias => ChatChannel.Emotes,
- ChatManager.RadioAlias => ChatChannel.Radio,
- ChatManager.AdminChatAlias => ChatChannel.AdminChat,
- ChatManager.OOCAlias => ChatChannel.OOC,
- ChatManager.ConCmdSlash => ChatChannel.Unspecified,
- _ => null
- };
- }
-
- private static string GetPrefixFromChannel(ChatChannel channel)
- {
- char? prefixChar = channel switch
- {
- ChatChannel.Emotes => ChatManager.MeAlias,
- ChatChannel.Radio => ChatManager.RadioAlias,
- ChatChannel.AdminChat => ChatManager.AdminChatAlias,
- ChatChannel.OOC => ChatManager.OOCAlias,
- ChatChannel.Unspecified => ChatManager.ConCmdSlash,
- _ => null
- };
-
- return prefixChar.ToString() ?? string.Empty;
- }
-
- public static string ChannelSelectorName(ChatChannel channel)
- {
- return channel switch
- {
- ChatChannel.AdminChat => Loc.GetString("hud-chatbox-admin"),
- ChatChannel.Unspecified => Loc.GetString("hud-chatbox-console"),
- _ => Loc.GetString(channel.ToString())
- };
- }
-
- public void AddLine(string message, ChatChannel channel, Color color)
- {
- if (Disposed)
- {
- return;
- }
-
- var formatted = new FormattedMessage(3);
- formatted.PushColor(color);
- formatted.AddMarkup(message);
- formatted.Pop();
- Contents.AddMessage(formatted);
- }
-
- private void InputOnFocusExit(LineEdit.LineEditEventArgs obj)
- {
- // undo the temporary selection, otherwise it will be odd if user
- // comes back to it later only to have their selection cleared upon sending
- if (!_savedSelectedChannel.HasValue) return;
- SafelySelectChannel(_savedSelectedChannel.Value);
- _savedSelectedChannel = null;
- }
-
- private void Input_OnTextEntered(LineEdit.LineEditEventArgs args)
- {
- // We set it there to true so it's set to false by TextSubmitted.Invoke if necessary
- ClearOnEnter = true;
-
- if (!string.IsNullOrWhiteSpace(args.Text))
- {
- TextSubmitted?.Invoke(this, GetPrefixFromChannel(SelectedChannel)
- + args.Text);
- }
-
- if (ClearOnEnter)
- {
- Input.Clear();
- if (_savedSelectedChannel.HasValue)
- {
- SafelySelectChannel(_savedSelectedChannel.Value);
- _savedSelectedChannel = null;
- }
- }
-
- if (ReleaseFocusOnEnter)
- {
- Input.ReleaseKeyboardFocus();
- }
- }
- }
-
- ///
- /// Only needed to avoid the issue where right click on the button closes the popup
- /// but leaves the button highlighted.
- ///
- public sealed class ChannelSelectorButton : Button
- {
- public ChannelSelectorButton()
- {
- // needed so the popup is untoggled regardless of which key is pressed when hovering this button.
- // If we don't have this, then right clicking the button while it's toggled on will hide
- // the popup but keep the button toggled on
- Mode = ActionMode.Press;
- EnableAllKeybinds = true;
- }
-
- protected override void KeyBindDown(GUIBoundKeyEventArgs args)
- {
- // needed since we need EnableAllKeybinds - don't double-send both UI click and Use
- if (args.Function == EngineKeyFunctions.Use) return;
- base.KeyBindDown(args);
- }
- }
-
- public sealed class FilterButton : ContainerButton
- {
- private static readonly Color ColorNormal = Color.FromHex("#7b7e9e");
- private static readonly Color ColorHovered = Color.FromHex("#9699bb");
- private static readonly Color ColorPressed = Color.FromHex("#789B8C");
-
- private readonly TextureRect _textureRect;
-
- public FilterButton()
- {
- var filterTexture = IoCManager.Resolve()
- .GetTexture("/Textures/Interface/Nano/filter.svg.96dpi.png");
-
- // needed for same reason as ChannelSelectorButton
- Mode = ActionMode.Press;
- EnableAllKeybinds = true;
-
- AddChild(
- (_textureRect = new TextureRect
- {
- Texture = filterTexture,
- SizeFlagsVertical = SizeFlags.ShrinkCenter,
- SizeFlagsHorizontal = SizeFlags.ShrinkCenter
- })
- );
- ToggleMode = true;
- }
-
- protected override void KeyBindDown(GUIBoundKeyEventArgs args)
- {
- // needed since we need EnableAllKeybinds - don't double-send both UI click and Use
- if (args.Function == EngineKeyFunctions.Use) return;
- base.KeyBindDown(args);
- }
-
- private void UpdateChildColors()
- {
- if (_textureRect == null) return;
- switch (DrawMode)
- {
- case DrawModeEnum.Normal:
- _textureRect.ModulateSelfOverride = ColorNormal;
- break;
-
- case DrawModeEnum.Pressed:
- _textureRect.ModulateSelfOverride = ColorPressed;
- break;
-
- case DrawModeEnum.Hover:
- _textureRect.ModulateSelfOverride = ColorHovered;
- break;
-
- case DrawModeEnum.Disabled:
- break;
- }
- }
-
- protected override void DrawModeChanged()
- {
- base.DrawModeChanged();
- UpdateChildColors();
- }
-
- protected override void StylePropertiesChanged()
- {
- base.StylePropertiesChanged();
- UpdateChildColors();
- }
-
- }
-
- public sealed class ChannelItemButton : Button
- {
- public readonly ChatChannel Channel;
-
- public ChannelItemButton(ChatChannel channel)
- {
- Channel = channel;
- AddStyleClass(StyleNano.StyleClassChatChannelSelectorButton);
- Text = ChatBox.ChannelSelectorName(channel);
- }
- }
-
- public sealed class ChannelFilterCheckbox : CheckBox
- {
- public readonly ChatChannel Channel;
-
- public ChannelFilterCheckbox(ChatChannel channel, byte? unreadCount)
- {
- Channel = channel;
-
- UpdateText(unreadCount);
- }
-
- private void UpdateText(byte? unread)
- {
- var name = Channel switch
- {
- ChatChannel.AdminChat => Loc.GetString("hud-chatbox-admin"),
- ChatChannel.Unspecified => throw new InvalidOperationException(
- "cannot create chat filter for Unspecified"),
- _ => Loc.GetString(Channel.ToString())
- };
-
- if (unread > 0)
- {
- Text = name + " (" + (unread > 9 ? "9+" : unread) + ")";
- }
- else
- {
- Text = name;
- }
- }
-
- public void UpdateUnreadCount(byte? unread)
- {
- UpdateText(unread);
- }
- }
-
- public readonly struct ChatResizedEventArgs
- {
- /// new bottom that the chat rect is going to have in virtual pixels
- /// after the imminent relayout
- public readonly float NewBottom;
-
- public ChatResizedEventArgs(float newBottom)
- {
- NewBottom = newBottom;
- }
- }
-}
diff --git a/Content.Client/Chat/UI/ChatBox.xaml b/Content.Client/Chat/UI/ChatBox.xaml
new file mode 100644
index 0000000000..3f66665d95
--- /dev/null
+++ b/Content.Client/Chat/UI/ChatBox.xaml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/Chat/UI/ChatBox.xaml.cs b/Content.Client/Chat/UI/ChatBox.xaml.cs
new file mode 100644
index 0000000000..ee3ff56d9f
--- /dev/null
+++ b/Content.Client/Chat/UI/ChatBox.xaml.cs
@@ -0,0 +1,740 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Content.Client.Alerts.UI;
+using Content.Client.Chat.Managers;
+using Content.Client.Resources;
+using Content.Client.Stylesheets;
+using Content.Shared.Chat;
+using Content.Shared.Input;
+using Robust.Client.AutoGenerated;
+using Robust.Client.ResourceManagement;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Input;
+using Robust.Shared.IoC;
+using Robust.Shared.Localization;
+using Robust.Shared.Log;
+using Robust.Shared.Maths;
+using Robust.Shared.Utility;
+
+namespace Content.Client.Chat.UI
+{
+ [GenerateTypedNameReferences]
+ public partial class ChatBox : Control
+ {
+ [Dependency] protected readonly IChatManager ChatMgr = default!;
+
+ // order in which the available channel filters show up when available
+ private static readonly ChatChannel[] ChannelFilterOrder =
+ {
+ ChatChannel.Local,
+ ChatChannel.Emotes,
+ ChatChannel.Radio,
+ ChatChannel.OOC,
+ ChatChannel.Dead,
+ ChatChannel.Admin,
+ ChatChannel.Server
+ };
+
+ // order in which the channels show up in the channel selector
+ private static readonly ChatSelectChannel[] ChannelSelectorOrder =
+ {
+ ChatSelectChannel.Local,
+ ChatSelectChannel.Emotes,
+ ChatSelectChannel.Radio,
+ ChatSelectChannel.OOC,
+ ChatSelectChannel.Dead,
+ ChatSelectChannel.Admin
+ // NOTE: Console is not in there and it can never be permanently selected.
+ // You can, however, still submit commands as console by prefixing with /.
+ };
+
+ public const char AliasLocal = '.';
+ public const char AliasConsole = '/';
+ public const char AliasDead = '\\';
+ public const char AliasOOC = '[';
+ public const char AliasEmotes = '@';
+ public const char AliasAdmin = ']';
+ public const char AliasRadio = ';';
+
+ private static readonly Dictionary PrefixToChannel = new()
+ {
+ {AliasLocal, ChatSelectChannel.Local},
+ {AliasConsole, ChatSelectChannel.Console},
+ {AliasOOC, ChatSelectChannel.OOC},
+ {AliasEmotes, ChatSelectChannel.Emotes},
+ {AliasAdmin, ChatSelectChannel.Admin},
+ {AliasRadio, ChatSelectChannel.Radio},
+ {AliasDead, ChatSelectChannel.Dead}
+ };
+
+ private static readonly Dictionary ChannelPrefixes =
+ PrefixToChannel.ToDictionary(kv => kv.Value, kv => kv.Key);
+
+ private const float FilterPopupWidth = 110;
+
+ ///
+ /// The currently default channel that will be used if no prefix is specified.
+ ///
+ public ChatSelectChannel SelectedChannel { get; private set; } = ChatSelectChannel.OOC;
+
+ ///
+ /// The "preferred" channel. Will be switched to if permissions change and the channel becomes available,
+ /// such as by re-entering body. Gets changed if the user manually selects a channel with the buttons.
+ ///
+ public ChatSelectChannel PreferredChannel { get; set; } = ChatSelectChannel.OOC;
+
+ public bool ReleaseFocusOnEnter { get; set; } = true;
+
+ private readonly Popup _channelSelectorPopup;
+ private readonly BoxContainer _channelSelectorHBox;
+ private readonly Popup _filterPopup;
+ private readonly PanelContainer _filterPopupPanel;
+ private readonly BoxContainer _filterVBox;
+
+ ///
+ /// When lobbyMode is false, will position / add to correct location in StateRoot and
+ /// be resizable.
+ /// wWen true, will leave layout up to parent and not be resizable.
+ ///
+ public ChatBox()
+ {
+ IoCManager.InjectDependencies(this);
+ RobustXamlLoader.Load(this);
+
+ LayoutContainer.SetMarginLeft(this, 4);
+ LayoutContainer.SetMarginRight(this, 4);
+
+ _filterPopup = new Popup
+ {
+ Children =
+ {
+ (_filterPopupPanel = new PanelContainer
+ {
+ StyleClasses = {StyleNano.StyleClassBorderedWindowPanel},
+ Children =
+ {
+ new BoxContainer
+ {
+ Orientation = BoxContainer.LayoutOrientation.Horizontal,
+ Children =
+ {
+ new Control {MinSize = (4, 0)},
+ (_filterVBox = new BoxContainer
+ {
+ Margin = new Thickness(0, 10),
+ Orientation = BoxContainer.LayoutOrientation.Vertical,
+ SeparationOverride = 4
+ })
+ }
+ }
+ }
+ })
+ }
+ };
+
+ _channelSelectorPopup = new Popup
+ {
+ Children =
+ {
+ (_channelSelectorHBox = new BoxContainer
+ {
+ Orientation = BoxContainer.LayoutOrientation.Horizontal,
+ SeparationOverride = 1
+ })
+ }
+ };
+
+ ChannelSelector.OnToggled += OnChannelSelectorToggled;
+ FilterButton.OnToggled += OnFilterButtonToggled;
+ Input.OnKeyBindDown += InputKeyBindDown;
+ Input.OnTextEntered += Input_OnTextEntered;
+ Input.OnTextChanged += InputOnTextChanged;
+ _channelSelectorPopup.OnPopupHide += OnChannelSelectorPopupHide;
+ _filterPopup.OnPopupHide += OnFilterPopupHide;
+ }
+
+ protected override void EnteredTree()
+ {
+ base.EnteredTree();
+
+ ChatMgr.MessageAdded += WriteChatMessage;
+ ChatMgr.ChatPermissionsUpdated += OnChatPermissionsUpdated;
+ ChatMgr.UnreadMessageCountsUpdated += UpdateUnreadMessageCounts;
+ ChatMgr.FiltersUpdated += Repopulate;
+
+ // The chat manager may have messages logged from before there was a chat box.
+ // In this case, these messages will be marked as unread despite the filters allowing them through.
+ // Tell chat manager to clear these.
+ ChatMgr.ClearUnfilteredUnreads();
+
+ ChatPermissionsUpdated(0);
+ UpdateChannelSelectButton();
+ Repopulate();
+ }
+
+ protected override void ExitedTree()
+ {
+ base.ExitedTree();
+
+ ChatMgr.MessageAdded -= WriteChatMessage;
+ ChatMgr.ChatPermissionsUpdated -= OnChatPermissionsUpdated;
+ ChatMgr.UnreadMessageCountsUpdated -= UpdateUnreadMessageCounts;
+ ChatMgr.FiltersUpdated -= Repopulate;
+ }
+
+ private void OnChatPermissionsUpdated(ChatPermissionsUpdatedEventArgs eventArgs)
+ {
+ ChatPermissionsUpdated(eventArgs.OldSelectableChannels);
+ }
+
+ private void ChatPermissionsUpdated(ChatSelectChannel oldSelectable)
+ {
+ // update the channel selector
+ _channelSelectorHBox.Children.Clear();
+ foreach (var selectableChannel in ChannelSelectorOrder)
+ {
+ if ((ChatMgr.SelectableChannels & selectableChannel) == 0)
+ continue;
+
+ var newButton = new ChannelItemButton(selectableChannel);
+ newButton.OnPressed += OnChannelSelectorItemPressed;
+ _channelSelectorHBox.AddChild(newButton);
+ }
+
+ // Selected channel no longer available, switch to OOC?
+ if ((ChatMgr.SelectableChannels & SelectedChannel) == 0)
+ {
+ // Handle local -> dead mapping when you e.g. ghost.
+ // Only necessary for admins because they always have deadchat
+ // so the normal preferred check won't see it as newly available and do nothing.
+ var mappedSelect = MapLocalIfGhost(SelectedChannel);
+ if ((ChatMgr.SelectableChannels & mappedSelect) != 0)
+ SafelySelectChannel(mappedSelect);
+ else
+ SafelySelectChannel(ChatSelectChannel.OOC);
+ }
+
+ // If the preferred channel just became available, switch to it.
+ var pref = MapLocalIfGhost(PreferredChannel);
+ if ((oldSelectable & pref) == 0 && (ChatMgr.SelectableChannels & pref) != 0)
+ SafelySelectChannel(pref);
+
+ // update the channel filters
+ _filterVBox.Children.Clear();
+ foreach (var channelFilter in ChannelFilterOrder)
+ {
+ if ((ChatMgr.FilterableChannels & channelFilter) == 0)
+ continue;
+
+ int? unreadCount = null;
+ if (ChatMgr.UnreadMessages.TryGetValue(channelFilter, out var unread))
+ unreadCount = unread;
+
+ var newCheckBox = new ChannelFilterCheckbox(channelFilter, unreadCount)
+ {
+ Pressed = (ChatMgr.ChannelFilters & channelFilter) != 0
+ };
+
+ newCheckBox.OnToggled += OnFilterCheckboxToggled;
+ _filterVBox.AddChild(newCheckBox);
+ }
+
+ UpdateChannelSelectButton();
+ }
+
+ private void UpdateUnreadMessageCounts()
+ {
+ foreach (var channelFilter in _filterVBox.Children)
+ {
+ if (channelFilter is not ChannelFilterCheckbox filterCheckbox) continue;
+ if (ChatMgr.UnreadMessages.TryGetValue(filterCheckbox.Channel, out var unread))
+ {
+ filterCheckbox.UpdateUnreadCount(unread);
+ }
+ else
+ {
+ filterCheckbox.UpdateUnreadCount(null);
+ }
+ }
+ }
+
+ private void OnFilterCheckboxToggled(BaseButton.ButtonToggledEventArgs args)
+ {
+ if (args.Button is not ChannelFilterCheckbox checkbox)
+ return;
+
+ ChatMgr.OnFilterButtonToggled(checkbox.Channel, checkbox.Pressed);
+ }
+
+ private void OnFilterButtonToggled(BaseButton.ButtonToggledEventArgs args)
+ {
+ if (args.Pressed)
+ {
+ var globalPos = FilterButton.GlobalPosition;
+ var (minX, minY) = _filterPopupPanel.MinSize;
+ var box = UIBox2.FromDimensions(globalPos - (FilterPopupWidth, 0),
+ (Math.Max(minX, FilterPopupWidth), minY));
+ UserInterfaceManager.ModalRoot.AddChild(_filterPopup);
+ _filterPopup.Open(box);
+ }
+ else
+ {
+ _filterPopup.Close();
+ }
+ }
+
+ private void OnChannelSelectorToggled(BaseButton.ButtonToggledEventArgs args)
+ {
+ if (args.Pressed)
+ {
+ var globalLeft = GlobalPosition.X;
+ var globalBot = GlobalPosition.Y + Height;
+ var box = UIBox2.FromDimensions((globalLeft, globalBot), (SizeBox.Width, AlertsUI.ChatSeparation));
+ UserInterfaceManager.ModalRoot.AddChild(_channelSelectorPopup);
+ _channelSelectorPopup.Open(box);
+ }
+ else
+ {
+ _channelSelectorPopup.Close();
+ }
+ }
+
+ private void OnFilterPopupHide()
+ {
+ OnPopupHide(_filterPopup, FilterButton);
+ }
+
+ private void OnChannelSelectorPopupHide()
+ {
+ OnPopupHide(_channelSelectorPopup, ChannelSelector);
+ }
+
+ private void OnPopupHide(Control popup, BaseButton button)
+ {
+ UserInterfaceManager.ModalRoot.RemoveChild(popup);
+
+ // this weird check here is because the hiding of the popup happens prior to the button
+ // receiving the keydown, which would cause it to then become unpressed
+ // and reopen immediately. To avoid this, if the popup was hidden due to clicking on the button,
+ // we will not auto-unpress the button, instead leaving it up to the button toggle logic
+ // (and this requires the button to be set to EnableAllKeybinds = true)
+ if (UserInterfaceManager.CurrentlyHovered != button)
+ {
+ button.Pressed = false;
+ }
+ }
+
+ private void OnChannelSelectorItemPressed(BaseButton.ButtonEventArgs obj)
+ {
+ if (obj.Button is not ChannelItemButton button)
+ return;
+
+ PreferredChannel = button.Channel;
+ SafelySelectChannel(button.Channel);
+ _channelSelectorPopup.Close();
+ }
+
+ public bool SafelySelectChannel(ChatSelectChannel toSelect)
+ {
+ toSelect = MapLocalIfGhost(toSelect);
+ if ((ChatMgr.SelectableChannels & toSelect) == 0)
+ return false;
+
+ SelectedChannel = toSelect;
+ UpdateChannelSelectButton();
+ return true;
+ }
+
+ private void UpdateChannelSelectButton()
+ {
+ var (prefixChannel, _) = SplitInputContents();
+
+ var channel = prefixChannel == 0 ? SelectedChannel : prefixChannel;
+
+ ChannelSelector.Text = ChannelSelectorName(channel);
+ ChannelSelector.Modulate = ChannelSelectColor(channel);
+ }
+
+ protected override void KeyBindDown(GUIBoundKeyEventArgs args)
+ {
+ base.KeyBindDown(args);
+
+ if (args.CanFocus)
+ {
+ Input.GrabKeyboardFocus();
+ }
+ }
+
+ public void CycleChatChannel(bool forward)
+ {
+ Input.IgnoreNext = true;
+
+ var idx = Array.IndexOf(ChannelSelectorOrder, SelectedChannel);
+ do
+ {
+ // go over every channel until we find one we can actually select.
+ idx += forward ? 1 : -1;
+ idx = MathHelper.Mod(idx, ChannelSelectorOrder.Length);
+ } while ((ChatMgr.SelectableChannels & ChannelSelectorOrder[idx]) == 0);
+
+ SafelySelectChannel(ChannelSelectorOrder[idx]);
+ }
+
+ private void Repopulate()
+ {
+ Contents.Clear();
+
+ foreach (var msg in ChatMgr.History)
+ {
+ WriteChatMessage(msg);
+ }
+ }
+
+ private void WriteChatMessage(StoredChatMessage message)
+ {
+ Logger.DebugS("chat", $"{message.Channel}: {message.Message}");
+
+ if (IsFilteredOut(message.Channel))
+ return;
+
+ // TODO: Can make this "smarter" later by only setting it false when the message has been scrolled to
+ message.Read = true;
+
+ var messageText = FormattedMessage.EscapeText(message.Message);
+ if (!string.IsNullOrEmpty(message.MessageWrap))
+ {
+ messageText = string.Format(message.MessageWrap, messageText);
+ }
+
+ var color = message.MessageColorOverride != Color.Transparent
+ ? message.MessageColorOverride
+ : ChatHelper.ChatColor(message.Channel);
+
+ AddLine(messageText, message.Channel, color);
+ }
+
+ private bool IsFilteredOut(ChatChannel channel)
+ {
+ return (ChatMgr.ChannelFilters & channel) == 0;
+ }
+
+ private void InputKeyBindDown(GUIBoundKeyEventArgs args)
+ {
+ if (args.Function == EngineKeyFunctions.TextReleaseFocus)
+ {
+ Input.ReleaseKeyboardFocus();
+ args.Handle();
+ return;
+ }
+
+ if (args.Function == ContentKeyFunctions.CycleChatChannelForward)
+ {
+ CycleChatChannel(true);
+ args.Handle();
+ return;
+ }
+
+ if (args.Function == ContentKeyFunctions.CycleChatChannelBackward)
+ {
+ CycleChatChannel(false);
+ args.Handle();
+ }
+ }
+
+ private (ChatSelectChannel selChannel, ReadOnlyMemory text) SplitInputContents()
+ {
+ var text = Input.Text.AsMemory().Trim();
+ if (text.Length == 0)
+ return default;
+
+ var prefixChar = text.Span[0];
+ var channel = GetChannelFromPrefix(prefixChar);
+
+ if ((ChatMgr.SelectableChannels & channel) != 0)
+ // Cut off prefix if it's valid and we can use the channel in question.
+ text = text[1..];
+ else
+ channel = 0;
+
+ channel = MapLocalIfGhost(channel);
+
+ // Trim from start again to cut out any whitespace between the prefix and message, if any.
+ return (channel, text.TrimStart());
+ }
+
+ private void InputOnTextChanged(LineEdit.LineEditEventArgs obj)
+ {
+ // Update channel select button to correct channel if we have a prefix.
+ UpdateChannelSelectButton();
+ }
+
+ private static ChatSelectChannel GetChannelFromPrefix(char prefix)
+ {
+ return PrefixToChannel.GetValueOrDefault(prefix);
+ }
+
+ public static char GetPrefixFromChannel(ChatSelectChannel channel)
+ {
+ return ChannelPrefixes.GetValueOrDefault(channel);
+ }
+
+ public static string ChannelSelectorName(ChatSelectChannel channel)
+ {
+ return Loc.GetString($"hud-chatbox-select-channel-{channel}");
+ }
+
+ public static Color ChannelSelectColor(ChatSelectChannel channel)
+ {
+ return channel switch
+ {
+ ChatSelectChannel.Radio => Color.Green,
+ ChatSelectChannel.OOC => Color.LightSkyBlue,
+ ChatSelectChannel.Dead => Color.MediumPurple,
+ ChatSelectChannel.Admin => Color.Red,
+ _ => Color.DarkGray
+ };
+ }
+
+ public void AddLine(string message, ChatChannel channel, Color color)
+ {
+ DebugTools.Assert(!Disposed);
+
+ var formatted = new FormattedMessage(3);
+ formatted.PushColor(color);
+ formatted.AddMarkup(message);
+ formatted.Pop();
+ Contents.AddMessage(formatted);
+ }
+
+ private void Input_OnTextEntered(LineEdit.LineEditEventArgs args)
+ {
+ if (!string.IsNullOrWhiteSpace(args.Text))
+ {
+ var (prefixChannel, text) = SplitInputContents();
+
+ // Check if message is longer than the character limit
+ if (text.Length > ChatMgr.MaxMessageLength)
+ {
+ string locWarning = Loc.GetString(
+ "chat-manager-max-message-length",
+ ("maxMessageLength", ChatMgr.MaxMessageLength));
+
+ AddLine(locWarning, ChatChannel.Server, Color.Orange);
+ return;
+ }
+
+ ChatMgr.OnChatBoxTextSubmitted(this, text, prefixChannel == 0 ? SelectedChannel : prefixChannel);
+ }
+
+ Input.Clear();
+ UpdateChannelSelectButton();
+
+ if (ReleaseFocusOnEnter)
+ Input.ReleaseKeyboardFocus();
+ }
+
+ public void Focus(ChatSelectChannel? channel = null)
+ {
+ var selectStart = Index.End;
+ if (channel != null)
+ {
+ channel = MapLocalIfGhost(channel.Value);
+
+ // Channel not selectable, just do NOTHING (not even focus).
+ if (!((ChatMgr.SelectableChannels & channel.Value) != 0))
+ return;
+
+ var (_, text) = SplitInputContents();
+
+ var newPrefix = GetPrefixFromChannel(channel.Value);
+ DebugTools.Assert(newPrefix != default, "Focus channel must have prefix!");
+
+ if (channel == SelectedChannel)
+ {
+ // New selected channel is just the selected channel,
+ // just remove prefix (if any) and leave text unchanged.
+
+ Input.Text = text.ToString();
+ selectStart = Index.Start;
+ }
+ else
+ {
+ // Change prefix to new focused channel prefix and leave text unchanged.
+ Input.Text = string.Concat(newPrefix.ToString(), " ", text.Span);
+ selectStart = Index.FromStart(2);
+ }
+
+ UpdateChannelSelectButton();
+ }
+
+ Input.IgnoreNext = true;
+ Input.GrabKeyboardFocus();
+
+ Input.CursorPosition = Input.Text.Length;
+ Input.SelectionStart = selectStart.GetOffset(Input.Text.Length);
+ }
+
+ private ChatSelectChannel MapLocalIfGhost(ChatSelectChannel channel)
+ {
+ if (channel == ChatSelectChannel.Local && ChatMgr.IsGhost)
+ return ChatSelectChannel.Dead;
+
+ return channel;
+ }
+ }
+
+ ///
+ /// Only needed to avoid the issue where right click on the button closes the popup
+ /// but leaves the button highlighted.
+ ///
+ public sealed class ChannelSelectorButton : Button
+ {
+ public ChannelSelectorButton()
+ {
+ // needed so the popup is untoggled regardless of which key is pressed when hovering this button.
+ // If we don't have this, then right clicking the button while it's toggled on will hide
+ // the popup but keep the button toggled on
+ Mode = ActionMode.Press;
+ EnableAllKeybinds = true;
+ }
+
+ protected override void KeyBindDown(GUIBoundKeyEventArgs args)
+ {
+ // needed since we need EnableAllKeybinds - don't double-send both UI click and Use
+ if (args.Function == EngineKeyFunctions.Use)
+ return;
+
+ base.KeyBindDown(args);
+ }
+ }
+
+ public sealed class FilterButton : ContainerButton
+ {
+ private static readonly Color ColorNormal = Color.FromHex("#7b7e9e");
+ private static readonly Color ColorHovered = Color.FromHex("#9699bb");
+ private static readonly Color ColorPressed = Color.FromHex("#789B8C");
+
+ private readonly TextureRect _textureRect;
+
+ public FilterButton()
+ {
+ var filterTexture = IoCManager.Resolve()
+ .GetTexture("/Textures/Interface/Nano/filter.svg.96dpi.png");
+
+ // needed for same reason as ChannelSelectorButton
+ Mode = ActionMode.Press;
+ EnableAllKeybinds = true;
+
+ AddChild(
+ (_textureRect = new TextureRect
+ {
+ Texture = filterTexture,
+ HorizontalAlignment = HAlignment.Center,
+ VerticalAlignment = VAlignment.Center
+ })
+ );
+
+ ToggleMode = true;
+ }
+
+ protected override void KeyBindDown(GUIBoundKeyEventArgs args)
+ {
+ // needed since we need EnableAllKeybinds - don't double-send both UI click and Use
+ if (args.Function == EngineKeyFunctions.Use) return;
+ base.KeyBindDown(args);
+ }
+
+ private void UpdateChildColors()
+ {
+ if (_textureRect == null) return;
+ switch (DrawMode)
+ {
+ case DrawModeEnum.Normal:
+ _textureRect.ModulateSelfOverride = ColorNormal;
+ break;
+
+ case DrawModeEnum.Pressed:
+ _textureRect.ModulateSelfOverride = ColorPressed;
+ break;
+
+ case DrawModeEnum.Hover:
+ _textureRect.ModulateSelfOverride = ColorHovered;
+ break;
+
+ case DrawModeEnum.Disabled:
+ break;
+ }
+ }
+
+ protected override void DrawModeChanged()
+ {
+ base.DrawModeChanged();
+ UpdateChildColors();
+ }
+
+ protected override void StylePropertiesChanged()
+ {
+ base.StylePropertiesChanged();
+ UpdateChildColors();
+ }
+ }
+
+ public sealed class ChannelItemButton : Button
+ {
+ public readonly ChatSelectChannel Channel;
+
+ public ChannelItemButton(ChatSelectChannel channel)
+ {
+ Channel = channel;
+ AddStyleClass(StyleNano.StyleClassChatChannelSelectorButton);
+ Text = ChatBox.ChannelSelectorName(channel);
+
+ var prefix = ChatBox.GetPrefixFromChannel(channel);
+ if (prefix != default)
+ Text = Loc.GetString("hud-chatbox-select-name-prefixed", ("name", Text), ("prefix", prefix));
+ }
+ }
+
+ public sealed class ChannelFilterCheckbox : CheckBox
+ {
+ public readonly ChatChannel Channel;
+
+ public ChannelFilterCheckbox(ChatChannel channel, int? unreadCount)
+ {
+ Channel = channel;
+
+ UpdateText(unreadCount);
+ }
+
+ private void UpdateText(int? unread)
+ {
+ var name = Loc.GetString($"hud-chatbox-channel-{Channel}");
+
+ if (unread > 0)
+ // todo: proper fluent stuff here.
+ name += " (" + (unread > 9 ? "9+" : unread) + ")";
+
+ Text = name;
+ }
+
+ public void UpdateUnreadCount(int? unread)
+ {
+ UpdateText(unread);
+ }
+ }
+
+ public readonly struct ChatResizedEventArgs
+ {
+ /// new bottom that the chat rect is going to have in virtual pixels
+ /// after the imminent relayout
+ public readonly float NewBottom;
+
+ public ChatResizedEventArgs(float newBottom)
+ {
+ NewBottom = newBottom;
+ }
+ }
+}
diff --git a/Content.Client/Chat/UI/HudChatBox.cs b/Content.Client/Chat/UI/HudChatBox.cs
new file mode 100644
index 0000000000..824a906d01
--- /dev/null
+++ b/Content.Client/Chat/UI/HudChatBox.cs
@@ -0,0 +1,235 @@
+using System;
+using Robust.Client.Graphics;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using Robust.Shared.Input;
+using Robust.Shared.IoC;
+using Robust.Shared.Maths;
+using Robust.Shared.Timing;
+
+namespace Content.Client.Chat.UI
+{
+ public class HudChatBox : ChatBox
+ {
+ // TODO: Revisit the resizing stuff after https://github.com/space-wizards/RobustToolbox/issues/1392 is done,
+ // Probably not "supposed" to inject IClyde, but I give up.
+ // I can't find any other way to allow this control to properly resize when the
+ // window is resized. Resized() isn't reliably called when resizing the window,
+ // and layoutcontainer anchor / margin don't seem to adjust how we need
+ // them to when the window is resized. We need it to be able to resize
+ // within some bounds so that it doesn't overlap other UI elements, while still
+ // being freely resizable within those bounds.
+ [Dependency] private readonly IClyde _clyde = default!;
+
+ public const float InitialChatBottom = 235;
+ private const int DragMarginSize = 7;
+ private const int MinDistanceFromBottom = 255;
+ private const int MinLeft = 500;
+ private DragMode _currentDrag = DragMode.None;
+ private Vector2 _dragOffsetTopLeft;
+ private Vector2 _dragOffsetBottomRight;
+
+ private byte _clampIn;
+
+ protected override void EnteredTree()
+ {
+ base.EnteredTree();
+
+ _clyde.OnWindowResized += ClydeOnOnWindowResized;
+ }
+
+ protected override void ExitedTree()
+ {
+ base.ExitedTree();
+
+ _clyde.OnWindowResized -= ClydeOnOnWindowResized;
+ }
+
+ protected override void KeyBindDown(GUIBoundKeyEventArgs args)
+ {
+ if (args.Function == EngineKeyFunctions.UIClick)
+ {
+ _currentDrag = GetDragModeFor(args.RelativePosition);
+
+ if (_currentDrag != DragMode.None)
+ {
+ _dragOffsetTopLeft = args.PointerLocation.Position / UIScale - Position;
+ _dragOffsetBottomRight = Position + Size - args.PointerLocation.Position / UIScale;
+ }
+ }
+
+ base.KeyBindDown(args);
+ }
+
+ protected override void KeyBindUp(GUIBoundKeyEventArgs args)
+ {
+ base.KeyBindUp(args);
+
+ if (args.Function != EngineKeyFunctions.UIClick)
+ return;
+
+ _dragOffsetTopLeft = _dragOffsetBottomRight = Vector2.Zero;
+ _currentDrag = DragMode.None;
+
+ // If this is done in MouseDown, Godot won't fire MouseUp as you need focus to receive MouseUps.
+ UserInterfaceManager.KeyboardFocused?.ReleaseKeyboardFocus();
+ }
+
+
+ // TODO: this drag and drop stuff is somewhat duplicated from Robust BaseWindow but also modified
+ [Flags]
+ private enum DragMode : byte
+ {
+ None = 0,
+ Bottom = 1 << 1,
+ Left = 1 << 2
+ }
+
+ private DragMode GetDragModeFor(Vector2 relativeMousePos)
+ {
+ var mode = DragMode.None;
+
+ if (relativeMousePos.Y > Size.Y - DragMarginSize)
+ {
+ mode = DragMode.Bottom;
+ }
+
+ if (relativeMousePos.X < DragMarginSize)
+ {
+ mode |= DragMode.Left;
+ }
+
+ return mode;
+ }
+
+ protected override void MouseMove(GUIMouseMoveEventArgs args)
+ {
+ base.MouseMove(args);
+
+ if (Parent == null)
+ return;
+
+ if (_currentDrag == DragMode.None)
+ {
+ var cursor = CursorShape.Arrow;
+ var previewDragMode = GetDragModeFor(args.RelativePosition);
+ switch (previewDragMode)
+ {
+ case DragMode.Bottom:
+ cursor = CursorShape.VResize;
+ break;
+
+ case DragMode.Left:
+ cursor = CursorShape.HResize;
+ break;
+
+ case DragMode.Bottom | DragMode.Left:
+ cursor = CursorShape.Crosshair;
+ break;
+ }
+
+ DefaultCursorShape = cursor;
+ }
+ else
+ {
+ var top = Rect.Top;
+ var bottom = Rect.Bottom;
+ var left = Rect.Left;
+ var right = Rect.Right;
+ var (minSizeX, minSizeY) = MinSize;
+ if ((_currentDrag & DragMode.Bottom) == DragMode.Bottom)
+ {
+ bottom = Math.Max(args.GlobalPosition.Y + _dragOffsetBottomRight.Y, top + minSizeY);
+ }
+
+ if ((_currentDrag & DragMode.Left) == DragMode.Left)
+ {
+ var maxX = right - minSizeX;
+ left = Math.Min(args.GlobalPosition.X - _dragOffsetTopLeft.X, maxX);
+ }
+
+ ClampSize(left, bottom);
+ }
+ }
+
+ protected override void UIScaleChanged()
+ {
+ base.UIScaleChanged();
+ ClampAfterDelay();
+ }
+
+ private void ClydeOnOnWindowResized(WindowResizedEventArgs obj)
+ {
+ ClampAfterDelay();
+ }
+
+ private void ClampAfterDelay()
+ {
+ _clampIn = 2;
+ }
+
+ protected override void FrameUpdate(FrameEventArgs args)
+ {
+ base.FrameUpdate(args);
+
+ // we do the clamping after a delay (after UI scale / window resize)
+ // because we need to wait for our parent container to properly resize
+ // first, so we can calculate where we should go. If we do it right away,
+ // we won't have the correct values from the parent to know how to adjust our margins.
+ if (_clampIn <= 0)
+ return;
+
+ _clampIn -= 1;
+ if (_clampIn == 0)
+ ClampSize();
+ }
+
+ private void ClampSize(float? desiredLeft = null, float? desiredBottom = null)
+ {
+ if (Parent == null)
+ return;
+
+ // var top = Rect.Top;
+ var right = Rect.Right;
+ var left = desiredLeft ?? Rect.Left;
+ var bottom = desiredBottom ?? Rect.Bottom;
+
+ // clamp so it doesn't go too high or low (leave space for alerts UI)
+ var maxBottom = Parent.Size.Y - MinDistanceFromBottom;
+ if (maxBottom <= MinHeight)
+ {
+ // we can't fit in our given space (window made awkwardly small), so give up
+ // and overlap at our min height
+ bottom = MinHeight;
+ }
+ else
+ {
+ bottom = Math.Clamp(bottom, MinHeight, maxBottom);
+ }
+
+ var maxLeft = Parent.Size.X - MinWidth;
+ if (maxLeft <= MinLeft)
+ {
+ // window too narrow, give up and overlap at our max left
+ left = maxLeft;
+ }
+ else
+ {
+ left = Math.Clamp(left, MinLeft, maxLeft);
+ }
+
+ LayoutContainer.SetMarginLeft(this, -((right + 10) - left));
+ LayoutContainer.SetMarginBottom(this, bottom);
+
+ ChatMgr.ChatBoxOnResized(new ChatResizedEventArgs(bottom));
+ }
+
+ protected override void MouseExited()
+ {
+ base.MouseExited();
+
+ if (_currentDrag == DragMode.None)
+ DefaultCursorShape = CursorShape.Arrow;
+ }
+ }
+}
diff --git a/Content.Client/Chemistry/UI/ChemMasterWindow.cs b/Content.Client/Chemistry/UI/ChemMasterWindow.cs
index f46fc8fd0e..c627470286 100644
--- a/Content.Client/Chemistry/UI/ChemMasterWindow.cs
+++ b/Content.Client/Chemistry/UI/ChemMasterWindow.cs
@@ -14,6 +14,7 @@ using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using static Content.Shared.Chemistry.Components.SharedChemMasterComponent;
using static Robust.Client.UserInterface.Controls.BaseButton;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Chemistry.UI
{
@@ -25,11 +26,11 @@ namespace Content.Client.Chemistry.UI
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
/// Contains info about the reagent container such as it's contents, if one is loaded into the dispenser.
- private readonly VBoxContainer ContainerInfo;
+ private readonly BoxContainer ContainerInfo;
- private readonly VBoxContainer BufferInfo;
+ private readonly BoxContainer BufferInfo;
- private readonly VBoxContainer PackagingInfo;
+ private readonly BoxContainer PackagingInfo;
/// Ejects the reagent container from the dispenser.
public Button EjectButton { get; }
@@ -41,8 +42,8 @@ namespace Content.Client.Chemistry.UI
public event Action? OnChemButtonPressed;
- public HBoxContainer PillInfo { get; set; }
- public HBoxContainer BottleInfo { get; set; }
+ public BoxContainer PillInfo { get; set; }
+ public BoxContainer BottleInfo { get; set; }
public SpinBox PillAmount { get; set; }
public SpinBox BottleAmount { get; set; }
public Button CreatePills { get; }
@@ -57,13 +58,15 @@ namespace Content.Client.Chemistry.UI
MinSize = SetSize = (400, 525);
IoCManager.InjectDependencies(this);
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
//Container
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = Loc.GetString("chem-master-window-container-label")},
@@ -84,8 +87,9 @@ namespace Content.Client.Chemistry.UI
Children =
{
//Currently empty, when server sends state data this will have container contents and fill volume.
- (ContainerInfo = new VBoxContainer
+ (ContainerInfo = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true,
Children =
{
@@ -102,8 +106,9 @@ namespace Content.Client.Chemistry.UI
new Control {MinSize = (0.0f, 10.0f)},
//Buffer
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = Loc.GetString("chem-master-window-buffer-text")},
@@ -126,8 +131,9 @@ namespace Content.Client.Chemistry.UI
Children =
{
//Buffer reagent list
- (BufferInfo = new VBoxContainer
+ (BufferInfo = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true,
Children =
{
@@ -144,8 +150,9 @@ namespace Content.Client.Chemistry.UI
new Control {MinSize = (0.0f, 10.0f)},
//Packaging
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = $"{Loc.GetString("chem-master-window-packaging-text")} "},
@@ -165,8 +172,9 @@ namespace Content.Client.Chemistry.UI
Children =
{
//Packaging options
- (PackagingInfo = new VBoxContainer
+ (PackagingInfo = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true,
}),
@@ -176,8 +184,9 @@ namespace Content.Client.Chemistry.UI
});
//Pills
- PillInfo = new HBoxContainer
+ PillInfo = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label
@@ -213,8 +222,9 @@ namespace Content.Client.Chemistry.UI
PillInfo.AddChild(CreatePills);
//Bottles
- BottleInfo = new HBoxContainer
+ BottleInfo = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label
@@ -315,8 +325,9 @@ namespace Content.Client.Chemistry.UI
return;
}
- ContainerInfo.Children.Add(new HBoxContainer // Name of the container and its fill status (Ex: 44/100u)
+ ContainerInfo.Children.Add(new BoxContainer // Name of the container and its fill status (Ex: 44/100u)
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = $"{state.ContainerName}: "},
@@ -339,8 +350,9 @@ namespace Content.Client.Chemistry.UI
if (proto != null)
{
- ContainerInfo.Children.Add(new HBoxContainer
+ ContainerInfo.Children.Add(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = $"{name}: "},
@@ -371,7 +383,10 @@ namespace Content.Client.Chemistry.UI
return;
}
- var bufferHBox = new HBoxContainer();
+ var bufferHBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
BufferInfo.AddChild(bufferHBox);
var bufferLabel = new Label { Text = $"{Loc.GetString("chem-master-window-buffer-label")} " };
@@ -394,8 +409,9 @@ namespace Content.Client.Chemistry.UI
if (proto != null)
{
- BufferInfo.Children.Add(new HBoxContainer
+ BufferInfo.Children.Add(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
//SizeFlagsHorizontal = SizeFlags.ShrinkEnd,
Children =
{
diff --git a/Content.Client/Chemistry/UI/ReagentDispenserWindow.cs b/Content.Client/Chemistry/UI/ReagentDispenserWindow.cs
index acf11ca5fc..e5b3571027 100644
--- a/Content.Client/Chemistry/UI/ReagentDispenserWindow.cs
+++ b/Content.Client/Chemistry/UI/ReagentDispenserWindow.cs
@@ -12,6 +12,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using static Content.Shared.Chemistry.Dispenser.SharedReagentDispenserComponent;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Chemistry.UI
{
@@ -23,7 +24,7 @@ namespace Content.Client.Chemistry.UI
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
/// Contains info about the reagent container such as it's contents, if one is loaded into the dispenser.
- private readonly VBoxContainer ContainerInfo;
+ private readonly BoxContainer ContainerInfo;
/// Sets the dispense amount to 1 when pressed.
public Button DispenseButton1 { get; }
@@ -72,13 +73,15 @@ namespace Content.Client.Chemistry.UI
var dispenseAmountGroup = new ButtonGroup();
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
//First, our dispense amount buttons
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = Loc.GetString("reagent-dispenser-window-amount-to-dispense-label")},
@@ -104,8 +107,9 @@ namespace Content.Client.Chemistry.UI
}),
//Padding
new Control {MinSize = (0.0f, 10.0f)},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = Loc.GetString("reagent-dispenser-window-container-label") + " "},
@@ -126,8 +130,9 @@ namespace Content.Client.Chemistry.UI
Children =
{
//Currently empty, when server sends state data this will have container contents and fill volume.
- (ContainerInfo = new VBoxContainer
+ (ContainerInfo = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true,
Children =
{
@@ -263,8 +268,9 @@ namespace Content.Client.Chemistry.UI
return;
}
- ContainerInfo.Children.Add(new HBoxContainer // Name of the container and its fill status (Ex: 44/100u)
+ ContainerInfo.Children.Add(new BoxContainer // Name of the container and its fill status (Ex: 44/100u)
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = $"{state.ContainerName}: "},
@@ -293,8 +299,9 @@ namespace Content.Client.Chemistry.UI
//Check if the reagent is being moused over. If so, color it green.
if (proto != null && proto.ID == highlightedReagentId)
{
- ContainerInfo.Children.Add(new HBoxContainer
+ ContainerInfo.Children.Add(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label
@@ -312,8 +319,9 @@ namespace Content.Client.Chemistry.UI
}
else //Otherwise, color it the normal colors.
{
- ContainerInfo.Children.Add(new HBoxContainer
+ ContainerInfo.Children.Add(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = $"{name}: "},
diff --git a/Content.Client/Chemistry/UI/TransferAmountBoundUserInterface.cs b/Content.Client/Chemistry/UI/TransferAmountBoundUserInterface.cs
new file mode 100644
index 0000000000..03eb454372
--- /dev/null
+++ b/Content.Client/Chemistry/UI/TransferAmountBoundUserInterface.cs
@@ -0,0 +1,35 @@
+using Content.Shared.Chemistry;
+using Content.Shared.Chemistry.Reagent;
+using JetBrains.Annotations;
+using Robust.Client.GameObjects;
+using Robust.Shared.GameObjects;
+
+namespace Content.Client.Chemistry.UI
+{
+ [UsedImplicitly]
+ public class TransferAmountBoundUserInterface : BoundUserInterface
+ {
+ private TransferAmountWindow? _window;
+
+ protected override void Open()
+ {
+ base.Open();
+ _window = new TransferAmountWindow();
+
+ _window.applyButton.OnPressed += _ =>
+ {
+ if (int.TryParse(_window.amountLineEdit.Text, out var i))
+ {
+ SendMessage(new TransferAmountSetValueMessage(ReagentUnit.New(i)));
+ _window.Close();
+ }
+ };
+
+ _window.OpenCentered();
+ }
+
+ public TransferAmountBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
+ {
+ }
+ }
+}
diff --git a/Content.Client/Chemistry/UI/TransferAmountWindow.xaml b/Content.Client/Chemistry/UI/TransferAmountWindow.xaml
new file mode 100644
index 0000000000..50716c563c
--- /dev/null
+++ b/Content.Client/Chemistry/UI/TransferAmountWindow.xaml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/Chemistry/UI/TransferAmountWindow.xaml.cs b/Content.Client/Chemistry/UI/TransferAmountWindow.xaml.cs
new file mode 100644
index 0000000000..1c94789444
--- /dev/null
+++ b/Content.Client/Chemistry/UI/TransferAmountWindow.xaml.cs
@@ -0,0 +1,19 @@
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Client.UserInterface.XAML;
+
+namespace Content.Client.Chemistry.UI
+{
+ [GenerateTypedNameReferences]
+ public partial class TransferAmountWindow : SS14Window
+ {
+ public Button applyButton => ApplyButton;
+ public LineEdit amountLineEdit => AmountLineEdit;
+
+ public TransferAmountWindow()
+ {
+ RobustXamlLoader.Load(this);
+ }
+ }
+}
diff --git a/Content.Client/Chemistry/Visualizers/SolutionContainerVisualizer.cs b/Content.Client/Chemistry/Visualizers/SolutionContainerVisualizer.cs
index dfb9d4cfb3..47b39c4c96 100644
--- a/Content.Client/Chemistry/Visualizers/SolutionContainerVisualizer.cs
+++ b/Content.Client/Chemistry/Visualizers/SolutionContainerVisualizer.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System;
using Content.Shared.Chemistry.Solution.Components;
using JetBrains.Annotations;
diff --git a/Content.Client/Cloning/UI/AcceptCloningWindow.cs b/Content.Client/Cloning/UI/AcceptCloningWindow.cs
index c26d95a30f..b37e693679 100644
--- a/Content.Client/Cloning/UI/AcceptCloningWindow.cs
+++ b/Content.Client/Cloning/UI/AcceptCloningWindow.cs
@@ -2,6 +2,7 @@ using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Localization;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Cloning.UI
{
@@ -15,21 +16,24 @@ namespace Content.Client.Cloning.UI
Title = Loc.GetString("accept-cloning-window-title");
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
(new Label()
{
Text = Loc.GetString("accept-cloning-window-prompt-text-part")
}),
- new HBoxContainer
+ new BoxContainer
{
- Align = BoxContainer.AlignMode.Center,
+ Orientation = LayoutOrientation.Horizontal,
+ Align = AlignMode.Center,
Children =
{
(AcceptButton = new Button
diff --git a/Content.Client/Cloning/UI/CloningPodWindow.cs b/Content.Client/Cloning/UI/CloningPodWindow.cs
index b085c5294d..a52ef93ebd 100644
--- a/Content.Client/Cloning/UI/CloningPodWindow.cs
+++ b/Content.Client/Cloning/UI/CloningPodWindow.cs
@@ -9,6 +9,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
using static Content.Shared.Cloning.SharedCloningPodComponent;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Cloning.UI
{
@@ -16,7 +17,7 @@ namespace Content.Client.Cloning.UI
{
private Dictionary _scanManager;
- private readonly VBoxContainer _scanList;
+ private readonly BoxContainer _scanList;
public readonly Button CloneButton;
public readonly Button EjectButton;
private CloningScanButton? _selectedButton;
@@ -35,8 +36,9 @@ namespace Content.Client.Cloning.UI
Title = Loc.GetString("cloning-pod-window-title");
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
new ScrollContainer
@@ -45,11 +47,15 @@ namespace Content.Client.Cloning.UI
VerticalExpand = true,
Children =
{
- (_scanList = new VBoxContainer())
+ (_scanList = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ })
}
},
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
(CloneButton = new Button
@@ -74,8 +80,9 @@ namespace Content.Client.Cloning.UI
{
Text = Loc.GetString("cloning-pod-eject-body-button")
}),
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label()
@@ -219,8 +226,9 @@ namespace Content.Client.Cloning.UI
ToggleMode = true,
});
- AddChild(new HBoxContainer
+ AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
(EntityTextureRect = new TextureRect
diff --git a/Content.Client/Clothing/ClothingComponent.cs b/Content.Client/Clothing/ClothingComponent.cs
index 030ab4533b..4cd1d1ee46 100644
--- a/Content.Client/Clothing/ClothingComponent.cs
+++ b/Content.Client/Clothing/ClothingComponent.cs
@@ -1,4 +1,3 @@
-#nullable enable
using Content.Client.Inventory;
using Content.Client.Items.Components;
using Content.Shared.Clothing;
diff --git a/Content.Client/CombatMode/ColoredScreenBorderOverlay.cs b/Content.Client/CombatMode/ColoredScreenBorderOverlay.cs
index 4fc1d7a908..9b02e7ce21 100644
--- a/Content.Client/CombatMode/ColoredScreenBorderOverlay.cs
+++ b/Content.Client/CombatMode/ColoredScreenBorderOverlay.cs
@@ -1,4 +1,3 @@
-#nullable enable
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.IoC;
diff --git a/Content.Client/Commands/GroupingContextMenuCommand.cs b/Content.Client/Commands/GroupingContextMenuCommand.cs
index e306c7da11..1b640b0907 100644
--- a/Content.Client/Commands/GroupingContextMenuCommand.cs
+++ b/Content.Client/Commands/GroupingContextMenuCommand.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using Content.Shared;
+using Content.Shared;
using Content.Shared.CCVar;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
diff --git a/Content.Client/Communications/UI/CommunicationsConsoleMenu.cs b/Content.Client/Communications/UI/CommunicationsConsoleMenu.cs
index 56d8497104..af12b76965 100644
--- a/Content.Client/Communications/UI/CommunicationsConsoleMenu.cs
+++ b/Content.Client/Communications/UI/CommunicationsConsoleMenu.cs
@@ -5,6 +5,7 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
using Timer = Robust.Shared.Timing.Timer;
namespace Content.Client.Communications.UI
@@ -42,7 +43,12 @@ namespace Content.Client.Communications.UI
EmergencyShuttleButton.OnPressed += (_) => Owner.EmergencyShuttleButtonPressed();
EmergencyShuttleButton.Disabled = !owner.CanCall;
- var vbox = new VBoxContainer() {HorizontalExpand = true, VerticalExpand = true};
+ var vbox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical,
+ HorizontalExpand = true,
+ VerticalExpand = true
+ };
vbox.AddChild(_messageInput);
vbox.AddChild(new Control(){MinSize = new Vector2(0,10), HorizontalExpand = true});
vbox.AddChild(AnnounceButton);
@@ -50,7 +56,12 @@ namespace Content.Client.Communications.UI
vbox.AddChild(_countdownLabel);
vbox.AddChild(EmergencyShuttleButton);
- var hbox = new HBoxContainer() {HorizontalExpand = true, VerticalExpand = true};
+ var hbox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal,
+ HorizontalExpand = true,
+ VerticalExpand = true
+ };
hbox.AddChild(new Control(){MinSize = new Vector2(100,0), HorizontalExpand = true});
hbox.AddChild(vbox);
hbox.AddChild(new Control(){MinSize = new Vector2(100,0), HorizontalExpand = true});
diff --git a/Content.Client/Configurable/UI/ConfigurationMenu.cs b/Content.Client/Configurable/UI/ConfigurationMenu.cs
index ea0c717b3d..07ad8ecf99 100644
--- a/Content.Client/Configurable/UI/ConfigurationMenu.cs
+++ b/Content.Client/Configurable/UI/ConfigurationMenu.cs
@@ -6,6 +6,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using static Content.Shared.Configurable.SharedConfigurationComponent;
using static Robust.Client.UserInterface.Controls.BaseButton;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Configurable.UI
{
@@ -13,9 +14,8 @@ namespace Content.Client.Configurable.UI
{
public ConfigurationBoundUserInterface Owner { get; }
- private readonly VBoxContainer _baseContainer;
- private readonly VBoxContainer _column;
- private readonly HBoxContainer _row;
+ private readonly BoxContainer _column;
+ private readonly BoxContainer _row;
private readonly List<(string name, LineEdit input)> _inputs;
@@ -28,20 +28,23 @@ namespace Content.Client.Configurable.UI
Title = Loc.GetString("configuration-menu-device-title");
- _baseContainer = new VBoxContainer
+ BoxContainer baseContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
VerticalExpand = true,
HorizontalExpand = true
};
- _column = new VBoxContainer
+ _column = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(8),
SeparationOverride = 16,
};
- _row = new HBoxContainer
+ _row = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 16,
HorizontalExpand = true
};
@@ -63,9 +66,9 @@ namespace Content.Client.Configurable.UI
};
outerColumn.AddChild(_column);
- _baseContainer.AddChild(outerColumn);
- _baseContainer.AddChild(confirmButton);
- Contents.AddChild(_baseContainer);
+ baseContainer.AddChild(outerColumn);
+ baseContainer.AddChild(confirmButton);
+ Contents.AddChild(baseContainer);
}
public void Populate(ConfigurationBoundUserInterfaceState state)
@@ -97,7 +100,10 @@ namespace Content.Client.Configurable.UI
_inputs.Add((field.Key, input));
- var row = new HBoxContainer();
+ var row = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
CopyProperties(_row, row);
row.AddChild(label);
diff --git a/Content.Client/Construction/ConstructionSystem.cs b/Content.Client/Construction/ConstructionSystem.cs
index 7ffc1fbf81..e3524212dc 100644
--- a/Content.Client/Construction/ConstructionSystem.cs
+++ b/Content.Client/Construction/ConstructionSystem.cs
@@ -14,7 +14,6 @@ using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
-#nullable enable
namespace Content.Client.Construction
{
diff --git a/Content.Client/Construction/UI/ConstructionMenu.xaml b/Content.Client/Construction/UI/ConstructionMenu.xaml
index b95c4d4f58..2c943206bb 100644
--- a/Content.Client/Construction/UI/ConstructionMenu.xaml
+++ b/Content.Client/Construction/UI/ConstructionMenu.xaml
@@ -1,32 +1,32 @@
-
-
-
+
+
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
-
-
-
+
+
+
+
diff --git a/Content.Client/Construction/UI/ConstructionMenu.xaml.cs b/Content.Client/Construction/UI/ConstructionMenu.xaml.cs
index b1182c005c..7ad635d6b7 100644
--- a/Content.Client/Construction/UI/ConstructionMenu.xaml.cs
+++ b/Content.Client/Construction/UI/ConstructionMenu.xaml.cs
@@ -7,7 +7,6 @@ using Robust.Client.UserInterface.XAML;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
-#nullable enable
namespace Content.Client.Construction.UI
{
diff --git a/Content.Client/Construction/UI/ConstructionMenuPresenter.cs b/Content.Client/Construction/UI/ConstructionMenuPresenter.cs
index 53a174f9e7..78b93f5544 100644
--- a/Content.Client/Construction/UI/ConstructionMenuPresenter.cs
+++ b/Content.Client/Construction/UI/ConstructionMenuPresenter.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/Content.Client/ContextMenu/UI/ContextMenuElement.cs b/Content.Client/ContextMenu/UI/ContextMenuElement.cs
index 540aa07679..9f9c049763 100644
--- a/Content.Client/ContextMenu/UI/ContextMenuElement.cs
+++ b/Content.Client/ContextMenu/UI/ContextMenuElement.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using Content.Client.Interactable.Components;
@@ -14,6 +13,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
using Vector2 = Robust.Shared.Maths.Vector2;
namespace Content.Client.ContextMenu.UI
@@ -64,8 +64,9 @@ namespace Content.Client.ContextMenu.UI
OutlineComponent = ContextEntity.GetComponentOrNull();
AddChild(
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new LayoutContainer
@@ -130,14 +131,16 @@ namespace Content.Client.ContextMenu.UI
LayoutContainer.SetGrowVertical(_label, LayoutContainer.GrowDirection.Begin);
AddChild(
- new HBoxContainer()
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 6,
Children =
{
new LayoutContainer { Children = { _spriteView, _label } },
- new HBoxContainer()
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 6,
Children =
{
@@ -180,7 +183,7 @@ namespace Content.Client.ContextMenu.UI
private const int MaxItemsBeforeScroll = 10;
private const int MarginSizeBetweenElements = 2;
- public VBoxContainer List { get; }
+ public BoxContainer List { get; }
public int Depth { get; }
public ContextMenuPopup(int depth = 0)
@@ -191,7 +194,10 @@ namespace Content.Client.ContextMenu.UI
HScrollEnabled = false,
Children = { new PanelContainer
{
- Children = { (List = new VBoxContainer()) },
+ Children = { (List = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ }) },
PanelOverride = new StyleBoxFlat { BackgroundColor = MarginColor }
}}
});
diff --git a/Content.Client/ContextMenu/UI/ContextMenuPresenter.cs b/Content.Client/ContextMenu/UI/ContextMenuPresenter.cs
index 21ca65f75a..d85eda0ce8 100644
--- a/Content.Client/ContextMenu/UI/ContextMenuPresenter.cs
+++ b/Content.Client/ContextMenu/UI/ContextMenuPresenter.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System;
+using System;
using System.Linq;
using System.Threading;
using Content.Client.Examine;
diff --git a/Content.Client/ContextMenu/UI/ContextMenuView.cs b/Content.Client/ContextMenu/UI/ContextMenuView.cs
index cef321f5b1..ed41f6314a 100644
--- a/Content.Client/ContextMenu/UI/ContextMenuView.cs
+++ b/Content.Client/ContextMenu/UI/ContextMenuView.cs
@@ -1,5 +1,4 @@
-#nullable enable
-
+
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/Content.Client/ContextMenu/UI/ContextMenuViewGrouping.cs b/Content.Client/ContextMenu/UI/ContextMenuViewGrouping.cs
index 84797f8467..67556dbdc4 100644
--- a/Content.Client/ContextMenu/UI/ContextMenuViewGrouping.cs
+++ b/Content.Client/ContextMenu/UI/ContextMenuViewGrouping.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using Robust.Client.GameObjects;
diff --git a/Content.Client/Crayon/UI/CrayonWindow.cs b/Content.Client/Crayon/UI/CrayonWindow.cs
index a1b1fc33d1..6c6de15a10 100644
--- a/Content.Client/Crayon/UI/CrayonWindow.cs
+++ b/Content.Client/Crayon/UI/CrayonWindow.cs
@@ -9,6 +9,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
using static Robust.Client.UserInterface.Controls.BaseButton;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Crayon.UI
{
@@ -27,7 +28,10 @@ namespace Content.Client.Crayon.UI
Title = Loc.GetString("crayon-window-title");
Owner = owner;
- var vbox = new VBoxContainer();
+ var vbox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
Contents.AddChild(vbox);
_search = new LineEdit();
diff --git a/Content.Client/Credits/CreditsWindow.cs b/Content.Client/Credits/CreditsWindow.cs
index a755979ee5..b617f25fb1 100644
--- a/Content.Client/Credits/CreditsWindow.cs
+++ b/Content.Client/Credits/CreditsWindow.cs
@@ -16,6 +16,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Credits
{
@@ -71,8 +72,9 @@ namespace Content.Client.Credits
private void PopulateLicenses(ScrollContainer licensesList)
{
- var vBox = new VBoxContainer
+ var vBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(2, 2, 0, 0)
};
@@ -93,8 +95,9 @@ namespace Content.Client.Credits
private void PopulatePatronsList(Control patronsList)
{
- var vBox = new VBoxContainer
+ var vBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(2, 2, 0, 0)
};
var patrons = LoadPatrons();
@@ -152,13 +155,15 @@ namespace Content.Client.Credits
{
Button contributeButton;
- var vBox = new VBoxContainer
+ var vBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(2, 2, 0, 0)
};
- vBox.AddChild(new HBoxContainer
+ vBox.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalAlignment = HAlignment.Center,
SeparationOverride = 20,
Children =
diff --git a/Content.Client/Disposal/UI/DisposalMailingUnitWindow.cs b/Content.Client/Disposal/UI/DisposalMailingUnitWindow.cs
index 13e49516ad..db6b24044d 100644
--- a/Content.Client/Disposal/UI/DisposalMailingUnitWindow.cs
+++ b/Content.Client/Disposal/UI/DisposalMailingUnitWindow.cs
@@ -7,6 +7,7 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using static Content.Shared.Disposal.Components.SharedDisposalMailingUnitComponent;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Disposal.UI
{
@@ -30,18 +31,21 @@ namespace Content.Client.Disposal.UI
{
MinSize = SetSize = (460, 230);
TargetList = new List();
- Contents.AddChild(new HBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true,
Margin = new Thickness(8, 0),
Children =
{
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = $"{Loc.GetString("disposal-mailing-unit-window-state-label")} "},
@@ -50,8 +54,9 @@ namespace Content.Client.Disposal.UI
}
},
new Control {MinSize = (0, 10)},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
Children =
{
@@ -73,8 +78,9 @@ namespace Content.Client.Disposal.UI
}
},
new Control {MinSize = (0, 10)},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
Children =
{
@@ -94,8 +100,9 @@ namespace Content.Client.Disposal.UI
}
},
new Control {MinSize = (0, 10)},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
Children =
{
@@ -114,8 +121,9 @@ namespace Content.Client.Disposal.UI
}
},
new Control {MinSize = (0, 10)},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
(Power = new CheckButton {Text = Loc.GetString("disposal-mailing-unit-power-button")}),
@@ -123,13 +131,15 @@ namespace Content.Client.Disposal.UI
}
}
},
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(12, 0, 8, 0),
Children =
{
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label
@@ -139,8 +149,9 @@ namespace Content.Client.Disposal.UI
}
},
new Control {MinSize = new Vector2(0, 8)},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
VerticalExpand = true,
Children =
{
@@ -161,16 +172,19 @@ namespace Content.Client.Disposal.UI
HorizontalExpand = true,
MinSize = new Vector2(0, 1),
},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Margin = new Thickness(4, 0, 0, 0),
Children =
{
diff --git a/Content.Client/Disposal/UI/DisposalRouterWindow.cs b/Content.Client/Disposal/UI/DisposalRouterWindow.cs
index aed47c39bf..b81e9cb5ae 100644
--- a/Content.Client/Disposal/UI/DisposalRouterWindow.cs
+++ b/Content.Client/Disposal/UI/DisposalRouterWindow.cs
@@ -4,6 +4,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Localization;
using static Content.Shared.Disposal.Components.SharedDisposalRouterComponent;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Disposal.UI
{
@@ -20,14 +21,16 @@ namespace Content.Client.Disposal.UI
MinSize = SetSize = (500, 110);
Title = Loc.GetString("disposal-router-window-title");
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
new Label {Text = Loc.GetString("disposal-router-window-tags-label")},
new Control {MinSize = (0, 10)},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
(TagInput = new LineEdit
diff --git a/Content.Client/Disposal/UI/DisposalTaggerWindow.cs b/Content.Client/Disposal/UI/DisposalTaggerWindow.cs
index d548a7da30..3ff60c676b 100644
--- a/Content.Client/Disposal/UI/DisposalTaggerWindow.cs
+++ b/Content.Client/Disposal/UI/DisposalTaggerWindow.cs
@@ -4,6 +4,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Localization;
using static Content.Shared.Disposal.Components.SharedDisposalTaggerComponent;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Disposal.UI
{
@@ -20,14 +21,16 @@ namespace Content.Client.Disposal.UI
MinSize = SetSize = (500, 110);
Title = Loc.GetString("disposal-tagger-window-title");
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
new Label {Text = Loc.GetString("disposal-tagger-window-tag-input-label")},
new Control {MinSize = (0, 10)},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
(TagInput = new LineEdit
diff --git a/Content.Client/Disposal/UI/DisposalUnitWindow.cs b/Content.Client/Disposal/UI/DisposalUnitWindow.cs
index a1bdd0d211..627cad95b4 100644
--- a/Content.Client/Disposal/UI/DisposalUnitWindow.cs
+++ b/Content.Client/Disposal/UI/DisposalUnitWindow.cs
@@ -8,6 +8,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using static Content.Shared.Disposal.Components.SharedDisposalUnitComponent;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Disposal.UI
{
@@ -27,12 +28,14 @@ namespace Content.Client.Disposal.UI
IoCManager.InjectDependencies(this);
MinSize = SetSize = (300, 140);
Resizable = false;
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 4,
Children =
{
@@ -41,8 +44,9 @@ namespace Content.Client.Disposal.UI
}
},
new Control {MinSize = (0, 5)},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 4,
Children =
{
@@ -59,8 +63,9 @@ namespace Content.Client.Disposal.UI
}
},
new Control {MinSize = (0, 10)},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
(Engage = new Button
diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs
index 566e2fd3ef..805c620ea0 100644
--- a/Content.Client/Entry/IgnoredComponents.cs
+++ b/Content.Client/Entry/IgnoredComponents.cs
@@ -21,7 +21,6 @@ namespace Content.Client.Entry
"EmitSoundOnActivate",
"FootstepModifier",
"HeatResistance",
- "ItemTeleporter",
"EntityStorage",
"Wirecutter",
"Screwdriver",
@@ -58,7 +57,6 @@ namespace Content.Client.Entry
"CablePlacer",
"Drink",
"Food",
- "FoodContainer",
"MagicMirror",
"FloorTile",
"ShuttleController",
@@ -78,8 +76,7 @@ namespace Content.Client.Entry
"CanSpill",
"SpeedLoader",
"Hitscan",
- "ExplosiveProjectile",
- "StunnableProjectile",
+ "StunOnCollide",
"RandomPottedPlant",
"CommunicationsConsole",
"BarSign",
@@ -97,8 +94,11 @@ namespace Content.Client.Entry
"SecureEntityStorage",
"PresetIdCard",
"SolarControlConsole",
- "FlashExplosive",
- "FlashProjectile",
+ "FlashOnTrigger",
+ "SoundOnTrigger",
+ "TriggerOnCollide",
+ "DeleteOnTrigger",
+ "ExplodeOnTrigger",
"Utensil",
"UnarmedCombat",
"TimedSpawner",
@@ -233,7 +233,7 @@ namespace Content.Client.Entry
"ConveyorAssembly",
"TwoWayLever",
"FirelockElectronics",
- "ChemicalInjectionProjectile",
+ "SolutionInjectOnCollide",
"Machine",
"MachinePart",
"MachineFrame",
@@ -276,6 +276,7 @@ namespace Content.Client.Entry
"Advertise",
"PowerNetworkBattery",
"BatteryCharger",
+ "SpawnItemsOnUse"
};
}
}
diff --git a/Content.Client/EscapeMenu/UI/EscapeMenu.xaml b/Content.Client/EscapeMenu/UI/EscapeMenu.xaml
index aa892e473b..baed55524a 100644
--- a/Content.Client/EscapeMenu/UI/EscapeMenu.xaml
+++ b/Content.Client/EscapeMenu/UI/EscapeMenu.xaml
@@ -4,11 +4,11 @@
Title="{Loc 'ui-escape-title'}"
Resizable="False">
-
+
-
+
diff --git a/Content.Client/EscapeMenu/UI/OptionsMenu.Audio.cs b/Content.Client/EscapeMenu/UI/OptionsMenu.Audio.cs
deleted file mode 100644
index 40815acde2..0000000000
--- a/Content.Client/EscapeMenu/UI/OptionsMenu.Audio.cs
+++ /dev/null
@@ -1,198 +0,0 @@
-using Content.Client.HUD.UI;
-using Content.Client.Stylesheets;
-using Content.Shared;
-using Content.Shared.CCVar;
-using Robust.Client.Graphics;
-using Robust.Client.UserInterface;
-using Robust.Client.UserInterface.Controls;
-using Robust.Shared;
-using Robust.Shared.Configuration;
-using Robust.Shared.Localization;
-using Robust.Shared.Maths;
-
-namespace Content.Client.EscapeMenu.UI
-{
- public sealed partial class OptionsMenu
- {
- private sealed class AudioControl : Control
- {
- private readonly IConfigurationManager _cfg;
- private readonly IClydeAudio _clydeAudio;
-
- private readonly Button ApplyButton;
- private readonly Label MasterVolumeLabel;
- private readonly Slider MasterVolumeSlider;
- private readonly CheckBox AmbienceCheckBox;
- private readonly CheckBox LobbyMusicCheckBox;
- private readonly Button ResetButton;
-
- public AudioControl(IConfigurationManager cfg, IClydeAudio clydeAudio)
- {
- _cfg = cfg;
- _clydeAudio = clydeAudio;
-
- var vBox = new VBoxContainer();
-
- var contents = new VBoxContainer
- {
- Margin = new Thickness(2, 2, 2, 0),
- VerticalExpand = true,
- };
-
- MasterVolumeSlider = new Slider
- {
- MinValue = 0.0f,
- MaxValue = 100.0f,
- HorizontalExpand = true,
- MinSize = (80, 8),
- Rounded = true
- };
-
- MasterVolumeLabel = new Label
- {
- MinSize = (48, 0),
- Align = Label.AlignMode.Right
- };
-
- contents.AddChild(new HBoxContainer
- {
- Children =
- {
- new Control {MinSize = (4, 0)},
- new Label {Text = Loc.GetString("ui-options-master-volume")},
- new Control {MinSize = (8, 0)},
- MasterVolumeSlider,
- new Control {MinSize = (8, 0)},
- MasterVolumeLabel,
- new Control {MinSize = (4, 0)},
- }
- });
-
- // sets up ambience checkbox. i am sorry for not fixing the rest of this code.
- AmbienceCheckBox = new CheckBox {Text = Loc.GetString("ui-options-ambient-hum")};
- contents.AddChild(AmbienceCheckBox);
- AmbienceCheckBox.Pressed = _cfg.GetCVar(CCVars.AmbienceBasicEnabled);
-
- LobbyMusicCheckBox = new CheckBox {Text = Loc.GetString("ui-options-lobby-music")};
- contents.AddChild(LobbyMusicCheckBox);
- LobbyMusicCheckBox.Pressed = _cfg.GetCVar(CCVars.LobbyMusicEnabled);
-
- ApplyButton = new Button
- {
- Text = Loc.GetString("ui-options-apply"), TextAlign = Label.AlignMode.Center,
- HorizontalAlignment = HAlignment.Right
- };
-
- vBox.AddChild(new Label
- {
- Text = Loc.GetString("ui-options-volume-sliders"),
- FontColorOverride = StyleNano.NanoGold,
- StyleClasses = {StyleNano.StyleClassLabelKeyText}
- });
-
- vBox.AddChild(contents);
-
- ResetButton = new Button
- {
- Text = Loc.GetString("ui-options-reset-all"),
- StyleClasses = {StyleBase.ButtonCaution},
- HorizontalExpand = true,
- HorizontalAlignment = HAlignment.Right
- };
-
- vBox.AddChild(new StripeBack
- {
- HasBottomEdge = false,
- HasMargins = false,
- Children =
- {
- new HBoxContainer
- {
- Align = BoxContainer.AlignMode.End,
- HorizontalExpand = true,
- VerticalExpand = true,
- Children =
- {
- ResetButton,
- new Control {MinSize = (2, 0)},
- ApplyButton
- }
- }
- }
- });
-
- ApplyButton.OnPressed += OnApplyButtonPressed;
- ResetButton.OnPressed += OnResetButtonPressed;
- MasterVolumeSlider.OnValueChanged += OnMasterVolumeSliderChanged;
- AmbienceCheckBox.OnToggled += OnAmbienceCheckToggled;
- LobbyMusicCheckBox.OnToggled += OnLobbyMusicCheckToggled;
-
- AddChild(vBox);
-
- Reset();
- }
-
- protected override void Dispose(bool disposing)
- {
- ApplyButton.OnPressed -= OnApplyButtonPressed;
- ResetButton.OnPressed -= OnResetButtonPressed;
- MasterVolumeSlider.OnValueChanged -= OnMasterVolumeSliderChanged;
- AmbienceCheckBox.OnToggled -= OnAmbienceCheckToggled;
- base.Dispose(disposing);
- }
-
- private void OnMasterVolumeSliderChanged(Range range)
- {
- MasterVolumeLabel.Text =
- Loc.GetString("ui-options-volume-percent", ("volume", MasterVolumeSlider.Value / 100));
- _clydeAudio.SetMasterVolume(MasterVolumeSlider.Value / 100);
- UpdateChanges();
- }
-
- private void OnAmbienceCheckToggled(BaseButton.ButtonEventArgs args)
- {
- UpdateChanges();
- }
-
- private void OnLobbyMusicCheckToggled(BaseButton.ButtonEventArgs args)
- {
- UpdateChanges();
- }
-
- private void OnApplyButtonPressed(BaseButton.ButtonEventArgs args)
- {
- _cfg.SetCVar(CVars.AudioMasterVolume, MasterVolumeSlider.Value / 100);
- _cfg.SetCVar(CCVars.AmbienceBasicEnabled, AmbienceCheckBox.Pressed);
- _cfg.SetCVar(CCVars.LobbyMusicEnabled, LobbyMusicCheckBox.Pressed);
- _cfg.SaveToFile();
- UpdateChanges();
- }
-
- private void OnResetButtonPressed(BaseButton.ButtonEventArgs args)
- {
- Reset();
- }
-
- private void Reset()
- {
- MasterVolumeSlider.Value = _cfg.GetCVar(CVars.AudioMasterVolume) * 100;
- MasterVolumeLabel.Text =
- Loc.GetString("ui-options-volume-percent", ("volume", MasterVolumeSlider.Value / 100));
- AmbienceCheckBox.Pressed = _cfg.GetCVar(CCVars.AmbienceBasicEnabled);
- LobbyMusicCheckBox.Pressed = _cfg.GetCVar(CCVars.LobbyMusicEnabled);
- UpdateChanges();
- }
-
- private void UpdateChanges()
- {
- var isMasterVolumeSame =
- System.Math.Abs(MasterVolumeSlider.Value - _cfg.GetCVar(CVars.AudioMasterVolume) * 100) < 0.01f;
- var isAmbienceSame = AmbienceCheckBox.Pressed == _cfg.GetCVar(CCVars.AmbienceBasicEnabled);
- var isLobbySame = LobbyMusicCheckBox.Pressed == _cfg.GetCVar(CCVars.LobbyMusicEnabled);
- var isEverythingSame = isMasterVolumeSame && isAmbienceSame && isLobbySame;
- ApplyButton.Disabled = isEverythingSame;
- ResetButton.Disabled = isEverythingSame;
- }
- }
- }
-}
diff --git a/Content.Client/EscapeMenu/UI/OptionsMenu.Graphics.cs b/Content.Client/EscapeMenu/UI/OptionsMenu.Graphics.cs
deleted file mode 100644
index 88e67f702c..0000000000
--- a/Content.Client/EscapeMenu/UI/OptionsMenu.Graphics.cs
+++ /dev/null
@@ -1,337 +0,0 @@
-using Content.Client.HUD.UI;
-using Content.Shared;
-using Content.Shared.CCVar;
-using Content.Shared.HUD;
-using Robust.Client.Graphics;
-using Robust.Client.UserInterface;
-using Robust.Client.UserInterface.Controls;
-using Robust.Shared;
-using Robust.Shared.Configuration;
-using Robust.Shared.Localization;
-using Robust.Shared.Maths;
-using Robust.Shared.Prototypes;
-
-namespace Content.Client.EscapeMenu.UI
-{
- public sealed partial class OptionsMenu
- {
- private sealed class GraphicsControl : Control
- {
- private static readonly float[] UIScaleOptions =
- {
- 0f,
- 0.75f,
- 1f,
- 1.25f,
- 1.50f,
- 1.75f,
- 2f
- };
-
- private readonly IConfigurationManager _cfg;
- private readonly IPrototypeManager _prototypeManager;
-
- private readonly Button ApplyButton;
- private readonly CheckBox VSyncCheckBox;
- private readonly CheckBox FullscreenCheckBox;
- private readonly OptionButton LightingPresetOption;
- private readonly OptionButton _uiScaleOption;
- private readonly OptionButton _hudThemeOption;
- private readonly CheckBox _viewportStretchCheckBox;
- private readonly CheckBox _viewportLowResCheckBox;
- private readonly Slider _viewportScaleSlider;
- private readonly Control _viewportScaleBox;
- private readonly Label _viewportScaleText;
-
- public GraphicsControl(IConfigurationManager cfg, IPrototypeManager proMan)
- {
- _cfg = cfg;
- _prototypeManager = proMan;
- var vBox = new VBoxContainer();
-
- var contents = new VBoxContainer
- {
- Margin = new Thickness(2, 2, 2, 0),
- VerticalExpand = true,
- };
-
- VSyncCheckBox = new CheckBox {Text = Loc.GetString("ui-options-vsync")};
- contents.AddChild(VSyncCheckBox);
- VSyncCheckBox.OnToggled += OnCheckBoxToggled;
-
- FullscreenCheckBox = new CheckBox {Text = Loc.GetString("ui-options-fullscreen")};
- contents.AddChild(FullscreenCheckBox);
- FullscreenCheckBox.OnToggled += OnCheckBoxToggled;
-
- LightingPresetOption = new OptionButton {MinSize = (100, 0)};
- LightingPresetOption.AddItem(Loc.GetString("ui-options-lighting-very-low"));
- LightingPresetOption.AddItem(Loc.GetString("ui-options-lighting-low"));
- LightingPresetOption.AddItem(Loc.GetString("ui-options-lighting-medium"));
- LightingPresetOption.AddItem(Loc.GetString("ui-options-lighting-high"));
- LightingPresetOption.OnItemSelected += OnLightingQualityChanged;
-
- contents.AddChild(new HBoxContainer
- {
- Children =
- {
- new Label {Text = Loc.GetString("ui-options-lighting-label")},
- new Control {MinSize = (4, 0)},
- LightingPresetOption
- }
- });
-
- ApplyButton = new Button
- {
- Text = Loc.GetString("ui-options-apply"), TextAlign = Label.AlignMode.Center,
- HorizontalAlignment = HAlignment.Right
- };
-
- _uiScaleOption = new OptionButton();
- _uiScaleOption.AddItem(Loc.GetString("ui-options-scale-auto",
- ("scale", UserInterfaceManager.DefaultUIScale)));
- _uiScaleOption.AddItem(Loc.GetString("ui-options-scale-75"));
- _uiScaleOption.AddItem(Loc.GetString("ui-options-scale-100"));
- _uiScaleOption.AddItem(Loc.GetString("ui-options-scale-125"));
- _uiScaleOption.AddItem(Loc.GetString("ui-options-scale-150"));
- _uiScaleOption.AddItem(Loc.GetString("ui-options-scale-175"));
- _uiScaleOption.AddItem(Loc.GetString("ui-options-scale-200"));
- _uiScaleOption.OnItemSelected += OnUIScaleChanged;
-
- contents.AddChild(new HBoxContainer
- {
- Children =
- {
- new Label {Text = Loc.GetString("ui-options-scale-label")},
- new Control {MinSize = (4, 0)},
- _uiScaleOption
- }
- });
-
- _hudThemeOption = new OptionButton();
- foreach (var gear in _prototypeManager.EnumeratePrototypes())
- {
- _hudThemeOption.AddItem(Loc.GetString(gear.Name));
- }
- _hudThemeOption.OnItemSelected += OnHudThemeChanged;
-
- contents.AddChild(new HBoxContainer
- {
- Children =
- {
- new Label {Text = Loc.GetString("ui-options-hud-theme")},
- new Control {MinSize = (4, 0)},
- _hudThemeOption
- }
- });
-
- _viewportStretchCheckBox = new CheckBox
- {
- Text = Loc.GetString("ui-options-vp-stretch")
- };
-
- _viewportStretchCheckBox.OnToggled += _ =>
- {
- UpdateViewportScale();
- UpdateApplyButton();
- };
-
- _viewportScaleSlider = new Slider
- {
- MinValue = 1,
- MaxValue = 5,
- Rounded = true,
- MinWidth = 200
- };
-
- _viewportScaleSlider.OnValueChanged += _ =>
- {
- UpdateApplyButton();
- UpdateViewportScale();
- };
-
- _viewportLowResCheckBox = new CheckBox { Text = Loc.GetString("ui-options-vp-low-res")};
- _viewportLowResCheckBox.OnToggled += OnCheckBoxToggled;
-
- contents.AddChild(new HBoxContainer
- {
- Children =
- {
- _viewportStretchCheckBox,
- (_viewportScaleBox = new HBoxContainer
- {
- Children =
- {
- (_viewportScaleText = new Label
- {
- Margin = new Thickness(8, 0)
- }),
- _viewportScaleSlider,
- }
- })
- }
- });
-
- contents.AddChild(_viewportLowResCheckBox);
-
- vBox.AddChild(contents);
-
- vBox.AddChild(new StripeBack
- {
- HasBottomEdge = false,
- HasMargins = false,
- Children =
- {
- ApplyButton
- }
- });
- ApplyButton.OnPressed += OnApplyButtonPressed;
-
- VSyncCheckBox.Pressed = _cfg.GetCVar(CVars.DisplayVSync);
- FullscreenCheckBox.Pressed = ConfigIsFullscreen;
- LightingPresetOption.SelectId(GetConfigLightingQuality());
- _uiScaleOption.SelectId(GetConfigUIScalePreset(ConfigUIScale));
- _hudThemeOption.SelectId(_cfg.GetCVar(CCVars.HudTheme));
- _viewportScaleSlider.Value = _cfg.GetCVar(CCVars.ViewportFixedScaleFactor);
- _viewportStretchCheckBox.Pressed = _cfg.GetCVar(CCVars.ViewportStretch);
- _viewportLowResCheckBox.Pressed = !_cfg.GetCVar(CCVars.ViewportScaleRender);
-
- UpdateViewportScale();
- UpdateApplyButton();
-
- AddChild(vBox);
- }
-
- private void OnUIScaleChanged(OptionButton.ItemSelectedEventArgs args)
- {
- _uiScaleOption.SelectId(args.Id);
- UpdateApplyButton();
- }
-
- private void OnHudThemeChanged(OptionButton.ItemSelectedEventArgs args)
- {
- _hudThemeOption.SelectId(args.Id);
- UpdateApplyButton();
- }
-
- private void OnApplyButtonPressed(BaseButton.ButtonEventArgs args)
- {
- _cfg.SetCVar(CVars.DisplayVSync, VSyncCheckBox.Pressed);
- SetConfigLightingQuality(LightingPresetOption.SelectedId);
- if (_hudThemeOption.SelectedId != _cfg.GetCVar(CCVars.HudTheme)) // Don't unnecessarily redraw the HUD
- {
- _cfg.SetCVar(CCVars.HudTheme, _hudThemeOption.SelectedId);
- }
-
- _cfg.SetCVar(CVars.DisplayWindowMode,
- (int) (FullscreenCheckBox.Pressed ? WindowMode.Fullscreen : WindowMode.Windowed));
- _cfg.SetCVar(CVars.DisplayUIScale, UIScaleOptions[_uiScaleOption.SelectedId]);
- _cfg.SetCVar(CCVars.ViewportStretch, _viewportStretchCheckBox.Pressed);
- _cfg.SetCVar(CCVars.ViewportFixedScaleFactor, (int) _viewportScaleSlider.Value);
- _cfg.SetCVar(CCVars.ViewportScaleRender, !_viewportLowResCheckBox.Pressed);
- _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(CVars.DisplayVSync);
- var isFullscreenSame = FullscreenCheckBox.Pressed == ConfigIsFullscreen;
- var isLightingQualitySame = LightingPresetOption.SelectedId == GetConfigLightingQuality();
- var isHudThemeSame = _hudThemeOption.SelectedId == _cfg.GetCVar(CCVars.HudTheme);
- var isUIScaleSame = MathHelper.CloseTo(UIScaleOptions[_uiScaleOption.SelectedId], ConfigUIScale);
- var isVPStretchSame = _viewportStretchCheckBox.Pressed == _cfg.GetCVar(CCVars.ViewportStretch);
- var isVPScaleSame = (int) _viewportScaleSlider.Value == _cfg.GetCVar(CCVars.ViewportFixedScaleFactor);
- var isVPResSame = _viewportLowResCheckBox.Pressed == !_cfg.GetCVar(CCVars.ViewportScaleRender);
-
- ApplyButton.Disabled = isVSyncSame &&
- isFullscreenSame &&
- isLightingQualitySame &&
- isUIScaleSame &&
- isVPStretchSame &&
- isVPScaleSame &&
- isVPResSame &&
- isHudThemeSame;
- }
-
- private bool ConfigIsFullscreen =>
- _cfg.GetCVar(CVars.DisplayWindowMode) == (int) WindowMode.Fullscreen;
-
- private float ConfigUIScale => _cfg.GetCVar(CVars.DisplayUIScale);
-
- private int GetConfigLightingQuality()
- {
- var val = _cfg.GetCVar(CVars.DisplayLightMapDivider);
- var soft = _cfg.GetCVar(CVars.DisplaySoftShadows);
- 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(CVars.DisplayLightMapDivider, 8);
- _cfg.SetCVar(CVars.DisplaySoftShadows, false);
- break;
- case 1:
- _cfg.SetCVar(CVars.DisplayLightMapDivider, 2);
- _cfg.SetCVar(CVars.DisplaySoftShadows, false);
- break;
- case 2:
- _cfg.SetCVar(CVars.DisplayLightMapDivider, 2);
- _cfg.SetCVar(CVars.DisplaySoftShadows, true);
- break;
- case 3:
- _cfg.SetCVar(CVars.DisplayLightMapDivider, 1);
- _cfg.SetCVar(CVars.DisplaySoftShadows, true);
- break;
- }
- }
-
- private static int GetConfigUIScalePreset(float value)
- {
- for (var i = 0; i < UIScaleOptions.Length; i++)
- {
- if (MathHelper.CloseTo(UIScaleOptions[i], value))
- {
- return i;
- }
- }
-
- return 0;
- }
-
- private void UpdateViewportScale()
- {
- _viewportScaleBox.Visible = !_viewportStretchCheckBox.Pressed;
- _viewportScaleText.Text = Loc.GetString("ui-options-vp-scale", ("scale", _viewportScaleSlider.Value));
- }
- }
- }
-}
diff --git a/Content.Client/EscapeMenu/UI/OptionsMenu.KeyRebind.cs b/Content.Client/EscapeMenu/UI/OptionsMenu.KeyRebind.cs
deleted file mode 100644
index ffde940423..0000000000
--- a/Content.Client/EscapeMenu/UI/OptionsMenu.KeyRebind.cs
+++ /dev/null
@@ -1,491 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Content.Client.HUD.UI;
-using Content.Client.Stylesheets;
-using Content.Shared.Input;
-using Robust.Client.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.Maths;
-using Robust.Shared.Timing;
-using Robust.Shared.Utility;
-
-namespace Content.Client.EscapeMenu.UI
-{
- 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()
- {
- EngineKeyFunctions.ShowDebugMonitors,
- EngineKeyFunctions.HideUI,
- };
-
- [Dependency] private readonly IInputManager _inputManager = default!;
-
- private BindButton? _currentlyRebinding;
-
- private readonly Dictionary _keyControls =
- new();
-
- private readonly List _deferCommands = new();
-
- public KeyRebindControl()
- {
- IoCManager.InjectDependencies(this);
-
- Button resetAllButton;
- var vBox = new VBoxContainer {Margin = new Thickness(2, 0, 0, 0)};
- AddChild(new VBoxContainer
- {
- Children =
- {
- new ScrollContainer
- {
- VerticalExpand = true,
- Children = {vBox}
- },
-
- new StripeBack
- {
- HasBottomEdge = false,
- HasMargins = false,
- Children =
- {
- new HBoxContainer
- {
- Children =
- {
- new Control {MinSize = (2, 0)},
- new Label
- {
- StyleClasses = {StyleBase.StyleClassLabelSubText},
- Text = Loc.GetString("ui-options-binds-explanation")
- },
- (resetAllButton = new Button
- {
- Text = Loc.GetString("ui-options-binds-reset-all"),
- StyleClasses = {StyleBase.ButtonCaution},
- HorizontalExpand = true,
- HorizontalAlignment = HAlignment.Right
- })
- }
- }
- }
- }
- }
- });
-
- resetAllButton.OnPressed += _ =>
- {
- _deferCommands.Add(() =>
- {
- _inputManager.ResetAllBindings();
- _inputManager.SaveToUserData();
- });
- };
-
- var first = true;
-
- void AddHeader(string headerContents)
- {
- if (!first)
- {
- vBox.AddChild(new Control {MinSize = (0, 8)});
- }
-
- first = false;
- vBox.AddChild(new Label
- {
- Text = Loc.GetString(headerContents),
- FontColorOverride = StyleNano.NanoGold,
- StyleClasses = {StyleNano.StyleClassLabelKeyText}
- });
- }
-
- void AddButton(BoundKeyFunction function)
- {
- var control = new KeyControl(this, function);
- vBox.AddChild(control);
- _keyControls.Add(function, control);
- }
-
- AddHeader("ui-options-header-movement");
- AddButton(EngineKeyFunctions.MoveUp);
- AddButton(EngineKeyFunctions.MoveLeft);
- AddButton(EngineKeyFunctions.MoveDown);
- AddButton(EngineKeyFunctions.MoveRight);
- AddButton(EngineKeyFunctions.Walk);
-
- AddHeader("ui-options-header-interaction-basic");
- AddButton(EngineKeyFunctions.Use);
- AddButton(ContentKeyFunctions.WideAttack);
- AddButton(ContentKeyFunctions.ActivateItemInHand);
- AddButton(ContentKeyFunctions.ActivateItemInWorld);
- AddButton(ContentKeyFunctions.Drop);
- AddButton(ContentKeyFunctions.ExamineEntity);
- AddButton(ContentKeyFunctions.SwapHands);
-
- AddHeader("ui-options-header-interaction-adv");
- AddButton(ContentKeyFunctions.SmartEquipBackpack);
- AddButton(ContentKeyFunctions.SmartEquipBelt);
- AddButton(ContentKeyFunctions.ThrowItemInHand);
- AddButton(ContentKeyFunctions.TryPullObject);
- AddButton(ContentKeyFunctions.MovePulledObject);
- AddButton(ContentKeyFunctions.ReleasePulledObject);
- AddButton(ContentKeyFunctions.Point);
-
- AddHeader("ui-options-header-ui");
- AddButton(ContentKeyFunctions.FocusChat);
- AddButton(ContentKeyFunctions.FocusLocalChat);
- AddButton(ContentKeyFunctions.FocusRadio);
- AddButton(ContentKeyFunctions.FocusOOC);
- AddButton(ContentKeyFunctions.FocusAdminChat);
- AddButton(ContentKeyFunctions.CycleChatChannelForward);
- AddButton(ContentKeyFunctions.CycleChatChannelBackward);
- AddButton(ContentKeyFunctions.OpenCharacterMenu);
- AddButton(ContentKeyFunctions.OpenContextMenu);
- AddButton(ContentKeyFunctions.OpenCraftingMenu);
- AddButton(ContentKeyFunctions.OpenInventoryMenu);
- AddButton(ContentKeyFunctions.OpenInfo);
- AddButton(ContentKeyFunctions.OpenActionsMenu);
- AddButton(ContentKeyFunctions.OpenEntitySpawnWindow);
- AddButton(ContentKeyFunctions.OpenSandboxWindow);
- AddButton(ContentKeyFunctions.OpenTileSpawnWindow);
- AddButton(ContentKeyFunctions.OpenAdminMenu);
-
- AddHeader("ui-options-header-misc");
- AddButton(ContentKeyFunctions.TakeScreenshot);
- AddButton(ContentKeyFunctions.TakeScreenshotNoUI);
-
- AddHeader("ui-options-header-hotbar");
- AddButton(ContentKeyFunctions.Hotbar1);
- AddButton(ContentKeyFunctions.Hotbar2);
- AddButton(ContentKeyFunctions.Hotbar3);
- AddButton(ContentKeyFunctions.Hotbar4);
- AddButton(ContentKeyFunctions.Hotbar5);
- AddButton(ContentKeyFunctions.Hotbar6);
- AddButton(ContentKeyFunctions.Hotbar7);
- AddButton(ContentKeyFunctions.Hotbar8);
- AddButton(ContentKeyFunctions.Hotbar9);
- AddButton(ContentKeyFunctions.Hotbar0);
- AddButton(ContentKeyFunctions.Loadout1);
- AddButton(ContentKeyFunctions.Loadout2);
- AddButton(ContentKeyFunctions.Loadout3);
- AddButton(ContentKeyFunctions.Loadout4);
- AddButton(ContentKeyFunctions.Loadout5);
- AddButton(ContentKeyFunctions.Loadout6);
- AddButton(ContentKeyFunctions.Loadout7);
- AddButton(ContentKeyFunctions.Loadout8);
- AddButton(ContentKeyFunctions.Loadout9);
-
- AddHeader("ui-options-header-map-editor");
- AddButton(EngineKeyFunctions.EditorPlaceObject);
- AddButton(EngineKeyFunctions.EditorCancelPlace);
- AddButton(EngineKeyFunctions.EditorGridPlace);
- AddButton(EngineKeyFunctions.EditorLinePlace);
- AddButton(EngineKeyFunctions.EditorRotateObject);
-
- AddHeader("ui-options-header-dev");
- AddButton(EngineKeyFunctions.ShowDebugConsole);
- AddButton(EngineKeyFunctions.ShowDebugMonitors);
- AddButton(EngineKeyFunctions.HideUI);
-
- 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("ui-options-key-prompt");
-
- 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, BoundKeyFunction function)
- {
- Function = function;
- var name = new Label
- {
- Text = Loc.GetString(
- $"ui-options-function-{CaseConversion.PascalToKebab(function.FunctionName)}"),
- HorizontalExpand = true,
- HorizontalAlignment = HAlignment.Left
- };
-
- BindButton1 = new BindButton(parent, this, StyleBase.ButtonOpenRight);
- BindButton2 = new BindButton(parent, this, StyleBase.ButtonOpenLeft);
- ResetButton = new Button {Text = Loc.GetString("ui-options-bind-reset"), StyleClasses = {StyleBase.ButtonCaution}};
-
- var hBox = new HBoxContainer
- {
- Children =
- {
- new Control {MinSize = (5, 0)},
- name,
- BindButton1,
- BindButton2,
- new Control {MinSize = (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;
-
- MinSize = (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() ?? Loc.GetString("ui-options-unbound");
- }
- }
- }
- }
-}
diff --git a/Content.Client/EscapeMenu/UI/OptionsMenu.cs b/Content.Client/EscapeMenu/UI/OptionsMenu.cs
deleted file mode 100644
index 5203494fc2..0000000000
--- a/Content.Client/EscapeMenu/UI/OptionsMenu.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using Robust.Client.Graphics;
-using Robust.Client.UserInterface.Controls;
-using Robust.Client.UserInterface.CustomControls;
-using Robust.Shared.Configuration;
-using Robust.Shared.IoC;
-using Robust.Shared.Localization;
-using Robust.Shared.Prototypes;
-
-namespace Content.Client.EscapeMenu.UI
-{
- public sealed partial class OptionsMenu : SS14Window
- {
- [Dependency] private readonly IConfigurationManager _configManager = default!;
- [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- [Dependency] private readonly IClydeAudio _clydeAudio = default!;
-
- public OptionsMenu()
- {
- SetSize = MinSize = (800, 450);
- IoCManager.InjectDependencies(this);
-
- Title = Loc.GetString("ui-options-title");
-
- GraphicsControl graphicsControl;
- KeyRebindControl rebindControl;
- AudioControl audioControl;
-
- var tabs = new TabContainer
- {
- Children =
- {
- (graphicsControl = new GraphicsControl(_configManager, _prototypeManager)),
- (rebindControl = new KeyRebindControl()),
- (audioControl = new AudioControl(_configManager, _clydeAudio)),
- }
- };
-
- TabContainer.SetTabTitle(graphicsControl, Loc.GetString("ui-options-tab-graphics"));
- TabContainer.SetTabTitle(rebindControl, Loc.GetString("ui-options-tab-controls"));
- TabContainer.SetTabTitle(audioControl, Loc.GetString("ui-options-tab-audio"));
-
- Contents.AddChild(tabs);
- }
- }
-}
diff --git a/Content.Client/EscapeMenu/UI/OptionsMenu.xaml b/Content.Client/EscapeMenu/UI/OptionsMenu.xaml
new file mode 100644
index 0000000000..84da16e1a1
--- /dev/null
+++ b/Content.Client/EscapeMenu/UI/OptionsMenu.xaml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/Content.Client/EscapeMenu/UI/OptionsMenu.xaml.cs b/Content.Client/EscapeMenu/UI/OptionsMenu.xaml.cs
new file mode 100644
index 0000000000..2e408d445f
--- /dev/null
+++ b/Content.Client/EscapeMenu/UI/OptionsMenu.xaml.cs
@@ -0,0 +1,22 @@
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.IoC;
+using Robust.Shared.Localization;
+
+namespace Content.Client.EscapeMenu.UI
+{
+ [GenerateTypedNameReferences]
+ public partial class OptionsMenu : SS14Window
+ {
+ public OptionsMenu()
+ {
+ RobustXamlLoader.Load(this);
+ IoCManager.InjectDependencies(this);
+
+ Tabs.SetTabTitle(0, Loc.GetString("ui-options-tab-graphics"));
+ Tabs.SetTabTitle(1, Loc.GetString("ui-options-tab-controls"));
+ Tabs.SetTabTitle(2, Loc.GetString("ui-options-tab-audio"));
+ }
+ }
+}
diff --git a/Content.Client/EscapeMenu/UI/Tabs/AudioTab.xaml b/Content.Client/EscapeMenu/UI/Tabs/AudioTab.xaml
new file mode 100644
index 0000000000..19c24ec270
--- /dev/null
+++ b/Content.Client/EscapeMenu/UI/Tabs/AudioTab.xaml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/EscapeMenu/UI/Tabs/AudioTab.xaml.cs b/Content.Client/EscapeMenu/UI/Tabs/AudioTab.xaml.cs
new file mode 100644
index 0000000000..22e905b032
--- /dev/null
+++ b/Content.Client/EscapeMenu/UI/Tabs/AudioTab.xaml.cs
@@ -0,0 +1,99 @@
+using Content.Shared.CCVar;
+using Robust.Client.AutoGenerated;
+using Robust.Client.Graphics;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared;
+using Robust.Shared.Configuration;
+using Robust.Shared.IoC;
+using Robust.Shared.Localization;
+
+namespace Content.Client.EscapeMenu.UI.Tabs
+{
+ [GenerateTypedNameReferences]
+ public partial class AudioTab : Control
+ {
+ [Dependency] private readonly IConfigurationManager _cfg = default!;
+ [Dependency] private readonly IClydeAudio _clydeAudio = default!;
+
+ public AudioTab()
+ {
+ RobustXamlLoader.Load(this);
+ IoCManager.InjectDependencies(this);
+
+ AmbienceCheckBox.Pressed = _cfg.GetCVar(CCVars.AmbienceBasicEnabled);
+ LobbyMusicCheckBox.Pressed = _cfg.GetCVar(CCVars.LobbyMusicEnabled);
+
+ ApplyButton.OnPressed += OnApplyButtonPressed;
+ ResetButton.OnPressed += OnResetButtonPressed;
+ MasterVolumeSlider.OnValueChanged += OnMasterVolumeSliderChanged;
+ AmbienceCheckBox.OnToggled += OnAmbienceCheckToggled;
+ LobbyMusicCheckBox.OnToggled += OnLobbyMusicCheckToggled;
+
+ Reset();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ ApplyButton.OnPressed -= OnApplyButtonPressed;
+ ResetButton.OnPressed -= OnResetButtonPressed;
+ MasterVolumeSlider.OnValueChanged -= OnMasterVolumeSliderChanged;
+ AmbienceCheckBox.OnToggled -= OnAmbienceCheckToggled;
+ base.Dispose(disposing);
+ }
+
+ private void OnMasterVolumeSliderChanged(Range range)
+ {
+ MasterVolumeLabel.Text =
+ Loc.GetString("ui-options-volume-percent", ("volume", MasterVolumeSlider.Value / 100));
+ _clydeAudio.SetMasterVolume(MasterVolumeSlider.Value / 100);
+ UpdateChanges();
+ }
+
+ private void OnAmbienceCheckToggled(BaseButton.ButtonEventArgs args)
+ {
+ UpdateChanges();
+ }
+
+ private void OnLobbyMusicCheckToggled(BaseButton.ButtonEventArgs args)
+ {
+ UpdateChanges();
+ }
+
+ private void OnApplyButtonPressed(BaseButton.ButtonEventArgs args)
+ {
+ _cfg.SetCVar(CVars.AudioMasterVolume, MasterVolumeSlider.Value / 100);
+ _cfg.SetCVar(CCVars.AmbienceBasicEnabled, AmbienceCheckBox.Pressed);
+ _cfg.SetCVar(CCVars.LobbyMusicEnabled, LobbyMusicCheckBox.Pressed);
+ _cfg.SaveToFile();
+ UpdateChanges();
+ }
+
+ private void OnResetButtonPressed(BaseButton.ButtonEventArgs args)
+ {
+ Reset();
+ }
+
+ private void Reset()
+ {
+ MasterVolumeSlider.Value = _cfg.GetCVar(CVars.AudioMasterVolume) * 100;
+ MasterVolumeLabel.Text =
+ Loc.GetString("ui-options-volume-percent", ("volume", MasterVolumeSlider.Value / 100));
+ AmbienceCheckBox.Pressed = _cfg.GetCVar(CCVars.AmbienceBasicEnabled);
+ LobbyMusicCheckBox.Pressed = _cfg.GetCVar(CCVars.LobbyMusicEnabled);
+ UpdateChanges();
+ }
+
+ private void UpdateChanges()
+ {
+ var isMasterVolumeSame =
+ System.Math.Abs(MasterVolumeSlider.Value - _cfg.GetCVar(CVars.AudioMasterVolume) * 100) < 0.01f;
+ var isAmbienceSame = AmbienceCheckBox.Pressed == _cfg.GetCVar(CCVars.AmbienceBasicEnabled);
+ var isLobbySame = LobbyMusicCheckBox.Pressed == _cfg.GetCVar(CCVars.LobbyMusicEnabled);
+ var isEverythingSame = isMasterVolumeSame && isAmbienceSame && isLobbySame;
+ ApplyButton.Disabled = isEverythingSame;
+ ResetButton.Disabled = isEverythingSame;
+ }
+ }
+}
diff --git a/Content.Client/EscapeMenu/UI/Tabs/GraphicsTab.xaml b/Content.Client/EscapeMenu/UI/Tabs/GraphicsTab.xaml
new file mode 100644
index 0000000000..f8ae37134a
--- /dev/null
+++ b/Content.Client/EscapeMenu/UI/Tabs/GraphicsTab.xaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/EscapeMenu/UI/Tabs/GraphicsTab.xaml.cs b/Content.Client/EscapeMenu/UI/Tabs/GraphicsTab.xaml.cs
new file mode 100644
index 0000000000..db27898a79
--- /dev/null
+++ b/Content.Client/EscapeMenu/UI/Tabs/GraphicsTab.xaml.cs
@@ -0,0 +1,230 @@
+using Content.Shared.CCVar;
+using Content.Shared.HUD;
+using Robust.Client.AutoGenerated;
+using Robust.Client.Graphics;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared;
+using Robust.Shared.Configuration;
+using Robust.Shared.IoC;
+using Robust.Shared.Localization;
+using Robust.Shared.Maths;
+using Robust.Shared.Prototypes;
+
+namespace Content.Client.EscapeMenu.UI.Tabs
+{
+ [GenerateTypedNameReferences]
+ public partial class GraphicsTab : Control
+ {
+ private static readonly float[] UIScaleOptions =
+ {
+ 0f,
+ 0.75f,
+ 1f,
+ 1.25f,
+ 1.50f,
+ 1.75f,
+ 2f
+ };
+
+ [Dependency] private readonly IConfigurationManager _cfg = default!;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+
+ public GraphicsTab()
+ {
+ IoCManager.InjectDependencies(this);
+ RobustXamlLoader.Load(this);
+
+ VSyncCheckBox.OnToggled += OnCheckBoxToggled;
+ FullscreenCheckBox.OnToggled += OnCheckBoxToggled;
+
+ LightingPresetOption.AddItem(Loc.GetString("ui-options-lighting-very-low"));
+ LightingPresetOption.AddItem(Loc.GetString("ui-options-lighting-low"));
+ LightingPresetOption.AddItem(Loc.GetString("ui-options-lighting-medium"));
+ LightingPresetOption.AddItem(Loc.GetString("ui-options-lighting-high"));
+ LightingPresetOption.OnItemSelected += OnLightingQualityChanged;
+
+ UIScaleOption.AddItem(Loc.GetString("ui-options-scale-auto",
+ ("scale", UserInterfaceManager.DefaultUIScale)));
+ UIScaleOption.AddItem(Loc.GetString("ui-options-scale-75"));
+ UIScaleOption.AddItem(Loc.GetString("ui-options-scale-100"));
+ UIScaleOption.AddItem(Loc.GetString("ui-options-scale-125"));
+ UIScaleOption.AddItem(Loc.GetString("ui-options-scale-150"));
+ UIScaleOption.AddItem(Loc.GetString("ui-options-scale-175"));
+ UIScaleOption.AddItem(Loc.GetString("ui-options-scale-200"));
+ UIScaleOption.OnItemSelected += OnUIScaleChanged;
+
+ foreach (var gear in _prototypeManager.EnumeratePrototypes())
+ {
+ HudThemeOption.AddItem(Loc.GetString(gear.Name));
+ }
+ HudThemeOption.OnItemSelected += OnHudThemeChanged;
+
+ ViewportStretchCheckBox.OnToggled += _ =>
+ {
+ UpdateViewportScale();
+ UpdateApplyButton();
+ };
+
+ ViewportScaleSlider.OnValueChanged += _ =>
+ {
+ UpdateApplyButton();
+ UpdateViewportScale();
+ };
+
+ IntegerScalingCheckBox.OnToggled += OnCheckBoxToggled;
+ ViewportLowResCheckBox.OnToggled += OnCheckBoxToggled;
+ ApplyButton.OnPressed += OnApplyButtonPressed;
+ VSyncCheckBox.Pressed = _cfg.GetCVar(CVars.DisplayVSync);
+ FullscreenCheckBox.Pressed = ConfigIsFullscreen;
+ LightingPresetOption.SelectId(GetConfigLightingQuality());
+ UIScaleOption.SelectId(GetConfigUIScalePreset(ConfigUIScale));
+ HudThemeOption.SelectId(_cfg.GetCVar(CCVars.HudTheme));
+ ViewportScaleSlider.Value = _cfg.GetCVar(CCVars.ViewportFixedScaleFactor);
+ ViewportStretchCheckBox.Pressed = _cfg.GetCVar(CCVars.ViewportStretch);
+ IntegerScalingCheckBox.Pressed = _cfg.GetCVar(CCVars.ViewportSnapToleranceMargin) != 0;
+ ViewportLowResCheckBox.Pressed = !_cfg.GetCVar(CCVars.ViewportScaleRender);
+
+ UpdateViewportScale();
+ UpdateApplyButton();
+ }
+
+ private void OnUIScaleChanged(OptionButton.ItemSelectedEventArgs args)
+ {
+ UIScaleOption.SelectId(args.Id);
+ UpdateApplyButton();
+ }
+
+ private void OnHudThemeChanged(OptionButton.ItemSelectedEventArgs args)
+ {
+ HudThemeOption.SelectId(args.Id);
+ UpdateApplyButton();
+ }
+
+ private void OnApplyButtonPressed(BaseButton.ButtonEventArgs args)
+ {
+ _cfg.SetCVar(CVars.DisplayVSync, VSyncCheckBox.Pressed);
+ SetConfigLightingQuality(LightingPresetOption.SelectedId);
+ if (HudThemeOption.SelectedId != _cfg.GetCVar(CCVars.HudTheme)) // Don't unnecessarily redraw the HUD
+ {
+ _cfg.SetCVar(CCVars.HudTheme, HudThemeOption.SelectedId);
+ }
+
+ _cfg.SetCVar(CVars.DisplayWindowMode,
+ (int) (FullscreenCheckBox.Pressed ? WindowMode.Fullscreen : WindowMode.Windowed));
+ _cfg.SetCVar(CVars.DisplayUIScale, UIScaleOptions[UIScaleOption.SelectedId]);
+ _cfg.SetCVar(CCVars.ViewportStretch, ViewportStretchCheckBox.Pressed);
+ _cfg.SetCVar(CCVars.ViewportFixedScaleFactor, (int) ViewportScaleSlider.Value);
+ _cfg.SetCVar(CCVars.ViewportSnapToleranceMargin,
+ IntegerScalingCheckBox.Pressed ? CCVars.ViewportSnapToleranceMargin.DefaultValue : 0);
+ _cfg.SetCVar(CCVars.ViewportScaleRender, !ViewportLowResCheckBox.Pressed);
+ _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(CVars.DisplayVSync);
+ var isFullscreenSame = FullscreenCheckBox.Pressed == ConfigIsFullscreen;
+ var isLightingQualitySame = LightingPresetOption.SelectedId == GetConfigLightingQuality();
+ var isHudThemeSame = HudThemeOption.SelectedId == _cfg.GetCVar(CCVars.HudTheme);
+ var isUIScaleSame = MathHelper.CloseTo(UIScaleOptions[UIScaleOption.SelectedId], ConfigUIScale);
+ var isVPStretchSame = ViewportStretchCheckBox.Pressed == _cfg.GetCVar(CCVars.ViewportStretch);
+ var isVPScaleSame = (int) ViewportScaleSlider.Value == _cfg.GetCVar(CCVars.ViewportFixedScaleFactor);
+ var isIntegerScalingSame = IntegerScalingCheckBox.Pressed == (_cfg.GetCVar(CCVars.ViewportSnapToleranceMargin) != 0);
+ var isVPResSame = ViewportLowResCheckBox.Pressed == !_cfg.GetCVar(CCVars.ViewportScaleRender);
+
+ ApplyButton.Disabled = isVSyncSame &&
+ isFullscreenSame &&
+ isLightingQualitySame &&
+ isUIScaleSame &&
+ isVPStretchSame &&
+ isVPScaleSame &&
+ isIntegerScalingSame &&
+ isVPResSame &&
+ isHudThemeSame;
+ }
+
+ private bool ConfigIsFullscreen =>
+ _cfg.GetCVar(CVars.DisplayWindowMode) == (int) WindowMode.Fullscreen;
+
+ private float ConfigUIScale => _cfg.GetCVar(CVars.DisplayUIScale);
+
+ private int GetConfigLightingQuality()
+ {
+ var val = _cfg.GetCVar(CVars.DisplayLightMapDivider);
+ var soft = _cfg.GetCVar(CVars.DisplaySoftShadows);
+ 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(CVars.DisplayLightMapDivider, 8);
+ _cfg.SetCVar(CVars.DisplaySoftShadows, false);
+ break;
+ case 1:
+ _cfg.SetCVar(CVars.DisplayLightMapDivider, 2);
+ _cfg.SetCVar(CVars.DisplaySoftShadows, false);
+ break;
+ case 2:
+ _cfg.SetCVar(CVars.DisplayLightMapDivider, 2);
+ _cfg.SetCVar(CVars.DisplaySoftShadows, true);
+ break;
+ case 3:
+ _cfg.SetCVar(CVars.DisplayLightMapDivider, 1);
+ _cfg.SetCVar(CVars.DisplaySoftShadows, true);
+ break;
+ }
+ }
+
+ private static int GetConfigUIScalePreset(float value)
+ {
+ for (var i = 0; i < UIScaleOptions.Length; i++)
+ {
+ if (MathHelper.CloseTo(UIScaleOptions[i], value))
+ {
+ return i;
+ }
+ }
+
+ return 0;
+ }
+
+ private void UpdateViewportScale()
+ {
+ ViewportScaleBox.Visible = !ViewportStretchCheckBox.Pressed;
+ IntegerScalingCheckBox.Visible = ViewportStretchCheckBox.Pressed;
+ ViewportScaleText.Text = Loc.GetString("ui-options-vp-scale", ("scale", ViewportScaleSlider.Value));
+ }
+ }
+}
diff --git a/Content.Client/EscapeMenu/UI/Tabs/KeyRebindTab.xaml b/Content.Client/EscapeMenu/UI/Tabs/KeyRebindTab.xaml
new file mode 100644
index 0000000000..0769aa9c0c
--- /dev/null
+++ b/Content.Client/EscapeMenu/UI/Tabs/KeyRebindTab.xaml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/EscapeMenu/UI/Tabs/KeyRebindTab.xaml.cs b/Content.Client/EscapeMenu/UI/Tabs/KeyRebindTab.xaml.cs
new file mode 100644
index 0000000000..bbd8fb0f6e
--- /dev/null
+++ b/Content.Client/EscapeMenu/UI/Tabs/KeyRebindTab.xaml.cs
@@ -0,0 +1,452 @@
+using System;
+using System.Collections.Generic;
+using Content.Client.Stylesheets;
+using Content.Shared.Input;
+using Robust.Client.AutoGenerated;
+using Robust.Client.Input;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Input;
+using Robust.Shared.IoC;
+using Robust.Shared.Localization;
+using Robust.Shared.Timing;
+using Robust.Shared.Utility;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
+
+namespace Content.Client.EscapeMenu.UI.Tabs
+{
+ [GenerateTypedNameReferences]
+ public partial class KeyRebindTab : Control
+ {
+ // List of key functions that must be registered as toggle instead.
+ private static readonly HashSet ToggleFunctions = new()
+ {
+ EngineKeyFunctions.ShowDebugMonitors,
+ EngineKeyFunctions.HideUI,
+ };
+
+ [Dependency] private readonly IInputManager _inputManager = default!;
+
+ private BindButton? _currentlyRebinding;
+
+ private readonly Dictionary _keyControls =
+ new();
+
+ private readonly List _deferCommands = new();
+
+ public KeyRebindTab()
+ {
+ IoCManager.InjectDependencies(this);
+ RobustXamlLoader.Load(this);
+
+ ResetAllButton.OnPressed += _ =>
+ {
+ _deferCommands.Add(() =>
+ {
+ _inputManager.ResetAllBindings();
+ _inputManager.SaveToUserData();
+ });
+ };
+
+ var first = true;
+
+ void AddHeader(string headerContents)
+ {
+ if (!first)
+ {
+ KeybindsContainer.AddChild(new Control {MinSize = (0, 8)});
+ }
+
+ first = false;
+ KeybindsContainer.AddChild(new Label
+ {
+ Text = Loc.GetString(headerContents),
+ FontColorOverride = StyleNano.NanoGold,
+ StyleClasses = {StyleNano.StyleClassLabelKeyText}
+ });
+ }
+
+ void AddButton(BoundKeyFunction function)
+ {
+ var control = new KeyControl(this, function);
+ KeybindsContainer.AddChild(control);
+ _keyControls.Add(function, control);
+ }
+
+ AddHeader("ui-options-header-movement");
+ AddButton(EngineKeyFunctions.MoveUp);
+ AddButton(EngineKeyFunctions.MoveLeft);
+ AddButton(EngineKeyFunctions.MoveDown);
+ AddButton(EngineKeyFunctions.MoveRight);
+ AddButton(EngineKeyFunctions.Walk);
+
+ AddHeader("ui-options-header-interaction-basic");
+ AddButton(EngineKeyFunctions.Use);
+ AddButton(ContentKeyFunctions.WideAttack);
+ AddButton(ContentKeyFunctions.ActivateItemInHand);
+ AddButton(ContentKeyFunctions.ActivateItemInWorld);
+ AddButton(ContentKeyFunctions.Drop);
+ AddButton(ContentKeyFunctions.ExamineEntity);
+ AddButton(ContentKeyFunctions.SwapHands);
+
+ AddHeader("ui-options-header-interaction-adv");
+ AddButton(ContentKeyFunctions.SmartEquipBackpack);
+ AddButton(ContentKeyFunctions.SmartEquipBelt);
+ AddButton(ContentKeyFunctions.ThrowItemInHand);
+ AddButton(ContentKeyFunctions.TryPullObject);
+ AddButton(ContentKeyFunctions.MovePulledObject);
+ AddButton(ContentKeyFunctions.ReleasePulledObject);
+ AddButton(ContentKeyFunctions.Point);
+
+ AddHeader("ui-options-header-ui");
+ AddButton(ContentKeyFunctions.FocusChat);
+ AddButton(ContentKeyFunctions.FocusLocalChat);
+ AddButton(ContentKeyFunctions.FocusRadio);
+ AddButton(ContentKeyFunctions.FocusOOC);
+ AddButton(ContentKeyFunctions.FocusAdminChat);
+ AddButton(ContentKeyFunctions.FocusDeadChat);
+ AddButton(ContentKeyFunctions.FocusConsoleChat);
+ AddButton(ContentKeyFunctions.CycleChatChannelForward);
+ AddButton(ContentKeyFunctions.CycleChatChannelBackward);
+ AddButton(ContentKeyFunctions.OpenCharacterMenu);
+ AddButton(ContentKeyFunctions.OpenContextMenu);
+ AddButton(ContentKeyFunctions.OpenCraftingMenu);
+ AddButton(ContentKeyFunctions.OpenInventoryMenu);
+ AddButton(ContentKeyFunctions.OpenInfo);
+ AddButton(ContentKeyFunctions.OpenActionsMenu);
+ AddButton(ContentKeyFunctions.OpenEntitySpawnWindow);
+ AddButton(ContentKeyFunctions.OpenSandboxWindow);
+ AddButton(ContentKeyFunctions.OpenTileSpawnWindow);
+ AddButton(ContentKeyFunctions.OpenAdminMenu);
+
+ AddHeader("ui-options-header-misc");
+ AddButton(ContentKeyFunctions.TakeScreenshot);
+ AddButton(ContentKeyFunctions.TakeScreenshotNoUI);
+
+ AddHeader("ui-options-header-hotbar");
+ AddButton(ContentKeyFunctions.Hotbar1);
+ AddButton(ContentKeyFunctions.Hotbar2);
+ AddButton(ContentKeyFunctions.Hotbar3);
+ AddButton(ContentKeyFunctions.Hotbar4);
+ AddButton(ContentKeyFunctions.Hotbar5);
+ AddButton(ContentKeyFunctions.Hotbar6);
+ AddButton(ContentKeyFunctions.Hotbar7);
+ AddButton(ContentKeyFunctions.Hotbar8);
+ AddButton(ContentKeyFunctions.Hotbar9);
+ AddButton(ContentKeyFunctions.Hotbar0);
+ AddButton(ContentKeyFunctions.Loadout1);
+ AddButton(ContentKeyFunctions.Loadout2);
+ AddButton(ContentKeyFunctions.Loadout3);
+ AddButton(ContentKeyFunctions.Loadout4);
+ AddButton(ContentKeyFunctions.Loadout5);
+ AddButton(ContentKeyFunctions.Loadout6);
+ AddButton(ContentKeyFunctions.Loadout7);
+ AddButton(ContentKeyFunctions.Loadout8);
+ AddButton(ContentKeyFunctions.Loadout9);
+
+ AddHeader("ui-options-header-map-editor");
+ AddButton(EngineKeyFunctions.EditorPlaceObject);
+ AddButton(EngineKeyFunctions.EditorCancelPlace);
+ AddButton(EngineKeyFunctions.EditorGridPlace);
+ AddButton(EngineKeyFunctions.EditorLinePlace);
+ AddButton(EngineKeyFunctions.EditorRotateObject);
+
+ AddHeader("ui-options-header-dev");
+ AddButton(EngineKeyFunctions.ShowDebugConsole);
+ AddButton(EngineKeyFunctions.ShowDebugMonitors);
+ AddButton(EngineKeyFunctions.HideUI);
+
+ 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("ui-options-key-prompt");
+
+ 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(KeyRebindTab parent, BoundKeyFunction function)
+ {
+ Function = function;
+ var name = new Label
+ {
+ Text = Loc.GetString(
+ $"ui-options-function-{CaseConversion.PascalToKebab(function.FunctionName)}"),
+ HorizontalExpand = true,
+ HorizontalAlignment = HAlignment.Left
+ };
+
+ BindButton1 = new BindButton(parent, this, StyleBase.ButtonOpenRight);
+ BindButton2 = new BindButton(parent, this, StyleBase.ButtonOpenLeft);
+ ResetButton = new Button {Text = Loc.GetString("ui-options-bind-reset"), StyleClasses = {StyleBase.ButtonCaution}};
+
+ var hBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal,
+ Children =
+ {
+ new Control {MinSize = (5, 0)},
+ name,
+ BindButton1,
+ BindButton2,
+ new Control {MinSize = (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 KeyRebindTab _tab;
+ public readonly KeyControl KeyControl;
+ public readonly Button Button;
+ public IKeyBinding? Binding;
+
+ public BindButton(KeyRebindTab tab, KeyControl keyControl, string styleClass)
+ {
+ _tab = tab;
+ KeyControl = keyControl;
+ Button = new Button {StyleClasses = {styleClass}};
+ UpdateText();
+ AddChild(Button);
+
+ Button.OnPressed += args =>
+ {
+ tab.RebindButtonPressed(this);
+ };
+
+ Button.OnKeyBindDown += ButtonOnOnKeyBindDown;
+
+ MinSize = (200, 0);
+ }
+
+ private void ButtonOnOnKeyBindDown(GUIBoundKeyEventArgs args)
+ {
+ if (args.Function == EngineKeyFunctions.UIRightClick)
+ {
+ if (Binding != null)
+ {
+ _tab._deferCommands.Add(() =>
+ {
+ _tab._inputManager.RemoveBinding(Binding);
+ _tab._inputManager.SaveToUserData();
+ });
+ }
+
+ args.Handle();
+ }
+ }
+
+ public void UpdateText()
+ {
+ Button.Text = Binding?.GetKeyString() ?? Loc.GetString("ui-options-unbound");
+ }
+ }
+ }
+}
diff --git a/Content.Client/Examine/ExamineSystem.cs b/Content.Client/Examine/ExamineSystem.cs
index 5302afc651..5d58fc47fd 100644
--- a/Content.Client/Examine/ExamineSystem.cs
+++ b/Content.Client/Examine/ExamineSystem.cs
@@ -8,6 +8,7 @@ using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
+using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.Input.Binding;
using Robust.Shared.IoC;
@@ -15,6 +16,8 @@ using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Players;
using Robust.Shared.Utility;
+using static Content.Shared.Interaction.SharedInteractionSystem;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Examine
{
@@ -26,6 +29,8 @@ namespace Content.Client.Examine
public const string StyleClassEntityTooltip = "entity-tooltip";
+ private IEntity? _examinedEntity;
+ private IEntity? _playerEntity;
private Popup? _examineTooltipOpen;
private CancellationTokenSource? _requestCancelTokenSource;
@@ -38,6 +43,24 @@ namespace Content.Client.Examine
.Register();
}
+ public override void Update(float frameTime)
+ {
+ if (_examineTooltipOpen == null || !_examineTooltipOpen.Visible) return;
+ if (_examinedEntity == null || _playerEntity == null) return;
+
+ Ignored predicate = entity => entity == _playerEntity || entity == _examinedEntity;
+
+ if (_playerEntity.TryGetContainer(out var container))
+ {
+ predicate += entity => entity == container.Owner;
+ }
+
+ if (!InRangeUnOccluded(_playerEntity, _examinedEntity, ExamineRange, predicate))
+ {
+ CloseTooltip();
+ }
+ }
+
public override void Shutdown()
{
CommandBinds.Unregister();
@@ -46,44 +69,54 @@ namespace Content.Client.Examine
private bool HandleExamine(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
{
- if (!uid.IsValid() || !EntityManager.TryGetEntity(uid, out var examined))
+ if (!uid.IsValid() || !EntityManager.TryGetEntity(uid, out _examinedEntity))
{
return false;
}
- var playerEntity = _playerManager.LocalPlayer?.ControlledEntity;
+ _playerEntity = _playerManager.LocalPlayer?.ControlledEntity;
- if (playerEntity == null || !CanExamine(playerEntity, examined))
+ if (_playerEntity == null || !CanExamine(_playerEntity, _examinedEntity))
{
return false;
}
- DoExamine(examined);
+ DoExamine(_examinedEntity);
return true;
}
public async void DoExamine(IEntity entity)
{
- const float minWidth = 300;
+ // Close any examine tooltip that might already be opened
CloseTooltip();
+ const float minWidth = 300;
var popupPos = _userInterfaceManager.MousePositionScaled;
// Actually open the tooltip.
- _examineTooltipOpen = new Popup { MaxWidth = 400};
+ _examineTooltipOpen = new Popup { MaxWidth = 400 };
_userInterfaceManager.ModalRoot.AddChild(_examineTooltipOpen);
var panel = new PanelContainer();
panel.AddStyleClass(StyleClassEntityTooltip);
panel.ModulateSelfOverride = Color.LightGray.WithAlpha(0.90f);
_examineTooltipOpen.AddChild(panel);
- //panel.SetAnchorAndMarginPreset(Control.LayoutPreset.Wide);
- var vBox = new VBoxContainer();
+
+ var vBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
panel.AddChild(vBox);
- var hBox = new HBoxContainer {SeparationOverride = 5};
+
+ var hBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal,
+ SeparationOverride = 5
+ };
vBox.AddChild(hBox);
+
if (entity.TryGetComponent(out ISpriteComponent? sprite))
{
- hBox.AddChild(new SpriteView {Sprite = sprite, OverrideDirection = Direction.South});
+ hBox.AddChild(new SpriteView { Sprite = sprite, OverrideDirection = Direction.South });
}
hBox.AddChild(new Label
@@ -104,7 +137,6 @@ namespace Content.Client.Examine
}
else
{
-
// Ask server for extra examine info.
RaiseNetworkEvent(new ExamineSystemMessages.RequestExamineInfoMessage(entity.Uid));
@@ -130,17 +162,16 @@ namespace Content.Client.Examine
foreach (var msg in message.Tags.OfType())
{
- if (!string.IsNullOrWhiteSpace(msg.Text))
- {
- var richLabel = new RichTextLabel();
- richLabel.SetMessage(message);
- vBox.AddChild(richLabel);
- break;
- }
+ if (string.IsNullOrWhiteSpace(msg.Text)) continue;
+
+ var richLabel = new RichTextLabel();
+ richLabel.SetMessage(message);
+ vBox.AddChild(richLabel);
+ break;
}
}
- public void CloseTooltip()
+ private void CloseTooltip()
{
if (_examineTooltipOpen != null)
{
diff --git a/Content.Client/Flash/FlashableComponent.cs b/Content.Client/Flash/FlashableComponent.cs
index 50b0d2a1e3..2c16df833a 100644
--- a/Content.Client/Flash/FlashableComponent.cs
+++ b/Content.Client/Flash/FlashableComponent.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System;
using Content.Shared.Flash;
using Robust.Client.Graphics;
diff --git a/Content.Client/Ghost/GhostGui.cs b/Content.Client/Ghost/GhostGui.cs
index 1f2d9c289c..6616e27e7f 100644
--- a/Content.Client/Ghost/GhostGui.cs
+++ b/Content.Client/Ghost/GhostGui.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System.Collections.Generic;
using Content.Shared.Ghost;
using Robust.Client.Console;
@@ -8,6 +7,7 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Ghost
{
@@ -44,8 +44,9 @@ namespace Content.Client.Ghost
_ghostRoles.OnPressed += _ => IoCManager.Resolve()
.RemoteExecuteCommand(null, "ghostroles");
- AddChild(new HBoxContainer
+ AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
_returnToBody,
@@ -77,7 +78,7 @@ namespace Content.Client.Ghost
private readonly GhostComponent _owner;
private readonly IEntityNetworkManager _netManager;
- private readonly VBoxContainer _buttonContainer;
+ private readonly BoxContainer _buttonContainer;
public List Locations { get; set; } = new();
@@ -90,8 +91,9 @@ namespace Content.Client.Ghost
_owner = owner;
_netManager = netManager;
- _buttonContainer = new VBoxContainer()
+ _buttonContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
VerticalExpand = true,
SeparationOverride = 5,
diff --git a/Content.Client/Ghost/Roles/UI/GhostRolesEntry.xaml b/Content.Client/Ghost/Roles/UI/GhostRolesEntry.xaml
index 60ac1dc697..04e50e46df 100644
--- a/Content.Client/Ghost/Roles/UI/GhostRolesEntry.xaml
+++ b/Content.Client/Ghost/Roles/UI/GhostRolesEntry.xaml
@@ -1,9 +1,9 @@
-
-
+
-
-
+
+
diff --git a/Content.Client/Ghost/Roles/UI/GhostRolesWindow.xaml b/Content.Client/Ghost/Roles/UI/GhostRolesWindow.xaml
index 8f6de8f9c3..9af69fba4e 100644
--- a/Content.Client/Ghost/Roles/UI/GhostRolesWindow.xaml
+++ b/Content.Client/Ghost/Roles/UI/GhostRolesWindow.xaml
@@ -4,7 +4,7 @@
-
+
diff --git a/Content.Client/Ghost/Roles/UI/MakeGhostRoleWindow.xaml b/Content.Client/Ghost/Roles/UI/MakeGhostRoleWindow.xaml
index 0a5dfa1850..0a51ef7bfb 100644
--- a/Content.Client/Ghost/Roles/UI/MakeGhostRoleWindow.xaml
+++ b/Content.Client/Ghost/Roles/UI/MakeGhostRoleWindow.xaml
@@ -1,26 +1,26 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/Content.Client/Ghost/Roles/UI/MakeGhostRoleWindow.xaml.cs b/Content.Client/Ghost/Roles/UI/MakeGhostRoleWindow.xaml.cs
index f7ce045357..7ec189cb43 100644
--- a/Content.Client/Ghost/Roles/UI/MakeGhostRoleWindow.xaml.cs
+++ b/Content.Client/Ghost/Roles/UI/MakeGhostRoleWindow.xaml.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using Robust.Client.AutoGenerated;
+using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.GameObjects;
diff --git a/Content.Client/Gravity/GravityGeneratorBoundUserInterface.cs b/Content.Client/Gravity/GravityGeneratorBoundUserInterface.cs
index 6dbbe28fb3..5d956ad632 100644
--- a/Content.Client/Gravity/GravityGeneratorBoundUserInterface.cs
+++ b/Content.Client/Gravity/GravityGeneratorBoundUserInterface.cs
@@ -7,6 +7,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Gravity
{
@@ -73,8 +74,9 @@ namespace Content.Client.Gravity
Title = Loc.GetString("gravity-generator-window-title");
- var vBox = new VBoxContainer
+ var vBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
MinSize = new Vector2(250, 100)
};
Status = new Label
diff --git a/Content.Client/Gravity/GravityGeneratorVisualizer.cs b/Content.Client/Gravity/GravityGeneratorVisualizer.cs
index ef43265d0c..2dffc2826b 100644
--- a/Content.Client/Gravity/GravityGeneratorVisualizer.cs
+++ b/Content.Client/Gravity/GravityGeneratorVisualizer.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System;
+using System;
using System.Collections.Generic;
using Content.Shared.Gravity;
using JetBrains.Annotations;
diff --git a/Content.Client/HUD/GameHud.cs b/Content.Client/HUD/GameHud.cs
index bda10542f3..1e780b4600 100644
--- a/Content.Client/HUD/GameHud.cs
+++ b/Content.Client/HUD/GameHud.cs
@@ -25,6 +25,7 @@ using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using static Robust.Client.Input.Keyboard.Key;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
using Control = Robust.Client.UserInterface.Control;
using LC = Robust.Client.UserInterface.Controls.LayoutContainer;
@@ -94,7 +95,7 @@ namespace Content.Client.HUD
internal sealed class GameHud : IGameHud
{
- private HBoxContainer _topButtonsContainer = default!;
+ private BoxContainer _topButtonsContainer = default!;
private TopButton _buttonEscapeMenu = default!;
private TopButton _buttonInfo = default!;
private TopButton _buttonCharacterMenu = default!;
@@ -105,8 +106,8 @@ namespace Content.Client.HUD
private TopButton _buttonSandboxMenu = default!;
private InfoWindow _infoWindow = default!;
private TargetingDoll _targetingDoll = default!;
- private VBoxContainer _combatPanelContainer = default!;
- private VBoxContainer _topNotificationContainer = default!;
+ private BoxContainer _combatPanelContainer = default!;
+ private BoxContainer _topNotificationContainer = default!;
[Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
@@ -183,8 +184,9 @@ namespace Content.Client.HUD
var infoTexture = _resourceCache.GetTexture("/Textures/Interface/info.svg.192dpi.png");
var sandboxTexture = _resourceCache.GetTexture("/Textures/Interface/sandbox.svg.192dpi.png");
- _topButtonsContainer = new HBoxContainer
+ _topButtonsContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 8
};
@@ -307,8 +309,9 @@ namespace Content.Client.HUD
InputCmdHandler.FromDelegate(s => ButtonInfoOnOnToggled()));
- _combatPanelContainer = new VBoxContainer
+ _combatPanelContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalAlignment = Control.HAlignment.Left,
VerticalAlignment = Control.VAlignment.Bottom,
Children =
@@ -324,8 +327,9 @@ namespace Content.Client.HUD
_targetingDoll.OnZoneChanged += args => OnTargetingZoneChanged?.Invoke(args);
- var centerBottomContainer = new VBoxContainer
+ var centerBottomContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
SeparationOverride = 5,
HorizontalAlignment = Control.HAlignment.Center
};
@@ -340,24 +344,28 @@ namespace Content.Client.HUD
VerticalAlignment = Control.VAlignment.Bottom,
HorizontalAlignment = Control.HAlignment.Center
};
- BottomRightInventoryQuickButtonContainer = new HBoxContainer()
+ BottomRightInventoryQuickButtonContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
VerticalAlignment = Control.VAlignment.Bottom,
HorizontalAlignment = Control.HAlignment.Right
};
- BottomLeftInventoryQuickButtonContainer = new HBoxContainer()
+ BottomLeftInventoryQuickButtonContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
VerticalAlignment = Control.VAlignment.Bottom,
HorizontalAlignment = Control.HAlignment.Left
};
- TopInventoryQuickButtonContainer = new HBoxContainer()
+ TopInventoryQuickButtonContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Visible = false,
VerticalAlignment = Control.VAlignment.Bottom,
HorizontalAlignment = Control.HAlignment.Center
};
- var bottomRow = new HBoxContainer()
+ var bottomRow = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalAlignment = Control.HAlignment.Center
};
@@ -376,8 +384,9 @@ namespace Content.Client.HUD
HorizontalAlignment = Control.HAlignment.Center
};
- var rightBottomContainer = new HBoxContainer
+ var rightBottomContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 5
};
LC.SetAnchorAndMarginPreset(rightBottomContainer, LC.LayoutPreset.BottomRight);
@@ -396,8 +405,9 @@ namespace Content.Client.HUD
LC.SetGrowHorizontal(SuspicionContainer, LC.GrowDirection.End);
LC.SetGrowVertical(SuspicionContainer, LC.GrowDirection.Begin);
- _topNotificationContainer = new VBoxContainer
+ _topNotificationContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
MinSize = (600, 0)
};
RootControl.AddChild(_topNotificationContainer);
@@ -405,7 +415,10 @@ namespace Content.Client.HUD
LC.SetGrowHorizontal(_topNotificationContainer, LC.GrowDirection.Both);
LC.SetGrowVertical(_topNotificationContainer, LC.GrowDirection.End);
- VoteContainer = new VBoxContainer();
+ VoteContainer = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
RootControl.AddChild(VoteContainer);
LC.SetAnchorPreset(VoteContainer, LC.LayoutPreset.TopLeft);
LC.SetMarginLeft(VoteContainer, 180);
@@ -564,8 +577,9 @@ namespace Content.Client.HUD
TooltipDelay = CustomTooltipDelay;
AddChild(
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
(_textureRect = new TextureRect
diff --git a/Content.Client/Hands/HandsGui.cs b/Content.Client/Hands/HandsGui.cs
index 22a7e643e3..ff0fa47b23 100644
--- a/Content.Client/Hands/HandsGui.cs
+++ b/Content.Client/Hands/HandsGui.cs
@@ -21,6 +21,7 @@ using Robust.Shared.Input;
using Robust.Shared.IoC;
using Robust.Shared.Timing;
using Robust.Shared.ViewVariables;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Hands
{
@@ -36,7 +37,7 @@ namespace Content.Client.Hands
private ItemStatusPanel StatusPanel { get; }
- private HBoxContainer HandsContainer { get; }
+ private BoxContainer HandsContainer { get; }
[ViewVariables]
public IReadOnlyList Hands => _hands;
@@ -53,18 +54,24 @@ namespace Content.Client.Hands
IoCManager.InjectDependencies(this);
_configManager.OnValueChanged(CCVars.HudTheme, UpdateHudTheme);
- AddChild(new HBoxContainer
+ AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 0,
HorizontalAlignment = HAlignment.Center,
Children =
{
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
(StatusPanel = ItemStatusPanel.FromSide(HandLocation.Middle)),
- (HandsContainer = new HBoxContainer() { HorizontalAlignment = HAlignment.Center } ),
+ (HandsContainer = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal,
+ HorizontalAlignment = HAlignment.Center
+ }),
}
},
}
diff --git a/Content.Client/Hands/HandsVisualizer.cs b/Content.Client/Hands/HandsVisualizer.cs
index 53a632fc2c..e8291d49ea 100644
--- a/Content.Client/Hands/HandsVisualizer.cs
+++ b/Content.Client/Hands/HandsVisualizer.cs
@@ -38,19 +38,21 @@ namespace Content.Client.Hands
{
var rsi = resourceCache.GetResource(SharedSpriteComponent.TextureRoot / hand.RsiPath).RSI;
- var layerKey = LocationToLayerKey(hand.Location);
- sprite.LayerMapReserveBlank(layerKey);
-
- var layer = sprite.LayerMapGet(layerKey);
- sprite.LayerSetVisible(layer, true);
- sprite.LayerSetRSI(layer, rsi);
- sprite.LayerSetColor(layer, hand.Color);
-
var state = $"inhand-{hand.Location.ToString().ToLowerInvariant()}";
if (hand.EquippedPrefix != null)
state = $"{hand.EquippedPrefix}-" + state;
- sprite.LayerSetState(layer, state);
+ if (rsi.TryGetState(state, out var _))
+ {
+ var layerKey = LocationToLayerKey(hand.Location);
+ sprite.LayerMapReserveBlank(layerKey);
+
+ var layer = sprite.LayerMapGet(layerKey);
+ sprite.LayerSetVisible(layer, true);
+ sprite.LayerSetRSI(layer, rsi);
+ sprite.LayerSetColor(layer, hand.Color);
+ sprite.LayerSetState(layer, state);
+ }
}
}
diff --git a/Content.Client/HealthOverlay/HealthOverlaySystem.cs b/Content.Client/HealthOverlay/HealthOverlaySystem.cs
index 2e92fb4245..f3c5a79266 100644
--- a/Content.Client/HealthOverlay/HealthOverlaySystem.cs
+++ b/Content.Client/HealthOverlay/HealthOverlaySystem.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System.Collections.Generic;
+using System.Collections.Generic;
using Content.Client.HealthOverlay.UI;
using Content.Shared.Damage.Components;
using Content.Shared.GameTicking;
diff --git a/Content.Client/HealthOverlay/UI/HealthOverlayGui.cs b/Content.Client/HealthOverlay/UI/HealthOverlayGui.cs
index 8d1d546f48..c1d4eea275 100644
--- a/Content.Client/HealthOverlay/UI/HealthOverlayGui.cs
+++ b/Content.Client/HealthOverlay/UI/HealthOverlayGui.cs
@@ -1,4 +1,3 @@
-#nullable enable
using Content.Client.IoC;
using Content.Client.Resources;
using Content.Shared.Damage.Components;
diff --git a/Content.Client/Info/InfoWindow.cs b/Content.Client/Info/InfoWindow.cs
index 9dd8b48d90..517e39e636 100644
--- a/Content.Client/Info/InfoWindow.cs
+++ b/Content.Client/Info/InfoWindow.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System.Collections.Generic;
using System.IO;
@@ -12,6 +11,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Info
{
@@ -57,8 +57,9 @@ namespace Content.Client.Info
private void PopulateRules(Control rulesList)
{
- var vBox = new VBoxContainer
+ var vBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(2, 2, 0, 0)
};
@@ -98,8 +99,9 @@ namespace Content.Client.Info
{
Button controlsButton;
- var vBox = new VBoxContainer
+ var vBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(2, 2, 0, 0)
};
@@ -131,8 +133,9 @@ namespace Content.Client.Info
AddSection(Loc.GetString("ui-info-header-intro"), "Intro.txt");
- vBox.AddChild(new HBoxContainer
+ vBox.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
MinSize = (0, 10),
Children =
{
@@ -140,8 +143,9 @@ namespace Content.Client.Info
}
});
- vBox.AddChild(new HBoxContainer
+ vBox.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 5,
Children =
{
diff --git a/Content.Client/Info/ServerInfo.cs b/Content.Client/Info/ServerInfo.cs
index 66f290a5a0..6cce59c2e8 100644
--- a/Content.Client/Info/ServerInfo.cs
+++ b/Content.Client/Info/ServerInfo.cs
@@ -21,7 +21,10 @@ namespace Content.Client.Info
};
AddChild(_richTextLabel);
- var buttons = new HBoxContainer();
+ var buttons = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
AddChild(buttons);
var uriOpener = IoCManager.Resolve();
diff --git a/Content.Client/Input/ContentContexts.cs b/Content.Client/Input/ContentContexts.cs
index 80e4cc96f4..494a85befd 100644
--- a/Content.Client/Input/ContentContexts.cs
+++ b/Content.Client/Input/ContentContexts.cs
@@ -17,6 +17,8 @@ namespace Content.Client.Input
common.AddFunction(ContentKeyFunctions.FocusRadio);
common.AddFunction(ContentKeyFunctions.FocusOOC);
common.AddFunction(ContentKeyFunctions.FocusAdminChat);
+ common.AddFunction(ContentKeyFunctions.FocusConsoleChat);
+ common.AddFunction(ContentKeyFunctions.FocusDeadChat);
common.AddFunction(ContentKeyFunctions.CycleChatChannelForward);
common.AddFunction(ContentKeyFunctions.CycleChatChannelBackward);
common.AddFunction(ContentKeyFunctions.ExamineEntity);
diff --git a/Content.Client/Instruments/UI/InstrumentMenu.xaml b/Content.Client/Instruments/UI/InstrumentMenu.xaml
index 6cd7f78b55..9eafb0a24b 100644
--- a/Content.Client/Instruments/UI/InstrumentMenu.xaml
+++ b/Content.Client/Instruments/UI/InstrumentMenu.xaml
@@ -1,26 +1,26 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/Content.Client/Inventory/HumanInventoryInterfaceController.cs b/Content.Client/Inventory/HumanInventoryInterfaceController.cs
index 0c5ed21557..fa52c89b71 100644
--- a/Content.Client/Inventory/HumanInventoryInterfaceController.cs
+++ b/Content.Client/Inventory/HumanInventoryInterfaceController.cs
@@ -17,6 +17,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using static Content.Shared.Inventory.EquipmentSlotDefines;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Inventory
{
@@ -102,8 +103,9 @@ namespace Content.Client.Inventory
AddButton(out _hudButtonEars, Slots.EARS, "ears");
AddButton(out _hudButtonHead, Slots.HEAD, "head");
- _topQuickButtonsContainer = new HBoxContainer
+ _topQuickButtonsContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
_hudButtonShoes,
@@ -119,8 +121,9 @@ namespace Content.Client.Inventory
SeparationOverride = 5
};
- _bottomRightQuickButtonsContainer = new HBoxContainer
+ _bottomRightQuickButtonsContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
_hudButtonPocket1,
@@ -129,8 +132,9 @@ namespace Content.Client.Inventory
},
SeparationOverride = 5
};
- _bottomLeftQuickButtonsContainer = new HBoxContainer
+ _bottomLeftQuickButtonsContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
_hudButtonBelt,
diff --git a/Content.Client/Items/Components/ItemComponent.cs b/Content.Client/Items/Components/ItemComponent.cs
index f26d349996..cd552ee288 100644
--- a/Content.Client/Items/Components/ItemComponent.cs
+++ b/Content.Client/Items/Components/ItemComponent.cs
@@ -1,4 +1,3 @@
-#nullable enable
using Content.Client.Hands;
using Content.Shared.Item;
using Robust.Shared.Containers;
diff --git a/Content.Client/Items/UI/ItemStatusPanel.cs b/Content.Client/Items/UI/ItemStatusPanel.cs
index 6162c59e51..d880d7ea49 100644
--- a/Content.Client/Items/UI/ItemStatusPanel.cs
+++ b/Content.Client/Items/UI/ItemStatusPanel.cs
@@ -12,6 +12,7 @@ using Robust.Shared.Maths;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
using static Content.Client.IoC.StaticIoC;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Items.UI
{
@@ -23,7 +24,7 @@ namespace Content.Client.Items.UI
[ViewVariables]
private readonly Label _itemNameLabel;
[ViewVariables]
- private readonly VBoxContainer _statusContents;
+ private readonly BoxContainer _statusContents;
[ViewVariables]
private readonly PanelContainer _panel;
@@ -47,12 +48,16 @@ namespace Content.Client.Items.UI
ModulateSelfOverride = Color.White.WithAlpha(0.9f),
Children =
{
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
SeparationOverride = 0,
Children =
{
- (_statusContents = new VBoxContainer()),
+ (_statusContents = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ }),
(_itemNameLabel = new Label
{
ClipText = true,
diff --git a/Content.Client/Kitchen/KitchenSpikeComponent.cs b/Content.Client/Kitchen/KitchenSpikeComponent.cs
index 0c7acf3137..efae8b89e6 100644
--- a/Content.Client/Kitchen/KitchenSpikeComponent.cs
+++ b/Content.Client/Kitchen/KitchenSpikeComponent.cs
@@ -1,4 +1,3 @@
-#nullable enable
using Content.Shared.DragDrop;
using Content.Shared.Kitchen.Components;
using Robust.Shared.GameObjects;
diff --git a/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs b/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs
index 252c6aa012..e336bb73a6 100644
--- a/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs
+++ b/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs
@@ -15,6 +15,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using static Robust.Client.UserInterface.Controls.BaseButton;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Kitchen.UI
{
@@ -165,9 +166,9 @@ namespace Content.Client.Kitchen.UI
public ButtonGroup CookTimeButtonGroup { get; }
- public VBoxContainer CookTimeButtonVbox { get; }
+ public BoxContainer CookTimeButtonVbox { get; }
- private VBoxContainer ButtonGridContainer { get; }
+ private BoxContainer ButtonGridContainer { get; }
private PanelContainer DisableCookingPanelOverlay { get; }
@@ -188,7 +189,10 @@ namespace Content.Client.Kitchen.UI
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.Black.WithAlpha(0.60f)},
};
- var hSplit = new HBoxContainer();
+ var hSplit = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
IngredientsListReagents = new ItemList
{
@@ -217,17 +221,19 @@ namespace Content.Client.Kitchen.UI
hSplit.AddChild(IngredientsList);
- var vSplit = new VBoxContainer
+ var vSplit = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
VerticalExpand = true,
HorizontalExpand = true,
};
hSplit.AddChild(vSplit);
- ButtonGridContainer = new VBoxContainer
+ ButtonGridContainer = new BoxContainer
{
- Align = BoxContainer.AlignMode.Center,
+ Orientation = LayoutOrientation.Vertical,
+ Align = AlignMode.Center,
SizeFlagsStretchRatio = 3
};
@@ -255,10 +261,11 @@ namespace Content.Client.Kitchen.UI
});
CookTimeButtonGroup = new ButtonGroup();
- CookTimeButtonVbox = new VBoxContainer
+ CookTimeButtonVbox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
VerticalExpand = true,
- Align = BoxContainer.AlignMode.Center,
+ Align = AlignMode.Center,
};
var index = 0;
@@ -301,8 +308,9 @@ namespace Content.Client.Kitchen.UI
Children =
{
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
new PanelContainer
diff --git a/Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs b/Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs
index 57bf60156b..e33cae9e5e 100644
--- a/Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs
+++ b/Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs
@@ -11,6 +11,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using static Content.Shared.Chemistry.Solution.Solution;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Kitchen.UI
{
@@ -238,10 +239,14 @@ namespace Content.Client.Kitchen.UI
Owner = owner;
Title = Loc.GetString("grinder-menu-title");
- var hSplit = new HBoxContainer();
-
- var vBoxGrindJuiceButtonPanel = new VBoxContainer
+ var hSplit = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal
+ };
+
+ var vBoxGrindJuiceButtonPanel = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical,
VerticalAlignment = VAlignment.Center
};
diff --git a/Content.Client/LateJoin/LateJoinGui.cs b/Content.Client/LateJoin/LateJoinGui.cs
index 780461f5bc..77e6d0f09d 100644
--- a/Content.Client/LateJoin/LateJoinGui.cs
+++ b/Content.Client/LateJoin/LateJoinGui.cs
@@ -16,6 +16,7 @@ using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.LateJoin
{
@@ -27,7 +28,7 @@ namespace Content.Client.LateJoin
public event Action? SelectedId;
private readonly Dictionary _jobButtons = new();
- private readonly Dictionary _jobCategories = new();
+ private readonly Dictionary _jobCategories = new();
public LateJoinGui()
{
@@ -38,9 +39,13 @@ namespace Content.Client.LateJoin
Title = Loc.GetString("late-join-gui-title");
- var jobList = new VBoxContainer();
- var vBox = new VBoxContainer
+ var jobList = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical
+ };
+ var vBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical,
Children =
{
new ScrollContainer
@@ -64,8 +69,9 @@ namespace Content.Client.LateJoin
{
if (!_jobCategories.TryGetValue(department, out var category))
{
- category = new VBoxContainer
+ category = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Name = department,
ToolTip = Loc.GetString("late-join-gui-jobs-amount-in-department-tooltip",
("departmentName", department))
@@ -101,8 +107,9 @@ namespace Content.Client.LateJoin
var jobButton = new JobButton(job.ID);
- var jobSelector = new HBoxContainer
+ var jobSelector = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true
};
diff --git a/Content.Client/Lathe/UI/LatheMenu.cs b/Content.Client/Lathe/UI/LatheMenu.cs
index 38bde6c6ca..12c6872156 100644
--- a/Content.Client/Lathe/UI/LatheMenu.cs
+++ b/Content.Client/Lathe/UI/LatheMenu.cs
@@ -8,6 +8,7 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Client.Utility;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Lathe.UI
{
@@ -36,14 +37,16 @@ namespace Content.Client.Lathe.UI
Title = "Lathe Menu";
- var vBox = new VBoxContainer()
+ var vBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
VerticalExpand = true,
SeparationOverride = 5,
};
- var hBoxButtons = new HBoxContainer()
+ var hBoxButtons = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
VerticalExpand = true,
SizeFlagsStretchRatio = 1,
@@ -76,8 +79,9 @@ namespace Content.Client.Lathe.UI
SizeFlagsStretchRatio = 3,
};
- var hBoxFilter = new HBoxContainer()
+ var hBoxFilter = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
VerticalExpand = true,
SizeFlagsStretchRatio = 1
diff --git a/Content.Client/Lathe/UI/LatheQueueMenu.cs b/Content.Client/Lathe/UI/LatheQueueMenu.cs
index eeabc96772..7c5cbcc8fb 100644
--- a/Content.Client/Lathe/UI/LatheQueueMenu.cs
+++ b/Content.Client/Lathe/UI/LatheQueueMenu.cs
@@ -5,6 +5,7 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Client.Utility;
using Robust.Shared.Localization;
using Robust.Shared.ViewVariables;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Lathe.UI
{
@@ -24,10 +25,14 @@ namespace Content.Client.Lathe.UI
SetSize = MinSize = (300, 450);
Title = Loc.GetString("lathequeue-menu-title");
- var vBox = new VBoxContainer();
-
- var hBox = new HBoxContainer()
+ var vBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical
+ };
+
+ var hBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
SizeFlagsStretchRatio = 2,
};
@@ -38,8 +43,9 @@ namespace Content.Client.Lathe.UI
SizeFlagsStretchRatio = 2,
};
- var vBoxInfo = new VBoxContainer()
+ var vBoxInfo = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
VerticalExpand = true,
SizeFlagsStretchRatio = 3,
};
diff --git a/Content.Client/Launcher/LauncherConnectingGui.xaml b/Content.Client/Launcher/LauncherConnectingGui.xaml
index f879c5ff73..2d4aa5f1cb 100644
--- a/Content.Client/Launcher/LauncherConnectingGui.xaml
+++ b/Content.Client/Launcher/LauncherConnectingGui.xaml
@@ -6,48 +6,48 @@
-
-
+
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
+
-
-
+
+
diff --git a/Content.Client/Light/Components/HandheldLightComponent.cs b/Content.Client/Light/Components/HandheldLightComponent.cs
index 707d5f8bb4..e2dfa67dbc 100644
--- a/Content.Client/Light/Components/HandheldLightComponent.cs
+++ b/Content.Client/Light/Components/HandheldLightComponent.cs
@@ -7,6 +7,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
using Robust.Shared.ViewVariables;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Light.Components
{
@@ -55,8 +56,9 @@ namespace Content.Client.Light.Components
{
_parent = parent;
- var wrapper = new HBoxContainer
+ var wrapper = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 4,
HorizontalAlignment = HAlignment.Center
};
diff --git a/Content.Client/Light/Visualizers/PoweredLightVisualizer.cs b/Content.Client/Light/Visualizers/PoweredLightVisualizer.cs
index 582f758899..703c76a14a 100644
--- a/Content.Client/Light/Visualizers/PoweredLightVisualizer.cs
+++ b/Content.Client/Light/Visualizers/PoweredLightVisualizer.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System;
using Content.Shared.Light;
using JetBrains.Annotations;
diff --git a/Content.Client/Lobby/LobbyState.cs b/Content.Client/Lobby/LobbyState.cs
index 6689c0f7c9..fb85b825e3 100644
--- a/Content.Client/Lobby/LobbyState.cs
+++ b/Content.Client/Lobby/LobbyState.cs
@@ -1,5 +1,6 @@
using System;
using System.Linq;
+using Content.Client.Chat;
using Content.Client.Chat.Managers;
using Content.Client.EscapeMenu.UI;
using Content.Client.GameTicking.Managers;
@@ -74,24 +75,9 @@ namespace Content.Client.Lobby
_chatManager.SetChatBox(_lobby.Chat);
_voteManager.SetPopupContainer(_lobby.VoteContainer);
- _lobby.Chat.DefaultChatFormat = "ooc \"{0}\"";
-
_lobby.ServerName.Text = _baseClient.GameInfo?.ServerName;
- _inputManager.SetInputCommand(ContentKeyFunctions.FocusChat,
- InputCmdHandler.FromDelegate(_ => GameScreen.FocusChat(_lobby.Chat)));
-
- _inputManager.SetInputCommand(ContentKeyFunctions.FocusOOC,
- InputCmdHandler.FromDelegate(_ => GameScreen.FocusChannel(_lobby.Chat, ChatChannel.OOC)));
-
- _inputManager.SetInputCommand(ContentKeyFunctions.FocusAdminChat,
- InputCmdHandler.FromDelegate(_ => GameScreen.FocusChannel(_lobby.Chat, ChatChannel.AdminChat)));
-
- _inputManager.SetInputCommand(ContentKeyFunctions.CycleChatChannelForward,
- InputCmdHandler.FromDelegate(_ => _lobby.Chat.CycleChatChannel(true)));
-
- _inputManager.SetInputCommand(ContentKeyFunctions.CycleChatChannelBackward,
- InputCmdHandler.FromDelegate(_ => _lobby.Chat.CycleChatChannel(false)));
+ ChatInput.SetupChatInputHandlers(_inputManager, _lobby.Chat);
UpdateLobbyUi();
diff --git a/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.cs b/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.cs
index 06d23ec908..45b66fd40e 100644
--- a/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.cs
+++ b/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.cs
@@ -16,6 +16,7 @@ using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using static Content.Shared.Inventory.EquipmentSlotDefines;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Lobby.UI
{
@@ -24,7 +25,7 @@ namespace Content.Client.Lobby.UI
private readonly IClientPreferencesManager _preferencesManager;
private IEntity _previewDummy;
private readonly Label _summaryLabel;
- private readonly VBoxContainer _loaded;
+ private readonly BoxContainer _loaded;
private readonly Label _unloaded;
public LobbyCharacterPreviewPanel(IEntityManager entityManager,
@@ -51,18 +52,28 @@ namespace Content.Client.Lobby.UI
var viewWest = MakeSpriteView(_previewDummy, Direction.West);
var viewEast = MakeSpriteView(_previewDummy, Direction.East);
- var vBox = new VBoxContainer();
+ var vBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
vBox.AddChild(header);
_unloaded = new Label {Text = Loc.GetString("lobby-character-preview-panel-unloaded-preferences-label")};
- _loaded = new VBoxContainer {Visible = false};
+ _loaded = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical,
+ Visible = false
+ };
_loaded.AddChild(CharacterSetupButton);
_loaded.AddChild(_summaryLabel);
- var hBox = new HBoxContainer();
+ var hBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
hBox.AddChild(viewSouth);
hBox.AddChild(viewNorth);
hBox.AddChild(viewWest);
diff --git a/Content.Client/Lobby/UI/LobbyGui.xaml b/Content.Client/Lobby/UI/LobbyGui.xaml
index 71501731f4..e047a9cf6a 100644
--- a/Content.Client/Lobby/UI/LobbyGui.xaml
+++ b/Content.Client/Lobby/UI/LobbyGui.xaml
@@ -18,9 +18,9 @@
-
+
-
+
@@ -28,7 +28,7 @@
-
+
@@ -37,20 +37,20 @@
-
+
-
+
-
+
-
+
-
+
@@ -67,7 +67,7 @@
-
+
-
+
-
+
-
-
+
+
diff --git a/Content.Client/Lobby/UI/LobbyGui.xaml.cs b/Content.Client/Lobby/UI/LobbyGui.xaml.cs
index a4bea076ff..f96344daa7 100644
--- a/Content.Client/Lobby/UI/LobbyGui.xaml.cs
+++ b/Content.Client/Lobby/UI/LobbyGui.xaml.cs
@@ -8,6 +8,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Lobby.UI
{
@@ -21,7 +22,7 @@ namespace Content.Client.Lobby.UI
public Button OptionsButton => COptionsButton;
public Button LeaveButton => CLeaveButton;
public ChatBox Chat => CChat;
- public VBoxContainer VoteContainer => CVoteContainer;
+ public BoxContainer VoteContainer => CVoteContainer;
public LobbyPlayerList OnlinePlayerList => COnlinePlayerList;
public ServerInfo ServerInfo => CServerInfo;
public LobbyCharacterPreviewPanel CharacterPreview { get; }
@@ -49,7 +50,7 @@ namespace Content.Client.Lobby.UI
public class LobbyPlayerList : Control
{
private readonly ScrollContainer _scroll;
- private readonly VBoxContainer _vBox;
+ private readonly BoxContainer _vBox;
public LobbyPlayerList()
{
@@ -57,7 +58,10 @@ namespace Content.Client.Lobby.UI
{
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#202028")},
};
- _vBox = new VBoxContainer();
+ _vBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
_scroll = new ScrollContainer();
_scroll.AddChild(_vBox);
panel.AddChild(_scroll);
@@ -67,8 +71,9 @@ namespace Content.Client.Lobby.UI
// Adds a row
public void AddItem(string name, string status)
{
- var hbox = new HBoxContainer
+ var hbox = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
};
diff --git a/Content.Client/MainMenu/MainMenu.cs b/Content.Client/MainMenu/MainMenu.cs
index 3cd942d225..0c4a791451 100644
--- a/Content.Client/MainMenu/MainMenu.cs
+++ b/Content.Client/MainMenu/MainMenu.cs
@@ -14,6 +14,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Network;
using Robust.Shared.Utility;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
using UsernameHelpers = Robust.Shared.AuthLib.UsernameHelpers;
namespace Content.Client.MainMenu
@@ -221,8 +222,9 @@ namespace Content.Client.MainMenu
var layout = new LayoutContainer();
AddChild(layout);
- var vBox = new VBoxContainer
+ var vBox = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
StyleIdentifier = "mainMenuVBox"
};
@@ -240,7 +242,11 @@ namespace Content.Client.MainMenu
};
vBox.AddChild(logo);
- var userNameHBox = new HBoxContainer {SeparationOverride = 4};
+ var userNameHBox = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal,
+ SeparationOverride = 4
+ };
vBox.AddChild(userNameHBox);
userNameHBox.AddChild(new Label {Text = Loc.GetString("main-menu-username-label") });
diff --git a/Content.Client/MedicalScanner/UI/MedicalScannerWindow.cs b/Content.Client/MedicalScanner/UI/MedicalScannerWindow.cs
index 5a51ee6f3f..2c42dc5fb9 100644
--- a/Content.Client/MedicalScanner/UI/MedicalScannerWindow.cs
+++ b/Content.Client/MedicalScanner/UI/MedicalScannerWindow.cs
@@ -6,6 +6,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using static Content.Shared.MedicalScanner.SharedMedicalScannerComponent;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.MedicalScanner.UI
{
@@ -17,8 +18,9 @@ namespace Content.Client.MedicalScanner.UI
{
SetSize = (250, 100);
- Contents.AddChild(new VBoxContainer
+ Contents.AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
(ScanButton = new Button
diff --git a/Content.Client/MobState/DamageStateVisualizer.cs b/Content.Client/MobState/DamageStateVisualizer.cs
index 2e25961141..00dc0c175d 100644
--- a/Content.Client/MobState/DamageStateVisualizer.cs
+++ b/Content.Client/MobState/DamageStateVisualizer.cs
@@ -1,4 +1,3 @@
-#nullable enable
using System.Collections.Generic;
using Content.Shared.DrawDepth;
using Content.Shared.MobState;
diff --git a/Content.Client/Morgue/Visualizers/MorgueVisualizer.cs b/Content.Client/Morgue/Visualizers/MorgueVisualizer.cs
index c1d5801780..cf1d385831 100644
--- a/Content.Client/Morgue/Visualizers/MorgueVisualizer.cs
+++ b/Content.Client/Morgue/Visualizers/MorgueVisualizer.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using Content.Shared.Morgue;
+using Content.Shared.Morgue;
using Robust.Client.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
diff --git a/Content.Client/Movement/Visualizers/HandTeleporterVisualizer.cs b/Content.Client/Movement/Visualizers/HandTeleporterVisualizer.cs
deleted file mode 100644
index 597029a37e..0000000000
--- a/Content.Client/Movement/Visualizers/HandTeleporterVisualizer.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System;
-using Content.Shared.Portal.Components;
-using JetBrains.Annotations;
-using Robust.Client.GameObjects;
-
-namespace Content.Client.Movement.Visualizers
-{
- [UsedImplicitly]
- public class HandTeleporterVisualizer : AppearanceVisualizer
- {
-
- public override void OnChangeData(AppearanceComponent component)
- {
- var sprite = component.Owner.GetComponent();
- if (!component.TryGetData(TeleporterVisuals.VisualState, out TeleporterVisualState state))
- {
- state = TeleporterVisualState.Ready;
- }
-
- switch (state)
- {
- case TeleporterVisualState.Charging:
- sprite.LayerSetState(0, "charging");
- break;
- case TeleporterVisualState.Ready:
- sprite.LayerSetState(0, "ready");
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
- }
-
-}
diff --git a/Content.Client/Movement/Visualizers/PortalVisualizer.cs b/Content.Client/Movement/Visualizers/PortalVisualizer.cs
deleted file mode 100644
index 4ab0bf605b..0000000000
--- a/Content.Client/Movement/Visualizers/PortalVisualizer.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using Content.Shared.Portal.Components;
-using JetBrains.Annotations;
-using Robust.Client.GameObjects;
-using Robust.Shared.GameObjects;
-
-namespace Content.Client.Movement.Visualizers
-{
- [UsedImplicitly]
- public class PortalVisualizer : AppearanceVisualizer
- {
- public override void InitializeEntity(IEntity entity)
- {
- base.InitializeEntity(entity);
-
- var sprite = entity.GetComponent();
-
- sprite.LayerMapSet(Layers.Portal, sprite.AddLayerState("portal-pending"));
- sprite.LayerSetShader(Layers.Portal, "unshaded");
-
- }
-
- public override void OnChangeData(AppearanceComponent component)
- {
- base.OnChangeData(component);
-
- var sprite = component.Owner.GetComponent();
- if (component.TryGetData(PortalVisuals.State, out var state))
- {
- switch (state)
- {
- case PortalState.Pending:
- sprite.LayerSetState(Layers.Portal, "portal-pending");
- break;
- // TODO: Spritework here?
- case PortalState.UnableToTeleport:
- sprite.LayerSetState(Layers.Portal, "portal-unconnected");
- break;
- case PortalState.RecentlyTeleported:
- sprite.LayerSetState(Layers.Portal, "portal-unconnected");
- break;
- }
- }
- else
- {
- sprite.LayerSetState(Layers.Portal, "portal-pending");
- }
- }
-
- enum Layers : byte
- {
- Portal
- }
- }
-}
diff --git a/Content.Client/Nutrition/Visualizers/DrinkFoodContainerVisualizer.cs b/Content.Client/Nutrition/Visualizers/DrinkFoodContainerVisualizer.cs
deleted file mode 100644
index 5117ebe5e2..0000000000
--- a/Content.Client/Nutrition/Visualizers/DrinkFoodContainerVisualizer.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System;
-using Content.Shared.Nutrition.Components;
-using Content.Shared.Rounding;
-using JetBrains.Annotations;
-using Robust.Client.GameObjects;
-using Robust.Shared.Serialization.Manager.Attributes;
-
-namespace Content.Client.Nutrition.Visualizers
-{
- [UsedImplicitly]
- public sealed class FoodContainerVisualizer : AppearanceVisualizer
- {
- [DataField("base_state", required: true)]
- private string? _baseState;
-
- [DataField("steps", required: true)]
- private int _steps;
-
- [DataField("mode")]
- private FoodContainerVisualMode _mode = FoodContainerVisualMode.Rounded;
-
- public override void OnChangeData(AppearanceComponent component)
- {
- var sprite = component.Owner.GetComponent();
-
- if (!component.TryGetData(FoodContainerVisuals.Current, out var current))
- {
- return;
- }
-
- if (!component.TryGetData(FoodContainerVisuals.Capacity, out var capacity))
- {
- return;
- }
-
- int step;
-
- switch (_mode)
- {
- case FoodContainerVisualMode.Discrete:
- step = Math.Min(_steps - 1, current);
- break;
- case FoodContainerVisualMode.Rounded:
- step = ContentHelpers.RoundToLevels(current, capacity, _steps);
- break;
- default:
- throw new NullReferenceException();
- }
-
- sprite.LayerSetState(0, $"{_baseState}-{step}");
- }
- }
-}
diff --git a/Content.Client/PDA/PDABoundUserInterface.cs b/Content.Client/PDA/PDABoundUserInterface.cs
index b02cdfb52a..32e9e76ea3 100644
--- a/Content.Client/PDA/PDABoundUserInterface.cs
+++ b/Content.Client/PDA/PDABoundUserInterface.cs
@@ -14,6 +14,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using static Robust.Client.UserInterface.Controls.BaseButton;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.PDA
{
@@ -243,15 +244,15 @@ namespace Content.Client.PDA
public PanelContainer IDInfoContainer { get; }
public RichTextLabel IDInfoLabel { get; }
- public VBoxContainer UplinkTabContainer { get; }
+ public BoxContainer UplinkTabContainer { get; }
protected readonly HSplitContainer CategoryAndListingsContainer;
private readonly IPrototypeManager _prototypeManager;
- public readonly VBoxContainer UplinkListingsContainer;
+ public readonly BoxContainer UplinkListingsContainer;
- public readonly VBoxContainer CategoryListContainer;
+ public readonly BoxContainer CategoryListContainer;
public readonly RichTextLabel BalanceInfo;
public event Action? OnListingButtonPressed;
public event Action? OnCategoryButtonPressed;
@@ -311,8 +312,9 @@ namespace Content.Client.PDA
VerticalAlignment = VAlignment.Center
};
- var innerHBoxContainer = new HBoxContainer
+ var innerHBoxContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
IDInfoLabel,
@@ -335,8 +337,9 @@ namespace Content.Client.PDA
ToggleMode = true,
};
- var mainMenuTabContainer = new VBoxContainer
+ var mainMenuTabContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
VerticalExpand = true,
HorizontalExpand = true,
MinSize = (50, 50),
@@ -353,8 +356,9 @@ namespace Content.Client.PDA
#region UPLINK_TAB
//Uplink Tab
- CategoryListContainer = new VBoxContainer
+ CategoryListContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical
};
BalanceInfo = new RichTextLabel
@@ -400,8 +404,9 @@ namespace Content.Client.PDA
masterPanelContainer.AddChild(CategoryAndListingsContainer);
//Actual list of buttons for buying a listing from the uplink.
- UplinkListingsContainer = new VBoxContainer
+ UplinkListingsContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true,
VerticalExpand = true,
SizeFlagsStretchRatio = 2,
@@ -409,8 +414,9 @@ namespace Content.Client.PDA
};
uplinkShopScrollContainer.AddChild(UplinkListingsContainer);
- var innerVboxContainer = new VBoxContainer
+ var innerVboxContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
VerticalExpand = true,
Children =
@@ -420,8 +426,9 @@ namespace Content.Client.PDA
}
};
- UplinkTabContainer = new VBoxContainer
+ UplinkTabContainer = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
innerVboxContainer
@@ -495,14 +502,16 @@ namespace Content.Client.PDA
};
//Padding for the price lable.
- var pricePadding = new HBoxContainer
+ var pricePadding = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
MinSize = (32, 1),
};
//Contains the name of the item and its price. Used for spacing item name and price.
- var listingButtonHbox = new HBoxContainer
+ var listingButtonHbox = new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
itemLabel,
diff --git a/Content.Client/Paper/UI/PaperWindow.cs b/Content.Client/Paper/UI/PaperWindow.cs
index 6a0c01c083..946aae3354 100644
--- a/Content.Client/Paper/UI/PaperWindow.cs
+++ b/Content.Client/Paper/UI/PaperWindow.cs
@@ -2,6 +2,7 @@
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Utility;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Paper.UI
{
@@ -13,7 +14,10 @@ namespace Content.Client.Paper.UI
public PaperWindow()
{
MinSize = SetSize = (300, 300);
- var container = new VBoxContainer();
+ var container = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
_label = new RichTextLabel();
Input = new LineEdit {Visible = false};
container.AddChild(_label);
diff --git a/Content.Client/ParticleAccelerator/UI/ParticleAcceleratorControlMenu.cs b/Content.Client/ParticleAccelerator/UI/ParticleAcceleratorControlMenu.cs
index b37cf86384..d7c41f53ce 100644
--- a/Content.Client/ParticleAccelerator/UI/ParticleAcceleratorControlMenu.cs
+++ b/Content.Client/ParticleAccelerator/UI/ParticleAcceleratorControlMenu.cs
@@ -15,6 +15,7 @@ using Robust.Shared.Maths;
using Robust.Shared.Noise;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.ParticleAccelerator.UI
{
@@ -32,7 +33,7 @@ namespace Content.Client.ParticleAccelerator.UI
private readonly Label _statusLabel;
private readonly SpinBox _stateSpinBox;
- private readonly VBoxContainer _alarmControl;
+ private readonly BoxContainer _alarmControl;
private readonly Animation _alarmControlAnimation;
private readonly PASegmentControl _endCapTexture;
@@ -138,8 +139,9 @@ namespace Content.Client.ParticleAccelerator.UI
};
_drawLabel = new Label();
var imgSize = new Vector2(32, 32);
- AddChild(new VBoxContainer
+ AddChild(new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
new Control
@@ -166,19 +168,22 @@ namespace Content.Client.ParticleAccelerator.UI
MinSize = (0, 4)
},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
VerticalExpand = true,
Children =
{
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(4, 0, 0, 0),
HorizontalExpand = true,
Children =
{
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label
@@ -191,8 +196,9 @@ namespace Content.Client.ParticleAccelerator.UI
_onButton
}
},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label
@@ -213,8 +219,9 @@ namespace Content.Client.ParticleAccelerator.UI
{
VerticalExpand = true,
},
- (_alarmControl = new VBoxContainer
+ (_alarmControl = new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
Children =
{
new Label
@@ -228,8 +235,9 @@ namespace Content.Client.ParticleAccelerator.UI
}),
}
},
- new VBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Vertical,
MinSize = (186, 0),
Children =
{
@@ -292,8 +300,9 @@ namespace Content.Client.ParticleAccelerator.UI
}
}
},
- new HBoxContainer
+ new BoxContainer
{
+ Orientation = LayoutOrientation.Horizontal,
Margin = new Thickness(12, 0, 0, 0),
Children =
{
diff --git a/Content.Client/Physics/Controllers/MoverController.cs b/Content.Client/Physics/Controllers/MoverController.cs
index 7b2d05aa50..de4e4eb7b3 100644
--- a/Content.Client/Physics/Controllers/MoverController.cs
+++ b/Content.Client/Physics/Controllers/MoverController.cs
@@ -1,4 +1,3 @@
-#nullable enable
using Content.Shared.Movement;
using Content.Shared.Movement.Components;
using Robust.Client.Player;
diff --git a/Content.Client/Portal/PortalComponent.cs b/Content.Client/Portal/PortalComponent.cs
deleted file mode 100644
index 7ef2899c32..0000000000
--- a/Content.Client/Portal/PortalComponent.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using Content.Shared.Portal.Components;
-using Robust.Shared.GameObjects;
-
-namespace Content.Client.Portal
-{
- [RegisterComponent]
- public class PortalComponent : SharedPortalComponent
- {
- }
-}
diff --git a/Content.Client/Power/APC/ApcBoundUserInterface.cs b/Content.Client/Power/APC/ApcBoundUserInterface.cs
index 0df4379d78..fd4724c544 100644
--- a/Content.Client/Power/APC/ApcBoundUserInterface.cs
+++ b/Content.Client/Power/APC/ApcBoundUserInterface.cs
@@ -8,6 +8,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
+using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Power.APC
{
@@ -143,19 +144,28 @@ namespace Content.Client.Power.APC
public ApcWindow()
{
Title = "APC";
- var rows = new VBoxContainer();
+ var rows = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Vertical
+ };
var statusHeader = new Label {Text = "Power Status: "};
rows.AddChild(statusHeader);
- var breaker = new HBoxContainer();
+ var breaker = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
var breakerLabel = new Label {Text = "Main Breaker: "};
BreakerButton = new CheckButton {Text = "Toggle"};
breaker.AddChild(breakerLabel);
breaker.AddChild(BreakerButton);
rows.AddChild(breaker);
- var externalStatus = new HBoxContainer();
+ var externalStatus = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
var externalStatusLabel = new Label {Text = "External Power: "};
ExternalPowerStateLabel = new Label {Text = "Good"};
ExternalPowerStateLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateGood);
@@ -163,7 +173,10 @@ namespace Content.Client.Power.APC
externalStatus.AddChild(ExternalPowerStateLabel);
rows.AddChild(externalStatus);
- var charge = new HBoxContainer();
+ var charge = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal
+ };
var chargeLabel = new Label {Text = "Charge:"};
ChargeBar = new ProgressBar
{
diff --git a/Content.Client/Power/SolarControlWindow.xaml b/Content.Client/Power/SolarControlWindow.xaml
index a51f57154c..f492c97fed 100644
--- a/Content.Client/Power/SolarControlWindow.xaml
+++ b/Content.Client/Power/SolarControlWindow.xaml
@@ -1,8 +1,8 @@
-
+