Merge branch 'master' into replace-sounds-with-sound-specifier

# Conflicts:
#	Content.Server/Actions/Actions/DisarmAction.cs
#	Content.Server/Actions/Actions/ScreamAction.cs
#	Content.Server/Arcade/Components/SpaceVillainArcadeComponent.cs
#	Content.Server/Damage/Components/DamageOnHighSpeedImpactComponent.cs
#	Content.Server/Explosion/Components/FlashExplosiveComponent.cs
#	Content.Server/Physics/Controllers/MoverController.cs
#	Content.Server/Portal/Components/PortalComponent.cs
#	Content.Server/Portal/Components/TeleporterComponent.cs
#	Content.Server/Projectiles/Components/ProjectileComponent.cs
#	Content.Server/Singularity/Components/EmitterComponent.cs
#	Content.Server/Sound/EmitSoundSystem.cs
#	Content.Server/Stunnable/Components/StunbatonComponent.cs
#	Content.Server/Tools/Components/MultitoolComponent.cs
#	Content.Server/Weapon/Ranged/Barrels/Components/ServerBatteryBarrelComponent.cs
#	Content.Shared/Gravity/GravityComponent.cs
#	Content.Shared/Light/Component/SharedExpendableLightComponent.cs
#	Content.Shared/Maps/ContentTileDefinition.cs
#	Content.Shared/Slippery/SlipperyComponent.cs
#	Content.Shared/Standing/StandingStateComponent.cs
#	Resources/Prototypes/Entities/Objects/Fun/bike_horn.yml
This commit is contained in:
Galactic Chimp
2021-07-25 14:12:00 +02:00
4171 changed files with 15603 additions and 14404 deletions

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
using Moq; using Moq;
using Robust.Shared.Exceptions; using Robust.Shared.Exceptions;
@@ -45,8 +45,7 @@ namespace Content.Benchmarks
var dummyReg = new Mock<IComponentRegistration>(); var dummyReg = new Mock<IComponentRegistration>();
dummyReg.SetupGet(p => p.Name).Returns("Dummy"); dummyReg.SetupGet(p => p.Name).Returns("Dummy");
dummyReg.SetupGet(p => p.Type).Returns(typeof(DummyComponent)); dummyReg.SetupGet(p => p.Type).Returns(typeof(DummyComponent));
dummyReg.SetupGet(p => p.NetID).Returns((uint?) null); dummyReg.SetupGet(p => p.NetID).Returns((ushort?) null);
dummyReg.SetupGet(p => p.NetworkSynchronizeExistence).Returns(false);
dummyReg.SetupGet(p => p.References).Returns(new [] {typeof(DummyComponent)}); dummyReg.SetupGet(p => p.References).Returns(new [] {typeof(DummyComponent)});
var componentFactory = new Mock<IComponentFactory>(); var componentFactory = new Mock<IComponentFactory>();

View File

@@ -8,6 +8,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.AI namespace Content.Client.AI
{ {
@@ -169,8 +170,9 @@ namespace Content.Client.AI
MouseFilter = Control.MouseFilterMode.Ignore, MouseFilter = Control.MouseFilterMode.Ignore,
}; };
var vBox = new VBoxContainer() var vBox = new BoxContainer()
{ {
Orientation = LayoutOrientation.Vertical,
SeparationOverride = 15, SeparationOverride = 15,
Children = {actionLabel, pathfindingLabel}, Children = {actionLabel, pathfindingLabel},
}; };

View File

@@ -6,6 +6,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using static Content.Shared.AME.SharedAMEControllerComponent; using static Content.Shared.AME.SharedAMEControllerComponent;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.AME.UI namespace Content.Client.AME.UI
{ {
@@ -30,61 +31,69 @@ namespace Content.Client.AME.UI
MinSize = SetSize = (250, 250); MinSize = SetSize = (250, 250);
Contents.AddChild(new VBoxContainer Contents.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label {Text = Loc.GetString("ame-window-engine-status-label")}, new Label {Text = Loc.GetString("ame-window-engine-status-label") + " "},
(InjectionStatus = new Label {Text = Loc.GetString("ame-window-engine-injection-status-not-injecting-label")}) (InjectionStatus = new Label {Text = Loc.GetString("ame-window-engine-injection-status-not-injecting-label")})
} }
}, },
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
(ToggleInjection = new Button {Text = Loc.GetString("ame-window-toggle-injection-button"), StyleClasses = {StyleBase.ButtonOpenBoth}, Disabled = true}), (ToggleInjection = new Button {Text = Loc.GetString("ame-window-toggle-injection-button"), StyleClasses = {StyleBase.ButtonOpenBoth}, Disabled = true}),
} }
}, },
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label {Text = Loc.GetString("ame-window-fuel-status-label")}, new Label {Text = Loc.GetString("ame-window-fuel-status-label") + " "},
(FuelAmount = new Label {Text = Loc.GetString("ame-window-fuel-not-inserted-text")}) (FuelAmount = new Label {Text = Loc.GetString("ame-window-fuel-not-inserted-text")})
} }
}, },
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
(EjectButton = new Button {Text = Loc.GetString("ame-window-eject-button"), StyleClasses = {StyleBase.ButtonOpenBoth}, Disabled = true}), (EjectButton = new Button {Text = Loc.GetString("ame-window-eject-button"), StyleClasses = {StyleBase.ButtonOpenBoth}, Disabled = true}),
} }
}, },
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label {Text = Loc.GetString("ame-window-injection-amount-label")}, new Label {Text = Loc.GetString("ame-window-injection-amount-label") + " "},
(InjectionAmount = new Label {Text = "0"}) (InjectionAmount = new Label {Text = "0"})
} }
}, },
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
(IncreaseFuelButton = new Button {Text = Loc.GetString("ame-window-increase-fuel-button"), StyleClasses = {StyleBase.ButtonOpenRight}}), (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}}), (DecreaseFuelButton = new Button {Text = Loc.GetString("ame-window-decrease-fuel-button"), StyleClasses = {StyleBase.ButtonOpenLeft}}),
} }
}, },
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label { Text = Loc.GetString("ame-window-core-count-label")}, new Label { Text = Loc.GetString("ame-window-core-count-label") + " "},
(CoreCount = new Label { Text = "0"}), (CoreCount = new Label { Text = "0"}),
} }
} }
@@ -130,7 +139,7 @@ namespace Content.Client.AME.UI
EjectButton.Disabled = false; EjectButton.Disabled = false;
} }
if(!castState.HasFuelJar) if (!castState.HasFuelJar)
{ {
EjectButton.Disabled = true; EjectButton.Disabled = true;
ToggleInjection.Disabled = true; ToggleInjection.Disabled = true;
@@ -143,18 +152,18 @@ namespace Content.Client.AME.UI
FuelAmount.Text = $"{castState.FuelAmount}"; FuelAmount.Text = $"{castState.FuelAmount}";
} }
if(!castState.IsMaster) if (!castState.IsMaster)
{ {
ToggleInjection.Disabled = true; ToggleInjection.Disabled = true;
} }
if (!castState.Injecting) if (!castState.Injecting)
{ {
InjectionStatus.Text = Loc.GetString("ame-window-engine-injection-status-not-injecting-label"); InjectionStatus.Text = Loc.GetString("ame-window-engine-injection-status-not-injecting-label") + " ";
} }
else else
{ {
InjectionStatus.Text = Loc.GetString("ame-window-engine-injection-status-injecting-label"); InjectionStatus.Text = Loc.GetString("ame-window-engine-injection-status-injecting-label") + " ";
} }
CoreCount.Text = $"{castState.CoreCount}"; CoreCount.Text = $"{castState.CoreCount}";

View File

@@ -8,6 +8,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using static Content.Shared.Access.SharedIdCardConsoleComponent; using static Content.Shared.Access.SharedIdCardConsoleComponent;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Access.UI namespace Content.Client.Access.UI
{ {
@@ -38,7 +39,10 @@ namespace Content.Client.Access.UI
{ {
MinSize = SetSize = (650, 290); MinSize = SetSize = (650, 290);
_owner = owner; _owner = owner;
var vBox = new VBoxContainer(); var vBox = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
};
vBox.AddChild(new GridContainer vBox.AddChild(new GridContainer
{ {

View File

@@ -4,6 +4,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Actions.UI namespace Content.Client.Actions.UI
{ {
@@ -28,8 +29,12 @@ namespace Content.Client.Actions.UI
SetOnlyStyleClass(StyleNano.StyleClassTooltipPanel); SetOnlyStyleClass(StyleNano.StyleClassTooltipPanel);
VBoxContainer vbox; BoxContainer vbox;
AddChild(vbox = new VBoxContainer {RectClipContent = true}); AddChild(vbox = new BoxContainer
{
Orientation = LayoutOrientation.Vertical,
RectClipContent = true
});
var nameLabel = new RichTextLabel var nameLabel = new RichTextLabel
{ {
MaxWidth = TooltipTextMaxWidth, MaxWidth = TooltipTextMaxWidth,

View File

@@ -19,6 +19,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Log; using Robust.Shared.Log;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using static Robust.Client.UserInterface.Controls.BaseButton; using static Robust.Client.UserInterface.Controls.BaseButton;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Actions.UI namespace Content.Client.Actions.UI
{ {
@@ -71,12 +72,14 @@ namespace Content.Client.Actions.UI
Title = Loc.GetString("ui-actionmenu-title"); Title = Loc.GetString("ui-actionmenu-title");
MinSize = (300, 300); MinSize = (300, 300);
Contents.AddChild(new VBoxContainer Contents.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
(_searchBar = new LineEdit (_searchBar = new LineEdit
@@ -87,7 +90,7 @@ namespace Content.Client.Actions.UI
}), }),
(_filterButton = new MultiselectOptionButton<string>() (_filterButton = new MultiselectOptionButton<string>()
{ {
Label = Loc.GetString("ui-actionmenu-filter-buttonr") Label = Loc.GetString("ui-actionmenu-filter-button")
}) })
} }
}, },

View File

@@ -16,6 +16,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Actions.UI namespace Content.Client.Actions.UI
{ {
@@ -174,8 +175,9 @@ namespace Content.Client.Actions.UI
_cooldownGraphic = new CooldownGraphic {Progress = 0, Visible = false}; _cooldownGraphic = new CooldownGraphic {Progress = 0, Visible = false};
// padding to the left of the number to shift it right // padding to the left of the number to shift it right
var paddingBox = new HBoxContainer() var paddingBox = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true, HorizontalExpand = true,
VerticalExpand = true, VerticalExpand = true,
MinSize = (64, 64) MinSize = (64, 64)
@@ -187,8 +189,9 @@ namespace Content.Client.Actions.UI
paddingBox.AddChild(_number); paddingBox.AddChild(_number);
// padding to the left of the small icon // padding to the left of the small icon
var paddingBoxItemIcon = new HBoxContainer() var paddingBoxItemIcon = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true, HorizontalExpand = true,
VerticalExpand = true, VerticalExpand = true,
MinSize = (64, 64) MinSize = (64, 64)

View File

@@ -18,6 +18,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Log; using Robust.Shared.Log;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Actions.UI namespace Content.Client.Actions.UI
{ {
@@ -42,7 +43,7 @@ namespace Content.Client.Actions.UI
private readonly Label _loadoutNumber; private readonly Label _loadoutNumber;
private readonly Texture _lockTexture; private readonly Texture _lockTexture;
private readonly Texture _unlockTexture; private readonly Texture _unlockTexture;
private readonly HBoxContainer _loadoutContainer; private readonly BoxContainer _loadoutContainer;
private readonly TextureRect _dragShadow; private readonly TextureRect _dragShadow;
@@ -108,15 +109,17 @@ namespace Content.Client.Actions.UI
}; };
AddChild(panelContainer); AddChild(panelContainer);
var hotbarContainer = new VBoxContainer var hotbarContainer = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
SeparationOverride = 3, SeparationOverride = 3,
HorizontalAlignment = HAlignment.Left HorizontalAlignment = HAlignment.Left
}; };
panelContainer.AddChild(hotbarContainer); panelContainer.AddChild(hotbarContainer);
var settingsContainer = new HBoxContainer var settingsContainer = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true HorizontalExpand = true
}; };
hotbarContainer.AddChild(settingsContainer); hotbarContainer.AddChild(settingsContainer);
@@ -156,8 +159,9 @@ namespace Content.Client.Actions.UI
}; };
hotbarContainer.AddChild(_slotContainer); hotbarContainer.AddChild(_slotContainer);
_loadoutContainer = new HBoxContainer _loadoutContainer = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true, HorizontalExpand = true,
MouseFilter = MouseFilterMode.Stop MouseFilter = MouseFilterMode.Stop
}; };

View File

@@ -8,6 +8,7 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Administration.UI namespace Content.Client.Administration.UI
{ {
@@ -65,8 +66,9 @@ namespace Content.Client.Administration.UI
Title = Loc.GetString("admin-add-reagent-eui-title"); Title = Loc.GetString("admin-add-reagent-eui-title");
Contents.AddChild(new VBoxContainer Contents.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
new GridContainer new GridContainer
@@ -88,8 +90,9 @@ namespace Content.Client.Administration.UI
HorizontalExpand = true, HorizontalExpand = true,
VerticalExpand = true VerticalExpand = true
}, },
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
(_errorLabel = new Label (_errorLabel = new Label

View File

@@ -1,4 +1,3 @@
#nullable enable
using System.Collections.Generic; using System.Collections.Generic;
using Content.Client.Administration.UI.Tabs; using Content.Client.Administration.UI.Tabs;
using Content.Client.HUD; using Content.Client.HUD;

View File

@@ -1,5 +1,4 @@
#nullable enable using Robust.Client.Console;
using Robust.Client.Console;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -9,7 +8,7 @@ namespace Content.Client.Administration.UI.CustomControls
{ {
public string? Command { get; set; } public string? Command { get; set; }
public CommandButton() : base() public CommandButton()
{ {
OnPressed += Execute; OnPressed += Execute;
} }

View File

@@ -1,13 +1,13 @@
<VBoxContainer <BoxContainer Orientation="Vertical"
xmlns="https://spacestation14.io"> xmlns="https://spacestation14.io">
<Control CustomMinimumSize="0 5" /> <Control CustomMinimumSize="0 5" />
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<!-- <Label Text="{Loc Search}" CustomMinimumSize="100 0" /> --> <!-- <Label Text="{Loc Search}" CustomMinimumSize="100 0" /> -->
<!-- <Control CustomMinimumSize="50 0" /> --> <!-- <Control CustomMinimumSize="50 0" /> -->
<LineEdit Name="FilterLineEdit" CustomMinimumSize="100 0" SizeFlagsHorizontal="FillExpand" PlaceHolder="{Loc Filter}"/> <LineEdit Name="FilterLineEdit" CustomMinimumSize="100 0" SizeFlagsHorizontal="FillExpand" PlaceHolder="{Loc Filter}"/>
</HBoxContainer> </BoxContainer>
<!-- <Control CustomMinimumSize="0 5" /> --> <!-- <Control CustomMinimumSize="0 5" /> -->
<ItemList <ItemList
Name="PlayerItemList" SelectMode="Single" SizeFlagsVertical="FillExpand" SizeFlagsHorizontal="FillExpand" Name="PlayerItemList" SelectMode="Single" SizeFlagsVertical="FillExpand" SizeFlagsHorizontal="FillExpand"
CustomMinimumSize="100 100" /> CustomMinimumSize="100 100" />
</VBoxContainer> </BoxContainer>

View File

@@ -1,5 +1,4 @@
#nullable enable using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;

View File

@@ -1,5 +1,4 @@
#nullable enable using System;
using System;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC; using Robust.Shared.IoC;

View File

@@ -14,6 +14,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using static Content.Shared.Administration.PermissionsEuiMsg; using static Content.Shared.Administration.PermissionsEuiMsg;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Administration.UI namespace Content.Client.Administration.UI
{ {
@@ -316,15 +317,17 @@ namespace Content.Client.Administration.UI
}; };
AdminsList = new GridContainer {Columns = 5, VerticalExpand = true}; AdminsList = new GridContainer {Columns = 5, VerticalExpand = true};
var adminVBox = new VBoxContainer var adminVBox = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = {AdminsList, AddAdminButton}, Children = {AdminsList, AddAdminButton},
}; };
TabContainer.SetTabTitle(adminVBox, Loc.GetString("permissions-eui-menu-admins-tab-title")); TabContainer.SetTabTitle(adminVBox, Loc.GetString("permissions-eui-menu-admins-tab-title"));
AdminRanksList = new GridContainer {Columns = 3}; AdminRanksList = new GridContainer {Columns = 3};
var rankVBox = new VBoxContainer var rankVBox = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = { AdminRanksList, AddAdminRankButton} Children = { AdminRanksList, AddAdminRankButton}
}; };
TabContainer.SetTabTitle(rankVBox, Loc.GetString("permissions-eui-menu-admin-ranks-tab-title")); 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)); FlagButtons.Add(flag, (inherit, sub, plus));
} }
var bottomButtons = new HBoxContainer(); var bottomButtons = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
if (data != null) if (data != null)
{ {
// show remove button. // show remove button.
@@ -461,17 +467,20 @@ namespace Content.Client.Administration.UI
bottomButtons.AddChild(SaveButton); bottomButtons.AddChild(SaveButton);
Contents.AddChild(new VBoxContainer Contents.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 2, SeparationOverride = 2,
Children = Children =
{ {
new VBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true, HorizontalExpand = true,
Children = Children =
{ {
@@ -541,7 +550,10 @@ namespace Content.Client.Administration.UI
HorizontalAlignment = HAlignment.Right, HorizontalAlignment = HAlignment.Right,
HorizontalExpand = true HorizontalExpand = true
}; };
var flagsBox = new VBoxContainer(); var flagsBox = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
};
foreach (var flag in AdminFlagsHelper.AllFlags) foreach (var flag in AdminFlagsHelper.AllFlags)
{ {
@@ -565,7 +577,10 @@ namespace Content.Client.Administration.UI
flagsBox.AddChild(checkBox); flagsBox.AddChild(checkBox);
} }
var bottomButtons = new HBoxContainer(); var bottomButtons = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
if (data != null) if (data != null)
{ {
// show remove button. // show remove button.
@@ -575,8 +590,9 @@ namespace Content.Client.Administration.UI
bottomButtons.AddChild(SaveButton); bottomButtons.AddChild(SaveButton);
Contents.AddChild(new VBoxContainer Contents.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
NameEdit, NameEdit,

View File

@@ -1,15 +1,15 @@
<SS14Window <SS14Window
xmlns="https://spacestation14.io"> xmlns="https://spacestation14.io">
<HBoxContainer HorizontalExpand="True"> <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<VBoxContainer HorizontalExpand="True" SizeFlagsStretchRatio="0.45"> <BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.45">
<HBoxContainer HorizontalExpand="True" VerticalExpand="True" <BoxContainer Orientation="Horizontal" HorizontalExpand="True" VerticalExpand="True"
SizeFlagsStretchRatio="0.1"> SizeFlagsStretchRatio="0.1">
<LineEdit Name="SearchBar" PlaceHolder="Search" HorizontalExpand="True" <LineEdit Name="SearchBar" PlaceHolder="Search" HorizontalExpand="True"
SizeFlagsStretchRatio="0.6" /> SizeFlagsStretchRatio="0.6" />
</HBoxContainer> </BoxContainer>
<ItemList Name="OutfitList" SelectMode="Single" VerticalExpand="True" <ItemList Name="OutfitList" SelectMode="Single" VerticalExpand="True"
SizeFlagsStretchRatio="0.9" /> SizeFlagsStretchRatio="0.9" />
<Button Name="ConfirmButton" HorizontalExpand="True" /> <Button Name="ConfirmButton" HorizontalExpand="True" />
</VBoxContainer> </BoxContainer>
</HBoxContainer> </BoxContainer>
</SS14Window> </SS14Window>

View File

@@ -5,7 +5,7 @@
xmlns:at="clr-namespace:Content.Client.Administration.UI.Tabs.AdminTab" xmlns:at="clr-namespace:Content.Client.Administration.UI.Tabs.AdminTab"
Margin="4" Margin="4"
MinSize="50 50"> MinSize="50 50">
<VBoxContainer> <BoxContainer Orientation="Vertical">
<GridContainer Columns="4"> <GridContainer Columns="4">
<cc:UICommandButton Command="kick" Text="{Loc Kick}" WindowType="{x:Type at:KickWindow}" /> <cc:UICommandButton Command="kick" Text="{Loc Kick}" WindowType="{x:Type at:KickWindow}" />
<cc:UICommandButton Command="ban" Text="{Loc Ban}" WindowType="{x:Type at:BanWindow}" /> <cc:UICommandButton Command="ban" Text="{Loc Ban}" WindowType="{x:Type at:BanWindow}" />
@@ -13,5 +13,5 @@
<cc:UICommandButton Command="tpto" Text="{Loc Teleport}" WindowType="{x:Type at:TeleportWindow}" /> <cc:UICommandButton Command="tpto" Text="{Loc Teleport}" WindowType="{x:Type at:TeleportWindow}" />
<cc:CommandButton Command="permissions" Text="{Loc Permissions Panel}" /> <cc:CommandButton Command="permissions" Text="{Loc Permissions Panel}" />
</GridContainer> </GridContainer>
</VBoxContainer> </BoxContainer>
</Control> </Control>

View File

@@ -1,5 +1,4 @@
#nullable enable using Robust.Client.AutoGenerated;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
namespace Content.Client.Administration.UI.Tabs.AdminTab namespace Content.Client.Administration.UI.Tabs.AdminTab

View File

@@ -1,23 +1,23 @@
<SS14Window <SS14Window
xmlns="https://spacestation14.io" xmlns="https://spacestation14.io"
Title="{Loc Ban}" MinSize="425 162"> Title="{Loc Ban}" MinSize="425 162">
<VBoxContainer> <BoxContainer Orientation="Vertical">
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Player}" MinWidth="100" /> <Label Text="{Loc Player}" MinWidth="100" />
<Control MinWidth="50" /> <Control MinWidth="50" />
<LineEdit Name="PlayerNameLine" MinWidth="100" HorizontalExpand="True" /> <LineEdit Name="PlayerNameLine" MinWidth="100" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Reason}" MinSize="100 0" /> <Label Text="{Loc Reason}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<LineEdit Name="ReasonLine" MinSize="100 0" HorizontalExpand="True" /> <LineEdit Name="ReasonLine" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Minutes}" MinWidth="100" /> <Label Text="{Loc Minutes}" MinWidth="100" />
<Control MinWidth="50" /> <Control MinWidth="50" />
<LineEdit Name="MinutesLine" MinWidth="100" HorizontalExpand="True" PlaceHolder="{Loc 0 minutes for a permanent ban}" /> <LineEdit Name="MinutesLine" MinWidth="100" HorizontalExpand="True" PlaceHolder="{Loc 0 minutes for a permanent ban}" />
</HBoxContainer> </BoxContainer>
<Control MinWidth="50" /> <Control MinWidth="50" />
<Button Name="SubmitButton" Text="{Loc Ban}" /> <Button Name="SubmitButton" Text="{Loc Ban}" />
</VBoxContainer> </BoxContainer>
</SS14Window> </SS14Window>

View File

@@ -1,5 +1,4 @@
#nullable enable using JetBrains.Annotations;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.Console; using Robust.Client.Console;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;

View File

@@ -2,13 +2,13 @@
xmlns="https://spacestation14.io" xmlns="https://spacestation14.io"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls" xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc Kick}" MinSize="425 272"> Title="{Loc Kick}" MinSize="425 272">
<VBoxContainer> <BoxContainer Orientation="Vertical">
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Reason}" MinWidth="100" /> <Label Text="{Loc Reason}" MinWidth="100" />
<Control MinWidth="50" /> <Control MinWidth="50" />
<LineEdit Name="ReasonLine" MinWidth="100" HorizontalExpand="True" /> <LineEdit Name="ReasonLine" MinWidth="100" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<cc:PlayerListControl Name="PlayerList" /> <cc:PlayerListControl Name="PlayerList" />
<Button Name="SubmitButton" Text="{Loc Kick}" /> <Button Name="SubmitButton" Text="{Loc Kick}" />
</VBoxContainer> </BoxContainer>
</SS14Window> </SS14Window>

View File

@@ -1,5 +1,4 @@
#nullable enable using JetBrains.Annotations;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.Console; using Robust.Client.Console;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;

View File

@@ -2,8 +2,8 @@
xmlns="https://spacestation14.io" xmlns="https://spacestation14.io"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls" xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc Teleport}" MinSize="425 230"> Title="{Loc Teleport}" MinSize="425 230">
<VBoxContainer> <BoxContainer Orientation="Vertical">
<cc:PlayerListControl Name="PlayerList" /> <cc:PlayerListControl Name="PlayerList" />
<Button Name="SubmitButton" Text="{Loc Teleport}" /> <Button Name="SubmitButton" Text="{Loc Teleport}" />
</VBoxContainer> </BoxContainer>
</SS14Window> </SS14Window>

View File

@@ -1,5 +1,4 @@
#nullable enable using JetBrains.Annotations;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.Console; using Robust.Client.Console;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;

View File

@@ -1,5 +1,4 @@
#nullable enable using Content.Client.Administration.Managers;
using Content.Client.Administration.Managers;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.Placement; using Robust.Client.Placement;
using Robust.Client.ResourceManagement; using Robust.Client.ResourceManagement;
@@ -15,6 +14,9 @@ namespace Content.Client.Administration.UI.Tabs.AdminbusTab
[GenerateTypedNameReferences] [GenerateTypedNameReferences]
public partial class AdminbusTab : Control public partial class AdminbusTab : Control
{ {
private EntitySpawnWindow? _entitySpawnWindow;
private TileSpawnWindow? _tileSpawnWindow;
protected override void EnteredTree() protected override void EnteredTree()
{ {
// For the SpawnEntitiesButton and SpawnTilesButton we need to do the press manually // 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; SpawnTilesButton.OnPressed += SpawnTilesButtonOnOnPressed;
} }
private static void SpawnEntitiesButtonOnOnPressed(BaseButton.ButtonEventArgs obj) private void SpawnEntitiesButtonOnOnPressed(BaseButton.ButtonEventArgs obj)
{ {
var manager = IoCManager.Resolve<IAdminMenuManager>(); var manager = IoCManager.Resolve<IAdminMenuManager>();
var window = new EntitySpawnWindow(IoCManager.Resolve<IPlacementManager>(), _entitySpawnWindow ??= new EntitySpawnWindow(IoCManager.Resolve<IPlacementManager>(),
IoCManager.Resolve<IPrototypeManager>(), IoCManager.Resolve<IPrototypeManager>(),
IoCManager.Resolve<IResourceCache>()); IoCManager.Resolve<IResourceCache>());
manager.OpenCommand(window); manager.OpenCommand(_entitySpawnWindow);
} }
private static void SpawnTilesButtonOnOnPressed(BaseButton.ButtonEventArgs obj) private void SpawnTilesButtonOnOnPressed(BaseButton.ButtonEventArgs obj)
{ {
var manager = IoCManager.Resolve<IAdminMenuManager>(); var manager = IoCManager.Resolve<IAdminMenuManager>();
var window = new TileSpawnWindow(IoCManager.Resolve<ITileDefinitionManager>(), _tileSpawnWindow ??= new TileSpawnWindow(IoCManager.Resolve<ITileDefinitionManager>(),
IoCManager.Resolve<IPlacementManager>(), IoCManager.Resolve<IPlacementManager>(),
IoCManager.Resolve<IResourceCache>()); IoCManager.Resolve<IResourceCache>());
manager.OpenCommand(window); manager.OpenCommand(_tileSpawnWindow);
} }
} }
} }

View File

@@ -1,13 +1,13 @@
<SS14Window <SS14Window
xmlns="https://spacestation14.io" Title="Kick"> xmlns="https://spacestation14.io" Title="Kick">
<VBoxContainer> <BoxContainer Orientation="Vertical">
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Event}" MinSize="100 0" /> <Label Text="{Loc Event}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<OptionButton Name="EventsOptions" MinSize="100 0" HorizontalExpand="True" /> <OptionButton Name="EventsOptions" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<Button Name="PauseButton" Text="{Loc Pause}" /> <Button Name="PauseButton" Text="{Loc Pause}" />
<Button Name="ResumeButton" Text="{Loc Resume}" /> <Button Name="ResumeButton" Text="{Loc Resume}" />
<Button Name="SubmitButton" Text="{Loc Run}" /> <Button Name="SubmitButton" Text="{Loc Run}" />
</VBoxContainer> </BoxContainer>
</SS14Window> </SS14Window>

View File

@@ -1,4 +1,3 @@
#nullable enable
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Content.Client.StationEvents.Managers; using Content.Client.StationEvents.Managers;

View File

@@ -1,11 +1,11 @@
<SS14Window <SS14Window
xmlns="https://spacestation14.io" Title="{Loc Add Atmos}"> xmlns="https://spacestation14.io" Title="{Loc Add Atmos}">
<VBoxContainer> <BoxContainer Orientation="Vertical">
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Grid}" MinSize="100 0" /> <Label Text="{Loc Grid}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" /> <OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<Button Name="SubmitButton" Text="{Loc Add Atmos}" /> <Button Name="SubmitButton" Text="{Loc Add Atmos}" />
</VBoxContainer> </BoxContainer>
</SS14Window> </SS14Window>

View File

@@ -1,5 +1,4 @@
#nullable enable using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;

View File

@@ -1,31 +1,31 @@
<SS14Window <SS14Window
xmlns="https://spacestation14.io" Title="{Loc Add Gas}"> xmlns="https://spacestation14.io" Title="{Loc Add Gas}">
<VBoxContainer> <BoxContainer Orientation="Vertical">
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Grid}" MinSize="100 0" /> <Label Text="{Loc Grid}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" /> <OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc TileX}" MinSize="100 0" /> <Label Text="{Loc TileX}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<SpinBox Name="TileXSpin" MinSize="100 0" HorizontalExpand="True" /> <SpinBox Name="TileXSpin" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc TileY}" MinSize="100 0" /> <Label Text="{Loc TileY}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<SpinBox Name="TileYSpin" MinSize="100 0" HorizontalExpand="True" /> <SpinBox Name="TileYSpin" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Gas}" MinSize="100 0" /> <Label Text="{Loc Gas}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<OptionButton Name="GasOptions" MinSize="100 0" HorizontalExpand="True" /> <OptionButton Name="GasOptions" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Amount}" MinSize="100 0" /> <Label Text="{Loc Amount}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<SpinBox Name="AmountSpin" MinSize="100 0" HorizontalExpand="True" /> <SpinBox Name="AmountSpin" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<Button Name="SubmitButton" Text="{Loc Add Gas}" /> <Button Name="SubmitButton" Text="{Loc Add Gas}" />
</VBoxContainer> </BoxContainer>
</SS14Window> </SS14Window>

View File

@@ -1,5 +1,4 @@
#nullable enable using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Content.Client.Atmos.EntitySystems; using Content.Client.Atmos.EntitySystems;
using Content.Shared.Atmos; using Content.Shared.Atmos;

View File

@@ -1,5 +1,4 @@
#nullable enable using Robust.Client.AutoGenerated;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
namespace Content.Client.Administration.UI.Tabs.AtmosTab namespace Content.Client.Administration.UI.Tabs.AtmosTab

View File

@@ -1,21 +1,21 @@
<SS14Window <SS14Window
xmlns="https://spacestation14.io" Title="{Loc Fill Gas}"> xmlns="https://spacestation14.io" Title="{Loc Fill Gas}">
<VBoxContainer> <BoxContainer Orientation="Vertical">
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Grid}" MinSize="100 0" /> <Label Text="{Loc Grid}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" /> <OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Gas}" MinSize="100 0" /> <Label Text="{Loc Gas}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<OptionButton Name="GasOptions" MinSize="100 0" HorizontalExpand="True" /> <OptionButton Name="GasOptions" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Amount}" MinSize="100 0" /> <Label Text="{Loc Amount}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<SpinBox Name="AmountSpin" MinSize="100 0" HorizontalExpand="True" /> <SpinBox Name="AmountSpin" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<Button Name="SubmitButton" Text="{Loc Fill Gas}" /> <Button Name="SubmitButton" Text="{Loc Fill Gas}" />
</VBoxContainer> </BoxContainer>
</SS14Window> </SS14Window>

View File

@@ -1,5 +1,4 @@
#nullable enable using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Content.Client.Atmos.EntitySystems; using Content.Client.Atmos.EntitySystems;
using Content.Shared.Atmos; using Content.Shared.Atmos;

View File

@@ -1,26 +1,26 @@
<SS14Window <SS14Window
xmlns="https://spacestation14.io" Title="{Loc Set Temperature}"> xmlns="https://spacestation14.io" Title="{Loc Set Temperature}">
<VBoxContainer> <BoxContainer Orientation="Vertical">
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Grid}" MinSize="100 0" /> <Label Text="{Loc Grid}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" /> <OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc TileX}" MinSize="100 0" /> <Label Text="{Loc TileX}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<SpinBox Name="TileXSpin" MinSize="100 0" HorizontalExpand="True" /> <SpinBox Name="TileXSpin" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc TileY}" MinSize="100 0" /> <Label Text="{Loc TileY}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<SpinBox Name="TileYSpin" MinSize="100 0" HorizontalExpand="True" /> <SpinBox Name="TileYSpin" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc Temperature}" MinSize="100 0" /> <Label Text="{Loc Temperature}" MinSize="100 0" />
<Control MinSize="50 0" /> <Control MinSize="50 0" />
<SpinBox Name="TemperatureSpin" MinSize="100 0" HorizontalExpand="True" /> <SpinBox Name="TemperatureSpin" MinSize="100 0" HorizontalExpand="True" />
</HBoxContainer> </BoxContainer>
<Button Name="SubmitButton" Text="{Loc Set Temperature}" /> <Button Name="SubmitButton" Text="{Loc Set Temperature}" />
</VBoxContainer> </BoxContainer>
</SS14Window> </SS14Window>

View File

@@ -1,5 +1,4 @@
#nullable enable using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;

View File

@@ -1,14 +1,14 @@
<Control xmlns="https://spacestation14.io"> <Control xmlns="https://spacestation14.io">
<VBoxContainer> <BoxContainer Orientation="Vertical">
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Name="PlayerCount" HorizontalExpand="True" SizeFlagsStretchRatio="0.7" <Label Name="PlayerCount" HorizontalExpand="True" SizeFlagsStretchRatio="0.7"
Text="{Loc Player Count}" /> Text="{Loc Player Count}" />
<Button Name="RefreshButton" HorizontalExpand="True" SizeFlagsStretchRatio="0.3" <Button Name="RefreshButton" HorizontalExpand="True" SizeFlagsStretchRatio="0.3"
Text="{Loc Refresh}" /> Text="{Loc Refresh}" />
</HBoxContainer> </BoxContainer>
<Control MinSize="0 5" /> <Control MinSize="0 5" />
<ScrollContainer HorizontalExpand="True" VerticalExpand="True"> <ScrollContainer HorizontalExpand="True" VerticalExpand="True">
<VBoxContainer Name="PlayerList" /> <BoxContainer Orientation="Vertical" Name="PlayerList" />
</ScrollContainer> </ScrollContainer>
</VBoxContainer> </BoxContainer>
</Control> </Control>

View File

@@ -1,5 +1,4 @@
#nullable enable 
using System.Collections.Generic; using System.Collections.Generic;
using Content.Shared.Administration.Menu; using Content.Shared.Administration.Menu;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
@@ -10,6 +9,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML; using Robust.Client.UserInterface.XAML;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Administration.UI.Tabs namespace Content.Client.Administration.UI.Tabs
{ {
@@ -41,8 +41,9 @@ namespace Content.Client.Administration.UI.Tabs
var altColor = Color.FromHex("#292B38"); var altColor = Color.FromHex("#292B38");
var defaultColor = Color.FromHex("#2F2F3B"); var defaultColor = Color.FromHex("#2F2F3B");
var header = new HBoxContainer var header = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true, HorizontalExpand = true,
SeparationOverride = 4, SeparationOverride = 4,
Children = Children =
@@ -85,8 +86,9 @@ namespace Content.Client.Administration.UI.Tabs
var useAltColor = false; var useAltColor = false;
foreach (var player in players) foreach (var player in players)
{ {
var hBox = new HBoxContainer var hBox = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true, HorizontalExpand = true,
SeparationOverride = 4, SeparationOverride = 4,
Children = Children =

View File

@@ -1,5 +1,4 @@
#nullable enable using Robust.Client.AutoGenerated;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
namespace Content.Client.Administration.UI.Tabs namespace Content.Client.Administration.UI.Tabs

View File

@@ -1,5 +1,4 @@
#nullable enable using Robust.Client.AutoGenerated;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
namespace Content.Client.Administration.UI.Tabs namespace Content.Client.Administration.UI.Tabs

View File

@@ -48,7 +48,7 @@ namespace Content.Client.Alerts.UI
base.EnteredTree(); base.EnteredTree();
var _chatManager = IoCManager.Resolve<IChatManager>(); var _chatManager = IoCManager.Resolve<IChatManager>();
_chatManager.OnChatBoxResized += OnChatResized; _chatManager.OnChatBoxResized += OnChatResized;
OnChatResized(new ChatResizedEventArgs(ChatBox.InitialChatBottom)); OnChatResized(new ChatResizedEventArgs(HudChatBox.InitialChatBottom));
} }
protected override void ExitedTree() protected override void ExitedTree()

View File

@@ -14,6 +14,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Arcade namespace Content.Client.Arcade
{ {
@@ -28,7 +29,7 @@ namespace Content.Client.Arcade
private readonly PanelContainer _mainPanel; private readonly PanelContainer _mainPanel;
private VBoxContainer _gameRootContainer; private BoxContainer _gameRootContainer;
private GridContainer _gameGrid = default!; private GridContainer _gameGrid = default!;
private GridContainer _nextBlockGrid = default!; private GridContainer _nextBlockGrid = default!;
private GridContainer _holdBlockGrid = default!; private GridContainer _holdBlockGrid = default!;
@@ -68,7 +69,10 @@ namespace Content.Client.Arcade
#region Game Menu #region Game Menu
// building the game container // building the game container
_gameRootContainer = new VBoxContainer(); _gameRootContainer = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
};
_levelLabel = new Label _levelLabel = new Label
{ {
@@ -92,7 +96,10 @@ namespace Content.Client.Arcade
MinSize = new Vector2(1,10) MinSize = new Vector2(1,10)
}); });
var gameBox = new HBoxContainer(); var gameBox = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
gameBox.AddChild(SetupHoldBox(backgroundTexture)); gameBox.AddChild(SetupHoldBox(backgroundTexture));
gameBox.AddChild(new Control gameBox.AddChild(new Control
{ {
@@ -152,8 +159,9 @@ namespace Content.Client.Arcade
_menuRootContainer.AddChild(pauseMenuInnerPanel); _menuRootContainer.AddChild(pauseMenuInnerPanel);
var pauseMenuContainer = new VBoxContainer var pauseMenuContainer = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
HorizontalAlignment = HAlignment.Center, HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center VerticalAlignment = VAlignment.Center
}; };
@@ -224,8 +232,9 @@ namespace Content.Client.Arcade
_gameOverRootContainer.AddChild(gameOverMenuInnerPanel); _gameOverRootContainer.AddChild(gameOverMenuInnerPanel);
var gameOverMenuContainer = new VBoxContainer var gameOverMenuContainer = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
HorizontalAlignment = HAlignment.Center, HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center VerticalAlignment = VAlignment.Center
}; };
@@ -282,8 +291,9 @@ namespace Content.Client.Arcade
_highscoresRootContainer.AddChild(menuInnerPanel); _highscoresRootContainer.AddChild(menuInnerPanel);
var menuContainer = new VBoxContainer() var menuContainer = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
HorizontalAlignment = HAlignment.Center, HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.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 Label{Text = Loc.GetString("blockgame-menu-label-highscores")});
menuContainer.AddChild(new Control{MinSize = new Vector2(1,10)}); menuContainer.AddChild(new Control{MinSize = new Vector2(1,10)});
var highScoreBox = new HBoxContainer(); var highScoreBox = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
_localHighscoresLabel = new Label _localHighscoresLabel = new Label
{ {

View File

@@ -1,4 +1,3 @@
#nullable enable
using System.Collections.Generic; using System.Collections.Generic;
using Content.Client.Atmos.Overlays; using Content.Client.Atmos.Overlays;
using Content.Shared.Atmos; using Content.Shared.Atmos;

View File

@@ -1,4 +1,3 @@
#nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Content.Client.Atmos.Overlays; using Content.Client.Atmos.Overlays;

View File

@@ -10,6 +10,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using static Content.Shared.Atmos.Components.SharedGasAnalyzerComponent; using static Content.Shared.Atmos.Components.SharedGasAnalyzerComponent;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Atmos.UI namespace Content.Client.Atmos.UI
{ {
@@ -61,11 +62,15 @@ namespace Content.Client.Atmos.UI
LayoutContainer.SetAnchorPreset(bottomWrap, LayoutContainer.LayoutPreset.VerticalCenterWide); LayoutContainer.SetAnchorPreset(bottomWrap, LayoutContainer.LayoutPreset.VerticalCenterWide);
LayoutContainer.SetGrowHorizontal(bottomWrap, LayoutContainer.GrowDirection.Both); LayoutContainer.SetGrowHorizontal(bottomWrap, LayoutContainer.GrowDirection.Both);
var topContainerWrap = new VBoxContainer var topContainerWrap = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
(_topContainer = new VBoxContainer()), (_topContainer = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
}),
new Control {MinSize = (0, 110)} 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); var fontSmall = resourceCache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 10);
Button refreshButton; Button refreshButton;
var topRow = new HBoxContainer var topRow = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Margin = new Thickness(4, 4, 12, 2), Margin = new Thickness(4, 4, 12, 2),
Children = Children =
{ {
@@ -118,8 +124,9 @@ namespace Content.Client.Atmos.UI
PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#202025") }, PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#202025") },
Children = Children =
{ {
(_statusContainer = new VBoxContainer (_statusContainer = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(8, 8, 4, 4) Margin = new Thickness(8, 8, 4, 4)
}) })
} }
@@ -178,10 +185,17 @@ namespace Content.Client.Atmos.UI
}); });
// Add a table with all the gases // Add a table with all the gases
var tableKey = new VBoxContainer(); var tableKey = new BoxContainer
var tableVal = new VBoxContainer();
_statusContainer.AddChild(new HBoxContainer
{ {
Orientation = LayoutOrientation.Vertical
};
var tableVal = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
};
_statusContainer.AddChild(new BoxContainer
{
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
tableKey, tableKey,
@@ -195,8 +209,9 @@ namespace Content.Client.Atmos.UI
// This is the gas bar thingy // This is the gas bar thingy
var height = 30; var height = 30;
var minSize = 24; // This basically allows gases which are too small, to be shown properly 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, HorizontalExpand = true,
MinSize = new Vector2(0, height) MinSize = new Vector2(0, height)
}; };

View File

@@ -2,51 +2,51 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:Content.Client.Stylesheets" xmlns:s="clr-namespace:Content.Client.Stylesheets"
MinSize="480 400" Title="Canister"> MinSize="480 400" Title="Canister">
<VBoxContainer Margin="5 5 5 5" SeparationOverride="10"> <BoxContainer Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
<VBoxContainer VerticalExpand="True"> <BoxContainer Orientation="Vertical" VerticalExpand="True">
<Label Text="{Loc comp-gas-canister-ui-canister-status}" FontColorOverride="{x:Static s:StyleNano.NanoGold}" StyleClasses="LabelBig"/> <Label Text="{Loc comp-gas-canister-ui-canister-status}" FontColorOverride="{x:Static s:StyleNano.NanoGold}" StyleClasses="LabelBig"/>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc comp-gas-canister-ui-canister-pressure}"/> <Label Text="{Loc comp-gas-canister-ui-canister-pressure}"/>
<Label Name="CanisterPressureLabel" Align="Center" HorizontalExpand="True"/> <Label Name="CanisterPressureLabel" Align="Center" HorizontalExpand="True"/>
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc comp-gas-canister-ui-port-status}"/> <Label Text="{Loc comp-gas-canister-ui-port-status}"/>
<Label Name="PortStatusLabel" Align="Center" HorizontalExpand="True"/> <Label Name="PortStatusLabel" Align="Center" HorizontalExpand="True"/>
</HBoxContainer> </BoxContainer>
</VBoxContainer> </BoxContainer>
<VBoxContainer VerticalExpand="True"> <BoxContainer Orientation="Vertical" VerticalExpand="True">
<Label Text="{Loc comp-gas-canister-ui-holding-tank-status}" FontColorOverride="{x:Static s:StyleNano.NanoGold}" StyleClasses="LabelBig"/> <Label Text="{Loc comp-gas-canister-ui-holding-tank-status}" FontColorOverride="{x:Static s:StyleNano.NanoGold}" StyleClasses="LabelBig"/>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc comp-gas-canister-ui-holding-tank-label}"/> <Label Text="{Loc comp-gas-canister-ui-holding-tank-label}"/>
<Label Name="TankLabelLabel" Text="{Loc comp-gas-canister-ui-holding-tank-label-empty}" Align="Center" HorizontalExpand="True"/> <Label Name="TankLabelLabel" Text="{Loc comp-gas-canister-ui-holding-tank-label-empty}" Align="Center" HorizontalExpand="True"/>
<Button Name="TankEjectButton" Text="{Loc comp-gas-canister-ui-holding-tank-eject}"/> <Button Name="TankEjectButton" Text="{Loc comp-gas-canister-ui-holding-tank-eject}"/>
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc comp-gas-canister-ui-holding-tank-pressure}"/> <Label Text="{Loc comp-gas-canister-ui-holding-tank-pressure}"/>
<Label Name="TankPressureLabel" Align="Center" HorizontalExpand="True"/> <Label Name="TankPressureLabel" Align="Center" HorizontalExpand="True"/>
</HBoxContainer> </BoxContainer>
</VBoxContainer> </BoxContainer>
<VBoxContainer VerticalExpand="True"> <BoxContainer Orientation="Vertical" VerticalExpand="True">
<Label Text="{Loc comp-gas-canister-ui-release-valve-status}" FontColorOverride="{x:Static s:StyleNano.NanoGold}" StyleClasses="LabelBig"/> <Label Text="{Loc comp-gas-canister-ui-release-valve-status}" FontColorOverride="{x:Static s:StyleNano.NanoGold}" StyleClasses="LabelBig"/>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<VBoxContainer> <BoxContainer Orientation="Vertical">
<Label Text="{Loc comp-gas-canister-ui-release-pressure}"/> <Label Text="{Loc comp-gas-canister-ui-release-pressure}"/>
<Control VerticalExpand="True"/> <Control VerticalExpand="True"/>
</VBoxContainer> </BoxContainer>
<VBoxContainer HorizontalExpand="True" Margin="15 0 0 15" SeparationOverride="5"> <BoxContainer Orientation="Vertical" HorizontalExpand="True" Margin="15 0 0 15" SeparationOverride="5">
<Slider Name="ReleasePressureSlider" HorizontalExpand="True"/> <Slider Name="ReleasePressureSlider" HorizontalExpand="True"/>
<Label Name="ReleasePressureLabel" Align="Center" HorizontalExpand="True"/> <Label Name="ReleasePressureLabel" Align="Center" HorizontalExpand="True"/>
</VBoxContainer> </BoxContainer>
</HBoxContainer> </BoxContainer>
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc comp-gas-canister-ui-release-valve}"/> <Label Text="{Loc comp-gas-canister-ui-release-valve}"/>
<Control HorizontalExpand="True"/> <Control HorizontalExpand="True"/>
<Button Name="ReleaseValveOpenButton" Text="{Loc comp-gas-canister-ui-release-valve-open}" ToggleMode="True"/> <Button Name="ReleaseValveOpenButton" Text="{Loc comp-gas-canister-ui-release-valve-open}" ToggleMode="True"/>
<Button Name="ReleaseValveCloseButton" Text="{Loc comp-gas-canister-ui-release-valve-close}" ToggleMode="True"/> <Button Name="ReleaseValveCloseButton" Text="{Loc comp-gas-canister-ui-release-valve-close}" ToggleMode="True"/>
<Control HorizontalExpand="True"/> <Control HorizontalExpand="True"/>
</HBoxContainer> </BoxContainer>
</VBoxContainer> </BoxContainer>
</VBoxContainer> </BoxContainer>
</SS14Window> </SS14Window>

View File

@@ -4,7 +4,7 @@ using Robust.Client.GameObjects;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.Atmos.Piping namespace Content.Client.Atmos.Visualizers
{ {
[UsedImplicitly] [UsedImplicitly]
public abstract class EnabledAtmosDeviceVisualizer : AppearanceVisualizer public abstract class EnabledAtmosDeviceVisualizer : AppearanceVisualizer

View File

@@ -2,7 +2,7 @@ using System;
using Content.Shared.Atmos.Piping; using Content.Shared.Atmos.Piping;
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Content.Client.Atmos.Piping namespace Content.Client.Atmos.Visualizers
{ {
[UsedImplicitly] [UsedImplicitly]
public class OutletInjectorVisualizer : EnabledAtmosDeviceVisualizer public class OutletInjectorVisualizer : EnabledAtmosDeviceVisualizer

View File

@@ -2,7 +2,7 @@ using System;
using Content.Shared.Atmos.Piping; using Content.Shared.Atmos.Piping;
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Content.Client.Atmos.Piping namespace Content.Client.Atmos.Visualizers
{ {
[UsedImplicitly] [UsedImplicitly]
public class PassiveVentVisualizer : EnabledAtmosDeviceVisualizer public class PassiveVentVisualizer : EnabledAtmosDeviceVisualizer

View File

@@ -0,0 +1,30 @@
using Content.Shared.Atmos.Piping;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
namespace Content.Client.Atmos.Visualizers
{
[UsedImplicitly]
public class PipeColorVisualizer : AppearanceVisualizer
{
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (!component.Owner.TryGetComponent(out SpriteComponent? sprite))
return;
if (component.TryGetData(PipeColorVisuals.Color, out Color color))
{
sprite.LayerSetColor(Layers.Pipe, color);
}
}
public enum Layers : byte
{
Pipe,
}
}
}

View File

@@ -1,6 +1,6 @@
#nullable enable
using System; using System;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Atmos.Piping;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Client.Graphics; using Robust.Client.Graphics;
@@ -8,16 +8,17 @@ using Robust.Client.ResourceManagement;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Log; using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.Atmos.Piping namespace Content.Client.Atmos.Visualizers
{ {
[UsedImplicitly] [UsedImplicitly]
public class PipeConnectorVisualizer : AppearanceVisualizer, ISerializationHooks public class PipeConnectorVisualizer : AppearanceVisualizer, ISerializationHooks
{ {
[DataField("rsi")] [DataField("rsi")]
private string _rsi = "Constructible/Atmos/pipe.rsi"; private string _rsi = "Structures/Piping/Atmospherics/pipe.rsi";
[DataField("baseState")] [DataField("baseState")]
private string _baseState = "pipeConnector"; private string _baseState = "pipeConnector";
@@ -62,6 +63,9 @@ namespace Content.Client.Atmos.Piping
if (!component.Owner.TryGetComponent<ISpriteComponent>(out var sprite)) if (!component.Owner.TryGetComponent<ISpriteComponent>(out var sprite))
return; return;
if (!component.TryGetData(PipeColorVisuals.Color, out Color color))
color = Color.White;
if (!component.TryGetData(PipeVisuals.VisualState, out PipeVisualState state)) if (!component.TryGetData(PipeVisuals.VisualState, out PipeVisualState state))
return; return;
@@ -72,6 +76,7 @@ namespace Content.Client.Atmos.Piping
var layer = sprite.LayerMapGet(layerKey); var layer = sprite.LayerMapGet(layerKey);
sprite.LayerSetVisible(layer, layerVisible); sprite.LayerSetVisible(layer, layerVisible);
sprite.LayerSetColor(layer, color);
} }
} }

View File

@@ -2,7 +2,7 @@ using System;
using Content.Shared.Atmos.Piping; using Content.Shared.Atmos.Piping;
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Content.Client.Atmos.Piping namespace Content.Client.Atmos.Visualizers
{ {
[UsedImplicitly] [UsedImplicitly]
public class PressurePumpVisualizer : EnabledAtmosDeviceVisualizer public class PressurePumpVisualizer : EnabledAtmosDeviceVisualizer

View File

@@ -1,9 +1,8 @@
using Content.Shared.Atmos.Piping.Unary.Visuals; using Content.Shared.Atmos.Piping.Unary.Visuals;
using Content.Shared.Atmos.Visuals;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
namespace Content.Client.Atmos.Piping namespace Content.Client.Atmos.Visualizers
{ {
[UsedImplicitly] [UsedImplicitly]
public class ScrubberVisualizer : AppearanceVisualizer public class ScrubberVisualizer : AppearanceVisualizer

View File

@@ -2,7 +2,7 @@ using System;
using Content.Shared.Atmos.Piping; using Content.Shared.Atmos.Piping;
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Content.Client.Atmos.Piping namespace Content.Client.Atmos.Visualizers
{ {
[UsedImplicitly] [UsedImplicitly]
public class ThermoMachineVisualizer : EnabledAtmosDeviceVisualizer public class ThermoMachineVisualizer : EnabledAtmosDeviceVisualizer

View File

@@ -2,7 +2,7 @@ using Content.Shared.Atmos.Visuals;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
namespace Content.Client.Atmos.Piping namespace Content.Client.Atmos.Visualizers
{ {
[UsedImplicitly] [UsedImplicitly]
public class VentPumpVisualizer : AppearanceVisualizer public class VentPumpVisualizer : AppearanceVisualizer

View File

@@ -1,4 +1,3 @@
#nullable enable
using Content.Client.GameTicking.Managers; using Content.Client.GameTicking.Managers;
using Content.Client.Lobby; using Content.Client.Lobby;
using Content.Client.Viewport; using Content.Client.Viewport;

View File

@@ -8,6 +8,7 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using static Robust.Client.UserInterface.Controls.BoxContainer;
using static Robust.Client.UserInterface.Controls.ItemList; using static Robust.Client.UserInterface.Controls.ItemList;
namespace Content.Client.Body.UI namespace Content.Client.Body.UI
@@ -25,8 +26,9 @@ namespace Content.Client.Body.UI
Owner = owner; Owner = owner;
Title = Loc.GetString("body-scanner-display-title"); Title = Loc.GetString("body-scanner-display-title");
var hSplit = new HBoxContainer var hSplit = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
// Left half // Left half
@@ -39,20 +41,23 @@ namespace Content.Client.Body.UI
} }
}, },
// Right half // Right half
new VBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true, HorizontalExpand = true,
Children = Children =
{ {
// Top half of the right half // Top half of the right half
new VBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
VerticalExpand = true, VerticalExpand = true,
Children = Children =
{ {
(BodyPartLabel = new Label()), (BodyPartLabel = new Label()),
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label new Label

View File

@@ -5,6 +5,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Body.UI namespace Content.Client.Body.UI
{ {
@@ -12,7 +13,7 @@ namespace Content.Client.Body.UI
{ {
public delegate void OptionSelectedCallback(int selectedOptionData); public delegate void OptionSelectedCallback(int selectedOptionData);
private readonly VBoxContainer _optionsBox; private readonly BoxContainer _optionsBox;
private OptionSelectedCallback? _optionSelectedCallback; private OptionSelectedCallback? _optionSelectedCallback;
public SurgeryWindow() public SurgeryWindow()
@@ -21,8 +22,9 @@ namespace Content.Client.Body.UI
Title = Loc.GetString("surgery-window-title"); Title = Loc.GetString("surgery-window-title");
RectClipContent = true; RectClipContent = true;
var vSplitContainer = new VBoxContainer var vSplitContainer = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
new ScrollContainer new ScrollContainer
@@ -33,8 +35,9 @@ namespace Content.Client.Body.UI
VScrollEnabled = true, VScrollEnabled = true,
Children = Children =
{ {
(_optionsBox = new VBoxContainer (_optionsBox = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true HorizontalExpand = true
}) })
} }
@@ -94,8 +97,9 @@ namespace Content.Client.Body.UI
AddChild(Button); AddChild(Button);
AddChild(new HBoxContainer AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
(SpriteView = new SpriteView (SpriteView = new SpriteView

View File

@@ -22,7 +22,7 @@ namespace Content.Client.Botany
sprite.LayerMapReserveBlank(PlantHolderLayers.AlertLight); sprite.LayerMapReserveBlank(PlantHolderLayers.AlertLight);
sprite.LayerMapReserveBlank(PlantHolderLayers.HarvestLight); sprite.LayerMapReserveBlank(PlantHolderLayers.HarvestLight);
var hydroTools = new ResourcePath("Constructible/Hydroponics/overlays.rsi"); var hydroTools = new ResourcePath("Structures/Hydroponics/overlays.rsi");
sprite.LayerSetSprite(PlantHolderLayers.HealthLight, sprite.LayerSetSprite(PlantHolderLayers.HealthLight,
new SpriteSpecifier.Rsi(hydroTools, "lowhealth3")); new SpriteSpecifier.Rsi(hydroTools, "lowhealth3"));

View File

@@ -1,5 +1,4 @@
#nullable enable using Content.Shared.Buckle.Components;
using Content.Shared.Buckle.Components;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;

View File

@@ -1,4 +1,3 @@
#nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Content.Client.Stylesheets; using Content.Client.Stylesheets;
@@ -11,6 +10,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using static Robust.Client.UserInterface.Controls.BaseButton; using static Robust.Client.UserInterface.Controls.BaseButton;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Cargo.UI namespace Content.Client.Cargo.UI
{ {
@@ -28,12 +28,12 @@ namespace Content.Client.Cargo.UI
private Label _pointsLabel { get; set; } private Label _pointsLabel { get; set; }
private Label _shuttleStatusLabel { get; set; } private Label _shuttleStatusLabel { get; set; }
private Label _shuttleCapacityLabel { get; set; } private Label _shuttleCapacityLabel { get; set; }
private VBoxContainer _requests { get; set; } private BoxContainer _requests { get; set; }
private VBoxContainer _orders { get; set; } private BoxContainer _orders { get; set; }
private OptionButton _categories { get; set; } private OptionButton _categories { get; set; }
private LineEdit _searchBar { get; set; } private LineEdit _searchBar { get; set; }
public VBoxContainer Products { get; set; } public BoxContainer Products { get; set; }
public Button CallShuttleButton { get; set; } public Button CallShuttleButton { get; set; }
public Button PermissionsButton { get; set; } public Button PermissionsButton { get; set; }
@@ -50,9 +50,15 @@ namespace Content.Client.Cargo.UI
else else
Title = Loc.GetString("cargo-console-menu-title"); 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 { var accountNameLabel = new Label {
Text = Loc.GetString("cargo-console-menu-account-name-label") + " ", Text = Loc.GetString("cargo-console-menu-account-name-label") + " ",
StyleClasses = { StyleNano.StyleClassLabelKeyText } StyleClasses = { StyleNano.StyleClassLabelKeyText }
@@ -64,7 +70,10 @@ namespace Content.Client.Cargo.UI
accountName.AddChild(_accountNameLabel); accountName.AddChild(_accountNameLabel);
rows.AddChild(accountName); rows.AddChild(accountName);
var points = new HBoxContainer(); var points = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
var pointsLabel = new Label var pointsLabel = new Label
{ {
Text = Loc.GetString("cargo-console-menu-points-label") + " ", Text = Loc.GetString("cargo-console-menu-points-label") + " ",
@@ -78,7 +87,10 @@ namespace Content.Client.Cargo.UI
points.AddChild(_pointsLabel); points.AddChild(_pointsLabel);
rows.AddChild(points); rows.AddChild(points);
var shuttleStatus = new HBoxContainer(); var shuttleStatus = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
var shuttleStatusLabel = new Label var shuttleStatusLabel = new Label
{ {
Text = Loc.GetString("cargo-console-menu-shuttle-status-label") + " ", Text = Loc.GetString("cargo-console-menu-shuttle-status-label") + " ",
@@ -92,7 +104,10 @@ namespace Content.Client.Cargo.UI
shuttleStatus.AddChild(_shuttleStatusLabel); shuttleStatus.AddChild(_shuttleStatusLabel);
rows.AddChild(shuttleStatus); rows.AddChild(shuttleStatus);
var shuttleCapacity = new HBoxContainer(); var shuttleCapacity = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
var shuttleCapacityLabel = new Label var shuttleCapacityLabel = new Label
{ {
Text = Loc.GetString("cargo-console-menu-order-capacity-label") + " ", Text = Loc.GetString("cargo-console-menu-order-capacity-label") + " ",
@@ -106,7 +121,10 @@ namespace Content.Client.Cargo.UI
shuttleCapacity.AddChild(_shuttleCapacityLabel); shuttleCapacity.AddChild(_shuttleCapacityLabel);
rows.AddChild(shuttleCapacity); rows.AddChild(shuttleCapacity);
var buttons = new HBoxContainer(); var buttons = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
CallShuttleButton = new Button() CallShuttleButton = new Button()
{ {
//Text = Loc.GetString("Call Shuttle"), //Text = Loc.GetString("Call Shuttle"),
@@ -123,7 +141,10 @@ namespace Content.Client.Cargo.UI
buttons.AddChild(PermissionsButton); buttons.AddChild(PermissionsButton);
rows.AddChild(buttons); rows.AddChild(buttons);
var category = new HBoxContainer(); var category = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
_categories = new OptionButton _categories = new OptionButton
{ {
Prefix = Loc.GetString("cargo-console-menu-categories-label") + " ", Prefix = Loc.GetString("cargo-console-menu-categories-label") + " ",
@@ -146,8 +167,9 @@ namespace Content.Client.Cargo.UI
VerticalExpand = true, VerticalExpand = true,
SizeFlagsStretchRatio = 6 SizeFlagsStretchRatio = 6
}; };
Products = new VBoxContainer() Products = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true, HorizontalExpand = true,
VerticalExpand = true VerticalExpand = true
}; };
@@ -164,17 +186,22 @@ namespace Content.Client.Cargo.UI
{ {
VerticalExpand = true VerticalExpand = true
}; };
var rAndOVBox = new VBoxContainer(); var rAndOVBox = new BoxContainer
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
{ {
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" }, StyleClasses = { "transparentItemList" },
VerticalExpand = true, VerticalExpand = true,
SizeFlagsStretchRatio = 1, SizeFlagsStretchRatio = 1,
}; };
var ordersLabel = new Label { Text = Loc.GetString("cargo-console-menu-orders-label") }; var ordersLabel = new Label { Text = Loc.GetString("cargo-console-menu-orders-label") };
_orders = new VBoxContainer _orders = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
StyleClasses = { "transparentItemList" }, StyleClasses = { "transparentItemList" },
VerticalExpand = true, VerticalExpand = true,
SizeFlagsStretchRatio = 1, SizeFlagsStretchRatio = 1,
@@ -386,8 +413,9 @@ namespace Content.Client.Cargo.UI
}; };
AddChild(MainButton); AddChild(MainButton);
var hBox = new HBoxContainer var hBox = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true HorizontalExpand = true
}; };
@@ -433,8 +461,9 @@ namespace Content.Client.Cargo.UI
{ {
HorizontalExpand = true; HorizontalExpand = true;
var hBox = new HBoxContainer var hBox = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true, HorizontalExpand = true,
}; };
@@ -445,8 +474,9 @@ namespace Content.Client.Cargo.UI
}; };
hBox.AddChild(Icon); hBox.AddChild(Icon);
var vBox = new VBoxContainer var vBox = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true, HorizontalExpand = true,
VerticalExpand = true VerticalExpand = true
}; };

View File

@@ -3,6 +3,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Cargo.UI namespace Content.Client.Cargo.UI
{ {
@@ -19,7 +20,10 @@ namespace Content.Client.Cargo.UI
Title = Loc.GetString("cargo-console-order-menu-title"); 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 gridContainer = new GridContainer { Columns = 2 };
var requesterLabel = new Label { Text = Loc.GetString("cargo-console-order-menu-requester-label") }; var requesterLabel = new Label { Text = Loc.GetString("cargo-console-order-menu-requester-label") };
@@ -27,12 +31,12 @@ namespace Content.Client.Cargo.UI
gridContainer.AddChild(requesterLabel); gridContainer.AddChild(requesterLabel);
gridContainer.AddChild(Requester); gridContainer.AddChild(Requester);
var reasonLabel = new Label { Text = Loc.GetString("cargo-console-order-menu-reason-label:") }; var reasonLabel = new Label { Text = Loc.GetString("cargo-console-order-menu-reason-label") };
Reason = new LineEdit(); Reason = new LineEdit();
gridContainer.AddChild(reasonLabel); gridContainer.AddChild(reasonLabel);
gridContainer.AddChild(Reason); gridContainer.AddChild(Reason);
var amountLabel = new Label { Text = Loc.GetString("cargo-console-order-menu-amount-label:") }; var amountLabel = new Label { Text = Loc.GetString("cargo-console-order-menu-amount-label") };
Amount = new SpinBox Amount = new SpinBox
{ {
HorizontalExpand = true, HorizontalExpand = true,

View File

@@ -13,7 +13,6 @@ using Robust.Shared.Serialization.Markdown;
using Robust.Shared.Serialization.Markdown.Mapping; using Robust.Shared.Serialization.Markdown.Mapping;
using Robust.Shared.Utility; using Robust.Shared.Utility;
#nullable enable
namespace Content.Client.Changelog namespace Content.Client.Changelog
{ {

View File

@@ -3,20 +3,20 @@
xmlns:ui="clr-namespace:Content.Client.HUD.UI" xmlns:ui="clr-namespace:Content.Client.HUD.UI"
MinSize="500 400" MouseFilter="Stop"> MinSize="500 400" MouseFilter="Stop">
<PanelContainer StyleClasses="AngleRect" /> <PanelContainer StyleClasses="AngleRect" />
<VBoxContainer> <BoxContainer Orientation="Vertical">
<HBoxContainer> <BoxContainer Orientation="Horizontal">
<Label Margin="6 0 0 0" HorizontalExpand="True" Text="{Loc 'changelog-window-title'}" VAlign="Center" <Label Margin="6 0 0 0" HorizontalExpand="True" Text="{Loc 'changelog-window-title'}" VAlign="Center"
StyleClasses="LabelHeading" /> StyleClasses="LabelHeading" />
<TextureButton Margin="0 0 8 0" Name="CloseButton" StyleClasses="windowCloseButton" <TextureButton Margin="0 0 8 0" Name="CloseButton" StyleClasses="windowCloseButton"
VerticalAlignment="Center" /> VerticalAlignment="Center" />
</HBoxContainer> </BoxContainer>
<ui:HighDivider /> <ui:HighDivider />
<ScrollContainer VerticalExpand="True" HScrollEnabled="False"> <ScrollContainer VerticalExpand="True" HScrollEnabled="False">
<VBoxContainer Name="ChangelogBody" /> <BoxContainer Orientation="Vertical" Name="ChangelogBody" />
</ScrollContainer> </ScrollContainer>
<PanelContainer StyleClasses="LowDivider" /> <PanelContainer StyleClasses="LowDivider" />
<Label Name="VersionLabel" HorizontalAlignment="Right" StyleClasses="LabelSubText" Margin="4 0" /> <Label Name="VersionLabel" HorizontalAlignment="Right" StyleClasses="LabelSubText" Margin="4 0" />
</VBoxContainer> </BoxContainer>
</changelog:ChangelogWindow> </changelog:ChangelogWindow>

View File

@@ -15,6 +15,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using static Content.Client.Changelog.ChangelogManager; using static Content.Client.Changelog.ChangelogManager;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Changelog namespace Content.Client.Changelog
{ {
@@ -94,10 +95,14 @@ namespace Content.Client.Changelog
var upArrow = var upArrow =
_resourceCache.GetTexture("/Textures/Interface/Changelog/up_arrow.svg.192dpi.png"); _resourceCache.GetTexture("/Textures/Interface/Changelog/up_arrow.svg.192dpi.png");
var readDivider = new VBoxContainer(); var readDivider = new BoxContainer
var hBox = new HBoxContainer
{ {
Orientation = LayoutOrientation.Vertical
};
var hBox = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal,
HorizontalAlignment = HAlignment.Center, HorizontalAlignment = HAlignment.Center,
Children = Children =
{ {
@@ -148,8 +153,9 @@ namespace Content.Client.Changelog
{ {
var text = new RichTextLabel(); var text = new RichTextLabel();
text.SetMessage(FormattedMessage.FromMarkup(change.Message)); text.SetMessage(FormattedMessage.FromMarkup(change.Message));
ChangelogBody.AddChild(new HBoxContainer ChangelogBody.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Margin = new Thickness(14, 1, 10, 2), Margin = new Thickness(14, 1, 10, 2),
Children = Children =
{ {

View File

@@ -13,6 +13,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using static Content.Shared.CharacterAppearance.Components.SharedMagicMirrorComponent; using static Content.Shared.CharacterAppearance.Components.SharedMagicMirrorComponent;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.CharacterAppearance namespace Content.Client.CharacterAppearance
{ {
@@ -107,8 +108,9 @@ namespace Content.Client.CharacterAppearance
MinSize = (50, 0) MinSize = (50, 0)
}; };
AddChild(new HBoxContainer AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
_slider, _slider,
@@ -204,10 +206,16 @@ namespace Content.Client.CharacterAppearance
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
var vBox = new VBoxContainer(); var vBox = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
};
AddChild(vBox); AddChild(vBox);
_colorContainer = new VBoxContainer(); _colorContainer = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
};
vBox.AddChild(_colorContainer); vBox.AddChild(_colorContainer);
_colorContainer.AddChild(_colorSliderR = new ColorSlider(StyleNano.StyleClassSliderRed)); _colorContainer.AddChild(_colorSliderR = new ColorSlider(StyleNano.StyleClassSliderRed));
_colorContainer.AddChild(_colorSliderG = new ColorSlider(StyleNano.StyleClassSliderGreen)); _colorContainer.AddChild(_colorSliderG = new ColorSlider(StyleNano.StyleClassSliderGreen));
@@ -289,7 +297,10 @@ namespace Content.Client.CharacterAppearance
public EyeColorPicker() public EyeColorPicker()
{ {
var vBox = new VBoxContainer(); var vBox = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
};
AddChild(vBox); AddChild(vBox);
vBox.AddChild(_colorSliderR = new ColorSlider(StyleNano.StyleClassSliderRed)); vBox.AddChild(_colorSliderR = new ColorSlider(StyleNano.StyleClassSliderRed));
@@ -340,8 +351,9 @@ namespace Content.Client.CharacterAppearance
_eyeColorPicker = new EyeColorPicker {SizeFlagsHorizontal = SizeFlags.FillExpand}; _eyeColorPicker = new EyeColorPicker {SizeFlagsHorizontal = SizeFlags.FillExpand};
_eyeColorPicker.OnEyeColorPicked += newColor => owner.EyeColorSelected(newColor); _eyeColorPicker.OnEyeColorPicked += newColor => owner.EyeColorSelected(newColor);
Contents.AddChild(new HBoxContainer Contents.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 8, SeparationOverride = 8,
Children = {_hairStylePicker, _facialHairStylePicker, _eyeColorPicker} Children = {_hairStylePicker, _facialHairStylePicker, _eyeColorPicker}
}); });

View File

@@ -62,19 +62,21 @@ namespace Content.Client.CharacterInfo.Components
public Label NameLabel { get; } public Label NameLabel { get; }
public Label SubText { get; } public Label SubText { get; }
public VBoxContainer ObjectivesContainer { get; } public BoxContainer ObjectivesContainer { get; }
public CharacterInfoControl(IResourceCache resourceCache) public CharacterInfoControl(IResourceCache resourceCache)
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
AddChild(new HBoxContainer AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
(SpriteView = new SpriteView { Scale = (2, 2)}), (SpriteView = new SpriteView { Scale = (2, 2)}),
new VBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
VerticalAlignment = VAlignment.Top, VerticalAlignment = VAlignment.Top,
Children = Children =
{ {
@@ -100,7 +102,10 @@ namespace Content.Client.CharacterInfo.Components
Text = Loc.GetString("character-info-objectives-label"), Text = Loc.GetString("character-info-objectives-label"),
HorizontalAlignment = HAlignment.Center HorizontalAlignment = HAlignment.Center
}); });
ObjectivesContainer = new VBoxContainer(); ObjectivesContainer = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
};
AddChild(ObjectivesContainer); AddChild(ObjectivesContainer);
AddChild(new Placeholder() AddChild(new Placeholder()
@@ -116,8 +121,9 @@ namespace Content.Client.CharacterInfo.Components
ObjectivesContainer.RemoveAllChildren(); ObjectivesContainer.RemoveAllChildren();
foreach (var (groupId, objectiveConditions) in characterInfoMessage.Objectives) foreach (var (groupId, objectiveConditions) in characterInfoMessage.Objectives)
{ {
var vbox = new VBoxContainer var vbox = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Modulate = Color.Gray Modulate = Color.Gray
}; };
@@ -129,7 +135,10 @@ namespace Content.Client.CharacterInfo.Components
foreach (var objectiveCondition in objectiveConditions) foreach (var objectiveCondition in objectiveConditions)
{ {
var hbox = new HBoxContainer(); var hbox = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
hbox.AddChild(new ProgressTextureRect hbox.AddChild(new ProgressTextureRect
{ {
Texture = objectiveCondition.SpriteSpecifier.Frame0(), Texture = objectiveCondition.SpriteSpecifier.Frame0(),
@@ -140,8 +149,9 @@ namespace Content.Client.CharacterInfo.Components
{ {
MinSize = (10,0) MinSize = (10,0)
}); });
hbox.AddChild(new VBoxContainer hbox.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
new Label{Text = objectiveCondition.Title}, new Label{Text = objectiveCondition.Title},

View File

@@ -9,6 +9,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.CharacterInterface namespace Content.Client.CharacterInterface
{ {
@@ -110,14 +111,17 @@ namespace Content.Client.CharacterInterface
/// </summary> /// </summary>
public class CharacterWindow : SS14Window public class CharacterWindow : SS14Window
{ {
private readonly VBoxContainer _contentsVBox; private readonly BoxContainer _contentsVBox;
private readonly List<ICharacterUI> _windowComponents; private readonly List<ICharacterUI> _windowComponents;
public CharacterWindow(List<ICharacterUI> windowComponents) public CharacterWindow(List<ICharacterUI> windowComponents)
{ {
Title = "Character"; Title = "Character";
_contentsVBox = new VBoxContainer(); _contentsVBox = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
};
Contents.AddChild(_contentsVBox); Contents.AddChild(_contentsVBox);
windowComponents.Sort((a, b) => ((int) a.Priority).CompareTo((int) b.Priority)); windowComponents.Sort((a, b) => ((int) a.Priority).CompareTo((int) b.Priority));

View File

@@ -12,7 +12,7 @@ namespace Content.Client.Chat
ChatChannel.Radio => Color.Green, ChatChannel.Radio => Color.Green,
ChatChannel.OOC => Color.LightSkyBlue, ChatChannel.OOC => Color.LightSkyBlue,
ChatChannel.Dead => Color.MediumPurple, ChatChannel.Dead => Color.MediumPurple,
ChatChannel.AdminChat => Color.Red, ChatChannel.Admin => Color.Red,
_ => Color.DarkGray _ => Color.DarkGray
}; };
} }

View File

@@ -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)));
}
}
}

View File

@@ -1,20 +1,21 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Content.Client.Administration.Managers; using Content.Client.Administration.Managers;
using Content.Client.Chat.UI; using Content.Client.Chat.UI;
using Content.Client.Ghost; using Content.Client.Ghost;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.CCVar;
using Content.Shared.Chat; using Content.Shared.Chat;
using Robust.Client.Console; using Robust.Client.Console;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.Player; using Robust.Client.Player;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Log; using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Network; using Robust.Shared.Network;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -52,23 +53,17 @@ namespace Content.Client.Chat.Managers
/// <summary> /// <summary>
/// The max amount of characters an entity can send in one message /// The max amount of characters an entity can send in one message
/// </summary> /// </summary>
private int _maxMessageLength = 1000; public int MaxMessageLength => _cfg.GetCVar(CCVars.ChatMaxMessageLength);
public const char ConCmdSlash = '/'; private readonly List<StoredChatMessage> _history = new();
public const char OOCAlias = '['; public IReadOnlyList<StoredChatMessage> History => _history;
public const char MeAlias = '@';
public const char AdminChatAlias = ']';
public const char RadioAlias = ';';
private readonly List<StoredChatMessage> _filteredHistory = new(); // currently enabled channel filters set by the user.
// All values default to on, even if they aren't a filterable chat channel currently.
// 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)
// Note that these are persisted here, at the manager, // Note that these are persisted here, at the manager,
// rather than the chatbox so that these settings persist between instances of different // rather than the chatbox so that these settings persist between instances of different
// chatboxes. // chatboxes.
public readonly Dictionary<ChatChannel, bool> _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) // Maintains which channels a client should be able to filter (for showing in the chatbox)
// and select (for attempting to send on). // 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, // Note that Command is an available selection in the chatbox channel selector,
// which is not actually a chat channel but is always available. // which is not actually a chat channel but is always available.
private readonly HashSet<ChatChannel> _filterableChannels = new(); public ChatSelectChannel SelectableChannels { get; private set; }
private readonly List<ChatChannel> _selectableChannels = new(); public ChatChannel FilterableChannels { get; private set; }
// Flag Enums for holding filtered channels
private ChatChannel _filteredChannels;
/// <summary> /// <summary>
/// For currently disabled chat filters, /// For currently disabled chat filters,
/// unread messages (messages received since the channel has been filtered /// unread messages (messages received since the channel has been filtered out).
/// out). Never goes above 10 (9+ should be shown when at 10)
/// </summary> /// </summary>
private readonly Dictionary<ChatChannel, byte> _unreadMessages = new(); private readonly Dictionary<ChatChannel, int> _unreadMessages = new();
public IReadOnlyDictionary<ChatChannel, int> UnreadMessages => _unreadMessages;
[Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IClientNetManager _netManager = 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 IEyeManager _eyeManager = default!;
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
[Dependency] private readonly IClientAdminManager _adminMgr = default!; [Dependency] private readonly IClientAdminManager _adminMgr = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
/// <summary> /// <summary>
/// Current chat box control. This can be modified, so do not depend on saving a reference to this. /// Current chat box control. This can be modified, so do not depend on saving a reference to this.
/// </summary> /// </summary>
public ChatBox? CurrentChatBox { get; private set; } public ChatBox? CurrentChatBox { get; private set; }
/// <summary> /// <summary>
/// Invoked when CurrentChatBox is resized (including after setting initial default size) /// Invoked when CurrentChatBox is resized (including after setting initial default size)
/// </summary> /// </summary>
public event Action<ChatResizedEventArgs>? OnChatBoxResized; public event Action<ChatResizedEventArgs>? OnChatBoxResized;
public event Action<ChatPermissionsUpdatedEventArgs>? ChatPermissionsUpdated;
public event Action? UnreadMessageCountsUpdated;
public event Action<StoredChatMessage>? MessageAdded;
public event Action? FiltersUpdated;
private Control _speechBubbleRoot = null!; private Control _speechBubbleRoot = null!;
/// <summary> /// <summary>
@@ -128,15 +128,11 @@ namespace Content.Client.Chat.Managers
public void Initialize() public void Initialize()
{ {
_netManager.RegisterNetMessage<MsgChatMessage>(OnChatMessage); _netManager.RegisterNetMessage<MsgChatMessage>(OnChatMessage);
_netManager.RegisterNetMessage<ChatMaxMsgLengthMessage>(OnMaxLengthReceived);
_speechBubbleRoot = new LayoutContainer(); _speechBubbleRoot = new LayoutContainer();
LayoutContainer.SetAnchorPreset(_speechBubbleRoot, LayoutContainer.LayoutPreset.Wide); LayoutContainer.SetAnchorPreset(_speechBubbleRoot, LayoutContainer.LayoutPreset.Wide);
_userInterfaceManager.StateRoot.AddChild(_speechBubbleRoot); _userInterfaceManager.StateRoot.AddChild(_speechBubbleRoot);
_speechBubbleRoot.SetPositionFirst(); _speechBubbleRoot.SetPositionFirst();
// When connexion is achieved, request the max chat message length
_netManager.Connected += RequestMaxLength;
} }
public void PostInject() public void PostInject()
@@ -178,83 +174,58 @@ namespace Content.Client.Chat.Managers
// for any newly-granted channels // for any newly-granted channels
private void UpdateChannelPermissions() private void UpdateChannelPermissions()
{ {
var oldSelectable = SelectableChannels;
SelectableChannels = default;
FilterableChannels = default;
// Can always send console stuff.
SelectableChannels |= ChatSelectChannel.Console;
// can always send/recieve OOC // can always send/recieve OOC
if (!_selectableChannels.Contains(ChatChannel.OOC)) SelectableChannels |= ChatSelectChannel.OOC;
{ FilterableChannels |= ChatChannel.OOC;
_selectableChannels.Add(ChatChannel.OOC);
}
AddFilterableChannel(ChatChannel.OOC);
// can always hear server (nobody can actually send server messages). // can always hear server (nobody can actually send server messages).
AddFilterableChannel(ChatChannel.Server); FilterableChannels |= ChatChannel.Server;
// can always hear local / radio / emote // can always hear local / radio / emote
AddFilterableChannel(ChatChannel.Local); // todo: this makes no sense the lobby exists fix this.
AddFilterableChannel(ChatChannel.Radio); FilterableChannels |= ChatChannel.Local;
AddFilterableChannel(ChatChannel.Emotes); FilterableChannels |= ChatChannel.Radio;
FilterableChannels |= ChatChannel.Emotes;
// Can only send local / radio / emote when attached to a non-ghost entity. // 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? // 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<GhostComponent>() ?? false) if (!IsGhost)
{ {
_selectableChannels.Add(ChatChannel.Local); SelectableChannels |= ChatSelectChannel.Local;
_selectableChannels.Add(ChatChannel.Radio); SelectableChannels |= ChatSelectChannel.Radio;
_selectableChannels.Add(ChatChannel.Emotes); SelectableChannels |= ChatSelectChannel.Emotes;
}
else
{
_selectableChannels.Remove(ChatChannel.Local);
_selectableChannels.Remove(ChatChannel.Radio);
_selectableChannels.Remove(ChatChannel.Emotes);
} }
// Only ghosts and admins can send / see deadchat. // Only ghosts and admins can send / see deadchat.
// TODO: Should spectators also be able to see deadchat? if (_adminMgr.HasFlag(AdminFlags.Admin) || IsGhost)
if (_adminMgr.HasFlag(AdminFlags.Admin) ||
(_playerManager?.LocalPlayer?.ControlledEntity?.HasComponent<GhostComponent>() ?? false))
{ {
AddFilterableChannel(ChatChannel.Dead); FilterableChannels |= ChatChannel.Dead;
if (!_selectableChannels.Contains(ChatChannel.Dead)) SelectableChannels |= ChatSelectChannel.Dead;
{
_selectableChannels.Add(ChatChannel.Dead);
}
}
else
{
_filterableChannels.Remove(ChatChannel.Dead);
_selectableChannels.Remove(ChatChannel.Dead);
} }
// only admins can see / filter asay // only admins can see / filter asay
if (_adminMgr.HasFlag(AdminFlags.Admin)) if (_adminMgr.HasFlag(AdminFlags.Admin))
{ {
AddFilterableChannel(ChatChannel.AdminChat); FilterableChannels |= ChatChannel.Admin;
if (!_selectableChannels.Contains(ChatChannel.AdminChat)) SelectableChannels |= ChatSelectChannel.Admin;
{
_selectableChannels.Add(ChatChannel.AdminChat);
}
}
else
{
_selectableChannels.Remove(ChatChannel.AdminChat);
_filterableChannels.Remove(ChatChannel.AdminChat);
} }
// 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 // let our chatbox know all the new settings
CurrentChatBox?.SetChannelPermissions(_selectableChannels, _filterableChannels, _channelFilters, _unreadMessages, true); ChatPermissionsUpdated?.Invoke(new ChatPermissionsUpdatedEventArgs {OldSelectableChannels = oldSelectable});
}
/// <summary>
/// Adds the channel to the set of filterable channels, defaulting it as enabled
/// if it doesn't currently have an explicit enable/disable setting
/// </summary>
private void AddFilterableChannel(ChatChannel channel)
{
if (!_channelFilters.ContainsKey(channel))
_channelFilters[channel] = true;
_filterableChannels.Add(channel);
} }
public bool IsGhost => _playerManager.LocalPlayer?.ControlledEntity?.HasComponent<GhostComponent>() ?? false;
public void FrameUpdate(FrameEventArgs delta) public void FrameUpdate(FrameEventArgs delta)
{ {
@@ -296,27 +267,19 @@ namespace Content.Client.Chat.Managers
public void SetChatBox(ChatBox chatBox) public void SetChatBox(ChatBox chatBox)
{ {
if (CurrentChatBox != null)
{
CurrentChatBox.TextSubmitted -= OnChatBoxTextSubmitted;
CurrentChatBox.FilterToggled -= OnFilterButtonToggled;
CurrentChatBox.OnResized -= ChatBoxOnResized;
}
CurrentChatBox = chatBox; 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); OnChatBoxResized?.Invoke(chatResizedEventArgs);
} }
@@ -334,158 +297,86 @@ namespace Content.Client.Chat.Managers
} }
} }
private void WriteChatMessage(StoredChatMessage message) public void OnChatBoxTextSubmitted(ChatBox chatBox, ReadOnlyMemory<char> text, ChatSelectChannel channel)
{
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)
{ {
DebugTools.Assert(chatBox == CurrentChatBox); DebugTools.Assert(chatBox == CurrentChatBox);
if (string.IsNullOrWhiteSpace(text)) var str = text.ToString();
return;
// Check if message is longer than the character limit switch (channel)
if (text.Length > _maxMessageLength)
{ {
if (CurrentChatBox != null) case ChatSelectChannel.Console:
{
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:
{
// run locally // run locally
var conInput = text.Substring(1); _consoleHost.ExecuteCommand(text.ToString());
_consoleHost.ExecuteCommand(conInput);
break; 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; break;
}
case MeAlias: case ChatSelectChannel.Admin:
{ _consoleHost.ExecuteCommand($"asay \"{CommandParsing.Escape(str)}\"");
var conInput = text.Substring(1);
if (string.IsNullOrWhiteSpace(conInput))
return;
_consoleHost.ExecuteCommand($"me \"{CommandParsing.Escape(conInput)}\"");
break; 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: default:
{ throw new ArgumentOutOfRangeException(nameof(channel), channel, null);
var conInput = CurrentChatBox?.DefaultChatFormat != null
? string.Format(CurrentChatBox.DefaultChatFormat, CommandParsing.Escape(text))
: text;
_consoleHost.ExecuteCommand(conInput);
break;
}
} }
} }
private void OnFilterButtonToggled(ChatChannel channel, bool enabled) public void OnFilterButtonToggled(ChatChannel channel, bool enabled)
{ {
if (enabled) if (enabled)
{ {
_channelFilters[channel] = true; ChannelFilters |= channel;
_filteredChannels &= ~channel;
_unreadMessages.Remove(channel); _unreadMessages.Remove(channel);
CurrentChatBox?.UpdateUnreadMessageCounts(_unreadMessages); UnreadMessageCountsUpdated?.Invoke();
} }
else else
{ {
_channelFilters[channel] = false; ChannelFilters &= ~channel;
_filteredChannels |= channel;
} }
RepopulateChat(_filteredHistory); FiltersUpdated?.Invoke();
}
private void RepopulateChat(IEnumerable<StoredChatMessage> filteredMessages)
{
if (CurrentChatBox == null)
{
return;
}
CurrentChatBox.Contents.Clear();
foreach (var msg in filteredMessages)
{
WriteChatMessage(msg);
}
} }
private void OnChatMessage(MsgChatMessage msg) private void OnChatMessage(MsgChatMessage msg)
{ {
// Log all incoming chat to repopulate when filter is un-toggled // Log all incoming chat to repopulate when filter is un-toggled
var storedMessage = new StoredChatMessage(msg); var storedMessage = new StoredChatMessage(msg);
_filteredHistory.Add(storedMessage); _history.Add(storedMessage);
WriteChatMessage(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. // Local messages that have an entity attached get a speech bubble.
if (msg.SenderEntity == default) if (msg.SenderEntity == default)
@@ -498,7 +389,7 @@ namespace Content.Client.Chat.Managers
break; break;
case ChatChannel.Dead: case ChatChannel.Dead:
if (!_playerManager.LocalPlayer?.ControlledEntity?.HasComponent<GhostComponent>() ?? true) if (!IsGhost)
break; break;
AddSpeechBubble(msg, SpeechBubble.SpeechType.Say); 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<ChatMaxMsgLengthMessage>();
_netManager.ClientSendMessage(msg);
}
private void AddSpeechBubble(MsgChatMessage msg, SpeechBubble.SpeechType speechType) private void AddSpeechBubble(MsgChatMessage msg, SpeechBubble.SpeechType speechType)
{ {
if (!_entityManager.TryGetEntity(msg.SenderEntity, out var entity)) if (!_entityManager.TryGetEntity(msg.SenderEntity, out var entity))
@@ -604,7 +484,8 @@ namespace Content.Client.Chat.Managers
private void CreateSpeechBubble(IEntity entity, SpeechBubbleData speechData) 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)) 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 private sealed class SpeechBubbleQueueData
{ {
/// <summary> /// <summary>

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic;
using Content.Client.Chat.UI; using Content.Client.Chat.UI;
using Content.Shared.Chat;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Timing; using Robust.Shared.Timing;
@@ -7,6 +9,10 @@ namespace Content.Client.Chat.Managers
{ {
public interface IChatManager public interface IChatManager
{ {
ChatChannel ChannelFilters { get; }
ChatSelectChannel SelectableChannels { get; }
ChatChannel FilterableChannels { get; }
void Initialize(); void Initialize();
void FrameUpdate(FrameEventArgs delta); void FrameUpdate(FrameEventArgs delta);
@@ -20,9 +26,29 @@ namespace Content.Client.Chat.Managers
/// </summary> /// </summary>
ChatBox? CurrentChatBox { get; } ChatBox? CurrentChatBox { get; }
IReadOnlyDictionary<ChatChannel, int> UnreadMessages { get; }
IReadOnlyList<StoredChatMessage> History { get; }
int MaxMessageLength { get; }
bool IsGhost { get; }
/// <summary> /// <summary>
/// Invoked when CurrentChatBox is resized (including after setting initial default size) /// Invoked when CurrentChatBox is resized (including after setting initial default size)
/// </summary> /// </summary>
event Action<ChatResizedEventArgs>? OnChatBoxResized; event Action<ChatResizedEventArgs>? OnChatBoxResized;
event Action<ChatPermissionsUpdatedEventArgs>? ChatPermissionsUpdated;
event Action? UnreadMessageCountsUpdated;
event Action<StoredChatMessage>? MessageAdded;
event Action? FiltersUpdated;
void ClearUnfilteredUnreads();
void ChatBoxOnResized(ChatResizedEventArgs chatResizedEventArgs);
void OnChatBoxTextSubmitted(ChatBox chatBox, ReadOnlyMemory<char> text, ChatSelectChannel channel);
void OnFilterButtonToggled(ChatChannel channel, bool enabled);
}
public struct ChatPermissionsUpdatedEventArgs
{
public ChatSelectChannel OldSelectableChannels;
} }
} }

View File

@@ -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<ChatResizedEventArgs>? OnResized;
// order in which the available channel filters show up when available
public static readonly IReadOnlyList<ChatChannel> ChannelFilterOrder = new List<ChatChannel>
{
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<ChatChannel> ChannelSelectorOrder = new List<ChatChannel>
{
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;
/// <summary>
/// Will be Unspecified if set to Console
/// </summary>
public ChatChannel SelectedChannel = ChatChannel.Unspecified;
/// <summary>
/// Default formatting string for the ClientChatConsole.
/// </summary>
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<ChatChannel> SelectableChannels = new();
/// <summary>
/// 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.
/// </summary>
public ChatBox()
{
//TODO Paul needs to fix xaml ctor args so we can pass this instead of resolving it.
var stateManager = IoCManager.Resolve<IStateManager>();
_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<IClyde>();
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;
}
}
/// <summary>
/// Update the available filters / selectable channels and the current filter settings using the provided
/// data.
/// </summary>
/// <param name="selectableChannels">channels currently selectable to send on</param>
/// <param name="filterableChannels">channels currently able ot filter on</param>
/// <param name="channelFilters">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)</param>
/// <param name="unreadMessages">unread message counts for each disabled channel, values 10 or higher will show as 9+</param>
public void SetChannelPermissions(List<ChatChannel> selectableChannels, IReadOnlySet<ChatChannel> filterableChannels,
IReadOnlyDictionary<ChatChannel, bool> channelFilters, IReadOnlyDictionary<ChatChannel, byte> 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)});
}
/// <summary>
/// Update the unread message counts in the filters based on the provided data.
/// </summary>
/// <param name="unreadMessages">counts for each channel, any values above 9 will show as 9+</param>
public void UpdateUnreadMessageCounts(IReadOnlyDictionary<ChatChannel, byte> 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();
}
/// <summary>
/// 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.
/// </summary>
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();
}
}
}
/// <summary>
/// Only needed to avoid the issue where right click on the button closes the popup
/// but leaves the button highlighted.
/// </summary>
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<IResourceCache>()
.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;
}
}
}

View File

@@ -0,0 +1,24 @@
<Control xmlns="https://spacestation14.io"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:chatUI="clr-namespace:Content.Client.Chat.UI"
MouseFilter="Stop"
MinSize="200 128">
<PanelContainer>
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#25252AAA" />
</PanelContainer.PanelOverride>
<BoxContainer Orientation="Vertical">
<OutputPanel Name="Contents" VerticalExpand="True" />
<PanelContainer StyleClasses="ChatSubPanel">
<BoxContainer Orientation="Horizontal" SeparationOverride="4">
<chatUI:ChannelSelectorButton Name="ChannelSelector" ToggleMode="True"
StyleClasses="chatSelectorOptionButton" MinWidth="75" />
<HistoryLineEdit Name="Input" PlaceHolder="{Loc 'hud-chatbox-info'}" HorizontalExpand="True"
StyleClasses="chatLineEdit" />
<chatUI:FilterButton Name="FilterButton" StyleClasses="chatFilterOptionButton" />
</BoxContainer>
</PanelContainer>
</BoxContainer>
</PanelContainer>
</Control>

View File

@@ -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<char, ChatSelectChannel> 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<ChatSelectChannel, char> ChannelPrefixes =
PrefixToChannel.ToDictionary(kv => kv.Value, kv => kv.Key);
private const float FilterPopupWidth = 110;
/// <summary>
/// The currently default channel that will be used if no prefix is specified.
/// </summary>
public ChatSelectChannel SelectedChannel { get; private set; } = ChatSelectChannel.OOC;
/// <summary>
/// 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.
/// </summary>
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;
/// <summary>
/// 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.
/// </summary>
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<char> 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;
}
}
/// <summary>
/// Only needed to avoid the issue where right click on the button closes the popup
/// but leaves the button highlighted.
/// </summary>
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<IResourceCache>()
.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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -14,6 +14,7 @@ using Robust.Shared.Maths;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using static Content.Shared.Chemistry.Components.SharedChemMasterComponent; using static Content.Shared.Chemistry.Components.SharedChemMasterComponent;
using static Robust.Client.UserInterface.Controls.BaseButton; using static Robust.Client.UserInterface.Controls.BaseButton;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Chemistry.UI namespace Content.Client.Chemistry.UI
{ {
@@ -25,11 +26,11 @@ namespace Content.Client.Chemistry.UI
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
/// <summary>Contains info about the reagent container such as it's contents, if one is loaded into the dispenser.</summary> /// <summary>Contains info about the reagent container such as it's contents, if one is loaded into the dispenser.</summary>
private readonly VBoxContainer ContainerInfo; private readonly BoxContainer ContainerInfo;
private readonly VBoxContainer BufferInfo; private readonly BoxContainer BufferInfo;
private readonly VBoxContainer PackagingInfo; private readonly BoxContainer PackagingInfo;
/// <summary>Ejects the reagent container from the dispenser.</summary> /// <summary>Ejects the reagent container from the dispenser.</summary>
public Button EjectButton { get; } public Button EjectButton { get; }
@@ -41,8 +42,8 @@ namespace Content.Client.Chemistry.UI
public event Action<ButtonEventArgs, ChemButton>? OnChemButtonPressed; public event Action<ButtonEventArgs, ChemButton>? OnChemButtonPressed;
public HBoxContainer PillInfo { get; set; } public BoxContainer PillInfo { get; set; }
public HBoxContainer BottleInfo { get; set; } public BoxContainer BottleInfo { get; set; }
public SpinBox PillAmount { get; set; } public SpinBox PillAmount { get; set; }
public SpinBox BottleAmount { get; set; } public SpinBox BottleAmount { get; set; }
public Button CreatePills { get; } public Button CreatePills { get; }
@@ -57,13 +58,15 @@ namespace Content.Client.Chemistry.UI
MinSize = SetSize = (400, 525); MinSize = SetSize = (400, 525);
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
Contents.AddChild(new VBoxContainer Contents.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
//Container //Container
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label {Text = Loc.GetString("chem-master-window-container-label")}, new Label {Text = Loc.GetString("chem-master-window-container-label")},
@@ -84,8 +87,9 @@ namespace Content.Client.Chemistry.UI
Children = Children =
{ {
//Currently empty, when server sends state data this will have container contents and fill volume. //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, HorizontalExpand = true,
Children = Children =
{ {
@@ -102,8 +106,9 @@ namespace Content.Client.Chemistry.UI
new Control {MinSize = (0.0f, 10.0f)}, new Control {MinSize = (0.0f, 10.0f)},
//Buffer //Buffer
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label {Text = Loc.GetString("chem-master-window-buffer-text")}, new Label {Text = Loc.GetString("chem-master-window-buffer-text")},
@@ -126,8 +131,9 @@ namespace Content.Client.Chemistry.UI
Children = Children =
{ {
//Buffer reagent list //Buffer reagent list
(BufferInfo = new VBoxContainer (BufferInfo = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true, HorizontalExpand = true,
Children = Children =
{ {
@@ -144,8 +150,9 @@ namespace Content.Client.Chemistry.UI
new Control {MinSize = (0.0f, 10.0f)}, new Control {MinSize = (0.0f, 10.0f)},
//Packaging //Packaging
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label {Text = $"{Loc.GetString("chem-master-window-packaging-text")} "}, new Label {Text = $"{Loc.GetString("chem-master-window-packaging-text")} "},
@@ -165,8 +172,9 @@ namespace Content.Client.Chemistry.UI
Children = Children =
{ {
//Packaging options //Packaging options
(PackagingInfo = new VBoxContainer (PackagingInfo = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true, HorizontalExpand = true,
}), }),
@@ -176,8 +184,9 @@ namespace Content.Client.Chemistry.UI
}); });
//Pills //Pills
PillInfo = new HBoxContainer PillInfo = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label new Label
@@ -213,8 +222,9 @@ namespace Content.Client.Chemistry.UI
PillInfo.AddChild(CreatePills); PillInfo.AddChild(CreatePills);
//Bottles //Bottles
BottleInfo = new HBoxContainer BottleInfo = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label new Label
@@ -315,8 +325,9 @@ namespace Content.Client.Chemistry.UI
return; 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 = Children =
{ {
new Label {Text = $"{state.ContainerName}: "}, new Label {Text = $"{state.ContainerName}: "},
@@ -339,8 +350,9 @@ namespace Content.Client.Chemistry.UI
if (proto != null) if (proto != null)
{ {
ContainerInfo.Children.Add(new HBoxContainer ContainerInfo.Children.Add(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label {Text = $"{name}: "}, new Label {Text = $"{name}: "},
@@ -371,7 +383,10 @@ namespace Content.Client.Chemistry.UI
return; return;
} }
var bufferHBox = new HBoxContainer(); var bufferHBox = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
BufferInfo.AddChild(bufferHBox); BufferInfo.AddChild(bufferHBox);
var bufferLabel = new Label { Text = $"{Loc.GetString("chem-master-window-buffer-label")} " }; var bufferLabel = new Label { Text = $"{Loc.GetString("chem-master-window-buffer-label")} " };
@@ -394,8 +409,9 @@ namespace Content.Client.Chemistry.UI
if (proto != null) if (proto != null)
{ {
BufferInfo.Children.Add(new HBoxContainer BufferInfo.Children.Add(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
//SizeFlagsHorizontal = SizeFlags.ShrinkEnd, //SizeFlagsHorizontal = SizeFlags.ShrinkEnd,
Children = Children =
{ {

View File

@@ -12,6 +12,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using static Content.Shared.Chemistry.Dispenser.SharedReagentDispenserComponent; using static Content.Shared.Chemistry.Dispenser.SharedReagentDispenserComponent;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Chemistry.UI namespace Content.Client.Chemistry.UI
{ {
@@ -23,7 +24,7 @@ namespace Content.Client.Chemistry.UI
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
/// <summary>Contains info about the reagent container such as it's contents, if one is loaded into the dispenser.</summary> /// <summary>Contains info about the reagent container such as it's contents, if one is loaded into the dispenser.</summary>
private readonly VBoxContainer ContainerInfo; private readonly BoxContainer ContainerInfo;
/// <summary>Sets the dispense amount to 1 when pressed.</summary> /// <summary>Sets the dispense amount to 1 when pressed.</summary>
public Button DispenseButton1 { get; } public Button DispenseButton1 { get; }
@@ -72,13 +73,15 @@ namespace Content.Client.Chemistry.UI
var dispenseAmountGroup = new ButtonGroup(); var dispenseAmountGroup = new ButtonGroup();
Contents.AddChild(new VBoxContainer Contents.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
//First, our dispense amount buttons //First, our dispense amount buttons
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label {Text = Loc.GetString("reagent-dispenser-window-amount-to-dispense-label")}, new Label {Text = Loc.GetString("reagent-dispenser-window-amount-to-dispense-label")},
@@ -104,8 +107,9 @@ namespace Content.Client.Chemistry.UI
}), }),
//Padding //Padding
new Control {MinSize = (0.0f, 10.0f)}, new Control {MinSize = (0.0f, 10.0f)},
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label {Text = Loc.GetString("reagent-dispenser-window-container-label") + " "}, new Label {Text = Loc.GetString("reagent-dispenser-window-container-label") + " "},
@@ -126,8 +130,9 @@ namespace Content.Client.Chemistry.UI
Children = Children =
{ {
//Currently empty, when server sends state data this will have container contents and fill volume. //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, HorizontalExpand = true,
Children = Children =
{ {
@@ -263,8 +268,9 @@ namespace Content.Client.Chemistry.UI
return; 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 = Children =
{ {
new Label {Text = $"{state.ContainerName}: "}, 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. //Check if the reagent is being moused over. If so, color it green.
if (proto != null && proto.ID == highlightedReagentId) if (proto != null && proto.ID == highlightedReagentId)
{ {
ContainerInfo.Children.Add(new HBoxContainer ContainerInfo.Children.Add(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label new Label
@@ -312,8 +319,9 @@ namespace Content.Client.Chemistry.UI
} }
else //Otherwise, color it the normal colors. else //Otherwise, color it the normal colors.
{ {
ContainerInfo.Children.Add(new HBoxContainer ContainerInfo.Children.Add(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label {Text = $"{name}: "}, new Label {Text = $"{name}: "},

View File

@@ -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)
{
}
}
}

View File

@@ -0,0 +1,11 @@
<SS14Window xmlns="https://spacestation14.io"
Title="{Loc 'ui-transfer-amount-title'}"
Resizable="False">
<VBoxContainer SeparationOverride="4" CustomMinimumSize="240 80">
<HBoxContainer>
<LineEdit Name="AmountLineEdit" HorizontalExpand="True" PlaceHolder="{Loc 'ui-transfer-amount-line-edit-placeholder'}"/>
</HBoxContainer>
<Button Name="ApplyButton" Text="{Loc 'ui-transfer-amount-apply'}"/>
</VBoxContainer>
</SS14Window>

View File

@@ -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);
}
}
}

View File

@@ -1,4 +1,3 @@
#nullable enable
using System; using System;
using Content.Shared.Chemistry.Solution.Components; using Content.Shared.Chemistry.Solution.Components;
using JetBrains.Annotations; using JetBrains.Annotations;

View File

@@ -2,6 +2,7 @@ using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Cloning.UI namespace Content.Client.Cloning.UI
{ {
@@ -15,21 +16,24 @@ namespace Content.Client.Cloning.UI
Title = Loc.GetString("accept-cloning-window-title"); Title = Loc.GetString("accept-cloning-window-title");
Contents.AddChild(new VBoxContainer Contents.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
new VBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
(new Label() (new Label()
{ {
Text = Loc.GetString("accept-cloning-window-prompt-text-part") Text = Loc.GetString("accept-cloning-window-prompt-text-part")
}), }),
new HBoxContainer new BoxContainer
{ {
Align = BoxContainer.AlignMode.Center, Orientation = LayoutOrientation.Horizontal,
Align = AlignMode.Center,
Children = Children =
{ {
(AcceptButton = new Button (AcceptButton = new Button

View File

@@ -9,6 +9,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using static Content.Shared.Cloning.SharedCloningPodComponent; using static Content.Shared.Cloning.SharedCloningPodComponent;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Cloning.UI namespace Content.Client.Cloning.UI
{ {
@@ -16,7 +17,7 @@ namespace Content.Client.Cloning.UI
{ {
private Dictionary<int, string?> _scanManager; private Dictionary<int, string?> _scanManager;
private readonly VBoxContainer _scanList; private readonly BoxContainer _scanList;
public readonly Button CloneButton; public readonly Button CloneButton;
public readonly Button EjectButton; public readonly Button EjectButton;
private CloningScanButton? _selectedButton; private CloningScanButton? _selectedButton;
@@ -35,8 +36,9 @@ namespace Content.Client.Cloning.UI
Title = Loc.GetString("cloning-pod-window-title"); Title = Loc.GetString("cloning-pod-window-title");
Contents.AddChild(new VBoxContainer Contents.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
new ScrollContainer new ScrollContainer
@@ -45,11 +47,15 @@ namespace Content.Client.Cloning.UI
VerticalExpand = true, VerticalExpand = true,
Children = Children =
{ {
(_scanList = new VBoxContainer()) (_scanList = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
})
} }
}, },
new VBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
(CloneButton = new Button (CloneButton = new Button
@@ -74,8 +80,9 @@ namespace Content.Client.Cloning.UI
{ {
Text = Loc.GetString("cloning-pod-eject-body-button") Text = Loc.GetString("cloning-pod-eject-body-button")
}), }),
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label() new Label()
@@ -219,8 +226,9 @@ namespace Content.Client.Cloning.UI
ToggleMode = true, ToggleMode = true,
}); });
AddChild(new HBoxContainer AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
(EntityTextureRect = new TextureRect (EntityTextureRect = new TextureRect

View File

@@ -1,14 +1,13 @@
#nullable enable
using Content.Client.Inventory; using Content.Client.Inventory;
using Content.Client.Items.Components; using Content.Client.Items.Components;
using Content.Shared.Clothing; using Content.Shared.Clothing;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Item; using Content.Shared.Item;
using Content.Shared.NetIDs;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.ResourceManagement; using Robust.Client.ResourceManagement;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -18,12 +17,12 @@ namespace Content.Client.Clothing
[RegisterComponent] [RegisterComponent]
[ComponentReference(typeof(SharedItemComponent))] [ComponentReference(typeof(SharedItemComponent))]
[ComponentReference(typeof(ItemComponent))] [ComponentReference(typeof(ItemComponent))]
[NetworkedComponent()]
public class ClothingComponent : ItemComponent public class ClothingComponent : ItemComponent
{ {
[DataField("femaleMask")] [DataField("femaleMask")]
private FemaleClothingMask _femaleMask = FemaleClothingMask.UniformFull; private FemaleClothingMask _femaleMask = FemaleClothingMask.UniformFull;
public override string Name => "Clothing"; public override string Name => "Clothing";
public override uint? NetID => ContentNetIDs.CLOTHING;
private string? _clothingEquippedPrefix; private string? _clothingEquippedPrefix;

View File

@@ -1,4 +1,3 @@
#nullable enable
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Shared.Enums; using Robust.Shared.Enums;
using Robust.Shared.IoC; using Robust.Shared.IoC;

View File

@@ -1,5 +1,4 @@
#nullable enable using Content.Shared;
using Content.Shared;
using Content.Shared.CCVar; using Content.Shared.CCVar;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
using Robust.Shared.Console; using Robust.Shared.Console;

View File

@@ -5,6 +5,7 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using static Robust.Client.UserInterface.Controls.BoxContainer;
using Timer = Robust.Shared.Timing.Timer; using Timer = Robust.Shared.Timing.Timer;
namespace Content.Client.Communications.UI namespace Content.Client.Communications.UI
@@ -42,7 +43,12 @@ namespace Content.Client.Communications.UI
EmergencyShuttleButton.OnPressed += (_) => Owner.EmergencyShuttleButtonPressed(); EmergencyShuttleButton.OnPressed += (_) => Owner.EmergencyShuttleButtonPressed();
EmergencyShuttleButton.Disabled = !owner.CanCall; 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(_messageInput);
vbox.AddChild(new Control(){MinSize = new Vector2(0,10), HorizontalExpand = true}); vbox.AddChild(new Control(){MinSize = new Vector2(0,10), HorizontalExpand = true});
vbox.AddChild(AnnounceButton); vbox.AddChild(AnnounceButton);
@@ -50,7 +56,12 @@ namespace Content.Client.Communications.UI
vbox.AddChild(_countdownLabel); vbox.AddChild(_countdownLabel);
vbox.AddChild(EmergencyShuttleButton); 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(new Control(){MinSize = new Vector2(100,0), HorizontalExpand = true});
hbox.AddChild(vbox); hbox.AddChild(vbox);
hbox.AddChild(new Control(){MinSize = new Vector2(100,0), HorizontalExpand = true}); hbox.AddChild(new Control(){MinSize = new Vector2(100,0), HorizontalExpand = true});

View File

@@ -6,6 +6,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using static Content.Shared.Configurable.SharedConfigurationComponent; using static Content.Shared.Configurable.SharedConfigurationComponent;
using static Robust.Client.UserInterface.Controls.BaseButton; using static Robust.Client.UserInterface.Controls.BaseButton;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Configurable.UI namespace Content.Client.Configurable.UI
{ {
@@ -13,9 +14,8 @@ namespace Content.Client.Configurable.UI
{ {
public ConfigurationBoundUserInterface Owner { get; } public ConfigurationBoundUserInterface Owner { get; }
private readonly VBoxContainer _baseContainer; private readonly BoxContainer _column;
private readonly VBoxContainer _column; private readonly BoxContainer _row;
private readonly HBoxContainer _row;
private readonly List<(string name, LineEdit input)> _inputs; private readonly List<(string name, LineEdit input)> _inputs;
@@ -28,20 +28,23 @@ namespace Content.Client.Configurable.UI
Title = Loc.GetString("configuration-menu-device-title"); Title = Loc.GetString("configuration-menu-device-title");
_baseContainer = new VBoxContainer BoxContainer baseContainer = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
VerticalExpand = true, VerticalExpand = true,
HorizontalExpand = true HorizontalExpand = true
}; };
_column = new VBoxContainer _column = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(8), Margin = new Thickness(8),
SeparationOverride = 16, SeparationOverride = 16,
}; };
_row = new HBoxContainer _row = new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 16, SeparationOverride = 16,
HorizontalExpand = true HorizontalExpand = true
}; };
@@ -63,9 +66,9 @@ namespace Content.Client.Configurable.UI
}; };
outerColumn.AddChild(_column); outerColumn.AddChild(_column);
_baseContainer.AddChild(outerColumn); baseContainer.AddChild(outerColumn);
_baseContainer.AddChild(confirmButton); baseContainer.AddChild(confirmButton);
Contents.AddChild(_baseContainer); Contents.AddChild(baseContainer);
} }
public void Populate(ConfigurationBoundUserInterfaceState state) public void Populate(ConfigurationBoundUserInterfaceState state)
@@ -97,7 +100,10 @@ namespace Content.Client.Configurable.UI
_inputs.Add((field.Key, input)); _inputs.Add((field.Key, input));
var row = new HBoxContainer(); var row = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
CopyProperties(_row, row); CopyProperties(_row, row);
row.AddChild(label); row.AddChild(label);

View File

@@ -14,7 +14,6 @@ using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Maths; using Robust.Shared.Maths;
#nullable enable
namespace Content.Client.Construction namespace Content.Client.Construction
{ {

View File

@@ -1,32 +1,32 @@
<SS14Window xmlns="https://spacestation14.io"> <SS14Window xmlns="https://spacestation14.io">
<HBoxContainer HorizontalExpand="True"> <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<VBoxContainer HorizontalExpand="True" SizeFlagsStretchRatio="0.4"> <BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.4">
<HBoxContainer HorizontalExpand="True"> <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<LineEdit Name="SearchBar" PlaceHolder="Search" HorizontalExpand="True"/> <LineEdit Name="SearchBar" PlaceHolder="Search" HorizontalExpand="True"/>
<OptionButton Name="Category" MinSize="130 0"/> <OptionButton Name="Category" MinSize="130 0"/>
</HBoxContainer> </BoxContainer>
<ItemList Name="RecipesList" SelectMode="Single" VerticalExpand="True"/> <ItemList Name="RecipesList" SelectMode="Single" VerticalExpand="True"/>
</VBoxContainer> </BoxContainer>
<Control MinSize="10 0"/> <Control MinSize="10 0"/>
<VBoxContainer HorizontalExpand="True" SizeFlagsStretchRatio="0.6"> <BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.6">
<Control> <Control>
<HBoxContainer Align="Center"> <BoxContainer Orientation="Horizontal" Align="Center">
<TextureRect Name="TargetTexture" HorizontalAlignment="Right" Stretch="Keep"/> <TextureRect Name="TargetTexture" HorizontalAlignment="Right" Stretch="Keep"/>
<Control MinSize="10 0"/> <Control MinSize="10 0"/>
<VBoxContainer> <BoxContainer Orientation="Vertical">
<RichTextLabel Name="TargetName"/> <RichTextLabel Name="TargetName"/>
<RichTextLabel Name="TargetDesc"/> <RichTextLabel Name="TargetDesc"/>
</VBoxContainer> </BoxContainer>
</HBoxContainer> </BoxContainer>
</Control> </Control>
<ItemList Name="StepList" VerticalExpand="True"/> <ItemList Name="StepList" VerticalExpand="True"/>
<VBoxContainer> <BoxContainer Orientation="Vertical">
<Button Name="BuildButton" Disabled="True" ToggleMode="True" VerticalExpand="True" SizeFlagsStretchRatio="0.5"/> <Button Name="BuildButton" Disabled="True" ToggleMode="True" VerticalExpand="True" SizeFlagsStretchRatio="0.5"/>
<HBoxContainer VerticalExpand="True" SizeFlagsStretchRatio="0.5"> <BoxContainer Orientation="Horizontal" VerticalExpand="True" SizeFlagsStretchRatio="0.5">
<Button Name="EraseButton" ToggleMode="True" HorizontalExpand="True" SizeFlagsStretchRatio="0.7"/> <Button Name="EraseButton" ToggleMode="True" HorizontalExpand="True" SizeFlagsStretchRatio="0.7"/>
<Button Name="ClearButton" HorizontalExpand="True" SizeFlagsStretchRatio="0.3"/> <Button Name="ClearButton" HorizontalExpand="True" SizeFlagsStretchRatio="0.3"/>
</HBoxContainer> </BoxContainer>
</VBoxContainer> </BoxContainer>
</VBoxContainer> </BoxContainer>
</HBoxContainer> </BoxContainer>
</SS14Window> </SS14Window>

View File

@@ -7,7 +7,6 @@ using Robust.Client.UserInterface.XAML;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
#nullable enable
namespace Content.Client.Construction.UI namespace Content.Client.Construction.UI
{ {

View File

@@ -1,4 +1,3 @@
#nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@@ -1,5 +1,4 @@
#nullable enable using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Content.Client.Interactable.Components; using Content.Client.Interactable.Components;
@@ -14,6 +13,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using static Robust.Client.UserInterface.Controls.BoxContainer;
using Vector2 = Robust.Shared.Maths.Vector2; using Vector2 = Robust.Shared.Maths.Vector2;
namespace Content.Client.ContextMenu.UI namespace Content.Client.ContextMenu.UI
@@ -64,8 +64,9 @@ namespace Content.Client.ContextMenu.UI
OutlineComponent = ContextEntity.GetComponentOrNull<InteractionOutlineComponent>(); OutlineComponent = ContextEntity.GetComponentOrNull<InteractionOutlineComponent>();
AddChild( AddChild(
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new LayoutContainer new LayoutContainer
@@ -130,14 +131,16 @@ namespace Content.Client.ContextMenu.UI
LayoutContainer.SetGrowVertical(_label, LayoutContainer.GrowDirection.Begin); LayoutContainer.SetGrowVertical(_label, LayoutContainer.GrowDirection.Begin);
AddChild( AddChild(
new HBoxContainer() new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 6, SeparationOverride = 6,
Children = Children =
{ {
new LayoutContainer { Children = { _spriteView, _label } }, new LayoutContainer { Children = { _spriteView, _label } },
new HBoxContainer() new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
SeparationOverride = 6, SeparationOverride = 6,
Children = Children =
{ {
@@ -180,7 +183,7 @@ namespace Content.Client.ContextMenu.UI
private const int MaxItemsBeforeScroll = 10; private const int MaxItemsBeforeScroll = 10;
private const int MarginSizeBetweenElements = 2; private const int MarginSizeBetweenElements = 2;
public VBoxContainer List { get; } public BoxContainer List { get; }
public int Depth { get; } public int Depth { get; }
public ContextMenuPopup(int depth = 0) public ContextMenuPopup(int depth = 0)
@@ -191,7 +194,10 @@ namespace Content.Client.ContextMenu.UI
HScrollEnabled = false, HScrollEnabled = false,
Children = { new PanelContainer Children = { new PanelContainer
{ {
Children = { (List = new VBoxContainer()) }, Children = { (List = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
}) },
PanelOverride = new StyleBoxFlat { BackgroundColor = MarginColor } PanelOverride = new StyleBoxFlat { BackgroundColor = MarginColor }
}} }}
}); });

View File

@@ -1,5 +1,4 @@
#nullable enable using System;
using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Content.Client.Examine; using Content.Client.Examine;

View File

@@ -1,5 +1,4 @@
#nullable enable 
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@@ -1,5 +1,4 @@
#nullable enable using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;

View File

@@ -9,6 +9,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using static Robust.Client.UserInterface.Controls.BaseButton; using static Robust.Client.UserInterface.Controls.BaseButton;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Crayon.UI namespace Content.Client.Crayon.UI
{ {
@@ -27,7 +28,10 @@ namespace Content.Client.Crayon.UI
Title = Loc.GetString("crayon-window-title"); Title = Loc.GetString("crayon-window-title");
Owner = owner; Owner = owner;
var vbox = new VBoxContainer(); var vbox = new BoxContainer
{
Orientation = LayoutOrientation.Vertical
};
Contents.AddChild(vbox); Contents.AddChild(vbox);
_search = new LineEdit(); _search = new LineEdit();

View File

@@ -16,6 +16,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel; using YamlDotNet.RepresentationModel;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Credits namespace Content.Client.Credits
{ {
@@ -71,8 +72,9 @@ namespace Content.Client.Credits
private void PopulateLicenses(ScrollContainer licensesList) private void PopulateLicenses(ScrollContainer licensesList)
{ {
var vBox = new VBoxContainer var vBox = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(2, 2, 0, 0) Margin = new Thickness(2, 2, 0, 0)
}; };
@@ -93,8 +95,9 @@ namespace Content.Client.Credits
private void PopulatePatronsList(Control patronsList) private void PopulatePatronsList(Control patronsList)
{ {
var vBox = new VBoxContainer var vBox = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(2, 2, 0, 0) Margin = new Thickness(2, 2, 0, 0)
}; };
var patrons = LoadPatrons(); var patrons = LoadPatrons();
@@ -152,13 +155,15 @@ namespace Content.Client.Credits
{ {
Button contributeButton; Button contributeButton;
var vBox = new VBoxContainer var vBox = new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Margin = new Thickness(2, 2, 0, 0) Margin = new Thickness(2, 2, 0, 0)
}; };
vBox.AddChild(new HBoxContainer vBox.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
HorizontalAlignment = HAlignment.Center, HorizontalAlignment = HAlignment.Center,
SeparationOverride = 20, SeparationOverride = 20,
Children = Children =

View File

@@ -7,6 +7,7 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using static Content.Shared.Disposal.Components.SharedDisposalMailingUnitComponent; using static Content.Shared.Disposal.Components.SharedDisposalMailingUnitComponent;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Disposal.UI namespace Content.Client.Disposal.UI
{ {
@@ -30,18 +31,21 @@ namespace Content.Client.Disposal.UI
{ {
MinSize = SetSize = (460, 230); MinSize = SetSize = (460, 230);
TargetList = new List<string>(); TargetList = new List<string>();
Contents.AddChild(new HBoxContainer Contents.AddChild(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new VBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
HorizontalExpand = true, HorizontalExpand = true,
Margin = new Thickness(8, 0), Margin = new Thickness(8, 0),
Children = Children =
{ {
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label {Text = $"{Loc.GetString("disposal-mailing-unit-window-state-label")} "}, 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 Control {MinSize = (0, 10)},
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true, HorizontalExpand = true,
Children = Children =
{ {
@@ -73,8 +78,9 @@ namespace Content.Client.Disposal.UI
} }
}, },
new Control {MinSize = (0, 10)}, new Control {MinSize = (0, 10)},
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true, HorizontalExpand = true,
Children = Children =
{ {
@@ -94,8 +100,9 @@ namespace Content.Client.Disposal.UI
} }
}, },
new Control {MinSize = (0, 10)}, new Control {MinSize = (0, 10)},
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true, HorizontalExpand = true,
Children = Children =
{ {
@@ -114,8 +121,9 @@ namespace Content.Client.Disposal.UI
} }
}, },
new Control {MinSize = (0, 10)}, new Control {MinSize = (0, 10)},
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
(Power = new CheckButton {Text = Loc.GetString("disposal-mailing-unit-power-button")}), (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), Margin = new Thickness(12, 0, 8, 0),
Children = Children =
{ {
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new Label new Label
@@ -139,8 +149,9 @@ namespace Content.Client.Disposal.UI
} }
}, },
new Control {MinSize = new Vector2(0, 8)}, new Control {MinSize = new Vector2(0, 8)},
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
VerticalExpand = true, VerticalExpand = true,
Children = Children =
{ {
@@ -161,16 +172,19 @@ namespace Content.Client.Disposal.UI
HorizontalExpand = true, HorizontalExpand = true,
MinSize = new Vector2(0, 1), MinSize = new Vector2(0, 1),
}, },
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Children = Children =
{ {
new VBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Vertical,
Children = Children =
{ {
new HBoxContainer new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal,
Margin = new Thickness(4, 0, 0, 0), Margin = new Thickness(4, 0, 0, 0),
Children = Children =
{ {

Some files were not shown because too many files have changed in this diff Show More