Files
RobustToolbox/Robust.Client/UserInterface/UserInterfaceManager.Layout.cs
Leon Friedrich 3500abfd47 Add IUserInterfaceManager.UpdateHovered() (#5083)
* Add `IUserInterfaceManager.UpdateHovered()`

* Try fix tests
2024-04-29 18:37:52 +10:00

169 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Numerics;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Profiling;
namespace Robust.Client.UserInterface;
internal sealed partial class UserInterfaceManager
{
private readonly List<Control> _modalStack = new();
private void RunMeasure(Control control)
{
if (control.IsMeasureValid || !control.IsInsideTree)
return;
if (control.Parent != null)
{
RunMeasure(control.Parent);
}
if (control is WindowRoot root)
{
control.Measure(root.Window.RenderTarget.Size / root.UIScale);
}
else if (control.PreviousMeasure.HasValue)
{
control.Measure(control.PreviousMeasure.Value);
}
}
private void RunArrange(Control control)
{
if (control.IsArrangeValid || !control.IsInsideTree)
return;
if (control.Parent != null)
{
RunArrange(control.Parent);
}
if (control is WindowRoot root)
{
control.Arrange(UIBox2.FromDimensions(Vector2.Zero, root.Window.RenderTarget.Size / root.UIScale));
}
else if (control.PreviousArrange.HasValue)
{
control.Arrange(control.PreviousArrange.Value);
}
}
public void Popup(string contents, string title = "Alert!")
{
var popup = new DefaultWindow
{
Title = title
};
popup.Contents.AddChild(new Label {Text = contents});
popup.OpenCentered();
}
public void ControlHidden(Control control)
{
// Does the same thing but it could later be changed so..
ControlRemovedFromTree(control);
}
public void ControlRemovedFromTree(Control control)
{
if (control.Root?.StoredKeyboardFocus == control)
control.Root.StoredKeyboardFocus = null;
ReleaseKeyboardFocus(control);
RemoveModal(control);
if (control == ControlFocused)
ControlFocused = null;
if (control == CurrentlyHovered)
UpdateHovered();
}
public void PushModal(Control modal)
{
_modalStack.Add(modal);
}
public void RemoveModal(Control modal)
{
if (_modalStack.Remove(modal))
{
modal.ModalRemoved();
}
}
public void Render(IRenderHandle renderHandle)
{
// Render secondary windows LAST.
// This makes it so that (hopefully) the GPU will be done rendering secondary windows
// by the times we try to blit to them at the end of Clyde's render cycle,
// So that the GL driver doesn't have to block on glWaitSync.
foreach (var root in _roots)
{
if (root.Window != _clyde.MainWindow)
{
using var _ = _prof.Group("Window");
_prof.WriteValue("ID", ProfData.Int32((int) root.Window.Id));
renderHandle.RenderInRenderTarget(
root.Window.RenderTarget,
() => DoRender(root),
root.ActualBgColor);
}
}
using (_prof.Group("Main"))
{
DoRender(_windowsToRoot[_clyde.MainWindow.Id]);
}
void DoRender(WindowRoot root)
{
try
{
var total = 0;
var drawingHandle = renderHandle.DrawingHandleScreen;
drawingHandle.SetTransform(Matrix3.Identity);
RenderControl(renderHandle, ref total, root, Vector2i.Zero, Color.White, null, Matrix3.Identity);
drawingHandle.SetTransform(Matrix3.Identity);
OnPostDrawUIRoot?.Invoke(new PostDrawUIRootEventArgs(root, drawingHandle));
_prof.WriteValue("Controls rendered", ProfData.Int32(total));
}
catch (Exception e)
{
_sawmillUI.Error($"Caught exception while trying to draw a UI element: {root}");
_runtime.LogException(e, nameof(UserInterfaceManager));
}
}
}
public void QueueStyleUpdate(Control control)
{
_styleUpdateQueue.Enqueue(control);
}
/// <summary>
/// Queues a control so that it gets remeasured in the next frame update. Does not queue an arrange update.
/// </summary>
public void QueueMeasureUpdate(Control control)
{
_measureUpdateQueue.Enqueue(control);
}
/// <summary>
/// Queues a control so that it gets rearranged in the next frame update. Does not queue a measure update.
/// </summary>
public void QueueArrangeUpdate(Control control)
{
_arrangeUpdateQueue.Enqueue(control);
}
}