A UI Panel named SpriteBox that displays a sprite by setting Style.BackgroundImage to a Texture retrieved from SpriteCatalog.GetTexture. It exposes properties to set the sprite id, mirror horizontally via a CSS class, and ensures the panel fills its container for background sizing.
namespace NoChillquarium;
/// <summary>
/// UI panel that paints a sprite via <see cref="PanelStyle.BackgroundImage"/> (Texture).
/// Mirror via CSS class <c>mirror-x</c> (Style.Transform is not a string in S&box).
/// </summary>
[Library( "spritebox" )]
public class SpriteBox : Panel
{
string _spriteId;
Texture _applied;
bool _mirror;
bool _filled;
public string Sprite
{
get => _spriteId;
set
{
if ( string.Equals( _spriteId, value, StringComparison.OrdinalIgnoreCase ) )
return;
_spriteId = value;
ApplyTexture();
}
}
public string SpriteId
{
get => Sprite;
set => Sprite = value;
}
/// <summary>When true, adds CSS class mirror-x (scaleX -1).</summary>
public bool Mirror
{
get => _mirror;
set
{
if ( _mirror == value )
return;
_mirror = value;
SetClass( "mirror-x", _mirror );
}
}
public SpriteBox()
{
AddClass( "spritebox" );
EnsureFill();
}
public override void Tick()
{
base.Tick();
// Only recover if texture never bound (panel recreated mid-frame).
if ( _applied is null && !string.IsNullOrEmpty( _spriteId ) )
ApplyTexture();
}
void EnsureFill()
{
if ( _filled )
return;
Style.Width = Length.Fraction( 1f );
Style.Height = Length.Fraction( 1f );
try
{
Style.BackgroundSizeX = Length.Percent( 100f );
Style.BackgroundSizeY = Length.Percent( 100f );
}
catch
{
// optional style props
}
_filled = true;
}
void ApplyTexture()
{
EnsureFill();
SetClass( "mirror-x", _mirror );
if ( string.IsNullOrWhiteSpace( _spriteId ) )
{
Style.BackgroundImage = null;
_applied = null;
return;
}
var tex = SpriteCatalog.GetTexture( _spriteId );
if ( tex is null )
{
Style.BackgroundImage = null;
_applied = null;
return;
}
if ( !ReferenceEquals( _applied, tex ) )
Style.BackgroundImage = tex;
_applied = tex;
}
}