* attempt at moving MainViewport to UIWidget

* oldchat (prototype)

* separate oldchat and default ss14 HUD into their own files

* restores original default game screen logic and adds that logic into separated chat game screen

* hand reloading, several tweaks to port oldchat to main ss14 branch

oldchat is currently not selectable

* screen type cvar, gameplay state screen reloading/loading

* reload screen on ui layout cvar change

* fixes up basic reloading (HUD switching is still very bad)

* some UI widget reloading for main UI screen switching

* alert sync on screen change

* inventory reload

* hotbar margin fix

* chat bubbles above viewport

* whoops

* fixes ordering of speech bubble root

* should fix the chat focus issue (at least in-game, not lobby yet)

* should fix up the lobby/game chat focus

* fixes chat for lobby, turns lobby into a UI state

* viewport UI controller

* viewport ratio selection

* whoops

* adds the /tg/ widescreen ratio

* removes warning from inventory UI controller, adds background to separated chat game screen's chat portion

* menu button reload

* unload menu buttons only from gameplay state shutdown

* bugfix

* character button fix

* adds config options for viewport width/UI layout

* variable naming changes, get or null instead of get to avoid exceptions

* moves entity system get into controller
This commit is contained in:
Flipp Syder
2022-10-17 15:13:41 -07:00
committed by GitHub
parent 730eddf0ab
commit a3dafd88dc
37 changed files with 910 additions and 208 deletions

View File

@@ -183,8 +183,7 @@ namespace Content.Client.Actions
if (uid != _playerManager.LocalPlayer?.ControlledEntity) if (uid != _playerManager.LocalPlayer?.ControlledEntity)
return; return;
LinkActions?.Invoke(component); LinkAllActions(component);
PlayerActions = component;
} }
private void OnPlayerDetached(EntityUid uid, ActionsComponent component, PlayerDetachedEvent? args = null) private void OnPlayerDetached(EntityUid uid, ActionsComponent component, PlayerDetachedEvent? args = null)
@@ -192,10 +191,27 @@ namespace Content.Client.Actions
if (uid != _playerManager.LocalPlayer?.ControlledEntity) if (uid != _playerManager.LocalPlayer?.ControlledEntity)
return; return;
UnlinkAllActions();
}
public void UnlinkAllActions()
{
UnlinkActions?.Invoke(); UnlinkActions?.Invoke();
PlayerActions = null; PlayerActions = null;
} }
public void LinkAllActions(ActionsComponent? actions = null)
{
var player = _playerManager.LocalPlayer?.ControlledEntity;
if (player == null || !Resolve(player.Value, ref actions))
{
return;
}
LinkActions?.Invoke(actions);
PlayerActions = actions;
}
public override void Shutdown() public override void Shutdown()
{ {
base.Shutdown(); base.Shutdown();

View File

@@ -2,6 +2,16 @@ using Content.Client.Construction.UI;
using Content.Client.Hands; using Content.Client.Hands;
using Content.Client.UserInterface.Controls; using Content.Client.UserInterface.Controls;
using Content.Client.UserInterface.Screens; using Content.Client.UserInterface.Screens;
using Content.Client.UserInterface.Systems.Actions;
using Content.Client.UserInterface.Systems.Alerts;
using Content.Client.UserInterface.Systems.Chat;
using Content.Client.UserInterface.Systems.Ghost;
using Content.Client.UserInterface.Systems.Hands;
using Content.Client.UserInterface.Systems.Hotbar;
using Content.Client.UserInterface.Systems.Hotbar.Widgets;
using Content.Client.UserInterface.Systems.Inventory;
using Content.Client.UserInterface.Systems.MenuBar;
using Content.Client.UserInterface.Systems.Viewport;
using Content.Client.Viewport; using Content.Client.Viewport;
using Content.Shared.CCVar; using Content.Shared.CCVar;
using Robust.Client.Graphics; using Robust.Client.Graphics;
@@ -26,36 +36,47 @@ namespace Content.Client.Gameplay
[Dependency] private readonly IConfigurationManager _configurationManager = default!; [Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly IEntityManager _entMan = default!; [Dependency] private readonly IEntityManager _entMan = default!;
protected override Type? LinkedScreenType => typeof(DefaultGameScreen);
public static readonly Vector2i ViewportSize = (EyeManager.PixelsPerMeter * 21, EyeManager.PixelsPerMeter * 15);
private FpsCounter _fpsCounter = default!; private FpsCounter _fpsCounter = default!;
public MainViewport Viewport { get; private set; } = default!; public MainViewport Viewport => _uiManager.ActiveScreen!.GetWidget<MainViewport>()!;
private readonly GhostUIController _ghostController;
private readonly ActionUIController _actionController;
private readonly AlertsUIController _alertsController;
private readonly HotbarUIController _hotbarController;
private readonly ChatUIController _chatController;
private readonly ViewportUIController _viewportController;
private readonly GameTopMenuBarUIController _menuController;
public GameplayState() public GameplayState()
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
_ghostController = _uiManager.GetUIController<GhostUIController>();
_actionController = _uiManager.GetUIController<ActionUIController>();
_alertsController = _uiManager.GetUIController<AlertsUIController>();
_hotbarController = _uiManager.GetUIController<HotbarUIController>();
_chatController = _uiManager.GetUIController<ChatUIController>();
_viewportController = _uiManager.GetUIController<ViewportUIController>();
_menuController = _uiManager.GetUIController<GameTopMenuBarUIController>();
} }
protected override void Startup() protected override void Startup()
{ {
base.Startup(); base.Startup();
Viewport = new MainViewport
{ LoadMainScreen();
Viewport =
{ // Add the hand-item overlay.
ViewportSize = ViewportSize
}
};
UserInterfaceManager.StateRoot.AddChild(Viewport);
LayoutContainer.SetAnchorPreset(Viewport, LayoutContainer.LayoutPreset.Wide);
Viewport.SetPositionFirst();
_eyeManager.MainViewport = Viewport.Viewport;
_overlayManager.AddOverlay(new ShowHandItemOverlay()); _overlayManager.AddOverlay(new ShowHandItemOverlay());
// FPS counter.
// yeah this can just stay here, whatever
_fpsCounter = new FpsCounter(_gameTiming); _fpsCounter = new FpsCounter(_gameTiming);
UserInterfaceManager.PopupRoot.AddChild(_fpsCounter); UserInterfaceManager.PopupRoot.AddChild(_fpsCounter);
_fpsCounter.Visible = _configurationManager.GetCVar(CCVars.HudFpsCounterVisible); _fpsCounter.Visible = _configurationManager.GetCVar(CCVars.HudFpsCounterVisible);
_configurationManager.OnValueChanged(CCVars.HudFpsCounterVisible, (show) => { _fpsCounter.Visible = show; }); _configurationManager.OnValueChanged(CCVars.HudFpsCounterVisible, (show) => { _fpsCounter.Visible = show; });
_configurationManager.OnValueChanged(CCVars.UILayout, _ => ReloadMainScreen());
} }
protected override void Shutdown() protected override void Shutdown()
@@ -63,36 +84,65 @@ namespace Content.Client.Gameplay
_overlayManager.RemoveOverlay<ShowHandItemOverlay>(); _overlayManager.RemoveOverlay<ShowHandItemOverlay>();
base.Shutdown(); base.Shutdown();
Viewport.Dispose();
// Clear viewport to some fallback, whatever. // Clear viewport to some fallback, whatever.
_eyeManager.MainViewport = UserInterfaceManager.MainViewport; _eyeManager.MainViewport = UserInterfaceManager.MainViewport;
_fpsCounter.Dispose(); _fpsCounter.Dispose();
_uiManager.ClearWindows(); _uiManager.ClearWindows();
UnloadMainScreen();
} }
public override void FrameUpdate(FrameEventArgs e) public void ReloadMainScreen()
{
if (_uiManager.ActiveScreen == null)
{ {
base.FrameUpdate(e);
Viewport.Viewport.Eye = _eyeManager.CurrentEye;
// verify that the current eye is not "null". Fuck IEyeManager.
var ent = _playerMan.LocalPlayer?.ControlledEntity;
if (_eyeManager.CurrentEye.Position != default || ent == null)
return; return;
_entMan.TryGetComponent(ent, out EyeComponent? eye);
if (eye?.Eye == _eyeManager.CurrentEye
&& _entMan.GetComponent<TransformComponent>(ent.Value).WorldPosition == default)
return; // nothing to worry about, the player is just in null space... actually that is probably a problem?
// Currently, this shouldn't happen. This likely happened because the main eye was set to null. When this
// does happen it can create hard to troubleshoot bugs, so lets print some helpful warnings:
Logger.Warning($"Main viewport's eye is in nullspace (main eye is null?). Attached entity: {_entMan.ToPrettyString(ent.Value)}. Entity has eye comp: {eye != null}");
} }
UnloadMainScreen();
LoadMainScreen();
}
private void UnloadMainScreen()
{
_chatController.SetMainChat(false);
_menuController.UnloadButtons();
_uiManager.UnloadScreen();
}
private void LoadMainScreen()
{
var screenTypeString = _configurationManager.GetCVar(CCVars.UILayout);
if (!Enum.TryParse(screenTypeString, out ScreenType screenType))
{
screenType = default;
}
switch (screenType)
{
case ScreenType.Default:
_uiManager.LoadScreen<DefaultGameScreen>();
break;
case ScreenType.Separated:
_uiManager.LoadScreen<SeparatedChatGameScreen>();
break;
}
_chatController.SetMainChat(true);
_viewportController.ReloadViewport();
_menuController.LoadButtons();
// TODO: This could just be like, the equivalent of an event or something
_ghostController.UpdateGui();
_actionController.RegisterActionContainer();
_alertsController.SyncAlerts();
_hotbarController.ReloadHotbar();
var viewportContainer = _uiManager.ActiveScreen!.FindControl<LayoutContainer>("ViewportContainer");
_chatController.SetSpeechBubbleRoot(viewportContainer);
}
protected override void OnKeyBindStateChanged(ViewportBoundKeyEventArgs args) protected override void OnKeyBindStateChanged(ViewportBoundKeyEventArgs args)
{ {
if (args.Viewport == null) if (args.Viewport == null)

View File

@@ -130,6 +130,16 @@ namespace Content.Client.Hands.Systems
} }
#endregion #endregion
public void ReloadHandButtons()
{
if (!TryGetPlayerHands(out var hands))
{
return;
}
OnPlayerHandsAdded?.Invoke(hands);
}
public override void DoDrop(EntityUid uid, Hand hand, bool doDropInteraction = true, SharedHandsComponent? hands = null) public override void DoDrop(EntityUid uid, Hand hand, bool doDropInteraction = true, SharedHandsComponent? hands = null)
{ {
base.DoDrop(uid, hand, doDropInteraction, hands); base.DoDrop(uid, hand, doDropInteraction, hands);

View File

@@ -158,6 +158,18 @@ namespace Content.Client.Inventory
} }
} }
public void ReloadInventory(ClientInventoryComponent? component = null)
{
var player = _playerManager.LocalPlayer?.ControlledEntity;
if (player == null || !Resolve(player.Value, ref component))
{
return;
}
OnUnlinkInventory?.Invoke();
OnLinkInventory?.Invoke(component);
}
public void SetSlotHighlight(EntityUid owner, ClientInventoryComponent component, string slotName, bool state) public void SetSlotHighlight(EntityUid owner, ClientInventoryComponent component, string slotName, bool state)
{ {
var oldData = component.SlotData[slotName]; var oldData = component.SlotData[slotName];

View File

@@ -4,6 +4,7 @@ using Content.Client.LateJoin;
using Content.Client.Lobby.UI; using Content.Client.Lobby.UI;
using Content.Client.Preferences; using Content.Client.Preferences;
using Content.Client.Preferences.UI; using Content.Client.Preferences.UI;
using Content.Client.UserInterface.Systems.Chat;
using Content.Client.Voting; using Content.Client.Voting;
using Robust.Client; using Robust.Client;
using Robust.Client.Console; using Robust.Client.Console;
@@ -34,45 +35,47 @@ namespace Content.Client.Lobby
[Dependency] private readonly IConfigurationManager _configurationManager = default!; [Dependency] private readonly IConfigurationManager _configurationManager = default!;
[ViewVariables] private CharacterSetupGui? _characterSetup; [ViewVariables] private CharacterSetupGui? _characterSetup;
[ViewVariables] private LobbyGui? _lobby;
private ClientGameTicker _gameTicker = default!; private ClientGameTicker _gameTicker = default!;
protected override Type? LinkedScreenType { get; } = typeof(LobbyGui);
private LobbyGui Lobby => (LobbyGui) _userInterfaceManager.ActiveScreen!;
protected override void Startup() protected override void Startup()
{ {
var chatController = _userInterfaceManager.GetUIController<ChatUIController>();
_gameTicker = _entityManager.System<ClientGameTicker>(); _gameTicker = _entityManager.System<ClientGameTicker>();
_characterSetup = new CharacterSetupGui(_entityManager, _resourceCache, _preferencesManager, _characterSetup = new CharacterSetupGui(_entityManager, _resourceCache, _preferencesManager,
_prototypeManager, _configurationManager); _prototypeManager, _configurationManager);
LayoutContainer.SetAnchorPreset(_characterSetup, LayoutContainer.LayoutPreset.Wide); LayoutContainer.SetAnchorPreset(_characterSetup, LayoutContainer.LayoutPreset.Wide);
_lobby = new LobbyGui(_entityManager, _preferencesManager); chatController.SetMainChat(true);
_userInterfaceManager.StateRoot.AddChild(_lobby);
_characterSetup.CloseButton.OnPressed += _ => _characterSetup.CloseButton.OnPressed += _ =>
{ {
_userInterfaceManager.StateRoot.AddChild(_lobby); _userInterfaceManager.StateRoot.AddChild(Lobby);
_userInterfaceManager.StateRoot.RemoveChild(_characterSetup); _userInterfaceManager.StateRoot.RemoveChild(_characterSetup);
}; };
_characterSetup.SaveButton.OnPressed += _ => _characterSetup.SaveButton.OnPressed += _ =>
{ {
_characterSetup.Save(); _characterSetup.Save();
_lobby?.CharacterPreview.UpdateUI(); Lobby?.CharacterPreview.UpdateUI();
}; };
LayoutContainer.SetAnchorPreset(_lobby, LayoutContainer.LayoutPreset.Wide); LayoutContainer.SetAnchorPreset(Lobby, LayoutContainer.LayoutPreset.Wide);
_voteManager.SetPopupContainer(_lobby.VoteContainer); _voteManager.SetPopupContainer(Lobby.VoteContainer);
_lobby.ServerName.Text = _baseClient.GameInfo?.ServerName; //The eye of refactor gazes upon you... Lobby.ServerName.Text = _baseClient.GameInfo?.ServerName; //The eye of refactor gazes upon you...
UpdateLobbyUi(); UpdateLobbyUi();
_lobby.CharacterPreview.CharacterSetupButton.OnPressed += _ => Lobby.CharacterPreview.CharacterSetupButton.OnPressed += _ =>
{ {
SetReady(false); SetReady(false);
_userInterfaceManager.StateRoot.RemoveChild(_lobby); _userInterfaceManager.StateRoot.RemoveChild(Lobby);
_userInterfaceManager.StateRoot.AddChild(_characterSetup); _userInterfaceManager.StateRoot.AddChild(_characterSetup);
}; };
_lobby.ReadyButton.OnPressed += _ => Lobby.ReadyButton.OnPressed += _ =>
{ {
if (!_gameTicker.IsGameStarted) if (!_gameTicker.IsGameStarted)
{ {
@@ -82,13 +85,13 @@ namespace Content.Client.Lobby
new LateJoinGui().OpenCentered(); new LateJoinGui().OpenCentered();
}; };
_lobby.ReadyButton.OnToggled += args => Lobby.ReadyButton.OnToggled += args =>
{ {
SetReady(args.Pressed); SetReady(args.Pressed);
}; };
_lobby.LeaveButton.OnPressed += _ => _consoleHost.ExecuteCommand("disconnect"); Lobby.LeaveButton.OnPressed += _ => _consoleHost.ExecuteCommand("disconnect");
_lobby.OptionsButton.OnPressed += _ => _userInterfaceManager.GetUIController<OptionsUIController>().ToggleWindow(); Lobby.OptionsButton.OnPressed += _ => _userInterfaceManager.GetUIController<OptionsUIController>().ToggleWindow();
_gameTicker.InfoBlobUpdated += UpdateLobbyUi; _gameTicker.InfoBlobUpdated += UpdateLobbyUi;
@@ -98,25 +101,22 @@ namespace Content.Client.Lobby
protected override void Shutdown() protected override void Shutdown()
{ {
var chatController = _userInterfaceManager.GetUIController<ChatUIController>();
chatController.SetMainChat(false);
_gameTicker.InfoBlobUpdated -= UpdateLobbyUi; _gameTicker.InfoBlobUpdated -= UpdateLobbyUi;
_gameTicker.LobbyStatusUpdated -= LobbyStatusUpdated; _gameTicker.LobbyStatusUpdated -= LobbyStatusUpdated;
_gameTicker.LobbyLateJoinStatusUpdated -= LobbyLateJoinStatusUpdated; _gameTicker.LobbyLateJoinStatusUpdated -= LobbyLateJoinStatusUpdated;
_lobby?.Dispose();
_characterSetup?.Dispose(); _characterSetup?.Dispose();
_lobby = null;
_characterSetup = null; _characterSetup = null;
} }
public override void FrameUpdate(FrameEventArgs e) public override void FrameUpdate(FrameEventArgs e)
{ {
if (_lobby == null)
return;
if (_gameTicker.IsGameStarted) if (_gameTicker.IsGameStarted)
{ {
_lobby.StartTime.Text = string.Empty; Lobby.StartTime.Text = string.Empty;
_lobby.StationTime.Text = Loc.GetString("lobby-state-player-status-station-time", ("stationTime", _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan).ToString("hh\\:mm"))); Lobby.StationTime.Text = Loc.GetString("lobby-state-player-status-station-time", ("stationTime", _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan).ToString("hh\\:mm")));
return; return;
} }
@@ -140,8 +140,8 @@ namespace Content.Client.Lobby
} }
} }
_lobby.StationTime.Text = Loc.GetString("lobby-state-player-status-station-time", ("stationTime", TimeSpan.Zero.ToString("hh\\:mm"))); Lobby.StationTime.Text = Loc.GetString("lobby-state-player-status-station-time", ("stationTime", TimeSpan.Zero.ToString("hh\\:mm")));
_lobby.StartTime.Text = Loc.GetString("lobby-state-round-start-countdown-text", ("timeLeft", text)); Lobby.StartTime.Text = Loc.GetString("lobby-state-round-start-countdown-text", ("timeLeft", text));
} }
private void LobbyStatusUpdated() private void LobbyStatusUpdated()
@@ -152,50 +152,43 @@ namespace Content.Client.Lobby
private void LobbyLateJoinStatusUpdated() private void LobbyLateJoinStatusUpdated()
{ {
if (_lobby == null) return; Lobby.ReadyButton.Disabled = _gameTicker.DisallowedLateJoin;
_lobby.ReadyButton.Disabled = _gameTicker.DisallowedLateJoin;
} }
private void UpdateLobbyUi() private void UpdateLobbyUi()
{ {
if (_lobby == null)
return;
if (_gameTicker.IsGameStarted) if (_gameTicker.IsGameStarted)
{ {
_lobby.ReadyButton.Text = Loc.GetString("lobby-state-ready-button-join-state"); Lobby.ReadyButton.Text = Loc.GetString("lobby-state-ready-button-join-state");
_lobby.ReadyButton.ToggleMode = false; Lobby.ReadyButton.ToggleMode = false;
_lobby.ReadyButton.Pressed = false; Lobby.ReadyButton.Pressed = false;
_lobby.ObserveButton.Disabled = false; Lobby.ObserveButton.Disabled = false;
} }
else else
{ {
_lobby.StartTime.Text = string.Empty; Lobby.StartTime.Text = string.Empty;
_lobby.ReadyButton.Text = Loc.GetString("lobby-state-ready-button-ready-up-state"); Lobby.ReadyButton.Text = Loc.GetString("lobby-state-ready-button-ready-up-state");
_lobby.ReadyButton.ToggleMode = true; Lobby.ReadyButton.ToggleMode = true;
_lobby.ReadyButton.Disabled = false; Lobby.ReadyButton.Disabled = false;
_lobby.ReadyButton.Pressed = _gameTicker.AreWeReady; Lobby.ReadyButton.Pressed = _gameTicker.AreWeReady;
_lobby.ObserveButton.Disabled = true; Lobby.ObserveButton.Disabled = true;
} }
if (_gameTicker.ServerInfoBlob != null) if (_gameTicker.ServerInfoBlob != null)
{ {
_lobby.ServerInfo.SetInfoBlob(_gameTicker.ServerInfoBlob); Lobby.ServerInfo.SetInfoBlob(_gameTicker.ServerInfoBlob);
} }
} }
private void UpdateLobbyBackground() private void UpdateLobbyBackground()
{ {
if (_lobby == null)
return;
if (_gameTicker.LobbyBackground != null) if (_gameTicker.LobbyBackground != null)
{ {
_lobby.Background.Texture = _resourceCache.GetResource<TextureResource>(_gameTicker.LobbyBackground ); Lobby.Background.Texture = _resourceCache.GetResource<TextureResource>(_gameTicker.LobbyBackground );
} }
else else
{ {
_lobby.Background.Texture = null; Lobby.Background.Texture = null;
} }
} }

View File

@@ -1,4 +1,4 @@
<Control xmlns="https://spacestation14.io" <lobbyUi:LobbyGui xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:maths="clr-namespace:Robust.Shared.Maths;assembly=Robust.Shared.Maths" xmlns:maths="clr-namespace:Robust.Shared.Maths;assembly=Robust.Shared.Maths"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls" xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
@@ -10,7 +10,7 @@
xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Chat.Widgets"> xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Chat.Widgets">
<!-- Background --> <!-- Background -->
<TextureRect Access="Public" Name = "Background" Stretch="KeepAspectCovered"/> <TextureRect Access="Public" Name = "Background" Stretch="KeepAspectCovered"/>
<BoxContainer Orientation="Horizontal" Margin="10 10 10 10" SeparationOverride="2"> <BoxContainer Name="MainContainer" Orientation="Horizontal" Margin="10 10 10 10" SeparationOverride="2">
<SplitContainer State="Auto" HorizontalExpand="True"> <SplitContainer State="Auto" HorizontalExpand="True">
<!-- LHS Controls --> <!-- LHS Controls -->
<BoxContainer Orientation="Vertical" SeparationOverride="4" HorizontalExpand="True"> <BoxContainer Orientation="Vertical" SeparationOverride="4" HorizontalExpand="True">
@@ -47,7 +47,7 @@
<!-- Top row --> <!-- Top row -->
<BoxContainer Orientation="Horizontal" MinSize="0 40" Name="HeaderContainer" Access="Public" SeparationOverride="4"> <BoxContainer Orientation="Horizontal" MinSize="0 40" Name="HeaderContainer" Access="Public" SeparationOverride="4">
<Label Margin="8 0 0 0" StyleClasses="LabelHeadingBigger" VAlign="Center" Text="{Loc 'ui-lobby-title'}" /> <Label Margin="8 0 0 0" StyleClasses="LabelHeadingBigger" VAlign="Center" Text="{Loc 'ui-lobby-title'}" />
<Label Name="ServerName" Access="Public" StyleClasses="LabelHeadingBigger" VAlign="Center" /> <Label Name="ServerName" Access="Public" StyleClasses="LabelHeadingBigger" VAlign="Center" HorizontalExpand="True" HorizontalAlignment="Center" />
</BoxContainer> </BoxContainer>
<!-- Gold line --> <!-- Gold line -->
<controls:HLine Color="{x:Static style:StyleNano.NanoGold}" Thickness="2"/> <controls:HLine Color="{x:Static style:StyleNano.NanoGold}" Thickness="2"/>
@@ -71,9 +71,9 @@
<!-- Gold line --> <!-- Gold line -->
<controls:HLine Color="{x:Static style:StyleNano.NanoGold}" Thickness="2" Access="Public"/> <controls:HLine Color="{x:Static style:StyleNano.NanoGold}" Thickness="2" Access="Public"/>
<controls:HSpacer Spacing="10"/> <controls:HSpacer Spacing="10"/>
<widgets:ChatBox Name="Chat" Access="Public" VerticalExpand="True" Margin="3 3 3 3" MinHeight="50" Main="True"/> <widgets:ChatBox Name="Chat" Access="Public" VerticalExpand="True" Margin="3 3 3 3" MinHeight="50" />
</BoxContainer> </BoxContainer>
</PanelContainer> </PanelContainer>
</SplitContainer> </SplitContainer>
</BoxContainer> </BoxContainer>
</Control> </lobbyUi:LobbyGui>

View File

@@ -15,14 +15,12 @@ using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Lobby.UI namespace Content.Client.Lobby.UI
{ {
[GenerateTypedNameReferences] [GenerateTypedNameReferences]
internal sealed partial class LobbyGui : Control internal sealed partial class LobbyGui : UIScreen
{ {
public LobbyGui(IEntityManager entityManager, public LobbyGui()
IClientPreferencesManager preferencesManager)
{ {
RobustXamlLoader.Load(this); RobustXamlLoader.Load(this);
ServerName.HorizontalExpand = true; SetAnchorPreset(MainContainer, LayoutPreset.Wide);
ServerName.HorizontalAlignment = HAlignment.Center;
} }
} }
} }

View File

@@ -32,6 +32,18 @@
MinWidth="200" /> MinWidth="200" />
</BoxContainer> </BoxContainer>
</BoxContainer> </BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Name="ViewportWidthSliderDisplay" />
<Control MinSize="4 0" />
<Slider Name="ViewportWidthSlider"
Rounded="True"
MinWidth="200" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'ui-options-hud-layout'}" />
<Control MinSize="4 0" />
<OptionButton Name="HudLayoutOption" />
</BoxContainer>
<CheckBox Name="IntegerScalingCheckBox" <CheckBox Name="IntegerScalingCheckBox"
Text="{Loc 'ui-options-vp-integer-scaling'}" Text="{Loc 'ui-options-vp-integer-scaling'}"
ToolTip="{Loc 'ui-options-vp-integer-scaling-tooltip'}" /> ToolTip="{Loc 'ui-options-vp-integer-scaling-tooltip'}" />

View File

@@ -1,3 +1,4 @@
using Content.Client.UserInterface.Screens;
using Content.Shared.CCVar; using Content.Shared.CCVar;
using Content.Shared.HUD; using Content.Shared.HUD;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
@@ -58,6 +59,27 @@ namespace Content.Client.Options.UI.Tabs
} }
HudThemeOption.OnItemSelected += OnHudThemeChanged; HudThemeOption.OnItemSelected += OnHudThemeChanged;
var hudLayout = _cfg.GetCVar(CCVars.UILayout);
var id = 0;
foreach (var layout in Enum.GetValues(typeof(ScreenType)))
{
var name = layout.ToString()!;
HudLayoutOption.AddItem(name, id);
if (name == hudLayout)
{
HudLayoutOption.SelectId(id);
}
HudLayoutOption.SetItemMetadata(id, name);
id++;
}
HudLayoutOption.OnItemSelected += args =>
{
HudLayoutOption.SelectId(args.Id);
UpdateApplyButton();
};
ViewportStretchCheckBox.OnToggled += _ => ViewportStretchCheckBox.OnToggled += _ =>
{ {
UpdateViewportScale(); UpdateViewportScale();
@@ -70,6 +92,12 @@ namespace Content.Client.Options.UI.Tabs
UpdateViewportScale(); UpdateViewportScale();
}; };
ViewportWidthSlider.OnValueChanged += _ =>
{
UpdateViewportWidthDisplay();
UpdateApplyButton();
};
ShowHeldItemCheckBox.OnToggled += OnCheckBoxToggled; ShowHeldItemCheckBox.OnToggled += OnCheckBoxToggled;
IntegerScalingCheckBox.OnToggled += OnCheckBoxToggled; IntegerScalingCheckBox.OnToggled += OnCheckBoxToggled;
ViewportLowResCheckBox.OnToggled += OnCheckBoxToggled; ViewportLowResCheckBox.OnToggled += OnCheckBoxToggled;
@@ -88,7 +116,13 @@ namespace Content.Client.Options.UI.Tabs
ParallaxLowQualityCheckBox.Pressed = _cfg.GetCVar(CCVars.ParallaxLowQuality); ParallaxLowQualityCheckBox.Pressed = _cfg.GetCVar(CCVars.ParallaxLowQuality);
FpsCounterCheckBox.Pressed = _cfg.GetCVar(CCVars.HudFpsCounterVisible); FpsCounterCheckBox.Pressed = _cfg.GetCVar(CCVars.HudFpsCounterVisible);
ShowHeldItemCheckBox.Pressed = _cfg.GetCVar(CCVars.HudHeldItemShow); ShowHeldItemCheckBox.Pressed = _cfg.GetCVar(CCVars.HudHeldItemShow);
ViewportWidthSlider.Value = _cfg.GetCVar(CCVars.ViewportWidth);
_cfg.OnValueChanged(CCVars.ViewportMinimumWidth, _ => UpdateViewportWidthRange());
_cfg.OnValueChanged(CCVars.ViewportMaximumWidth, _ => UpdateViewportWidthRange());
UpdateViewportWidthRange();
UpdateViewportWidthDisplay();
UpdateViewportScale(); UpdateViewportScale();
UpdateApplyButton(); UpdateApplyButton();
} }
@@ -125,6 +159,13 @@ namespace Content.Client.Options.UI.Tabs
_cfg.SetCVar(CCVars.ParallaxLowQuality, ParallaxLowQualityCheckBox.Pressed); _cfg.SetCVar(CCVars.ParallaxLowQuality, ParallaxLowQualityCheckBox.Pressed);
_cfg.SetCVar(CCVars.HudHeldItemShow, ShowHeldItemCheckBox.Pressed); _cfg.SetCVar(CCVars.HudHeldItemShow, ShowHeldItemCheckBox.Pressed);
_cfg.SetCVar(CCVars.HudFpsCounterVisible, FpsCounterCheckBox.Pressed); _cfg.SetCVar(CCVars.HudFpsCounterVisible, FpsCounterCheckBox.Pressed);
_cfg.SetCVar(CCVars.ViewportWidth, (int) ViewportWidthSlider.Value);
if (HudLayoutOption.SelectedMetadata is string opt)
{
_cfg.SetCVar(CCVars.UILayout, opt);
}
_cfg.SaveToFile(); _cfg.SaveToFile();
UpdateApplyButton(); UpdateApplyButton();
} }
@@ -154,6 +195,8 @@ namespace Content.Client.Options.UI.Tabs
var isPLQSame = ParallaxLowQualityCheckBox.Pressed == _cfg.GetCVar(CCVars.ParallaxLowQuality); var isPLQSame = ParallaxLowQualityCheckBox.Pressed == _cfg.GetCVar(CCVars.ParallaxLowQuality);
var isShowHeldItemSame = ShowHeldItemCheckBox.Pressed == _cfg.GetCVar(CCVars.HudHeldItemShow); var isShowHeldItemSame = ShowHeldItemCheckBox.Pressed == _cfg.GetCVar(CCVars.HudHeldItemShow);
var isFpsCounterVisibleSame = FpsCounterCheckBox.Pressed == _cfg.GetCVar(CCVars.HudFpsCounterVisible); var isFpsCounterVisibleSame = FpsCounterCheckBox.Pressed == _cfg.GetCVar(CCVars.HudFpsCounterVisible);
var isWidthSame = (int) ViewportWidthSlider.Value == _cfg.GetCVar(CCVars.ViewportWidth);
var isLayoutSame = HudLayoutOption.SelectedMetadata is string opt && opt == _cfg.GetCVar(CCVars.UILayout);
ApplyButton.Disabled = isVSyncSame && ApplyButton.Disabled = isVSyncSame &&
isFullscreenSame && isFullscreenSame &&
@@ -166,7 +209,9 @@ namespace Content.Client.Options.UI.Tabs
isPLQSame && isPLQSame &&
isHudThemeSame && isHudThemeSame &&
isShowHeldItemSame && isShowHeldItemSame &&
isFpsCounterVisibleSame; isFpsCounterVisibleSame &&
isWidthSame &&
isLayoutSame;
} }
private bool ConfigIsFullscreen => private bool ConfigIsFullscreen =>
@@ -242,5 +287,19 @@ namespace Content.Client.Options.UI.Tabs
IntegerScalingCheckBox.Visible = ViewportStretchCheckBox.Pressed; IntegerScalingCheckBox.Visible = ViewportStretchCheckBox.Pressed;
ViewportScaleText.Text = Loc.GetString("ui-options-vp-scale", ("scale", ViewportScaleSlider.Value)); ViewportScaleText.Text = Loc.GetString("ui-options-vp-scale", ("scale", ViewportScaleSlider.Value));
} }
private void UpdateViewportWidthRange()
{
var min = _cfg.GetCVar(CCVars.ViewportMinimumWidth);
var max = _cfg.GetCVar(CCVars.ViewportMaximumWidth);
ViewportWidthSlider.MinValue = min;
ViewportWidthSlider.MaxValue = max;
}
private void UpdateViewportWidthDisplay()
{
ViewportWidthSliderDisplay.Text = Loc.GetString("ui-options-vp-width", ("width", (int) ViewportWidthSlider.Value));
}
} }
} }

View File

@@ -1,6 +1,7 @@
using Content.Client.Viewport; using Content.Client.Viewport;
using Content.Shared.CCVar; using Content.Shared.CCVar;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
namespace Content.Client.UserInterface.Controls namespace Content.Client.UserInterface.Controls
@@ -9,7 +10,7 @@ namespace Content.Client.UserInterface.Controls
/// Wrapper for <see cref="ScalingViewport"/> that listens to configuration variables. /// Wrapper for <see cref="ScalingViewport"/> that listens to configuration variables.
/// Also does NN-snapping within tolerances. /// Also does NN-snapping within tolerances.
/// </summary> /// </summary>
public sealed class MainViewport : Control public sealed class MainViewport : UIWidget
{ {
[Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly ViewportManager _vpManager = default!; [Dependency] private readonly ViewportManager _vpManager = default!;

View File

@@ -7,14 +7,18 @@
xmlns:alerts="clr-namespace:Content.Client.UserInterface.Systems.Alerts.Widgets" xmlns:alerts="clr-namespace:Content.Client.UserInterface.Systems.Alerts.Widgets"
xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Ghost.Widgets" xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Ghost.Widgets"
xmlns:hotbar="clr-namespace:Content.Client.UserInterface.Systems.Hotbar.Widgets" xmlns:hotbar="clr-namespace:Content.Client.UserInterface.Systems.Hotbar.Widgets"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Name="DefaultHud" Name="DefaultHud"
VerticalExpand="False" VerticalExpand="False"
VerticalAlignment="Bottom" VerticalAlignment="Bottom"
HorizontalAlignment="Center"> HorizontalAlignment="Center">
<LayoutContainer Name="ViewportContainer" HorizontalExpand="True" VerticalExpand="True">
<controls:MainViewport Name="MainViewport"/>
</LayoutContainer>
<menuBar:GameTopMenuBar Name="TopBar" Access="Protected" /> <menuBar:GameTopMenuBar Name="TopBar" Access="Protected" />
<widgets:GhostGui Name="Ghost" Access="Protected" /> <widgets:GhostGui Name="Ghost" Access="Protected" />
<hotbar:HotbarGui Name="Hotbar" Access="Protected" /> <hotbar:HotbarGui Name="Hotbar" Access="Protected" />
<actions:ActionsBar Name="Actions" Access="Protected" /> <actions:ActionsBar Name="Actions" Access="Protected" />
<chat:ResizableChatBox Name="Chat" Access="Protected" Main="True" /> <chat:ResizableChatBox Name="Chat" Access="Protected" />
<alerts:AlertsUI Name="Alerts" Access="Protected" /> <alerts:AlertsUI Name="Alerts" Access="Protected" />
</screens:DefaultGameScreen> </screens:DefaultGameScreen>

View File

@@ -13,6 +13,8 @@ public sealed partial class DefaultGameScreen : UIScreen
AutoscaleMaxResolution = new Vector2i(1080, 770); AutoscaleMaxResolution = new Vector2i(1080, 770);
SetAnchorPreset(MainViewport, LayoutPreset.Wide);
SetAnchorPreset(ViewportContainer, LayoutPreset.Wide);
SetAnchorAndMarginPreset(TopBar, LayoutPreset.TopLeft, margin: 10); SetAnchorAndMarginPreset(TopBar, LayoutPreset.TopLeft, margin: 10);
SetAnchorAndMarginPreset(Actions, LayoutPreset.BottomLeft, margin: 10); SetAnchorAndMarginPreset(Actions, LayoutPreset.BottomLeft, margin: 10);
SetAnchorAndMarginPreset(Ghost, LayoutPreset.BottomWide, margin: 80); SetAnchorAndMarginPreset(Ghost, LayoutPreset.BottomWide, margin: 80);

View File

@@ -0,0 +1,13 @@
namespace Content.Client.UserInterface.Screens;
public enum ScreenType
{
/// <summary>
/// The modern SS14 user interface.
/// </summary>
Default,
/// <summary>
/// The classic SS13 user interface.
/// </summary>
Separated
}

View File

@@ -0,0 +1,35 @@
<screens:SeparatedChatGameScreen
xmlns="https://spacestation14.io"
xmlns:screens="clr-namespace:Content.Client.UserInterface.Screens"
xmlns:menuBar="clr-namespace:Content.Client.UserInterface.Systems.MenuBar.Widgets"
xmlns:actions="clr-namespace:Content.Client.UserInterface.Systems.Actions.Widgets"
xmlns:chat="clr-namespace:Content.Client.UserInterface.Systems.Chat.Widgets"
xmlns:alerts="clr-namespace:Content.Client.UserInterface.Systems.Alerts.Widgets"
xmlns:hotbar="clr-namespace:Content.Client.UserInterface.Systems.Hotbar.Widgets"
xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Ghost.Widgets"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
Name="SeparatedChatHud"
VerticalExpand="False"
VerticalAlignment="Bottom"
HorizontalAlignment="Center">
<SplitContainer Name="ScreenContainer" HorizontalExpand="True" VerticalExpand="True">
<LayoutContainer Name="ViewportContainer" HorizontalExpand="True" VerticalExpand="True">
<controls:MainViewport Name="MainViewport"/>
<widgets:GhostGui Name="Ghost" Access="Protected" />
<hotbar:HotbarGui Name="Hotbar" Access="Protected" />
<actions:ActionsBar Name="Actions" Access="Protected" />
<alerts:AlertsUI Name="Alerts" Access="Protected" />
</LayoutContainer>
<PanelContainer HorizontalExpand="True">
<PanelContainer.PanelOverride>
<graphics:StyleBoxFlat BackgroundColor="#2B2C3B" />
</PanelContainer.PanelOverride>
<BoxContainer Orientation="Vertical" HorizontalExpand="True" MinWidth="300" SeparationOverride="10" Margin="10">
<menuBar:GameTopMenuBar Name="TopBar" HorizontalExpand="True" Access="Protected" />
<chat:ChatBox VerticalExpand="True" HorizontalExpand="True" Name="Chat" Access="Protected" />
</BoxContainer>
</PanelContainer>
</SplitContainer>
</screens:SeparatedChatGameScreen>

View File

@@ -0,0 +1,24 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.UserInterface.Screens;
[GenerateTypedNameReferences]
public sealed partial class SeparatedChatGameScreen : UIScreen
{
public SeparatedChatGameScreen()
{
RobustXamlLoader.Load(this);
AutoscaleMaxResolution = new Vector2i(1080, 770);
SetAnchorPreset(ScreenContainer, LayoutPreset.Wide);
SetAnchorPreset(ViewportContainer, LayoutPreset.Wide);
SetAnchorPreset(MainViewport, LayoutPreset.Wide);
SetAnchorAndMarginPreset(Actions, LayoutPreset.BottomLeft, margin: 10);
SetAnchorAndMarginPreset(Ghost, LayoutPreset.BottomWide, margin: 80);
SetAnchorAndMarginPreset(Hotbar, LayoutPreset.BottomWide, margin: 5);
SetAnchorAndMarginPreset(Alerts, LayoutPreset.CenterRight, margin: 10);
}
}

View File

@@ -52,7 +52,7 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
private ActionsWindow? _window; private ActionsWindow? _window;
private ActionsBar? _actionsBar; private ActionsBar? _actionsBar;
private MenuButton? _actionButton; private MenuButton? ActionButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.ActionButton;
private ActionPage CurrentPage => _pages[_currentPageIndex]; private ActionPage CurrentPage => _pages[_currentPageIndex];
public bool IsDragging => _menuDragHelper.IsDragging; public bool IsDragging => _menuDragHelper.IsDragging;
@@ -88,7 +88,6 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
DebugTools.Assert(_window == null); DebugTools.Assert(_window == null);
_window = UIManager.CreateWindow<ActionsWindow>(); _window = UIManager.CreateWindow<ActionsWindow>();
_actionButton = UIManager.GetActiveUIWidget<MenuBar.Widgets.GameTopMenuBar>().ActionButton;
_actionsBar = UIManager.GetActiveUIWidget<ActionsBar>(); _actionsBar = UIManager.GetActiveUIWidget<ActionsBar>();
LayoutContainer.SetAnchorPreset(_window, LayoutContainer.LayoutPreset.CenterTop); LayoutContainer.SetAnchorPreset(_window, LayoutContainer.LayoutPreset.CenterTop);
@@ -97,7 +96,6 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
_window.ClearButton.OnPressed += OnClearPressed; _window.ClearButton.OnPressed += OnClearPressed;
_window.SearchBar.OnTextChanged += OnSearchChanged; _window.SearchBar.OnTextChanged += OnSearchChanged;
_window.FilterButton.OnItemSelected += OnFilterSelected; _window.FilterButton.OnItemSelected += OnFilterSelected;
_actionButton.OnPressed += ActionButtonPressed;
_actionsBar.PageButtons.LeftArrow.OnPressed += OnLeftArrowPressed; _actionsBar.PageButtons.LeftArrow.OnPressed += OnLeftArrowPressed;
_actionsBar.PageButtons.RightArrow.OnPressed += OnRightArrowPressed; _actionsBar.PageButtons.RightArrow.OnPressed += OnRightArrowPressed;
@@ -146,16 +144,36 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
.Register<ActionUIController>(); .Register<ActionUIController>();
} }
public void UnloadButton()
{
if (ActionButton == null)
{
return;
}
ActionButton.OnPressed -= ActionButtonPressed;
}
public void LoadButton()
{
if (ActionButton == null)
{
return;
}
ActionButton.OnPressed += ActionButtonPressed;
}
private void OnWindowOpened() private void OnWindowOpened()
{ {
if (_actionButton != null) if (ActionButton != null)
_actionButton.Pressed = true; ActionButton.Pressed = true;
} }
private void OnWindowClosed() private void OnWindowClosed()
{ {
if (_actionButton != null) if (ActionButton != null)
_actionButton.Pressed = false; ActionButton.Pressed = false;
} }
public void OnStateExited(GameplayState state) public void OnStateExited(GameplayState state)
@@ -186,12 +204,6 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
_actionsBar.PageButtons.RightArrow.OnPressed += OnRightArrowPressed; _actionsBar.PageButtons.RightArrow.OnPressed += OnRightArrowPressed;
} }
if (_actionButton != null)
{
_actionButton.OnPressed -= ActionButtonPressed;
_actionButton.Pressed = false;
}
CommandBinds.Unregister<ActionUIController>(); CommandBinds.Unregister<ActionUIController>();
} }
@@ -607,12 +619,37 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
_dragShadow.Visible = false; _dragShadow.Visible = false;
} }
public void ReloadActionContainer()
{
RegisterActionContainer();
}
public void RegisterActionContainer()
{
if (UIManager.ActiveScreen == null)
{
return;
}
var widget = UIManager.ActiveScreen.GetWidget<ActionsBar>();
if (widget == null)
{
return;
}
_actionsSystem?.UnlinkAllActions();
RegisterActionContainer(widget.ActionsContainer);
_actionsSystem?.LinkAllActions();
}
public void RegisterActionContainer(ActionButtonContainer container) public void RegisterActionContainer(ActionButtonContainer container)
{ {
if (_container != null) if (_container != null)
{ {
Logger.Warning("Action container already defined for UI controller"); _container.ActionPressed -= OnActionPressed;
return; _container.ActionUnpressed -= OnActionPressed;
} }
_container = container; _container = container;

View File

@@ -30,14 +30,13 @@ public sealed class AdminUIController : UIController, IOnStateEntered<GameplaySt
[UISystemDependency] private readonly VerbSystem _verbs = default!; [UISystemDependency] private readonly VerbSystem _verbs = default!;
private AdminMenuWindow? _window; private AdminMenuWindow? _window;
private MenuButton? _adminButton; private MenuButton? AdminButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.AdminButton;
public void OnStateEntered(GameplayState state) public void OnStateEntered(GameplayState state)
{ {
DebugTools.Assert(_window == null); DebugTools.Assert(_window == null);
_window = UIManager.CreateWindow<AdminMenuWindow>(); _window = UIManager.CreateWindow<AdminMenuWindow>();
_adminButton = UIManager.GetActiveUIWidget<MenuBar.Widgets.GameTopMenuBar>().AdminButton;
LayoutContainer.SetAnchorPreset(_window, LayoutContainer.LayoutPreset.Center); LayoutContainer.SetAnchorPreset(_window, LayoutContainer.LayoutPreset.Center);
_window.PlayerTabControl.OnEntryPressed += PlayerTabEntryPressed; _window.PlayerTabControl.OnEntryPressed += PlayerTabEntryPressed;
@@ -45,7 +44,6 @@ public sealed class AdminUIController : UIController, IOnStateEntered<GameplaySt
_window.OnOpen += OnWindowOpen; _window.OnOpen += OnWindowOpen;
_window.OnClose += OnWindowClosed; _window.OnClose += OnWindowClosed;
_admin.AdminStatusUpdated += AdminStatusUpdated; _admin.AdminStatusUpdated += AdminStatusUpdated;
_adminButton.OnPressed += AdminButtonPressed;
_input.SetInputCommand(ContentKeyFunctions.OpenAdminMenu, _input.SetInputCommand(ContentKeyFunctions.OpenAdminMenu,
InputCmdHandler.FromDelegate(_ => Toggle())); InputCmdHandler.FromDelegate(_ => Toggle()));
@@ -53,16 +51,36 @@ public sealed class AdminUIController : UIController, IOnStateEntered<GameplaySt
AdminStatusUpdated(); AdminStatusUpdated();
} }
public void UnloadButton()
{
if (AdminButton == null)
{
return;
}
AdminButton.OnPressed -= AdminButtonPressed;
}
public void LoadButton()
{
if (AdminButton == null)
{
return;
}
AdminButton.OnPressed += AdminButtonPressed;
}
private void OnWindowOpen() private void OnWindowOpen()
{ {
if (_adminButton != null) if (AdminButton != null)
_adminButton.Pressed = true; AdminButton.Pressed = true;
} }
private void OnWindowClosed() private void OnWindowClosed()
{ {
if (_adminButton != null) if (AdminButton != null)
_adminButton.Pressed = false; AdminButton.Pressed = false;
} }
public void OnStateExited(GameplayState state) public void OnStateExited(GameplayState state)
@@ -80,19 +98,12 @@ public sealed class AdminUIController : UIController, IOnStateEntered<GameplaySt
_admin.AdminStatusUpdated -= AdminStatusUpdated; _admin.AdminStatusUpdated -= AdminStatusUpdated;
if (_adminButton != null)
{
_adminButton.Pressed = false;
_adminButton.OnPressed -= AdminButtonPressed;
_adminButton = null;
}
CommandBinds.Unregister<AdminUIController>(); CommandBinds.Unregister<AdminUIController>();
} }
private void AdminStatusUpdated() private void AdminStatusUpdated()
{ {
_adminButton!.Visible = _conGroups.CanAdminMenu(); AdminButton!.Visible = _conGroups.CanAdminMenu();
} }
private void AdminButtonPressed(ButtonEventArgs args) private void AdminButtonPressed(ButtonEventArgs args)

View File

@@ -49,6 +49,11 @@ public sealed class AlertsUIController : UIController, IOnStateEntered<GameplayS
} }
// initially populate the frame if system is available // initially populate the frame if system is available
SyncAlerts();
}
public void SyncAlerts()
{
var alerts = _alertsSystem?.ActiveAlerts; var alerts = _alertsSystem?.ActiveAlerts;
if (alerts != null) if (alerts != null)
{ {

View File

@@ -29,14 +29,12 @@ public sealed class AHelpUIController: UIController, IOnStateChanged<GameplaySta
[Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IClyde _clyde = default!; [Dependency] private readonly IClyde _clyde = default!;
private BwoinkSystem? _bwoinkSystem; private BwoinkSystem? _bwoinkSystem;
private MenuButton? _ahelpButton; private MenuButton? AhelpButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.AHelpButton;
private IAHelpUIHandler? _uiHelper; private IAHelpUIHandler? _uiHelper;
public void OnStateEntered(GameplayState state) public void OnStateEntered(GameplayState state)
{ {
DebugTools.Assert(_uiHelper == null); DebugTools.Assert(_uiHelper == null);
_ahelpButton = UIManager.GetActiveUIWidget<MenuBar.Widgets.GameTopMenuBar>().AHelpButton;
_ahelpButton.OnPressed += AHelpButtonPressed;
_adminManager.AdminStatusUpdated += OnAdminStatusUpdated; _adminManager.AdminStatusUpdated += OnAdminStatusUpdated;
CommandBinds.Builder CommandBinds.Builder
@@ -45,6 +43,26 @@ public sealed class AHelpUIController: UIController, IOnStateChanged<GameplaySta
.Register<AHelpUIController>(); .Register<AHelpUIController>();
} }
public void UnloadButton()
{
if (AhelpButton == null)
{
return;
}
AhelpButton.OnPressed -= AHelpButtonPressed;
}
public void LoadButton()
{
if (AhelpButton == null)
{
return;
}
AhelpButton.OnPressed += AHelpButtonPressed;
}
private void OnAdminStatusUpdated() private void OnAdminStatusUpdated()
{ {
if (_uiHelper is not { IsOpen: true }) if (_uiHelper is not { IsOpen: true })
@@ -60,9 +78,7 @@ public sealed class AHelpUIController: UIController, IOnStateChanged<GameplaySta
public void OnStateExited(GameplayState state) public void OnStateExited(GameplayState state)
{ {
DebugTools.Assert(_ahelpButton != null);
SetAHelpPressed(false); SetAHelpPressed(false);
_ahelpButton!.OnPressed -= AHelpButtonPressed;
_adminManager.AdminStatusUpdated -= OnAdminStatusUpdated; _adminManager.AdminStatusUpdated -= OnAdminStatusUpdated;
_uiHelper?.Dispose(); _uiHelper?.Dispose();
_uiHelper = null; _uiHelper = null;
@@ -83,10 +99,10 @@ public sealed class AHelpUIController: UIController, IOnStateChanged<GameplaySta
private void SetAHelpPressed(bool pressed) private void SetAHelpPressed(bool pressed)
{ {
if (_ahelpButton == null || _ahelpButton.Pressed == pressed) if (AhelpButton == null || AhelpButton.Pressed == pressed)
return; return;
_ahelpButton.StyleClasses.Remove(MenuButton.StyleClassRedTopButton); AhelpButton.StyleClasses.Remove(MenuButton.StyleClassRedTopButton);
_ahelpButton.Pressed = pressed; AhelpButton.Pressed = pressed;
} }
private void RecievedBwoink(object? sender, SharedBwoinkSystem.BwoinkTextMessage message) private void RecievedBwoink(object? sender, SharedBwoinkSystem.BwoinkTextMessage message)
@@ -106,7 +122,7 @@ public sealed class AHelpUIController: UIController, IOnStateChanged<GameplaySta
EnsureUIHelper(); EnsureUIHelper();
if (!_uiHelper!.IsOpen) if (!_uiHelper!.IsOpen)
{ {
_ahelpButton?.StyleClasses.Add(MenuButton.StyleClassRedTopButton); AhelpButton?.StyleClasses.Add(MenuButton.StyleClassRedTopButton);
} }
_uiHelper!.Receive(message); _uiHelper!.Receive(message);
} }

View File

@@ -23,19 +23,16 @@ public sealed class CharacterUIController : UIController, IOnStateEntered<Gamepl
[UISystemDependency] private readonly CharacterInfoSystem _characterInfo = default!; [UISystemDependency] private readonly CharacterInfoSystem _characterInfo = default!;
private CharacterWindow? _window; private CharacterWindow? _window;
private MenuButton? _characterButton; private MenuButton? CharacterButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.CharacterButton;
public void OnStateEntered(GameplayState state) public void OnStateEntered(GameplayState state)
{ {
DebugTools.Assert(_window == null); DebugTools.Assert(_window == null);
_characterButton = UIManager.GetActiveUIWidget<MenuBar.Widgets.GameTopMenuBar>().CharacterButton;
_characterButton.OnPressed += CharacterButtonPressed;
_window = UIManager.CreateWindow<CharacterWindow>(); _window = UIManager.CreateWindow<CharacterWindow>();
LayoutContainer.SetAnchorPreset(_window, LayoutContainer.LayoutPreset.CenterTop); LayoutContainer.SetAnchorPreset(_window, LayoutContainer.LayoutPreset.CenterTop);
_window.OnClose += () => { _characterButton.Pressed = false; };
_window.OnOpen += () => { _characterButton.Pressed = true; };
CommandBinds.Builder CommandBinds.Builder
.Bind(ContentKeyFunctions.OpenCharacterMenu, .Bind(ContentKeyFunctions.OpenCharacterMenu,
@@ -51,13 +48,6 @@ public sealed class CharacterUIController : UIController, IOnStateEntered<Gamepl
_window = null; _window = null;
} }
if (_characterButton != null)
{
_characterButton.OnPressed -= CharacterButtonPressed;
_characterButton.Pressed = false;
_characterButton = null;
}
CommandBinds.Unregister<CharacterUIController>(); CommandBinds.Unregister<CharacterUIController>();
} }
@@ -73,6 +63,37 @@ public sealed class CharacterUIController : UIController, IOnStateEntered<Gamepl
system.OnCharacterDetached -= CharacterDetached; system.OnCharacterDetached -= CharacterDetached;
} }
public void UnloadButton()
{
if (CharacterButton == null)
{
return;
}
CharacterButton.OnPressed -= CharacterButtonPressed;
}
public void LoadButton()
{
if (CharacterButton == null)
{
return;
}
CharacterButton.OnPressed += CharacterButtonPressed;
if (_window == null)
{
return;
}
_window.OnClose += DeactivateButton;
_window.OnOpen += ActivateButton;
}
private void DeactivateButton() => CharacterButton!.Pressed = false;
private void ActivateButton() => CharacterButton!.Pressed = true;
private void CharacterUpdated(CharacterData data) private void CharacterUpdated(CharacterData data)
{ {
if (_window == null) if (_window == null)
@@ -141,6 +162,12 @@ public sealed class CharacterUIController : UIController, IOnStateEntered<Gamepl
{ {
if (_window == null) if (_window == null)
return; return;
if (CharacterButton != null)
{
CharacterButton.Pressed = !_window.IsOpen;
}
if (_window.IsOpen) if (_window.IsOpen)
{ {
CloseWindow(); CloseWindow();

View File

@@ -186,6 +186,22 @@ public sealed class ChatUIController : UIController
InputCmdHandler.FromDelegate(_ => CycleChatChannel(false))); InputCmdHandler.FromDelegate(_ => CycleChatChannel(false)));
} }
public void SetMainChat(bool setting)
{
// This isn't very nice to look at.
var widget = UIManager.ActiveScreen?.GetWidget<ChatBox>();
if (widget == null)
{
widget = UIManager.ActiveScreen?.GetWidget<ResizableChatBox>();
if (widget == null)
{
return;
}
}
widget.Main = setting;
}
private void FocusChat() private void FocusChat()
{ {
foreach (var chat in _chats) foreach (var chat in _chats)
@@ -230,13 +246,13 @@ public sealed class ChatUIController : UIController
} }
UpdateChannelPermissions(); UpdateChannelPermissions();
}
if (_speechBubbleRoot.Parent == UIManager.StateRoot) public void SetSpeechBubbleRoot(LayoutContainer root)
return; {
_speechBubbleRoot.Orphan(); _speechBubbleRoot.Orphan();
root.AddChild(_speechBubbleRoot);
LayoutContainer.SetAnchorPreset(_speechBubbleRoot, LayoutContainer.LayoutPreset.Wide); LayoutContainer.SetAnchorPreset(_speechBubbleRoot, LayoutContainer.LayoutPreset.Wide);
UIManager.StateRoot.AddChild(_speechBubbleRoot);
_speechBubbleRoot.SetPositionLast(); _speechBubbleRoot.SetPositionLast();
} }
@@ -701,6 +717,11 @@ public sealed class ChatUIController : UIController
return MapLocalIfGhost(PreferredChannel); return MapLocalIfGhost(PreferredChannel);
} }
public void NotifyChatTextChange()
{
_typingIndicator?.ClientChangedChatText();
}
private readonly record struct SpeechBubbleData(string Message, SpeechBubble.SpeechType Type); private readonly record struct SpeechBubbleData(string Message, SpeechBubble.SpeechType Type);
private sealed class SpeechBubbleQueueData private sealed class SpeechBubbleQueueData

View File

@@ -4,15 +4,17 @@
xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Chat.Widgets" xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Chat.Widgets"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Systems.Chat.Controls" xmlns:controls="clr-namespace:Content.Client.UserInterface.Systems.Chat.Controls"
MouseFilter="Stop" MouseFilter="Stop"
HorizontalExpand="True"
VerticalExpand="True"
MinSize="465 225"> MinSize="465 225">
<PanelContainer> <PanelContainer HorizontalExpand="True" VerticalExpand="True">
<PanelContainer.PanelOverride> <PanelContainer.PanelOverride>
<graphics:StyleBoxFlat BackgroundColor="#25252AAA" /> <graphics:StyleBoxFlat BackgroundColor="#25252AAA" />
</PanelContainer.PanelOverride> </PanelContainer.PanelOverride>
<BoxContainer Orientation="Vertical" SeparationOverride="4"> <BoxContainer Orientation="Vertical" SeparationOverride="4" HorizontalExpand="True" VerticalExpand="True">
<OutputPanel Name="Contents" VerticalExpand="True" /> <OutputPanel Name="Contents" HorizontalExpand="True" VerticalExpand="True" />
<controls:ChatInputBox Name="ChatInput" Access="Public" Margin="2"/> <controls:ChatInputBox HorizontalExpand="True" Name="ChatInput" Access="Public" Margin="2"/>
</BoxContainer> </BoxContainer>
</PanelContainer> </PanelContainer>
</widgets:ChatBox> </widgets:ChatBox>

View File

@@ -5,6 +5,7 @@ using Content.Shared.Chat;
using Content.Shared.Input; using Content.Shared.Input;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML; using Robust.Client.UserInterface.XAML;
using Robust.Shared.Input; using Robust.Shared.Input;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -14,7 +15,7 @@ namespace Content.Client.UserInterface.Systems.Chat.Widgets;
[GenerateTypedNameReferences] [GenerateTypedNameReferences]
#pragma warning disable RA0003 #pragma warning disable RA0003
public partial class ChatBox : Control public partial class ChatBox : UIWidget
#pragma warning restore RA0003 #pragma warning restore RA0003
{ {
private readonly ChatUIController _controller; private readonly ChatUIController _controller;
@@ -197,7 +198,7 @@ public partial class ChatBox : Control
UpdateSelectedChannel(); UpdateSelectedChannel();
// Warn typing indicator about change // Warn typing indicator about change
EntitySystem.Get<TypingIndicatorSystem>().ClientChangedChatText(); _controller.NotifyChatTextChange();
} }
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)

View File

@@ -11,24 +11,50 @@ namespace Content.Client.UserInterface.Systems.Crafting;
public sealed class CraftingUIController : UIController, IOnStateChanged<GameplayState> public sealed class CraftingUIController : UIController, IOnStateChanged<GameplayState>
{ {
private ConstructionMenuPresenter? _presenter; private ConstructionMenuPresenter? _presenter;
private MenuButton? _craftingButton; private MenuButton? CraftingButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.CraftingButton;
public void OnStateEntered(GameplayState state) public void OnStateEntered(GameplayState state)
{ {
DebugTools.Assert(_presenter == null); DebugTools.Assert(_presenter == null);
_presenter = new ConstructionMenuPresenter(); _presenter = new ConstructionMenuPresenter();
_craftingButton = UIManager.GetActiveUIWidget<MenuBar.Widgets.GameTopMenuBar>().CraftingButton;
_craftingButton.OnToggled += _presenter.OnHudCraftingButtonToggled;
} }
public void OnStateExited(GameplayState state) public void OnStateExited(GameplayState state)
{ {
if (_presenter == null) if (_presenter == null)
return; return;
_craftingButton!.Pressed = false; UnloadButton(_presenter);
_craftingButton!.OnToggled -= _presenter.OnHudCraftingButtonToggled;
_craftingButton = null;
_presenter.Dispose(); _presenter.Dispose();
_presenter = null; _presenter = null;
} }
internal void UnloadButton(ConstructionMenuPresenter? presenter = null)
{
if (CraftingButton == null)
{
return;
}
if (presenter == null)
{
presenter ??= _presenter;
if (presenter == null)
{
return;
}
}
CraftingButton.Pressed = false;
CraftingButton.OnToggled -= presenter.OnHudCraftingButtonToggled;
}
public void LoadButton()
{
if (CraftingButton == null || _presenter == null)
{
return;
}
CraftingButton.OnToggled += _presenter.OnHudCraftingButtonToggled;
}
} }

View File

@@ -26,17 +26,53 @@ public sealed class EscapeUIController : UIController, IOnStateEntered<GameplayS
private Options.UI.EscapeMenu? _escapeWindow; private Options.UI.EscapeMenu? _escapeWindow;
private MenuButton? _escapeButton; private MenuButton? EscapeButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.EscapeButton;
public void UnloadButton()
{
if (EscapeButton == null)
{
return;
}
EscapeButton.Pressed = false;
EscapeButton.OnPressed += EscapeButtonOnOnPressed;
if (_escapeWindow == null)
{
return;
}
_escapeWindow.OnClose -= DeactivateButton;
_escapeWindow.OnOpen -= ActivateButton;
}
public void LoadButton()
{
if (EscapeButton == null)
{
return;
}
EscapeButton.OnPressed += EscapeButtonOnOnPressed;
if (_escapeWindow == null)
{
return;
}
_escapeWindow.OnClose += DeactivateButton;
_escapeWindow.OnOpen += ActivateButton;
}
private void ActivateButton() => EscapeButton!.Pressed = true;
private void DeactivateButton() => EscapeButton!.Pressed = false;
public void OnStateEntered(GameplayState state) public void OnStateEntered(GameplayState state)
{ {
DebugTools.Assert(_escapeWindow == null); DebugTools.Assert(_escapeWindow == null);
_escapeButton = UIManager.GetActiveUIWidget<MenuBar.Widgets.GameTopMenuBar>().EscapeButton;
_escapeButton.OnPressed += EscapeButtonOnOnPressed;
_escapeWindow = UIManager.CreateWindow<Options.UI.EscapeMenu>(); _escapeWindow = UIManager.CreateWindow<Options.UI.EscapeMenu>();
_escapeWindow.OnClose += () => { _escapeButton.Pressed = false; };
_escapeWindow.OnOpen += () => { _escapeButton.Pressed = true; };
_escapeWindow.ChangelogButton.OnPressed += _ => _escapeWindow.ChangelogButton.OnPressed += _ =>
{ {
@@ -87,13 +123,6 @@ public sealed class EscapeUIController : UIController, IOnStateEntered<GameplayS
_escapeWindow = null; _escapeWindow = null;
} }
if (_escapeButton != null)
{
_escapeButton.OnPressed -= EscapeButtonOnOnPressed;
_escapeButton.Pressed = false;
_escapeButton = null;
}
CommandBinds.Unregister<EscapeUIController>(); CommandBinds.Unregister<EscapeUIController>();
} }
@@ -119,7 +148,7 @@ public sealed class EscapeUIController : UIController, IOnStateEntered<GameplayS
else else
{ {
_escapeWindow.OpenCentered(); _escapeWindow.OpenCentered();
_escapeButton!.Pressed = true; EscapeButton!.Pressed = true;
} }
} }
} }

View File

@@ -36,9 +36,15 @@ public sealed class GhostUIController : UIController, IOnStateChanged<GameplaySt
system.GhostRoleCountUpdated -= OnRoleCountUpdated; system.GhostRoleCountUpdated -= OnRoleCountUpdated;
} }
private void UpdateGui() public void UpdateGui()
{ {
Gui?.Update(_system?.AvailableGhostRoleCount, _system?.Player?.CanReturnToBody); if (Gui == null)
{
return;
}
Gui.Visible = _system?.IsGhost ?? false;
Gui.Update(_system?.AvailableGhostRoleCount, _system?.Player?.CanReturnToBody);
} }
private void OnPlayerRemoved(GhostComponent component) private void OnPlayerRemoved(GhostComponent component)
@@ -95,7 +101,6 @@ public sealed class GhostUIController : UIController, IOnStateChanged<GameplaySt
Gui.GhostRolesPressed += GhostRolesPressed; Gui.GhostRolesPressed += GhostRolesPressed;
Gui.TargetWindow.WarpClicked += OnWarpClicked; Gui.TargetWindow.WarpClicked += OnWarpClicked;
Gui.Visible = _system?.IsGhost ?? false;
UpdateGui(); UpdateGui();
} }

View File

@@ -10,6 +10,12 @@ public sealed class HandsContainer : ItemSlotUIContainer<HandButton>
public int ColumnLimit { get => _grid.Columns; set => _grid.Columns = value; } public int ColumnLimit { get => _grid.Columns; set => _grid.Columns = value; }
public int MaxButtonCount { get; set; } = 0; public int MaxButtonCount { get; set; } = 0;
/// <summary>
/// Indexer. This is used to reference a HandsContainer from the
/// controller.
/// </summary>
public string? Indexer { get; set; }
public HandsContainer() public HandsContainer()
{ {
AddChild(_grid = new GridContainer()); AddChild(_grid = new GridContainer());

View File

@@ -238,11 +238,59 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
if (!_handLookup.TryAdd(handName, button)) if (!_handLookup.TryAdd(handName, button))
throw new Exception("Tried to add hand with duplicate name to UI. Name:" + handName); throw new Exception("Tried to add hand with duplicate name to UI. Name:" + handName);
if (HandsGui != null)
{
HandsGui.HandContainer.AddButton(button);
}
else
{
GetFirstAvailableContainer().AddButton(button); GetFirstAvailableContainer().AddButton(button);
}
return button; return button;
} }
/// <summary>
/// Reload all hands.
/// </summary>
public void ReloadHands()
{
UnloadPlayerHands();
_handsSystem.ReloadHandButtons();
}
/// <summary>
/// Swap hands from one container to the other.
/// </summary>
/// <param name="other"></param>
/// <param name="source"></param>
public void SwapHands(HandsContainer other, HandsContainer? source = null)
{
if (HandsGui == null && source == null)
{
throw new ArgumentException("Cannot swap hands if no source hand container exists!");
}
source ??= HandsGui!.HandContainer;
var transfer = new List<Control>();
foreach (var child in source.Children)
{
if (child is not HandButton)
{
continue;
}
transfer.Add(child);
}
foreach (var control in transfer)
{
source.RemoveChild(control);
other.AddChild(control);
}
}
private void RemoveHand(string handName) private void RemoveHand(string handName)
{ {
RemoveHand(handName, out _); RemoveHand(handName, out _);
@@ -266,15 +314,15 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
public string RegisterHandContainer(HandsContainer handContainer) public string RegisterHandContainer(HandsContainer handContainer)
{ {
var name = "HandContainer_" + _backupSuffix; var name = "HandContainer_" + _backupSuffix;
;
if (handContainer.Name == null) if (handContainer.Indexer == null)
{ {
handContainer.Name = name; handContainer.Indexer = name;
_backupSuffix++; _backupSuffix++;
} }
else else
{ {
name = handContainer.Name; name = handContainer.Indexer;
} }
_handContainerIndices.Add(name, _handsContainers.Count); _handContainerIndices.Add(name, _handsContainers.Count);

View File

@@ -1,7 +1,9 @@
using Content.Client.UserInterface.Systems.Hands; using Content.Client.UserInterface.Systems.Hands;
using Content.Client.UserInterface.Systems.Hands.Controls; using Content.Client.UserInterface.Systems.Hands.Controls;
using Content.Client.UserInterface.Systems.Hotbar.Widgets;
using Content.Client.UserInterface.Systems.Inventory; using Content.Client.UserInterface.Systems.Inventory;
using Content.Client.UserInterface.Systems.Inventory.Controls; using Content.Client.UserInterface.Systems.Inventory.Controls;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controllers; using Robust.Client.UserInterface.Controllers;
namespace Content.Client.UserInterface.Systems.Hotbar; namespace Content.Client.UserInterface.Systems.Hotbar;
@@ -18,4 +20,46 @@ public sealed class HotbarUIController : UIController
_hands.RegisterHandContainer(handsContainer); _hands.RegisterHandContainer(handsContainer);
_inventory.RegisterInventoryBarContainer(inventoryBar); _inventory.RegisterInventoryBarContainer(inventoryBar);
} }
public void ReloadHotbar()
{
if (UIManager.ActiveScreen == null)
{
return;
}
var hotbar = UIManager.ActiveScreen.GetWidget<HotbarGui>();
if (hotbar == null)
{
return;
}
foreach (var container in GetAllItemSlotContainers(hotbar))
{
// Yes, this is dirty.
container.SlotGroup = container.SlotGroup;
}
_hands?.ReloadHands();
_inventory?.ReloadSlots();
_inventory?.RegisterInventoryBarContainer(hotbar.InventoryHotbar);
}
private IEnumerable<ItemSlotButtonContainer> GetAllItemSlotContainers(Control gui)
{
var result = new List<ItemSlotButtonContainer>();
foreach (var child in gui.Children)
{
if (child is ItemSlotButtonContainer container)
{
result.Add(container);
}
result.AddRange(GetAllItemSlotContainers(child));
}
return result;
}
} }

View File

@@ -15,6 +15,7 @@
/> />
<inventory:ItemSlotButtonContainer <inventory:ItemSlotButtonContainer
Name="InventoryHotbar" Name="InventoryHotbar"
Access="Public"
Visible="False" Visible="False"
Columns="10" Columns="10"
SlotGroup="Default" SlotGroup="Default"
@@ -34,7 +35,7 @@
HorizontalExpand="True"/> HorizontalExpand="True"/>
<hands:HandsContainer <hands:HandsContainer
Name="HandContainer" Name="HandContainer"
Access="Protected" Access="Public"
HorizontalAlignment="Center" HorizontalAlignment="Center"
ColumnLimit="6" /> ColumnLimit="6" />
<inventory:ItemSlotButtonContainer <inventory:ItemSlotButtonContainer

View File

@@ -31,20 +31,18 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
private StrippingWindow? _strippingWindow; private StrippingWindow? _strippingWindow;
private ItemSlotButtonContainer? _inventoryHotbar; private ItemSlotButtonContainer? _inventoryHotbar;
private MenuButton? _inventoryButton; private MenuButton? InventoryButton => UIManager.ActiveScreen?.GetWidget<MenuBar.Widgets.GameTopMenuBar>()?.InventoryButton;
public void OnStateEntered(GameplayState state) public void OnStateEntered(GameplayState state)
{ {
DebugTools.Assert(_strippingWindow == null); DebugTools.Assert(_strippingWindow == null);
_strippingWindow = UIManager.CreateWindow<StrippingWindow>(); _strippingWindow = UIManager.CreateWindow<StrippingWindow>();
_inventoryButton = UIManager.GetActiveUIWidget<MenuBar.Widgets.GameTopMenuBar>().InventoryButton;
LayoutContainer.SetAnchorPreset(_strippingWindow, LayoutContainer.LayoutPreset.Center); LayoutContainer.SetAnchorPreset(_strippingWindow, LayoutContainer.LayoutPreset.Center);
//bind open inventory key to OpenInventoryMenu; //bind open inventory key to OpenInventoryMenu;
CommandBinds.Builder CommandBinds.Builder
.Bind(ContentKeyFunctions.OpenInventoryMenu, InputCmdHandler.FromDelegate(_ => ToggleInventoryBar())) .Bind(ContentKeyFunctions.OpenInventoryMenu, InputCmdHandler.FromDelegate(_ => ToggleInventoryBar()))
.Register<ClientInventorySystem>(); .Register<ClientInventorySystem>();
_inventoryButton.OnPressed += InventoryButtonPressed;
} }
public void OnStateExited(GameplayState state) public void OnStateExited(GameplayState state)
@@ -60,14 +58,27 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
_inventoryHotbar.Visible = false; _inventoryHotbar.Visible = false;
} }
if (_inventoryButton != null) CommandBinds.Unregister<ClientInventorySystem>();
{
_inventoryButton.OnPressed -= InventoryButtonPressed;
_inventoryButton.Pressed = false;
_inventoryButton = null;
} }
CommandBinds.Unregister<ClientInventorySystem>(); public void UnloadButton()
{
if (InventoryButton == null)
{
return;
}
InventoryButton.OnPressed -= InventoryButtonPressed;
}
public void LoadButton()
{
if (InventoryButton == null)
{
return;
}
InventoryButton.OnPressed += InventoryButtonPressed;
} }
private SlotButton CreateSlotButton(SlotData data) private SlotButton CreateSlotButton(SlotData data)
@@ -166,14 +177,14 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
if (_inventoryHotbar.Visible) if (_inventoryHotbar.Visible)
{ {
_inventoryHotbar.Visible = false; _inventoryHotbar.Visible = false;
if (_inventoryButton != null) if (InventoryButton != null)
_inventoryButton.Pressed = false; InventoryButton.Pressed = false;
} }
else else
{ {
_inventoryHotbar.Visible = true; _inventoryHotbar.Visible = true;
if (_inventoryButton != null) if (InventoryButton != null)
_inventoryButton.Pressed = true; InventoryButton.Pressed = true;
} }
} }
@@ -279,6 +290,11 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
slotGroup.RemoveButton(data.SlotName); slotGroup.RemoveButton(data.SlotName);
} }
public void ReloadSlots()
{
_inventorySystem.ReloadInventory();
}
private void LoadSlots(ClientInventoryComponent clientInv) private void LoadSlots(ClientInventoryComponent clientInv)
{ {
UnloadSlots(); UnloadSlots();
@@ -322,7 +338,6 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
if (_slotGroups.TryAdd(slotContainer.SlotGroup, slotContainer)) if (_slotGroups.TryAdd(slotContainer.SlotGroup, slotContainer))
return true; return true;
Logger.Warning("Could not add container for slotgroup: " + slotContainer.SlotGroup);
return false; return false;
} }

View File

@@ -0,0 +1,51 @@
using Content.Client.Gameplay;
using Content.Client.UserInterface.Systems.Actions;
using Content.Client.UserInterface.Systems.Admin;
using Content.Client.UserInterface.Systems.Bwoink;
using Content.Client.UserInterface.Systems.Character;
using Content.Client.UserInterface.Systems.Crafting;
using Content.Client.UserInterface.Systems.EscapeMenu;
using Content.Client.UserInterface.Systems.Inventory;
using Content.Client.UserInterface.Systems.MenuBar.Widgets;
using Content.Client.UserInterface.Systems.Sandbox;
using Robust.Client.UserInterface.Controllers;
namespace Content.Client.UserInterface.Systems.MenuBar;
public sealed class GameTopMenuBarUIController : UIController
{
[Dependency] private readonly EscapeUIController _escape = default!;
[Dependency] private readonly InventoryUIController _inventory = default!;
[Dependency] private readonly AdminUIController _admin = default!;
[Dependency] private readonly CharacterUIController _character = default!;
[Dependency] private readonly CraftingUIController _crafting = default!;
[Dependency] private readonly AHelpUIController _ahelp = default!;
[Dependency] private readonly ActionUIController _action = default!;
[Dependency] private readonly SandboxUIController _sandbox = default!;
private GameTopMenuBar? GameTopMenuBar => UIManager.GetActiveUIWidgetOrNull<GameTopMenuBar>();
public void UnloadButtons()
{
_escape.UnloadButton();
_inventory.UnloadButton();
_admin.UnloadButton();
_character.UnloadButton();
_crafting.UnloadButton();
_ahelp.UnloadButton();
_action.UnloadButton();
_sandbox.UnloadButton();
}
public void LoadButtons()
{
_escape.LoadButton();
_inventory.LoadButton();
_admin.LoadButton();
_character.LoadButton();
_crafting.LoadButton();
_ahelp.LoadButton();
_action.LoadButton();
_sandbox.LoadButton();
}
}

View File

@@ -20,6 +20,7 @@
BoundKey = "{x:Static ic:EngineKeyFunctions.EscapeMenu}" BoundKey = "{x:Static ic:EngineKeyFunctions.EscapeMenu}"
ToolTip="{Loc 'game-hud-open-escape-menu-button-tooltip'}" ToolTip="{Loc 'game-hud-open-escape-menu-button-tooltip'}"
MinSize="70 64" MinSize="70 64"
HorizontalExpand="True"
AppendStyleClass="{x:Static style:StyleBase.ButtonOpenRight}" AppendStyleClass="{x:Static style:StyleBase.ButtonOpenRight}"
/> />
<ui:MenuButton <ui:MenuButton
@@ -29,6 +30,7 @@
ToolTip="{Loc 'game-hud-open-character-menu-button-tooltip'}" ToolTip="{Loc 'game-hud-open-character-menu-button-tooltip'}"
BoundKey = "{x:Static is:ContentKeyFunctions.OpenCharacterMenu}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenCharacterMenu}"
MinSize="42 64" MinSize="42 64"
HorizontalExpand="True"
AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}"
/> />
<ui:MenuButton <ui:MenuButton
@@ -38,6 +40,7 @@
BoundKey = "{x:Static is:ContentKeyFunctions.OpenInventoryMenu}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenInventoryMenu}"
ToolTip="{Loc 'game-hud-open-inventory-menu-button-tooltip'}" ToolTip="{Loc 'game-hud-open-inventory-menu-button-tooltip'}"
MinSize="42 64" MinSize="42 64"
HorizontalExpand="True"
AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}"
/> />
<ui:MenuButton <ui:MenuButton
@@ -47,6 +50,7 @@
BoundKey = "{x:Static is:ContentKeyFunctions.OpenCraftingMenu}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenCraftingMenu}"
ToolTip="{Loc 'game-hud-open-crafting-menu-button-tooltip'}" ToolTip="{Loc 'game-hud-open-crafting-menu-button-tooltip'}"
MinSize="42 64" MinSize="42 64"
HorizontalExpand="True"
AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}"
/> />
<ui:MenuButton <ui:MenuButton
@@ -56,6 +60,7 @@
BoundKey = "{x:Static is:ContentKeyFunctions.OpenActionsMenu}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenActionsMenu}"
ToolTip="{Loc 'game-hud-open-actions-menu-button-tooltip'}" ToolTip="{Loc 'game-hud-open-actions-menu-button-tooltip'}"
MinSize="42 64" MinSize="42 64"
HorizontalExpand="True"
AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}"
/> />
<ui:MenuButton <ui:MenuButton
@@ -65,6 +70,7 @@
BoundKey = "{x:Static is:ContentKeyFunctions.OpenAdminMenu}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenAdminMenu}"
ToolTip="{Loc 'game-hud-open-admin-menu-button-tooltip'}" ToolTip="{Loc 'game-hud-open-admin-menu-button-tooltip'}"
MinSize="42 64" MinSize="42 64"
HorizontalExpand="True"
AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}"
/> />
<ui:MenuButton <ui:MenuButton
@@ -74,6 +80,7 @@
BoundKey = "{x:Static is:ContentKeyFunctions.OpenSandboxWindow}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenSandboxWindow}"
ToolTip="{Loc 'game-hud-open-sandbox-menu-button-tooltip'}" ToolTip="{Loc 'game-hud-open-sandbox-menu-button-tooltip'}"
MinSize="42 64" MinSize="42 64"
HorizontalExpand="True"
AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}"
/> />
<ui:MenuButton <ui:MenuButton
@@ -83,6 +90,7 @@
BoundKey = "{x:Static is:ContentKeyFunctions.OpenAHelp}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenAHelp}"
ToolTip="{Loc 'ui-options-function-open-ahelp'}" ToolTip="{Loc 'ui-options-function-open-ahelp'}"
MinSize="42 64" MinSize="42 64"
HorizontalExpand="True"
AppendStyleClass="{x:Static style:StyleBase.ButtonOpenLeft}" AppendStyleClass="{x:Static style:StyleBase.ButtonOpenLeft}"
/> />
</widgets:GameTopMenuBar> </widgets:GameTopMenuBar>

View File

@@ -43,13 +43,11 @@ public sealed class SandboxUIController : UIController, IOnStateChanged<Gameplay
private TileSpawningUIController TileSpawningController => UIManager.GetUIController<TileSpawningUIController>(); private TileSpawningUIController TileSpawningController => UIManager.GetUIController<TileSpawningUIController>();
private DecalPlacerUIController DecalPlacerController => UIManager.GetUIController<DecalPlacerUIController>(); private DecalPlacerUIController DecalPlacerController => UIManager.GetUIController<DecalPlacerUIController>();
private MenuButton? _sandboxButton; private MenuButton? SandboxButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.SandboxButton;
public void OnStateEntered(GameplayState state) public void OnStateEntered(GameplayState state)
{ {
DebugTools.Assert(_window == null); DebugTools.Assert(_window == null);
_sandboxButton = UIManager.GetActiveUIWidget<MenuBar.Widgets.GameTopMenuBar>().SandboxButton;
_sandboxButton.OnPressed += SandboxButtonPressed;
EnsureWindow(); EnsureWindow();
CheckSandboxVisibility(); CheckSandboxVisibility();
@@ -68,13 +66,33 @@ public sealed class SandboxUIController : UIController, IOnStateChanged<Gameplay
.Register<SandboxSystem>(); .Register<SandboxSystem>();
} }
public void UnloadButton()
{
if (SandboxButton == null)
{
return;
}
SandboxButton.OnPressed -= SandboxButtonPressed;
}
public void LoadButton()
{
if (SandboxButton == null)
{
return;
}
SandboxButton.OnPressed += SandboxButtonPressed;
}
private void EnsureWindow() private void EnsureWindow()
{ {
if(_window is { Disposed: false }) if(_window is { Disposed: false })
return; return;
_window = UIManager.CreateWindow<SandboxWindow>(); _window = UIManager.CreateWindow<SandboxWindow>();
_window.OnOpen += () => { _sandboxButton!.Pressed = true; }; _window.OnOpen += () => { SandboxButton!.Pressed = true; };
_window.OnClose += () => { _sandboxButton!.Pressed = false; }; _window.OnClose += () => { SandboxButton!.Pressed = false; };
_window.ToggleLightButton.Pressed = !_light.Enabled; _window.ToggleLightButton.Pressed = !_light.Enabled;
_window.ToggleFovButton.Pressed = !_eye.CurrentEye.DrawFov; _window.ToggleFovButton.Pressed = !_eye.CurrentEye.DrawFov;
_window.ToggleShadowsButton.Pressed = !_light.DrawShadows; _window.ToggleShadowsButton.Pressed = !_light.DrawShadows;
@@ -100,10 +118,10 @@ public sealed class SandboxUIController : UIController, IOnStateChanged<Gameplay
private void CheckSandboxVisibility() private void CheckSandboxVisibility()
{ {
if (_sandboxButton == null) if (SandboxButton == null)
return; return;
_sandboxButton.Visible = _sandbox.SandboxAllowed; SandboxButton.Visible = _sandbox.SandboxAllowed;
} }
public void OnStateExited(GameplayState state) public void OnStateExited(GameplayState state)
@@ -114,13 +132,6 @@ public sealed class SandboxUIController : UIController, IOnStateChanged<Gameplay
_window = null; _window = null;
} }
if (_sandboxButton != null)
{
_sandboxButton.Pressed = false;
_sandboxButton.OnPressed -= SandboxButtonPressed;
_sandboxButton = null;
}
CommandBinds.Unregister<SandboxSystem>(); CommandBinds.Unregister<SandboxSystem>();
} }

View File

@@ -0,0 +1,89 @@
using Content.Client.UserInterface.Controls;
using Content.Shared.CCVar;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Client.UserInterface.Controllers;
using Robust.Shared.Configuration;
using Robust.Shared.Timing;
namespace Content.Client.UserInterface.Systems.Viewport;
public sealed class ViewportUIController : UIController
{
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IPlayerManager _playerMan = default!;
[Dependency] private readonly IEntityManager _entMan = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
public static readonly Vector2i ViewportSize = (EyeManager.PixelsPerMeter * 21, EyeManager.PixelsPerMeter * 15);
public const int ViewportHeight = 15;
private MainViewport? Viewport => UIManager.ActiveScreen?.GetWidget<MainViewport>();
public override void Initialize()
{
_configurationManager.OnValueChanged(CCVars.ViewportMinimumWidth, _ => UpdateViewportRatio());
_configurationManager.OnValueChanged(CCVars.ViewportMaximumWidth, _ => UpdateViewportRatio());
_configurationManager.OnValueChanged(CCVars.ViewportWidth, _ => UpdateViewportRatio());
}
private void UpdateViewportRatio()
{
if (Viewport == null)
{
return;
}
var min = _configurationManager.GetCVar(CCVars.ViewportMinimumWidth);
var max = _configurationManager.GetCVar(CCVars.ViewportMaximumWidth);
var width = _configurationManager.GetCVar(CCVars.ViewportWidth);
if (width < min || width > max)
{
width = CCVars.ViewportWidth.DefaultValue;
}
Viewport.Viewport.ViewportSize = (EyeManager.PixelsPerMeter * width, EyeManager.PixelsPerMeter * ViewportHeight);
}
public void ReloadViewport()
{
if (Viewport == null)
{
return;
}
UpdateViewportRatio();
Viewport.Viewport.HorizontalExpand = true;
Viewport.Viewport.VerticalExpand = true;
_eyeManager.MainViewport = Viewport.Viewport;
}
public override void FrameUpdate(FrameEventArgs e)
{
if (Viewport == null)
{
return;
}
base.FrameUpdate(e);
Viewport.Viewport.Eye = _eyeManager.CurrentEye;
// verify that the current eye is not "null". Fuck IEyeManager.
var ent = _playerMan.LocalPlayer?.ControlledEntity;
if (_eyeManager.CurrentEye.Position != default || ent == null)
return;
_entMan.TryGetComponent(ent, out EyeComponent? eye);
if (eye?.Eye == _eyeManager.CurrentEye
&& _entMan.GetComponent<TransformComponent>(ent.Value).WorldPosition == default)
return; // nothing to worry about, the player is just in null space... actually that is probably a problem?
// Currently, this shouldn't happen. This likely happened because the main eye was set to null. When this
// does happen it can create hard to troubleshoot bugs, so lets print some helpful warnings:
Logger.Warning($"Main viewport's eye is in nullspace (main eye is null?). Attached entity: {_entMan.ToPrettyString(ent.Value)}. Entity has eye comp: {eye != null}");
}
}

View File

@@ -1073,6 +1073,24 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<bool> ViewportScaleRender = public static readonly CVarDef<bool> ViewportScaleRender =
CVarDef.Create("viewport.scale_render", true, CVar.CLIENTONLY | CVar.ARCHIVE); CVarDef.Create("viewport.scale_render", true, CVar.CLIENTONLY | CVar.ARCHIVE);
public static readonly CVarDef<int> ViewportMinimumWidth =
CVarDef.Create("viewport.minimum_width", 15, CVar.REPLICATED);
public static readonly CVarDef<int> ViewportMaximumWidth =
CVarDef.Create("viewport.maximum_width", 21, CVar.REPLICATED);
public static readonly CVarDef<int> ViewportWidth =
CVarDef.Create("viewport.width", 21, CVar.CLIENTONLY | CVar.ARCHIVE);
/*
* UI
*/
public static readonly CVarDef<string> UILayout =
CVarDef.Create("ui.layout", "Default", CVar.CLIENTONLY | CVar.ARCHIVE);
/* /*
* CHAT * CHAT
*/ */

View File

@@ -57,6 +57,8 @@ ui-options-vp-integer-scaling-tooltip = If this option is enabled, the viewport
ui-options-vp-low-res = Low-resolution viewport ui-options-vp-low-res = Low-resolution viewport
ui-options-parallax-low-quality = Low-quality Parallax (background) ui-options-parallax-low-quality = Low-quality Parallax (background)
ui-options-fps-counter = Show FPS counter ui-options-fps-counter = Show FPS counter
ui-options-vp-width = Viewport width: { $width }
ui-options-hud-layout = HUD layout:
## Controls menu ## Controls menu