Feature/shader radial menu (#35152)

* it works! kinda

* so it works now

* minor cleanup

* central button now is useful too

* more cleanup

* minor cleanup

* more cleanup

* refactor: migrated code from toolbox (as it was rejected as too specific)

* feat: moved border drawing for radial menu into RadialMenuTextureButton. Radial menu position setting into was moved to OverrideArrange to not being called on every frame

* refactor: major reworks!

* renamed DrawBagleSector to DrawAnnulusSector

* Remove strange indexing

* Regularize math

* refactor: re-orienting segment elements to be Y-mirrored

* refactor: extracted radial menu radius multiplier property, changed color pallet for radial menu button

* refactor: removed icon backgrounds on textures used in current radial menu buttons with sectors, RadialContainer Radius renamed and now actually changed control radius.

* refactor: in RadialMenuTextureButtonWithSector all sector colors are converted to and from sRGB in property getter-setters

* refactor: renamed srgb to include Srgb suffix so devs gonna see that its srgb clearly

* fix: enabled any functional keys pressed when pushing radial menu buttons

* fix: radial menu sector now scales with UIScale

* fix: accept only one event when clicking on radial menu ContextualButton

* fix: now radial menu buttons accepts only click/alt-click, now clicks outside menu closes menu always

* feat: simple radial menu prototype for easier creation

* refactor: cleanup, restored emote filtering, button models now have class hierarchy

* refactor: remove usage of closure from 'outside code'

* refactor: remove non existing type from UiControlTest

* refactor: remove unused using

* refactor: revert ability to declare radial menu layers in xaml, scale 32px sprites using scale in radial menu

* refactor: whitespaces

* refactor: subscribe for dispose on existing radial menus

* feat: now simple radial menu button models can have custom color for each sector background (and hover background color). Also added OpenOverMouseScreenPosition inside SimpleRadialMenu

* fix: AI door menu now can be closed by verb if it gets unpowered

* overlay and its registration

* radial menu shader but it requires wierd offset

* remove unused file

* smol cleanup

* remove unused code

* neat internal subsctors in radial menu shaders

* refactor finalize visual style

* comments, simplify, extract variable and other minor refactors on radial-menu shader

* refactor: extract more data from radial menu with sector to radial container for shader drawing

* replaced DrawSeparators for RadialMenuTextureButtonWithSector with DrawBorder (no reason to make them separate), also now colors are properly applied

* refactor: simplify hiding border, extended xml-doc for simple radial menu settings

* refactor: remove duplication of radial menu shaders, use ValueList to collect ClearExistingChildrenRadialButtons buttons to remove

* refactor: remove linq

* fix: fix AI radial action serialization using invalid type

* refactor: fix duplicate ShowDeviceNotRespondingPopup for AI by properly checking if it can interact

* refactor: removed *if* blocks from shader, replaced with branchless logic

* refactor: whitespaces, changed list to array in simple radial button preparing methods

* fix: merge duplicated code

---------

Co-authored-by: pa.pecherskij <pa.pecherskij@interfax.ru>
Co-authored-by: Eoin Mcloughlin <helloworld@eoinrul.es>
This commit is contained in:
Fildrance
2025-04-10 13:42:53 +03:00
committed by GitHub
parent 2172eaa492
commit 56710697a9
5 changed files with 272 additions and 55 deletions

View File

@@ -1,12 +1,23 @@
using Robust.Client.UserInterface.Controls;
using System.Linq;
using System.Numerics;
using Robust.Client.Graphics;
using Robust.Shared.Prototypes;
namespace Content.Client.UserInterface.Controls;
[Virtual]
public class RadialContainer : LayoutContainer
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IClyde _clyde= default!;
private readonly ShaderInstance _shader;
private readonly float[] _angles = new float[64];
private readonly float[] _sectorMedians = new float[64];
private readonly Color[] _sectorColors = new Color[64];
private readonly Color[] _borderColors = new Color[64];
/// <summary>
/// Increment of radius per child element to be rendered.
/// </summary>
@@ -24,11 +35,7 @@ public class RadialContainer : LayoutContainer
[ViewVariables(VVAccess.ReadWrite)]
public Vector2 AngularRange
{
get
{
return _angularRange;
}
get => _angularRange;
set
{
var x = value.X;
@@ -89,7 +96,9 @@ public class RadialContainer : LayoutContainer
/// </summary>
public RadialContainer()
{
IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("RadialMenu")
.InstanceUnique();
}
/// <inheritdoc />
@@ -161,6 +170,67 @@ public class RadialContainer : LayoutContainer
return base.ArrangeOverride(finalSize);
}
/// <inheritdoc />
protected override void Draw(DrawingHandleScreen handle)
{
base.Draw(handle);
float selectedFrom = 0;
float selectedTo = 0;
var i = 0;
foreach (var child in Children)
{
if (child is not IRadialMenuItemWithSector menuWithSector)
{
continue;
}
_angles[i] = menuWithSector.AngleSectorTo;
_sectorMedians[i] = (menuWithSector.AngleSectorTo + menuWithSector.AngleSectorFrom) / 2;
if (menuWithSector.IsHovered)
{
// menuWithSector.DrawBackground;
// menuWithSector.DrawBorder;
_sectorColors[i] = menuWithSector.HoverBackgroundColor;
_borderColors[i] = menuWithSector.HoverBorderColor;
selectedFrom = menuWithSector.AngleSectorFrom;
selectedTo = menuWithSector.AngleSectorTo;
}
else
{
_sectorColors[i] = menuWithSector.BackgroundColor;
_borderColors[i] = menuWithSector.BorderColor;
}
i++;
}
var screenSize = _clyde.ScreenSize;
var menuCenter = new Vector2(
ScreenCoordinates.X + (Size.X / 2) * UIScale,
screenSize.Y - ScreenCoordinates.Y - (Size.Y / 2) * UIScale
);
_shader.SetParameter("separatorAngles", _angles);
_shader.SetParameter("sectorMedianAngles", _sectorMedians);
_shader.SetParameter("selectedFrom", selectedFrom);
_shader.SetParameter("selectedTo", selectedTo);
_shader.SetParameter("childCount", i);
_shader.SetParameter("sectorColors", _sectorColors);
_shader.SetParameter("borderColors", _borderColors);
_shader.SetParameter("centerPos", menuCenter);
_shader.SetParameter("screenSize", screenSize);
_shader.SetParameter("innerRadius", CalculatedRadius * InnerRadiusMultiplier * UIScale);
_shader.SetParameter("outerRadius", CalculatedRadius * OuterRadiusMultiplier * UIScale);
handle.UseShader(_shader);
handle.DrawRect(new UIBox2(0, 0, screenSize.X, screenSize.Y), Color.White);
handle.UseShader(null);
}
/// <summary>
/// Specifies the different radial alignment modes
/// </summary>