Fix screenspace popups (#24987)
* Fix screenspace popups Never got around to it earlier but need to draw it above UI controls. * Minor null change
This commit is contained in:
@@ -1,12 +1,6 @@
|
|||||||
using System.Numerics;
|
|
||||||
using Content.Client.Examine;
|
|
||||||
using Content.Shared.CCVar;
|
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Interaction;
|
|
||||||
using Content.Shared.Popups;
|
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
using Robust.Client.ResourceManagement;
|
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Shared;
|
using Robust.Shared;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
@@ -26,11 +20,9 @@ public sealed class PopupOverlay : Overlay
|
|||||||
private readonly IPlayerManager _playerMgr;
|
private readonly IPlayerManager _playerMgr;
|
||||||
private readonly IUserInterfaceManager _uiManager;
|
private readonly IUserInterfaceManager _uiManager;
|
||||||
private readonly PopupSystem _popup;
|
private readonly PopupSystem _popup;
|
||||||
|
private readonly PopupUIController _controller;
|
||||||
|
|
||||||
private readonly ShaderInstance _shader;
|
private readonly ShaderInstance _shader;
|
||||||
private readonly Font _smallFont;
|
|
||||||
private readonly Font _mediumFont;
|
|
||||||
private readonly Font _largeFont;
|
|
||||||
|
|
||||||
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
|
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
|
||||||
|
|
||||||
@@ -39,8 +31,8 @@ public sealed class PopupOverlay : Overlay
|
|||||||
IEntityManager entManager,
|
IEntityManager entManager,
|
||||||
IPlayerManager playerMgr,
|
IPlayerManager playerMgr,
|
||||||
IPrototypeManager protoManager,
|
IPrototypeManager protoManager,
|
||||||
IResourceCache cache,
|
|
||||||
IUserInterfaceManager uiManager,
|
IUserInterfaceManager uiManager,
|
||||||
|
PopupUIController controller,
|
||||||
PopupSystem popup)
|
PopupSystem popup)
|
||||||
{
|
{
|
||||||
_configManager = configManager;
|
_configManager = configManager;
|
||||||
@@ -48,11 +40,9 @@ public sealed class PopupOverlay : Overlay
|
|||||||
_playerMgr = playerMgr;
|
_playerMgr = playerMgr;
|
||||||
_uiManager = uiManager;
|
_uiManager = uiManager;
|
||||||
_popup = popup;
|
_popup = popup;
|
||||||
|
_controller = controller;
|
||||||
|
|
||||||
_shader = protoManager.Index<ShaderPrototype>("unshaded").Instance();
|
_shader = protoManager.Index<ShaderPrototype>("unshaded").Instance();
|
||||||
_smallFont = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Italic.ttf"), 10);
|
|
||||||
_mediumFont = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Italic.ttf"), 12);
|
|
||||||
_largeFont = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-BoldItalic.ttf"), 14);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Draw(in OverlayDrawArgs args)
|
protected override void Draw(in OverlayDrawArgs args)
|
||||||
@@ -68,19 +58,18 @@ public sealed class PopupOverlay : Overlay
|
|||||||
scale = _uiManager.DefaultUIScale;
|
scale = _uiManager.DefaultUIScale;
|
||||||
|
|
||||||
DrawWorld(args.ScreenHandle, args, scale);
|
DrawWorld(args.ScreenHandle, args, scale);
|
||||||
DrawScreen(args.ScreenHandle, args, scale);
|
|
||||||
|
|
||||||
args.DrawingHandle.UseShader(null);
|
args.DrawingHandle.UseShader(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawWorld(DrawingHandleScreen worldHandle, OverlayDrawArgs args, float scale)
|
private void DrawWorld(DrawingHandleScreen worldHandle, OverlayDrawArgs args, float scale)
|
||||||
{
|
{
|
||||||
if (_popup.WorldLabels.Count == 0)
|
if (_popup.WorldLabels.Count == 0 || args.ViewportControl == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var matrix = args.ViewportControl!.GetWorldToScreenMatrix();
|
var matrix = args.ViewportControl.GetWorldToScreenMatrix();
|
||||||
var viewPos = new MapCoordinates(args.WorldAABB.Center, args.MapId);
|
var viewPos = new MapCoordinates(args.WorldAABB.Center, args.MapId);
|
||||||
var ourEntity = _playerMgr.LocalPlayer?.ControlledEntity;
|
var ourEntity = _playerMgr.LocalEntity;
|
||||||
|
|
||||||
foreach (var popup in _popup.WorldLabels)
|
foreach (var popup in _popup.WorldLabels)
|
||||||
{
|
{
|
||||||
@@ -92,62 +81,12 @@ public sealed class PopupOverlay : Overlay
|
|||||||
var distance = (mapPos.Position - args.WorldBounds.Center).Length();
|
var distance = (mapPos.Position - args.WorldBounds.Center).Length();
|
||||||
|
|
||||||
// Should handle fade here too wyci.
|
// Should handle fade here too wyci.
|
||||||
if (!args.WorldAABB.Contains(mapPos.Position) || !ExamineSystemShared.InRangeUnOccluded(viewPos, mapPos, distance,
|
if (!args.WorldBounds.Contains(mapPos.Position) || !ExamineSystemShared.InRangeUnOccluded(viewPos, mapPos, distance,
|
||||||
e => e == popup.InitialPos.EntityId || e == ourEntity, entMan: _entManager))
|
e => e == popup.InitialPos.EntityId || e == ourEntity, entMan: _entManager))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var pos = matrix.Transform(mapPos.Position);
|
var pos = matrix.Transform(mapPos.Position);
|
||||||
DrawPopup(popup, worldHandle, pos, scale);
|
_controller.DrawPopup(popup, worldHandle, pos, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawScreen(DrawingHandleScreen screenHandle, OverlayDrawArgs args, float scale)
|
|
||||||
{
|
|
||||||
foreach (var popup in _popup.CursorLabels)
|
|
||||||
{
|
|
||||||
// Different window
|
|
||||||
if (popup.InitialPos.Window != args.ViewportControl?.Window?.Id)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
DrawPopup(popup, screenHandle, popup.InitialPos.Position, scale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawPopup(PopupSystem.PopupLabel popup, DrawingHandleScreen handle, Vector2 position, float scale)
|
|
||||||
{
|
|
||||||
var lifetime = PopupSystem.GetPopupLifetime(popup);
|
|
||||||
|
|
||||||
// Keep alpha at 1 until TotalTime passes half its lifetime, then gradually decrease to 0.
|
|
||||||
var alpha = MathF.Min(1f, 1f - MathF.Max(0f, popup.TotalTime - lifetime / 2) * 2 / lifetime);
|
|
||||||
|
|
||||||
var updatedPosition = position - new Vector2(0f, MathF.Min(8f, 12f * (popup.TotalTime * popup.TotalTime + popup.TotalTime)));
|
|
||||||
var font = _smallFont;
|
|
||||||
var color = Color.White.WithAlpha(alpha);
|
|
||||||
|
|
||||||
switch (popup.Type)
|
|
||||||
{
|
|
||||||
case PopupType.SmallCaution:
|
|
||||||
color = Color.Red;
|
|
||||||
break;
|
|
||||||
case PopupType.Medium:
|
|
||||||
font = _mediumFont;
|
|
||||||
color = Color.LightGray;
|
|
||||||
break;
|
|
||||||
case PopupType.MediumCaution:
|
|
||||||
font = _mediumFont;
|
|
||||||
color = Color.Red;
|
|
||||||
break;
|
|
||||||
case PopupType.Large:
|
|
||||||
font = _largeFont;
|
|
||||||
color = Color.LightGray;
|
|
||||||
break;
|
|
||||||
case PopupType.LargeCaution:
|
|
||||||
font = _largeFont;
|
|
||||||
color = Color.Red;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var dimensions = handle.GetDimensions(font, popup.Text, scale);
|
|
||||||
handle.DrawString(font, updatedPosition - dimensions / 2f, popup.Text, scale, color.WithAlpha(alpha));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ namespace Content.Client.Popups
|
|||||||
[Dependency] private readonly IOverlayManager _overlay = default!;
|
[Dependency] private readonly IOverlayManager _overlay = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
[Dependency] private readonly IResourceCache _resource = default!;
|
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
|
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
|
||||||
[Dependency] private readonly IReplayRecordingManager _replayRecording = default!;
|
[Dependency] private readonly IReplayRecordingManager _replayRecording = default!;
|
||||||
@@ -45,7 +44,14 @@ namespace Content.Client.Popups
|
|||||||
SubscribeNetworkEvent<PopupEntityEvent>(OnPopupEntityEvent);
|
SubscribeNetworkEvent<PopupEntityEvent>(OnPopupEntityEvent);
|
||||||
SubscribeNetworkEvent<RoundRestartCleanupEvent>(OnRoundRestart);
|
SubscribeNetworkEvent<RoundRestartCleanupEvent>(OnRoundRestart);
|
||||||
_overlay
|
_overlay
|
||||||
.AddOverlay(new PopupOverlay(_configManager, EntityManager, _playerManager, _prototype, _resource, _uiManager, this));
|
.AddOverlay(new PopupOverlay(
|
||||||
|
_configManager,
|
||||||
|
EntityManager,
|
||||||
|
_playerManager,
|
||||||
|
_prototype,
|
||||||
|
_uiManager,
|
||||||
|
_uiManager.GetUIController<PopupUIController>(),
|
||||||
|
this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
|
|||||||
121
Content.Client/Popups/PopupUIController.cs
Normal file
121
Content.Client/Popups/PopupUIController.cs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Content.Client.Gameplay;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Client.ResourceManagement;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controllers;
|
||||||
|
|
||||||
|
namespace Content.Client.Popups;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles screens-space popups. World popups are handled via PopupOverlay.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class PopupUIController : UIController, IOnStateEntered<GameplayState>, IOnStateExited<GameplayState>
|
||||||
|
{
|
||||||
|
[UISystemDependency] private readonly PopupSystem? _popup = default!;
|
||||||
|
|
||||||
|
private Font _smallFont = default!;
|
||||||
|
private Font _mediumFont = default!;
|
||||||
|
private Font _largeFont = default!;
|
||||||
|
|
||||||
|
private PopupRootControl? _popupControl;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
var cache = IoCManager.Resolve<IResourceCache>();
|
||||||
|
|
||||||
|
_smallFont = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Italic.ttf"), 10);
|
||||||
|
_mediumFont = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Italic.ttf"), 12);
|
||||||
|
_largeFont = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-BoldItalic.ttf"), 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnStateEntered(GameplayState state)
|
||||||
|
{
|
||||||
|
_popupControl = new PopupRootControl(_popup, this);
|
||||||
|
|
||||||
|
UIManager.RootControl.AddChild(_popupControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnStateExited(GameplayState state)
|
||||||
|
{
|
||||||
|
if (_popupControl == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UIManager.RootControl.RemoveChild(_popupControl);
|
||||||
|
_popupControl = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawPopup(PopupSystem.PopupLabel popup, DrawingHandleScreen handle, Vector2 position, float scale)
|
||||||
|
{
|
||||||
|
var lifetime = PopupSystem.GetPopupLifetime(popup);
|
||||||
|
|
||||||
|
// Keep alpha at 1 until TotalTime passes half its lifetime, then gradually decrease to 0.
|
||||||
|
var alpha = MathF.Min(1f, 1f - MathF.Max(0f, popup.TotalTime - lifetime / 2) * 2 / lifetime);
|
||||||
|
|
||||||
|
var updatedPosition = position - new Vector2(0f, MathF.Min(8f, 12f * (popup.TotalTime * popup.TotalTime + popup.TotalTime)));
|
||||||
|
var font = _smallFont;
|
||||||
|
var color = Color.White.WithAlpha(alpha);
|
||||||
|
|
||||||
|
switch (popup.Type)
|
||||||
|
{
|
||||||
|
case PopupType.SmallCaution:
|
||||||
|
color = Color.Red;
|
||||||
|
break;
|
||||||
|
case PopupType.Medium:
|
||||||
|
font = _mediumFont;
|
||||||
|
color = Color.LightGray;
|
||||||
|
break;
|
||||||
|
case PopupType.MediumCaution:
|
||||||
|
font = _mediumFont;
|
||||||
|
color = Color.Red;
|
||||||
|
break;
|
||||||
|
case PopupType.Large:
|
||||||
|
font = _largeFont;
|
||||||
|
color = Color.LightGray;
|
||||||
|
break;
|
||||||
|
case PopupType.LargeCaution:
|
||||||
|
font = _largeFont;
|
||||||
|
color = Color.Red;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dimensions = handle.GetDimensions(font, popup.Text, scale);
|
||||||
|
handle.DrawString(font, updatedPosition - dimensions / 2f, popup.Text, scale, color.WithAlpha(alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles drawing all screen popups.
|
||||||
|
/// </summary>
|
||||||
|
private sealed class PopupRootControl : Control
|
||||||
|
{
|
||||||
|
private readonly PopupSystem? _popup;
|
||||||
|
private readonly PopupUIController _controller;
|
||||||
|
|
||||||
|
public PopupRootControl(PopupSystem? system, PopupUIController controller)
|
||||||
|
{
|
||||||
|
_popup = system;
|
||||||
|
_controller = controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(DrawingHandleScreen handle)
|
||||||
|
{
|
||||||
|
base.Draw(handle);
|
||||||
|
|
||||||
|
if (_popup == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Different window
|
||||||
|
var windowId = UserInterfaceManager.RootControl.Window.Id;
|
||||||
|
|
||||||
|
foreach (var popup in _popup.CursorLabels)
|
||||||
|
{
|
||||||
|
if (popup.InitialPos.Window != windowId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_controller.DrawPopup(popup, handle, popup.InitialPos.Position, UIScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user