Code/Skins.cs
using System;
using Sandbox;
using Sandbox.UI;
namespace Goo;
/// <summary>
/// Factories for skin (border-image) styling on a <see cref="Container"/>.
/// </summary>
public static class Skins
{
/// <summary>Dev-diagnostic sink for the zero-width-border nine-slice case; null by default so non-logging contexts (tests) can use the helper.</summary>
public static Action<string>? OnZeroBorder;
/// <summary>A nine-slice skinned <see cref="Container"/> that sets source, slice insets, and rendered border together so the slice cannot be set without a width. <paramref name="sliceSrcPx"/> is in source-image pixels; <paramref name="renderedBorder"/> is on-screen px.</summary>
public static Container NineSlice(
Texture? source,
float sliceSrcPx,
float renderedBorder,
BorderImageRepeat repeat = BorderImageRepeat.Stretch,
BorderImageFill fill = BorderImageFill.Filled,
string? key = null)
{
if (sliceSrcPx <= 0f)
throw new ArgumentException("sliceSrcPx must be > 0 (the corner-art inset in source pixels)", nameof(sliceSrcPx));
if (ShouldWarnZeroBorder(source != null, renderedBorder))
OnZeroBorder?.Invoke($"Goo.Skins.NineSlice: a BorderImageSource is set but renderedBorder is {renderedBorder}; the skin paints into a zero-width border and renders nothing. Pass renderedBorder > 0.");
return new Container
{
Key = key,
Width = Length.Percent(100),
Height = Length.Percent(100),
BorderImageSource = source,
BorderImageWidthLeft = sliceSrcPx,
BorderImageWidthTop = sliceSrcPx,
BorderImageWidthRight = sliceSrcPx,
BorderImageWidthBottom = sliceSrcPx,
BorderWidth = renderedBorder,
BorderImageRepeat = repeat,
BorderImageFill = fill,
};
}
// The silent-blank footgun: a source paints into a zero-thickness border and shows nothing.
internal static bool ShouldWarnZeroBorder(bool hasSource, float renderedBorder)
=> hasSource && renderedBorder <= 0f;
}