mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Add saved BUI positions (#5650)
This commit is contained in:
@@ -35,11 +35,11 @@ END TEMPLATE-->
|
||||
|
||||
### Breaking changes
|
||||
|
||||
*None yet*
|
||||
* RemoveChild is called after OnClose for BaseWindow.
|
||||
|
||||
### New features
|
||||
|
||||
*None yet*
|
||||
* BUIs now have their positions saved when closed and re-used when opened when using the `CreateWindow<T>` helper or via manually registering it via RegisterControl.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.GameObjects;
|
||||
|
||||
public sealed class UserInterfaceSystem : SharedUserInterfaceSystem
|
||||
{
|
||||
private Dictionary<EntityUid, Dictionary<Enum, Vector2>> _savedPositions = new();
|
||||
private Dictionary<BoundUserInterface, Control> _registeredControls = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -17,6 +25,59 @@ public sealed class UserInterfaceSystem : SharedUserInterfaceSystem
|
||||
ProtoManager.PrototypesReloaded -= OnProtoReload;
|
||||
}
|
||||
|
||||
protected override void OnUserInterfaceShutdown(Entity<UserInterfaceComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
base.OnUserInterfaceShutdown(ent, ref args);
|
||||
_savedPositions.Remove(ent.Owner);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OpenUi(Entity<UserInterfaceComponent?> entity, Enum key, bool predicted = false)
|
||||
{
|
||||
var player = Player.LocalEntity;
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
OpenUi(entity, key, player.Value, predicted);
|
||||
}
|
||||
|
||||
protected override void SavePosition(BoundUserInterface bui)
|
||||
{
|
||||
if (!_registeredControls.Remove(bui, out var control))
|
||||
return;
|
||||
|
||||
var keyed = _savedPositions[bui.Owner];
|
||||
keyed[bui.UiKey] = control.Position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a control so it will later have its position stored by <see cref="SavePosition"/> when the BUI is closed.
|
||||
/// </summary>
|
||||
public void RegisterControl(BoundUserInterface bui, Control control)
|
||||
{
|
||||
DebugTools.Assert(!_registeredControls.ContainsKey(bui));
|
||||
_registeredControls[bui] = control;
|
||||
_savedPositions.GetOrNew(bui.Owner);
|
||||
}
|
||||
|
||||
public override bool TryGetPosition(Entity<UserInterfaceComponent?> entity, Enum key, out Vector2 position)
|
||||
{
|
||||
position = default;
|
||||
|
||||
if (!_savedPositions.TryGetValue(entity.Owner, out var keyed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!keyed.TryGetValue(key, out position))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnProtoReload(PrototypesReloadedEventArgs obj)
|
||||
{
|
||||
var player = Player.LocalEntity;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
@@ -6,14 +7,47 @@ namespace Robust.Client.UserInterface;
|
||||
|
||||
public static class BoundUserInterfaceExt
|
||||
{
|
||||
private static T GetWindow<T>(BoundUserInterface bui) where T : BaseWindow, new()
|
||||
{
|
||||
var window = bui.CreateDisposableControl<T>();
|
||||
window.OnClose += bui.Close;
|
||||
var system = bui.EntMan.System<UserInterfaceSystem>();
|
||||
system.RegisterControl(bui, window);
|
||||
return window;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a window and also handle closing the BUI when it's closed.
|
||||
/// </summary>
|
||||
public static T CreateWindow<T>(this BoundUserInterface bui) where T : BaseWindow, new()
|
||||
{
|
||||
var window = bui.CreateDisposableControl<T>();
|
||||
window.OpenCentered();
|
||||
window.OnClose += bui.Close;
|
||||
var window = GetWindow<T>(bui);
|
||||
|
||||
if (bui.EntMan.System<UserInterfaceSystem>().TryGetPosition(bui.Owner, bui.UiKey, out var position))
|
||||
{
|
||||
window.Open(position);
|
||||
}
|
||||
else
|
||||
{
|
||||
window.OpenCentered();
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
public static T CreateWindowCenteredLeft<T>(this BoundUserInterface bui) where T : BaseWindow, new()
|
||||
{
|
||||
var window = GetWindow<T>(bui);
|
||||
|
||||
if (bui.EntMan.System<UserInterfaceSystem>().TryGetPosition(bui.Owner, bui.UiKey, out var position))
|
||||
{
|
||||
window.Open(position);
|
||||
}
|
||||
else
|
||||
{
|
||||
window.OpenCenteredLeft();
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
@@ -36,8 +37,8 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
return;
|
||||
}
|
||||
|
||||
Parent.RemoveChild(this);
|
||||
OnClose?.Invoke();
|
||||
Parent.RemoveChild(this);
|
||||
}
|
||||
|
||||
protected internal override void KeyBindDown(GUIBoundKeyEventArgs args)
|
||||
@@ -229,6 +230,16 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
OnOpen?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the window and places it at the specified position.
|
||||
/// </summary>
|
||||
public void Open(Vector2 position)
|
||||
{
|
||||
Measure(Vector2Helpers.Infinity);
|
||||
Open();
|
||||
LayoutContainer.SetPosition(this, position);
|
||||
}
|
||||
|
||||
public void OpenCentered() => OpenCenteredAt(new Vector2(0.5f, 0.5f));
|
||||
|
||||
public void OpenToLeft() => OpenCenteredAt(new Vector2(0, 0.5f));
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Robust.Shared.GameObjects
|
||||
/// </summary>
|
||||
public abstract class BoundUserInterface : IDisposable
|
||||
{
|
||||
[Dependency] protected readonly IEntityManager EntMan = default!;
|
||||
[Dependency] protected internal readonly IEntityManager EntMan = default!;
|
||||
[Dependency] protected readonly ISharedPlayerManager PlayerManager = default!;
|
||||
protected readonly SharedUserInterfaceSystem UiSystem;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Collections;
|
||||
@@ -45,6 +46,8 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
/// </summary>
|
||||
private ValueList<Enum> _keys = new();
|
||||
|
||||
private ValueList<EntityUid> _entList = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -86,6 +89,11 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
SubscribeLocalEvent<UserInterfaceUserComponent, ComponentShutdown>(OnActorShutdown);
|
||||
}
|
||||
|
||||
private void AddQueued(BoundUserInterface bui, bool value)
|
||||
{
|
||||
_queuedBuis.Add((bui, value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the received message, and then pass it onto systems/components
|
||||
/// </summary>
|
||||
@@ -232,7 +240,7 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
|
||||
if (ent.Comp.ClientOpenInterfaces.TryGetValue(key, out var cBui))
|
||||
{
|
||||
_queuedBuis.Add((cBui, false));
|
||||
AddQueued(cBui, false);
|
||||
}
|
||||
|
||||
if (ent.Comp.Actors.Count == 0)
|
||||
@@ -274,18 +282,17 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
// PlayerAttachedEvent will catch some of these.
|
||||
foreach (var (key, bui) in ent.Comp.ClientOpenInterfaces)
|
||||
{
|
||||
_queuedBuis.Add((bui, true));
|
||||
AddQueued(bui, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnUserInterfaceShutdown(Entity<UserInterfaceComponent> ent, ref ComponentShutdown args)
|
||||
protected virtual void OnUserInterfaceShutdown(Entity<UserInterfaceComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
var actors = new List<EntityUid>();
|
||||
foreach (var (key, acts) in ent.Comp.Actors)
|
||||
{
|
||||
actors.Clear();
|
||||
actors.AddRange(acts);
|
||||
foreach (var actor in actors)
|
||||
_entList.Clear();
|
||||
_entList.AddRange(acts);
|
||||
foreach (var actor in _entList)
|
||||
{
|
||||
CloseUiInternal(ent!, key, actor);
|
||||
DebugTools.Assert(!acts.Contains(actor));
|
||||
@@ -456,7 +463,7 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
}
|
||||
|
||||
var bui = ent.Comp.ClientOpenInterfaces[key];
|
||||
_queuedBuis.Add((bui, false));
|
||||
AddQueued(bui, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -537,7 +544,7 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
if (!open)
|
||||
return;
|
||||
|
||||
_queuedBuis.Add((boundUserInterface, true));
|
||||
AddQueued(boundUserInterface, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -653,6 +660,14 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the UI for the local client. Does nothing on server.
|
||||
/// </summary>
|
||||
public virtual void OpenUi(Entity<UserInterfaceComponent?> entity, Enum key, bool predicted = false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OpenUi(Entity<UserInterfaceComponent?> entity, Enum key, EntityUid? actor, bool predicted = false)
|
||||
{
|
||||
if (actor == null || !UIQuery.Resolve(entity.Owner, ref entity.Comp, false))
|
||||
@@ -690,6 +705,23 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
OpenUi(entity, key, actorEnt.Value, predicted);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to return the saved position of a user interface.
|
||||
/// </summary>
|
||||
public virtual bool TryGetPosition(Entity<UserInterfaceComponent?> entity, Enum key, out Vector2 position)
|
||||
{
|
||||
position = Vector2.Zero;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a position for the BUI.
|
||||
/// </summary>
|
||||
protected virtual void SavePosition(BoundUserInterface bui)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a BUI state and networks it to all clients.
|
||||
/// </summary>
|
||||
@@ -1056,6 +1088,7 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// Close BUI
|
||||
else
|
||||
{
|
||||
if (UIQuery.TryComp(bui.Owner, out var uiComp))
|
||||
@@ -1063,6 +1096,7 @@ public abstract class SharedUserInterfaceSystem : EntitySystem
|
||||
uiComp.ClientOpenInterfaces.Remove(bui.UiKey);
|
||||
}
|
||||
|
||||
SavePosition(bui);
|
||||
bui.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user