feat(app): slice 7 fix round B item 11 — plain <slider> style, mirroring <menu style>
Plugin markup's <slider> always drew RetailScrollbarChrome's sprite
track/thumb, the same "big gold DAT art next to a plain plugin panel"
mismatch <menu style> already fixed for dropdowns. <slider style="..."> now
uses the identical plain/retail grammar (ValidateArtStyle, renamed and
generalized from the menu-only ValidateMenuStyle): plain (the default)
draws a flat dark track, 1px border, and a small flat nub via new
UiScrollbar.RetailArt=false + DrawPlainScalar — no SpriteResolve dependency
at all; style="retail" keeps RetailScrollbarChrome.ApplyHorizontal exactly
as before. RetailArt defaults to true on UiScrollbar itself, so every
non-plugin caller of this widget (retail LayoutDesc import, chat opacity
sliders, etc.) is byte-for-byte unaffected — only <slider>'s own
MarkupDocument case sets it false by default.
Every existing MossTank <slider> (Vitals' nine sliders, Buffs, Items'
Refill Worn Mana) has no style attribute, so they all switch to the plain
look automatically — consistent with the whole campaign's "no gold art"
direction, no XML changes needed.
Fixed a red pin this change created: Slider_MinMax_DrawsTheThumbAtTheRescaledNormalizedPosition
asserted the retail sprite thumb on a slider with no style attribute, which
now builds plain by default — opted it into style="retail" (same fix
shape as item 1's menu-scroll pin) and added a plain sibling,
Slider_NoStyleAttribute_DrawsAPlainFlatNubAtTheRescaledNormalizedPosition.
Mutation check: hardcoding DrawPlainScalar's horizontal nub x to 0 turned
the new plain test red ("expected a plain flat nub offset right of the
origin at 25%"); restoring the real ScalarPosition-driven x turns it green.
Documented <slider style> in docs/plugin-ui-markup.md, mirroring the
existing <menu style> paragraph.
tests/AcDream.Plugins.MossTank.Tests: 671/671 (unchanged — pure App-layer
rendering change, MossTank markup only sets no/default style).
tests/AcDream.App.Tests --filter Markup|Plugin|UiMenu|Slider: 278/3 skipped/281 (was 277/3/280, +1 new test).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
ed5378d9b0
commit
da42c1fce6
4 changed files with 148 additions and 14 deletions
|
|
@ -377,19 +377,26 @@ public class MarkupDocumentTests
|
|||
Assert.Equal(120f, binding.Value, 3);
|
||||
}
|
||||
|
||||
// Fix round B item 11: <slider> now defaults to the PLAIN style
|
||||
// (RetailArt=false), so a markup slider with no style attribute never
|
||||
// reaches RetailScrollbarChrome.ApplyHorizontal's sprite thumb any more
|
||||
// — it draws UiScrollbar.DrawPlainScalar's flat nub instead. This test
|
||||
// now opts INTO style="retail" to keep exercising the retail sprite
|
||||
// path; the plain default gets its own sibling below.
|
||||
[Fact]
|
||||
public void Slider_MinMax_DrawsTheThumbAtTheRescaledNormalizedPosition()
|
||||
{
|
||||
const string xml =
|
||||
"<panel x=\"0\" y=\"0\" w=\"160\" h=\"20\">" +
|
||||
"<slider x=\"0\" y=\"0\" w=\"150\" h=\"16\" min=\"0\" max=\"200\" " +
|
||||
"value=\"{Value}\"/>" +
|
||||
"value=\"{Value}\" style=\"retail\"/>" +
|
||||
"</panel>";
|
||||
var binding = new RangeBinding();
|
||||
|
||||
UiNineSlicePanel panel = MarkupDocument.Build(
|
||||
xml, binding, id => (id, 16, 16));
|
||||
var slider = Assert.IsType<UiScrollbar>(panel.Children[0]);
|
||||
Assert.True(slider.RetailArt);
|
||||
|
||||
var device = new RecordingGpuDevice();
|
||||
var renderer = new TextRenderer(device, new NullGpuFrameSource(), "unused");
|
||||
|
|
@ -417,6 +424,58 @@ public class MarkupDocumentTests
|
|||
$"expected the thumb offset right of the origin at 25%, got x={thumbMinX}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Slider_NoStyleAttribute_DrawsAPlainFlatNubAtTheRescaledNormalizedPosition()
|
||||
{
|
||||
const string xml =
|
||||
"<panel x=\"0\" y=\"0\" w=\"160\" h=\"20\">" +
|
||||
"<slider x=\"0\" y=\"0\" w=\"150\" h=\"16\" min=\"0\" max=\"200\" " +
|
||||
"value=\"{Value}\"/>" +
|
||||
"</panel>";
|
||||
var binding = new RangeBinding();
|
||||
|
||||
UiNineSlicePanel panel = MarkupDocument.Build(
|
||||
xml, binding, id => (id, 16, 16));
|
||||
var slider = Assert.IsType<UiScrollbar>(panel.Children[0]);
|
||||
Assert.False(slider.RetailArt);
|
||||
|
||||
var device = new RecordingGpuDevice();
|
||||
var renderer = new TextRenderer(device, new NullGpuFrameSource(), "unused");
|
||||
renderer.Begin(new Vector2(800f, 600f));
|
||||
var ctx = new UiRenderContext(renderer, new Vector2(800f, 600f));
|
||||
|
||||
slider.TickSelfAndChildren(0);
|
||||
Assert.Equal(0.25f, slider.ScalarPosition, 3);
|
||||
|
||||
slider.DrawSelfAndChildren(ctx);
|
||||
|
||||
// An untextured segment batches every DrawFill call in submission
|
||||
// order together (background track + nub both use texture=0), so
|
||||
// scan per-quad (6 verts x 8 floats = 48 floats) for one whose
|
||||
// color is PlainNubColor and whose left edge sits right of the
|
||||
// origin (proof the 25% position, not 0 or 1.0, drove the nub).
|
||||
const int floatsPerQuad = 6 * 8;
|
||||
bool foundOffsetNub = renderer.DebugSpriteSegmentVerts.Any(s =>
|
||||
{
|
||||
if (s.Texture != 0u) return false;
|
||||
for (int q = 0; q + floatsPerQuad <= s.Verts.Count; q += floatsPerQuad)
|
||||
{
|
||||
float xMin = float.MaxValue;
|
||||
for (int v = 0; v < 6; v++)
|
||||
xMin = MathF.Min(xMin, s.Verts[q + v * 8]);
|
||||
float r = s.Verts[q + 4], g = s.Verts[q + 5], b = s.Verts[q + 6], a = s.Verts[q + 7];
|
||||
bool isNubColor = MathF.Abs(r - slider.PlainNubColor.X) < 0.01f
|
||||
&& MathF.Abs(g - slider.PlainNubColor.Y) < 0.01f
|
||||
&& MathF.Abs(b - slider.PlainNubColor.Z) < 0.01f
|
||||
&& MathF.Abs(a - slider.PlainNubColor.W) < 0.01f;
|
||||
if (isNubColor && xMin > 0f)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
Assert.True(foundOffsetNub, "expected a plain flat nub offset right of the origin at 25%");
|
||||
}
|
||||
|
||||
// ── Campaign VT slice 7 S7.2: <menu scroll="true"> (KB 08 §3 gap) ────
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue