Files
Christopher Wiebe b451f83174 Initial commit: Theriapolis baseline at port/godot branch point
Captures the pre-Godot-port state of the codebase. This is the rollback
anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md).
All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:40:51 -07:00

64 lines
3.1 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Theriapolis.Game.CodexUI.Core;
/// <summary>
/// Renders a 9-slice texture into an arbitrary destination rectangle: the
/// four corners stay at their authored size, the four edges stretch along
/// one axis, and the centre stretches both axes. Used for parchment cards,
/// gilded borders, button backgrounds, and slot frames.
///
/// Per-side inset values describe how many source-texture pixels the
/// fixed-size corner+edge bands take. They must add up to less than the
/// source texture's width/height in each axis or the centre band collapses.
/// </summary>
public readonly struct NineSliceInsets
{
public readonly int Left, Top, Right, Bottom;
public NineSliceInsets(int uniform) : this(uniform, uniform, uniform, uniform) { }
public NineSliceInsets(int l, int t, int r, int b) { Left = l; Top = t; Right = r; Bottom = b; }
}
public static class NineSlice
{
/// <summary>
/// Draw a 9-slice <paramref name="texture"/> tinted with <paramref name="tint"/>
/// into <paramref name="dest"/> using <paramref name="insets"/> as the corner sizes.
/// </summary>
public static void Draw(SpriteBatch sb, Texture2D texture, Rectangle dest,
NineSliceInsets insets, Color tint)
{
int sw = texture.Width;
int sh = texture.Height;
int l = insets.Left, t = insets.Top, r = insets.Right, b = insets.Bottom;
int cw = sw - l - r; // source center width
int ch = sh - t - b; // source center height
if (cw < 1) cw = 1;
if (ch < 1) ch = 1;
int dl = dest.X;
int dt = dest.Y;
int dcw = System.Math.Max(0, dest.Width - l - r);
int dch = System.Math.Max(0, dest.Height - t - b);
int dr = dest.X + dest.Width - r;
int db = dest.Y + dest.Height - b;
// Corners (1× scale)
sb.Draw(texture, new Rectangle(dl, dt, l, t), new Rectangle(0, 0, l, t), tint);
sb.Draw(texture, new Rectangle(dr, dt, r, t), new Rectangle(sw - r, 0, r, t), tint);
sb.Draw(texture, new Rectangle(dl, db, l, b), new Rectangle(0, sh - b, l, b), tint);
sb.Draw(texture, new Rectangle(dr, db, r, b), new Rectangle(sw - r, sh - b, r, b), tint);
// Edges (stretched along their long axis)
sb.Draw(texture, new Rectangle(dl + l, dt, dcw, t), new Rectangle(l, 0, cw, t), tint);
sb.Draw(texture, new Rectangle(dl + l, db, dcw, b), new Rectangle(l, sh - b, cw, b), tint);
sb.Draw(texture, new Rectangle(dl, dt + t, l, dch), new Rectangle(0, t, l, ch), tint);
sb.Draw(texture, new Rectangle(dr, dt + t, r, dch), new Rectangle(sw - r, t, r, ch), tint);
// Centre (stretched both axes)
sb.Draw(texture, new Rectangle(dl + l, dt + t, dcw, dch), new Rectangle(l, t, cw, ch), tint);
}
}