Files
sbox-public/engine/Sandbox.Engine/Systems/UI/Controls/SvgPanel.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

103 lines
2.0 KiB
C#

using Sandbox.Rendering;
namespace Sandbox.UI;
/// <summary>
/// A generic panel that draws an SVG scaled to size
/// </summary>
[Library( "svg" ), Expose]
public partial class SvgPanel : Panel
{
/// <summary>
/// Content path to the SVG file
/// </summary>
public string Src
{
get => _src;
set
{
if ( _src == value )
return;
_src = value;
ReloadTexture();
}
}
internal string _src;
/// <summary>
/// Optional color to draw the SVG with
/// </summary>
public string Color
{
get => _color;
set
{
if ( _color == value )
return;
_color = value;
ReloadTexture();
}
}
internal string _color;
public override bool HasContent => texture != null;
Texture texture;
int sizeHash;
public override void FinalLayout( Vector2 offset )
{
base.FinalLayout( offset );
if ( !IsVisible ) return;
var hash = HashCode.Combine( Box.Rect.Width, Box.Rect.Height, ComputedStyle.BackgroundSizeX, ComputedStyle.BackgroundSizeY );
if ( hash == sizeHash ) return;
sizeHash = hash;
ReloadTexture();
}
private async void ReloadTexture()
{
if ( ComputedStyle is null )
return;
var rect = Box.Rect;
var width = rect.Width;
var height = rect.Height;
if ( ComputedStyle.BackgroundSizeX.HasValue && ComputedStyle.BackgroundSizeX != Length.Undefined )
width = ComputedStyle.BackgroundSizeX.Value.GetPixels( width );
if ( ComputedStyle.BackgroundSizeY.HasValue && ComputedStyle.BackgroundSizeY != Length.Undefined )
height = ComputedStyle.BackgroundSizeY.Value.GetPixels( height );
var url = $"{Src}?w={(int)width}&h={(int)height}";
if ( !string.IsNullOrEmpty( Color ) )
{
url += $"&color={Color}";
}
texture = await Texture.LoadAsync( url );
IsRenderDirty = true;
}
internal override void DrawContent( CommandList commandList, PanelRenderer renderer, ref RenderState state )
{
if ( texture == null )
return;
if ( renderer is PanelRenderer pr )
{
pr.BuildCommandList_BackgroundTexture( this, texture, state, Length.Cover, commandList );
}
}
}