Files
sbox-public/engine/Sandbox.Engine/Systems/UI/Render/PanelRenderer.Matrix.cs
Antoine Pilote 52cb42b65b Single commandlist UI system (#4182)
* added commandlist at root panel level so we dont have 1 commandlist per panel

* added codepath where panel renderer write to the panel roots commandlist instead of their one

* added rcon to toggle between both at runtime

* cache transform

* Build flat commandlist for panels

* added globalcommand list in UI system

each rootpanel command list will be appended to this global commandlist so we reduce overhead while drawing.

* removed debug Ui

* gather children command lists

* use Count instead of Count()

- remove some other code

* renamed FlatCommandList to PanelCommandlist

removed more unused code

* removed ref to cached transform

* simply loop

* remove useless line, remve unsafe keyword, remove should early cull

* added separate profiling scope for building, gathering and executing command lists

* forgot this

* check if yoga layout rect has changed before setting is render dirty

* dont need to draw this quad

* Dont append scissor every frame as we cache them.

* add seaprate scissor function that does append ot attributes only on rebuild

* only update scissor attributes if it has changes, otherwise used cached commandlist

* panel renderer check if panel has layer

* only build transform commandlist if transform has changed, otherwise used the cached transforms

* fixed some UI widgets not updating due to their opacity correctly. This is the bug where widgets wouldnt be visible until you hovered them

* use span for iterating commandlists

* dotnet format

* async SVG and texture loading mark as dirty once loading is done

* dont render UI panels flagged as render manually
2026-03-02 20:00:28 -08:00

75 lines
2.2 KiB
C#

using Sandbox.Rendering;
namespace Sandbox.UI;
internal partial class PanelRenderer
{
internal Matrix Matrix;
Stack<Matrix> MatrixStack = new Stack<Matrix>();
/// <summary>
/// Calculate and store the transform matrix for a panel during build phase.
/// The TransformMat attribute is stored in the panel's TransformCommandList.
/// </summary>
private void BuildTransformCommandList( Panel panel )
{
panel.GlobalMatrix = panel.Parent?.GlobalMatrix ?? null;
panel.LocalMatrix = null;
var style = panel.ComputedStyle;
Matrix transformMat;
if ( style.Transform.Value.IsEmpty() || panel.TransformMatrix == Matrix.Identity )
{
// No transform, just inherit parent's matrix
transformMat = panel.GlobalMatrix?.Inverted ?? Matrix.Identity;
}
else
{
Vector3 origin = panel.Box.Rect.Position;
origin.x += style.TransformOriginX.Value.GetPixels( panel.Box.Rect.Width, 0.0f );
origin.y += style.TransformOriginY.Value.GetPixels( panel.Box.Rect.Height, 0.0f );
// Transform origin from parent's untransformed space to parent's transformed space
Vector3 transformedOrigin = panel.Parent?.GlobalMatrix?.Inverted.Transform( origin ) ?? origin;
transformMat = panel.GlobalMatrix?.Inverted ?? Matrix.Identity;
transformMat *= Matrix.CreateTranslation( -transformedOrigin );
transformMat *= panel.TransformMatrix;
transformMat *= Matrix.CreateTranslation( transformedOrigin );
var mi = transformMat.Inverted;
// Local is current takeaway parent
if ( panel.GlobalMatrix.HasValue )
{
panel.LocalMatrix = panel.GlobalMatrix.Value.Inverted * mi;
}
else
{
panel.LocalMatrix = mi;
}
panel.GlobalMatrix = mi;
}
// Skip command list rebuild if transform and root status unchanged
var isRoot = panel is RootPanel;
if ( panel._lastTransformMat == transformMat && panel._lastTransformIsRoot == isRoot )
return;
panel._lastTransformMat = transformMat;
panel._lastTransformIsRoot = isRoot;
panel.TransformCommandList.Reset();
if ( isRoot )
{
panel.TransformCommandList.Attributes.Set( "LayerMat", Matrix.Identity );
}
panel.TransformCommandList.Attributes.Set( "TransformMat", transformMat );
}
}