fix(ui): render live component counts
Port retail text-surface clipping so the 15px component count field remains visible under the 16px DAT font. Cover SetStackSize decrements and final component removal while preserving desired restock values. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
a1175e6aac
commit
0527325b25
7 changed files with 217 additions and 36 deletions
51
src/AcDream.App/Rendering/QuadClipper.cs
Normal file
51
src/AcDream.App/Rendering/QuadClipper.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
namespace AcDream.App.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Clips one screen-space textured quad and remaps its UV rectangle to the surviving
|
||||
/// pixels. Shared by retained DAT sprites and fallback bitmap-font glyphs so every UI
|
||||
/// draw path applies the same edge semantics.
|
||||
/// </summary>
|
||||
internal static class QuadClipper
|
||||
{
|
||||
public static bool TryClip(
|
||||
float clipLeft,
|
||||
float clipTop,
|
||||
float clipRight,
|
||||
float clipBottom,
|
||||
ref float x,
|
||||
ref float y,
|
||||
ref float w,
|
||||
ref float h,
|
||||
ref float u0,
|
||||
ref float v0,
|
||||
ref float u1,
|
||||
ref float v1)
|
||||
{
|
||||
if (clipRight <= clipLeft || clipBottom <= clipTop || w <= 0f || h <= 0f)
|
||||
return false;
|
||||
|
||||
float left = MathF.Max(x, clipLeft);
|
||||
float top = MathF.Max(y, clipTop);
|
||||
float right = MathF.Min(x + w, clipRight);
|
||||
float bottom = MathF.Min(y + h, clipBottom);
|
||||
if (right <= left || bottom <= top)
|
||||
return false;
|
||||
|
||||
float oldX = x, oldY = y, oldW = w, oldH = h;
|
||||
float oldU0 = u0, oldV0 = v0, oldU1 = u1, oldV1 = v1;
|
||||
float tx0 = (left - oldX) / oldW;
|
||||
float tx1 = (right - oldX) / oldW;
|
||||
float ty0 = (top - oldY) / oldH;
|
||||
float ty1 = (bottom - oldY) / oldH;
|
||||
|
||||
x = left;
|
||||
y = top;
|
||||
w = right - left;
|
||||
h = bottom - top;
|
||||
u0 = oldU0 + (oldU1 - oldU0) * tx0;
|
||||
u1 = oldU0 + (oldU1 - oldU0) * tx1;
|
||||
v0 = oldV0 + (oldV1 - oldV0) * ty0;
|
||||
v1 = oldV0 + (oldV1 - oldV0) * ty1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -144,6 +144,41 @@ public sealed unsafe class TextRenderer : IDisposable
|
|||
/// typographic block. Handles '\n' as a line break.
|
||||
/// </summary>
|
||||
public void DrawString(BitmapFont font, string text, float x, float y, Vector4 color)
|
||||
=> DrawStringCore(
|
||||
font, text, x, y, color,
|
||||
clip: false, 0f, 0f, 0f, 0f);
|
||||
|
||||
/// <summary>
|
||||
/// Draw a bitmap-font string clipped to an absolute screen-space rectangle.
|
||||
/// The retained UI uses this overload when a text element intersects its authored
|
||||
/// surface edge. Retail <c>UIElement_Text::DrawSelf @ 0x00467AA0</c> clips the
|
||||
/// individual glyph blits instead of discarding the whole line.
|
||||
/// </summary>
|
||||
internal void DrawStringClipped(
|
||||
BitmapFont font,
|
||||
string text,
|
||||
float x,
|
||||
float y,
|
||||
Vector4 color,
|
||||
float clipLeft,
|
||||
float clipTop,
|
||||
float clipRight,
|
||||
float clipBottom)
|
||||
=> DrawStringCore(
|
||||
font, text, x, y, color,
|
||||
clip: true, clipLeft, clipTop, clipRight, clipBottom);
|
||||
|
||||
private void DrawStringCore(
|
||||
BitmapFont font,
|
||||
string text,
|
||||
float x,
|
||||
float y,
|
||||
Vector4 color,
|
||||
bool clip,
|
||||
float clipLeft,
|
||||
float clipTop,
|
||||
float clipRight,
|
||||
float clipBottom)
|
||||
{
|
||||
float cursorX = x;
|
||||
// The caller provides top-y; shift to baseline for glyph offset math.
|
||||
|
|
@ -170,11 +205,19 @@ public sealed unsafe class TextRenderer : IDisposable
|
|||
float gy = baseline + g.OffsetY;
|
||||
float gw = g.Width;
|
||||
float gh = g.Height;
|
||||
float u0 = g.UvMinX;
|
||||
float v0 = g.UvMinY;
|
||||
float u1 = g.UvMaxX;
|
||||
float v1 = g.UvMaxY;
|
||||
|
||||
if (gw > 0 && gh > 0)
|
||||
if (gw > 0 && gh > 0
|
||||
&& (!clip || QuadClipper.TryClip(
|
||||
clipLeft, clipTop, clipRight, clipBottom,
|
||||
ref gx, ref gy, ref gw, ref gh,
|
||||
ref u0, ref v0, ref u1, ref v1)))
|
||||
{
|
||||
if (OverlayMode) { AppendQuad(_overlayTextBuf, gx, gy, gw, gh, g.UvMinX, g.UvMinY, g.UvMaxX, g.UvMaxY, color); _overlayTextVerts += 6; }
|
||||
else { AppendQuad(_textBuf, gx, gy, gw, gh, g.UvMinX, g.UvMinY, g.UvMaxX, g.UvMaxY, color); _textVerts += 6; }
|
||||
if (OverlayMode) { AppendQuad(_overlayTextBuf, gx, gy, gw, gh, u0, v0, u1, v1, color); _overlayTextVerts += 6; }
|
||||
else { AppendQuad(_textBuf, gx, gy, gw, gh, u0, v0, u1, v1, color); _textVerts += 6; }
|
||||
}
|
||||
cursorX += g.Advance;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue