feat(D.2b): Slice 2 — UiViewport widget (dat Type 0xD) + IUiViewportRenderer seam
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
10cb31223f
commit
ebcdf44c0c
4 changed files with 72 additions and 6 deletions
11
src/AcDream.App/UI/IUiViewportRenderer.cs
Normal file
11
src/AcDream.App/UI/IUiViewportRenderer.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace AcDream.App.UI;
|
||||||
|
|
||||||
|
/// <summary>Renders a 3-D mini-scene into an off-screen buffer and returns the GL color-texture
|
||||||
|
/// handle. Called by the per-frame pre-UI hook (GameWindow), NOT from UiViewport.OnDraw. Implemented
|
||||||
|
/// by PaperdollViewportRenderer in AcDream.App.Rendering. Intra-App decoupling so the UI widget
|
||||||
|
/// doesn't depend on WbDrawDispatcher/GameWindow.</summary>
|
||||||
|
public interface IUiViewportRenderer
|
||||||
|
{
|
||||||
|
/// <summary>Render at (width,height); return the color-texture GL handle, or 0 if nothing rendered.</summary>
|
||||||
|
uint Render(int width, int height);
|
||||||
|
}
|
||||||
|
|
@ -62,13 +62,14 @@ public static class DatWidgetFactory
|
||||||
// still ships — it just isn't wired into the factory switch yet.
|
// still ships — it just isn't wired into the factory switch yet.
|
||||||
UiElement e = info.Type switch
|
UiElement e = info.Type switch
|
||||||
{
|
{
|
||||||
1 => new UiButton(info, resolve), // UIElement_Button (reg :125828)
|
1 => new UiButton(info, resolve), // UIElement_Button (reg :125828)
|
||||||
6 => new UiMenu(), // UIElement_Menu (reg :120163)
|
6 => new UiMenu(), // UIElement_Menu (reg :120163)
|
||||||
7 => BuildMeter(info, resolve, datFont), // UIElement_Meter
|
7 => BuildMeter(info, resolve, datFont), // UIElement_Meter
|
||||||
11 => new UiScrollbar(), // UIElement_Scrollbar (reg :124137)
|
0xD => new UiViewport(), // UIElement_Viewport — 3-D mini-scene blit leaf
|
||||||
12 => BuildText(info, resolve), // UIElement_Text (reg :115655)
|
11 => new UiScrollbar(), // UIElement_Scrollbar (reg :124137)
|
||||||
|
12 => BuildText(info, resolve), // UIElement_Text (reg :115655)
|
||||||
0x10000031u => new UiItemList(resolve), // UIElement_ItemList — toolbar/inventory/paperdoll slots
|
0x10000031u => new UiItemList(resolve), // UIElement_ItemList — toolbar/inventory/paperdoll slots
|
||||||
_ => new UiDatElement(info, resolve), // generic fallback (incl. Type 3 chrome/containers)
|
_ => new UiDatElement(info, resolve), // generic fallback (incl. Type 3 chrome/containers)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Propagate position + size (pixel-exact from the dat).
|
// Propagate position + size (pixel-exact from the dat).
|
||||||
|
|
|
||||||
25
src/AcDream.App/UI/UiViewport.cs
Normal file
25
src/AcDream.App/UI/UiViewport.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace AcDream.App.UI;
|
||||||
|
|
||||||
|
/// <summary>Leaf widget for dat Type 0xD (UIElement_Viewport). Blits the texture produced by its
|
||||||
|
/// IUiViewportRenderer (run in the pre-UI hook) as a single sprite at its own rect. The 3-D render
|
||||||
|
/// does NOT happen here (OnDraw only has a 2-D context).</summary>
|
||||||
|
public sealed class UiViewport : UiElement
|
||||||
|
{
|
||||||
|
public override bool ConsumesDatChildren => true;
|
||||||
|
|
||||||
|
/// <summary>Renderer that produces the off-screen texture. Set by GameWindow wiring (later task).</summary>
|
||||||
|
public IUiViewportRenderer? Renderer { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Last GL color-texture handle produced by the pre-UI hook. 0 = nothing to blit.</summary>
|
||||||
|
public uint TextureHandle { get; set; }
|
||||||
|
|
||||||
|
protected override void OnDraw(UiRenderContext ctx)
|
||||||
|
{
|
||||||
|
if (!Visible || TextureHandle == 0) return;
|
||||||
|
// Local origin is already at this widget's Left/Top (PushTransform applied by DrawSelfAndChildren).
|
||||||
|
// Draw the full-texture sprite with UV 0..1 and white tint (no color modulation).
|
||||||
|
ctx.DrawSprite(TextureHandle, 0f, 0f, Width, Height, 0f, 0f, 1f, 1f, Vector4.One);
|
||||||
|
}
|
||||||
|
}
|
||||||
29
tests/AcDream.App.Tests/UI/Layout/UiViewportFactoryTests.cs
Normal file
29
tests/AcDream.App.Tests/UI/Layout/UiViewportFactoryTests.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
using AcDream.App.UI;
|
||||||
|
using AcDream.App.UI.Layout;
|
||||||
|
|
||||||
|
namespace AcDream.App.Tests.UI.Layout;
|
||||||
|
|
||||||
|
public class UiViewportFactoryTests
|
||||||
|
{
|
||||||
|
private static (uint, int, int) NoTex(uint _) => (0, 0, 0);
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Factory_builds_UiViewport_for_dat_type_0xD()
|
||||||
|
{
|
||||||
|
var info = new ElementInfo { Type = 0xD, Width = 200, Height = 300 };
|
||||||
|
var widget = DatWidgetFactory.Create(info, NoTex, null);
|
||||||
|
var viewport = Assert.IsType<UiViewport>(widget);
|
||||||
|
Assert.True(viewport.ConsumesDatChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void UiViewport_rect_set_from_ElementInfo()
|
||||||
|
{
|
||||||
|
var info = new ElementInfo { Type = 0xD, X = 10, Y = 20, Width = 180, Height = 240 };
|
||||||
|
var widget = DatWidgetFactory.Create(info, NoTex, null)!;
|
||||||
|
Assert.Equal(10f, widget.Left);
|
||||||
|
Assert.Equal(20f, widget.Top);
|
||||||
|
Assert.Equal(180f, widget.Width);
|
||||||
|
Assert.Equal(240f, widget.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue