feat(render): Campaign V slice V4a - port TextRenderer/BitmapFont/DebugLineRenderer/TextureCache onto IGpuDevice
TextRenderer, BitmapFont, DebugLineRenderer, and TextureCache's UI-texture
upload path (GetOrUploadRenderSurface/UploadRgba8) now issue every draw and
resource creation through the pinned IGpuDevice/IGpuFrame/IGpuPassEncoder
RHI contract instead of raw GL. This is the RHI's first real production
consumer - V0-V3 only established the contract, GL backend skeleton, and a
shader-dialect migration with no live GL exercise. TextRenderer owns one
IGpuPipeline (ui_text shader, straight-alpha blend, depth disabled) and
allocates a per-bucket ring each Flush; BitmapFont's atlas texture is
created and uploaded via device.CreateTexture/.Upload; DebugLineRenderer
mirrors the same one-pipeline-per-Flush shape for its line-list draws.
World-path TextureCache methods (GetOrUpload, the raw-GL layer-array
upload) are untouched - still legacy GL, still out of scope.
Frame lifecycle: GpuDeviceFrameLifetime (RenderFrameOrchestrator.cs) wraps
IGpuDevice.BeginFrame()/IGpuFrame.End() inside the existing
IRenderFrameLifetime bracket HostInputCameraCompositionPhase already opens
per callback, additively - no frame-graph restructuring. Ported renderers
reach the frame via ICurrentGpuFrameSource, a plain interface (not a
delegate field) so WorldSceneDiagnosticsController keeps passing its
existing "no stored window/delegate" architectural-conformance test.
Two real bugs surfaced by actually exercising the RHI against a live GL
context (nothing here was previously reachable before this slice):
- GlGpuDevice.BeginFrame() now resets the render-state cache every frame.
The cache assumes it is the sole writer of GL program/blend/depth/cull
state, which was true while it had zero real consumers, but every
still-legacy renderer (WbDrawDispatcher, terrain, particles, EnvCells)
mutates that same GL state directly and never informs the cache. Once a
legacy renderer ran between two RHI binds, the cache's belief about the
current GL program went stale, so a later BindPipeline(text shader)
skipped re-issuing glUseProgram and the following push-constant upload
threw GL_INVALID_OPERATION against whatever program was actually bound.
Reset() at the frame boundary is the same defensive move BeginPass
already makes after a forced clear (see its comment); it costs one
redundant state application on the frame's first bind.
- GL_MULTISAMPLE has no representation in the pinned contract. Added a
GL-backend-internal Multisample field to GlRenderStateSnapshot/Changes,
computed from GpuPipelineDescription.SampleCount at BindPipeline time -
mirrors how Vulkan bakes MSAA into the pipeline instead of a separate
toggle.
Collateral, scoped to keep the port real rather than a stub:
- GpuTextureSlot (Unassigned = uint.MaxValue, NOT 0) now flows through
every consumer of TextureCache.GetOrUploadRenderSurface/UploadRgba8 and
TextRenderer.DrawSprite - the entire retained UI layer, since a pervasive
Func<uint,(uint,int,int)> sprite-resolve delegate threads through nearly
every UI element/controller. Every prior `== 0` / `!= 0` "no texture"
check became `.IsAssigned` / `!.IsAssigned`; slot 0 is a real assigned
slot (the device's default white texture), so the old sentinel would
have produced live visual regressions if left in place.
- GpuTextureSlot/IGpuDevice/IGpuFrame are internal, so ~270 previously
public AcDream.App types that touched them (directly or transitively)
are now internal too - safe, since AcDream.App is an exe with no
external project references; only the two test projects consume it, via
InternalsVisibleTo. A handful of unrelated types the sweep caught
(ElementInfo/ImportedLayout's property-bag hierarchy, several enums used
as public [Theory] parameters, CursorFeedbackSnapshot's DragAcceptState)
were reverted back to public where making them internal would have
either cascaded into unrelated files or broken xUnit's public-member
discovery.
- ExternalViewportTextureBridge (new) registers the still-raw-GL FBO
color textures PrivateEntityViewportRenderer/PaperdollViewportRenderer
produce (V4g's scope) into the device's texture table for
UiViewport.TextureHandle, via a temporary
GlGpuDevice.RegisterExternalColorTexture escape hatch (internal, not
part of IGpuDevice) deleted when V4g ports those viewports.
- TextRenderGlStateScope.cs and its test deleted: the pipeline description
now bakes what it used to restore by hand.
- ResourceCleanupGroupTests/GlTextureOwnershipTests: the two source-text
conformance tests keyed to TextRenderer's old multi-resource
construction shape (Shader + per-flight FrameBufferSet array + white
texture + tracked VAO/VBO, all via ResourceCleanupGroup) no longer apply
- that shape is gone, replaced by one IGpuPipeline created through
IGpuDevice. The construction-order test is deleted; the checked-commit
texture-creation check now targets GlGpuTexture (which already used
the same GlResourceCommand.CreateName primitive before this slice).
Gates:
- dotnet build -c Release: 0 warnings, 0 errors (AcDream.App has
TreatWarningsAsErrors).
- dotnet test tests/AcDream.App.Tests -c Release: 3,840 passed / 3
skipped (was 3,843/3 entering this slice - net 3 fewer tests:
TextRendererFailureSafetyTests.cs deleted (2, tested the now-deleted
TextRenderGlStateScope) plus the one retired ResourceCleanupGroupTests
method). Full solution: 8,908 passed / 5 skipped across all nine test
projects.
- Offline pixel gate (tools/run-offline-pixel-gate.ps1, parent ec414d60
vs this commit): differing fraction 0.318% (1,791/563,200 compared
pixels), above the 0.001 threshold. Investigated pixel-by-pixel rather
than waved through: a diff heatmap plus 4x crops at the differing
clusters show zero differences anywhere in the retained UI, terrain,
scenery, or static meshes - every differing pixel sits on continuously-
animated ambient content (flying-insect sprites over the swamp, foliage
sparkle/dew glints) whose exact phase depends on elapsed wall-clock
time, the same category the gate's own sky-masking rationale already
documents and the campaign doc's coverage table explicitly excludes
("Not covered - particles"). Confirming evidence: two same-commit
captures at HEAD compare clean against each other (0.0025%), and two
same-commit captures at the parent compare clean against each other
(0.0044%) - only base-vs-head is consistently elevated, which is what
frame-pacing drift from genuinely new per-frame RHI work (BeginFrame,
ring resets, the render-state reset above) would produce against a
fixed wall-clock capture deadline, not a rendering defect. Recommend a
quick user visual check of this capture pair alongside the automated
result, matching how V2c's particle work was already handled in this
campaign (flagged for user visual confirmation rather than blocked on
an automated gate that cannot cover animated content).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
ec414d60cd
commit
ceec3bc440
334 changed files with 3660 additions and 3840 deletions
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using System.Numerics;
|
||||
using AcDream.App.Spells;
|
||||
using AcDream.Content;
|
||||
|
|
@ -14,7 +15,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
public sealed class AppraisalUiControllerTests
|
||||
{
|
||||
private const uint ObjectId = 0x50000001u;
|
||||
private static (uint, int, int) NoTexture(uint _) => (0u, 0, 0);
|
||||
private static (GpuTextureSlot, int, int) NoTexture(uint _) => (GpuTextureSlot.Unassigned, 0, 0);
|
||||
|
||||
[Fact]
|
||||
public void ItemResponse_UsesAuthoredItemSubviewTitleAndScrollbars()
|
||||
|
|
@ -741,11 +742,11 @@ public sealed class AppraisalUiControllerTests
|
|||
() => { },
|
||||
selection: selection,
|
||||
spellbook: spellbook,
|
||||
resolveSpellIcon: id => id + 1_000u,
|
||||
resolveSpellIcon: id => new GpuTextureSlot(id + 1_000u),
|
||||
resolveComponentIcon: did =>
|
||||
{
|
||||
resolvedComponentIcons.Add(did);
|
||||
return did + 2_000u;
|
||||
return new GpuTextureSlot(did + 2_000u);
|
||||
},
|
||||
spellComponents: _ => components,
|
||||
magicSkill: _ => 200u,
|
||||
|
|
@ -801,14 +802,18 @@ public sealed class AppraisalUiControllerTests
|
|||
AppraisalUiController.SpellIconId)!;
|
||||
UiTextureElement icon = Assert.Single(
|
||||
iconHost.Children.OfType<UiTextureElement>());
|
||||
Assert.Equal(metadata.SpellId + 1_000u, icon.Texture);
|
||||
Assert.Equal(new GpuTextureSlot(metadata.SpellId + 1_000u), icon.Texture);
|
||||
Assert.Equal(
|
||||
new uint[] { 0x06000010u, 0x06000011u },
|
||||
resolvedComponentIcons);
|
||||
UiElement formula = layout.FindElement(
|
||||
AppraisalUiController.SpellFormulaListId)!;
|
||||
Assert.Equal(
|
||||
new uint[] { 0x06000010u + 2_000u, 0x06000011u + 2_000u },
|
||||
new[]
|
||||
{
|
||||
new GpuTextureSlot(0x06000010u + 2_000u),
|
||||
new GpuTextureSlot(0x06000011u + 2_000u),
|
||||
},
|
||||
formula.Children
|
||||
.OfType<UiDatElement>()
|
||||
.Select(cell => cell.RuntimeImageTexture!.Value));
|
||||
|
|
@ -828,8 +833,8 @@ public sealed class AppraisalUiControllerTests
|
|||
SelectionState? selection = null,
|
||||
RetailAppraisalNameResolver? itemNames = null,
|
||||
Spellbook? spellbook = null,
|
||||
Func<uint, uint>? resolveSpellIcon = null,
|
||||
Func<uint, uint>? resolveComponentIcon = null,
|
||||
Func<uint, GpuTextureSlot>? resolveSpellIcon = null,
|
||||
Func<uint, GpuTextureSlot>? resolveComponentIcon = null,
|
||||
Func<uint, IReadOnlyList<SpellExamineComponent>>? spellComponents = null,
|
||||
Func<MagicSchool, uint>? magicSkill = null,
|
||||
SpellExamineComponentTemplateFactory? spellComponentTemplates = null)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
@ -30,10 +31,10 @@ public sealed class CharacterLayoutImportProbe
|
|||
if (datDir is null) return;
|
||||
|
||||
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||
var layout = LayoutImporter.Import(dats, CharacterLayout, _ => (1u, 30, 26), null);
|
||||
var layout = LayoutImporter.Import(dats, CharacterLayout, _ => (new GpuTextureSlot(1u), 30, 26), null);
|
||||
Assert.NotNull(layout);
|
||||
|
||||
CharacterStatController.Bind(layout!, SampleData.SampleCharacter, spriteResolve: _ => (1u, 30, 26));
|
||||
CharacterStatController.Bind(layout!, SampleData.SampleCharacter, spriteResolve: _ => (new GpuTextureSlot(1u), 30, 26));
|
||||
|
||||
var rows = new List<UiClickablePanel>();
|
||||
CollectRows(layout!.Root, rows);
|
||||
|
|
@ -61,7 +62,7 @@ public sealed class CharacterLayoutImportProbe
|
|||
if (datDir is null) return;
|
||||
|
||||
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||
var layout = LayoutImporter.Import(dats, CharacterLayout, _ => (1u, 30, 26), null);
|
||||
var layout = LayoutImporter.Import(dats, CharacterLayout, _ => (new GpuTextureSlot(1u), 30, 26), null);
|
||||
Assert.NotNull(layout);
|
||||
|
||||
var close = layout!.FindElement(WindowChromeController.CharacterCloseButtonId);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.Studio;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
|
@ -281,7 +282,7 @@ public class CharacterStatControllerTests
|
|||
var layout = Fake((CharacterStatController.ListBoxId, list));
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16));
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16));
|
||||
|
||||
var rows = list.Children.OfType<UiPanel>().ToList();
|
||||
Assert.Equal(9, rows.Count);
|
||||
|
|
@ -547,7 +548,7 @@ public class CharacterStatControllerTests
|
|||
var layout = Fake((CharacterStatController.ListBoxId, list));
|
||||
|
||||
// Minimal sprite resolver — returns a fake non-zero handle so UiPanel draws it.
|
||||
static (uint, int, int) FakeResolve(uint id) => (1u, 32, 8);
|
||||
static (GpuTextureSlot, int, int) FakeResolve(uint id) => (new GpuTextureSlot(1), 32, 8);
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: FakeResolve);
|
||||
|
|
@ -566,7 +567,7 @@ public class CharacterStatControllerTests
|
|||
{
|
||||
var list = new UiPanel();
|
||||
var layout = Fake((CharacterStatController.ListBoxId, list));
|
||||
static (uint, int, int) FakeResolve(uint id) => (1u, 32, 8);
|
||||
static (GpuTextureSlot, int, int) FakeResolve(uint id) => (new GpuTextureSlot(1), 32, 8);
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: FakeResolve);
|
||||
|
||||
|
|
@ -791,7 +792,7 @@ public class CharacterStatControllerTests
|
|||
Assert.Equal(3, titles.Children.Count);
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16));
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16));
|
||||
|
||||
Assert.Equal(rootChildCount, layout.Root.Children.Count);
|
||||
Assert.Equal(RetailUiStateIds.Open, attributes.ActiveRetailStateId);
|
||||
|
|
@ -814,7 +815,7 @@ public class CharacterStatControllerTests
|
|||
var skills = Assert.IsType<UiText>(layout.FindElement(CharacterStatController.TabSkillsId));
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16));
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16));
|
||||
skills.OnClick!();
|
||||
|
||||
Assert.Equal(RetailUiStateIds.Closed, attributes.ActiveRetailStateId);
|
||||
|
|
@ -836,7 +837,7 @@ public class CharacterStatControllerTests
|
|||
var layout = Fake((CharacterStatController.ListBoxId, list));
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16));
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16));
|
||||
|
||||
ClickTab(layout, left: 92f);
|
||||
|
||||
|
|
@ -891,7 +892,7 @@ public class CharacterStatControllerTests
|
|||
var layout = Fake((CharacterStatController.ListBoxId, list));
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16));
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16));
|
||||
|
||||
ClickTab(layout, left: 92f);
|
||||
Assert.Equal(12, SkillRows(list).Count);
|
||||
|
|
@ -929,7 +930,7 @@ public class CharacterStatControllerTests
|
|||
});
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16));
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16));
|
||||
|
||||
Assert.Equal("Strength", FirstRowName(visibleList));
|
||||
Assert.Equal("<no row>", FirstRowName(hiddenDuplicateList));
|
||||
|
|
@ -963,7 +964,7 @@ public class CharacterStatControllerTests
|
|||
(CharacterStatController.FooterLine2Value, l2Value));
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16));
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16));
|
||||
|
||||
ClickTab(layout, left: 92f);
|
||||
var rows = SkillRows(list);
|
||||
|
|
@ -993,7 +994,7 @@ public class CharacterStatControllerTests
|
|||
var requests = new List<CharacterStatController.RaiseRequest>();
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16),
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16),
|
||||
onRaiseRequest: (request, completed) => { requests.Add(request); completed(); });
|
||||
|
||||
ClickTab(layout, left: 92f);
|
||||
|
|
@ -1027,7 +1028,7 @@ public class CharacterStatControllerTests
|
|||
(CharacterStatController.RaiseOneId, btn1));
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16));
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16));
|
||||
|
||||
ClickTab(layout, left: 92f);
|
||||
SkillRows(list)[5].OnClick!();
|
||||
|
|
@ -1052,7 +1053,7 @@ public class CharacterStatControllerTests
|
|||
var requests = new List<CharacterStatController.RaiseRequest>();
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16),
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16),
|
||||
onRaiseRequest: (request, completed) => { requests.Add(request); completed(); });
|
||||
|
||||
ClickTab(layout, left: 92f);
|
||||
|
|
@ -1096,7 +1097,7 @@ public class CharacterStatControllerTests
|
|||
var requests = new List<CharacterStatController.RaiseRequest>();
|
||||
|
||||
CharacterStatController.Bind(layout, () => sheet,
|
||||
spriteResolve: id => (id, 16, 16),
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16),
|
||||
onRaiseRequest: (request, completed) =>
|
||||
{
|
||||
requests.Add(request);
|
||||
|
|
@ -1149,7 +1150,7 @@ public class CharacterStatControllerTests
|
|||
Action? completeRaise = null;
|
||||
|
||||
CharacterStatController.Bind(layout, () => sheet,
|
||||
spriteResolve: id => (id, 16, 16),
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16),
|
||||
onRaiseRequest: (_, completed) => completeRaise = completed);
|
||||
|
||||
ClickTab(layout, left: 92f);
|
||||
|
|
@ -1213,7 +1214,7 @@ public class CharacterStatControllerTests
|
|||
});
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16));
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16));
|
||||
|
||||
ClickTab(layout, left: 92f);
|
||||
|
||||
|
|
@ -1537,7 +1538,7 @@ public class CharacterStatControllerTests
|
|||
CharacterStatController.Bind(
|
||||
layout,
|
||||
SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16));
|
||||
spriteResolve: id => (new GpuTextureSlot(id), 16, 16));
|
||||
|
||||
ApplyLayoutPass(layout.Root);
|
||||
|
||||
|
|
@ -1635,7 +1636,7 @@ public class CharacterStatControllerTests
|
|||
Width = width,
|
||||
Height = height,
|
||||
};
|
||||
return new UiDatElement(info, static _ => (0u, 0, 0))
|
||||
return new UiDatElement(info, static _ => (GpuTextureSlot.Unassigned, 0, 0))
|
||||
{
|
||||
Top = top,
|
||||
Width = width,
|
||||
|
|
@ -1649,7 +1650,7 @@ public class CharacterStatControllerTests
|
|||
var info = new ElementInfo { Id = id, Type = 1 };
|
||||
info.StateMedia["Normal"] = (1u, 1);
|
||||
info.StateMedia["Ghosted"] = (2u, 1);
|
||||
return new UiButton(info, static _ => (0u, 0, 0));
|
||||
return new UiButton(info, static _ => (GpuTextureSlot.Unassigned, 0, 0));
|
||||
}
|
||||
|
||||
private static UiText MakeTab(uint id, float left)
|
||||
|
|
@ -1676,7 +1677,7 @@ public class CharacterStatControllerTests
|
|||
Name = "Open",
|
||||
PassToChildren = true,
|
||||
};
|
||||
return Assert.IsType<UiText>(DatWidgetFactory.Create(info, static _ => (0u, 0, 0), null));
|
||||
return Assert.IsType<UiText>(DatWidgetFactory.Create(info, static _ => (GpuTextureSlot.Unassigned, 0, 0), null));
|
||||
}
|
||||
|
||||
private static ImportedLayout Fake(params (uint id, UiElement e)[] items)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
using AcDream.Core.Chat;
|
||||
|
|
@ -13,7 +14,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
/// </summary>
|
||||
public class ChatLayoutConformanceTests
|
||||
{
|
||||
private static (uint, int, int) NoTex(uint _) => (0, 0, 0);
|
||||
private static (GpuTextureSlot, int, int) NoTex(uint _) => (GpuTextureSlot.Unassigned, 0, 0);
|
||||
|
||||
private static ElementInfo? Find(ElementInfo n, uint id)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using System.Collections.Generic;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
|
@ -21,7 +22,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
public class ChatWindowControllerTests
|
||||
{
|
||||
// ── Null-resolve helper (no GL needed) ─────────────────────────────────
|
||||
private static (uint, int, int) NoTex(uint _) => (0u, 0, 0);
|
||||
private static (GpuTextureSlot, int, int) NoTex(uint _) => (GpuTextureSlot.Unassigned, 0, 0);
|
||||
|
||||
// ── Capture bus — records every Publish call ────────────────────────────
|
||||
private sealed class CaptureBus : ICommandBus
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
||||
|
|
@ -18,7 +19,7 @@ public sealed class CombatLayoutConformanceTests
|
|||
ElementInfo info = FixtureLoader.LoadCombatInfos();
|
||||
ImportedLayout layout = LayoutImporter.Build(
|
||||
info,
|
||||
_ => (0u, 0, 0),
|
||||
_ => (GpuTextureSlot.Unassigned, 0, 0),
|
||||
datFont: null,
|
||||
stringResolve: _ => "localized");
|
||||
ApplyAnchors(layout.Root);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.Combat;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
|
@ -9,7 +10,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
|
||||
public sealed class CombatUiControllerTests
|
||||
{
|
||||
private static (uint, int, int) NoTex(uint _) => (0u, 0, 0);
|
||||
private static (GpuTextureSlot, int, int) NoTex(uint _) => (GpuTextureSlot.Unassigned, 0, 0);
|
||||
|
||||
[Fact]
|
||||
public void CombatMode_ShowsPhysicalAndMagicPages_AndSelectsMediumByDefault()
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
using AcDream.Core.Items;
|
||||
|
|
@ -130,7 +131,7 @@ public sealed class CreatureAppraisalRowsTests
|
|||
{
|
||||
var templates = new CreatureAppraisalRowTemplateFactory(
|
||||
FixtureLoader.LoadExaminationRowTemplateInfos(),
|
||||
_ => (0u, 0, 0),
|
||||
_ => (GpuTextureSlot.Unassigned, 0, 0),
|
||||
defaultFont: null);
|
||||
var row = new CreatureAppraisalRow(
|
||||
"Strength",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
||||
|
|
@ -20,7 +21,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
/// </summary>
|
||||
public class DatWidgetFactoryFontResolveTests
|
||||
{
|
||||
private static (uint, int, int) NoTex(uint _) => (0, 0, 0);
|
||||
private static (GpuTextureSlot, int, int) NoTex(uint _) => (GpuTextureSlot.Unassigned, 0, 0);
|
||||
|
||||
// ── Test 1: null fontResolve → DatFont == datFont (backward-compat) ─────
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using System.Numerics;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
|
@ -5,7 +6,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
|
||||
public class DatWidgetFactoryTests
|
||||
{
|
||||
private static (uint, int, int) NoTex(uint _) => (0, 0, 0);
|
||||
private static (GpuTextureSlot, int, int) NoTex(uint _) => (GpuTextureSlot.Unassigned, 0, 0);
|
||||
|
||||
// ── Test 1: Type 7 → UiMeter ─────────────────────────────────────────────
|
||||
|
||||
|
|
@ -334,7 +335,7 @@ public class DatWidgetFactoryTests
|
|||
public void Create_buildsUiItemList_forItemListClassId()
|
||||
{
|
||||
var info = new AcDream.App.UI.Layout.ElementInfo { Id = 0x100001A7u, Type = 0x10000031u, Width = 32, Height = 32 };
|
||||
var w = AcDream.App.UI.Layout.DatWidgetFactory.Create(info, _ => (0u, 0, 0), null);
|
||||
var w = AcDream.App.UI.Layout.DatWidgetFactory.Create(info, _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
Assert.IsType<AcDream.App.UI.UiItemList>(w);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
using AcDream.Core.Spells;
|
||||
|
|
@ -6,7 +7,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
|
||||
public sealed class EffectsUiControllerTests
|
||||
{
|
||||
private static (uint, int, int) NoTex(uint _) => (0u, 0, 0);
|
||||
private static (GpuTextureSlot, int, int) NoTex(uint _) => (GpuTextureSlot.Unassigned, 0, 0);
|
||||
private static EffectRowTemplateFactory Templates()
|
||||
=> new(FixtureLoader.LoadEffectRowTemplateInfos(), NoTex, defaultFont: null);
|
||||
|
||||
|
|
@ -47,7 +48,7 @@ public sealed class EffectsUiControllerTests
|
|||
[EffectsUiController.InfoTextId] = info,
|
||||
});
|
||||
using EffectsUiController controller = EffectsUiController.Bind(
|
||||
layout, spellbook, positive: true, () => 0d, NoTex, id => id,
|
||||
layout, spellbook, positive: true, () => 0d, NoTex, id => new GpuTextureSlot(id),
|
||||
Templates(), "SELECT A SPELL")!;
|
||||
|
||||
Assert.False(info.PreserveEndOnLayout);
|
||||
|
|
@ -86,7 +87,7 @@ public sealed class EffectsUiControllerTests
|
|||
[EffectsUiController.ListId] = list,
|
||||
});
|
||||
using EffectsUiController controller = EffectsUiController.Bind(
|
||||
layout, spellbook, positive: true, () => 0d, NoTex, id => id,
|
||||
layout, spellbook, positive: true, () => 0d, NoTex, id => new GpuTextureSlot(id),
|
||||
Templates(), "SELECT A SPELL")!;
|
||||
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
|
||||
42u, 1u, 60f, 1u, Bucket: 1u, SpellCategory: 100u));
|
||||
|
|
@ -129,7 +130,7 @@ public sealed class EffectsUiControllerTests
|
|||
info.Width = 96f;
|
||||
|
||||
using EffectsUiController controller = EffectsUiController.Bind(
|
||||
layout, spellbook, positive, () => 0d, NoTex, id => id,
|
||||
layout, spellbook, positive, () => 0d, NoTex, id => new GpuTextureSlot(id),
|
||||
Templates(), "SELECT A SPELL")!;
|
||||
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
|
||||
42u, 1u, 60f, 1u, Bucket: 1u, SpellCategory: 42u));
|
||||
|
|
@ -173,7 +174,7 @@ public sealed class EffectsUiControllerTests
|
|||
[EffectsUiController.ListId] = list,
|
||||
});
|
||||
using EffectsUiController controller = EffectsUiController.Bind(
|
||||
layout, spellbook, positive: true, () => 0d, NoTex, id => id,
|
||||
layout, spellbook, positive: true, () => 0d, NoTex, id => new GpuTextureSlot(id),
|
||||
Templates(), "SELECT A SPELL")!;
|
||||
|
||||
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
|
||||
|
|
@ -225,7 +226,7 @@ public sealed class EffectsUiControllerTests
|
|||
int closes = 0;
|
||||
|
||||
using EffectsUiController? controller = EffectsUiController.Bind(
|
||||
layout, spellbook, positive, () => 0d, NoTex, id => id,
|
||||
layout, spellbook, positive, () => 0d, NoTex, id => new GpuTextureSlot(id),
|
||||
Templates(), "SELECT A SPELL", () => closes++);
|
||||
|
||||
Assert.NotNull(controller);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
using AcDream.App.World;
|
||||
|
|
@ -31,7 +32,7 @@ public sealed class ExternalContainerControllerTests
|
|||
RetailWindowHandle handle = RetailWindowFrame.Mount(
|
||||
screen,
|
||||
root,
|
||||
static _ => (0u, 0, 0),
|
||||
static _ => (GpuTextureSlot.Unassigned, 0, 0),
|
||||
options);
|
||||
|
||||
var frame = Assert.IsType<UiNineSlicePanel>(handle.OuterFrame);
|
||||
|
|
@ -75,7 +76,7 @@ public sealed class ExternalContainerControllerTests
|
|||
var root = new TestElement { Width = 800f, Height = 110f };
|
||||
var close = new UiButton(
|
||||
new ElementInfo { Id = ExternalContainerController.CloseButtonId, Type = 1 },
|
||||
static _ => (0u, 0, 0));
|
||||
static _ => (GpuTextureSlot.Unassigned, 0, 0));
|
||||
var scrollbar = new UiScrollbar { Width = 784f, Height = 16f };
|
||||
root.AddChild(Top);
|
||||
root.AddChild(Containers);
|
||||
|
|
@ -94,7 +95,7 @@ public sealed class ExternalContainerControllerTests
|
|||
Window = RetailWindowFrame.Mount(
|
||||
Screen,
|
||||
root,
|
||||
static _ => (0u, 0, 0),
|
||||
static _ => (GpuTextureSlot.Unassigned, 0, 0),
|
||||
new RetailWindowFrame.Options
|
||||
{
|
||||
WindowName = WindowNames.ExternalContainer,
|
||||
|
|
@ -129,8 +130,8 @@ public sealed class ExternalContainerControllerTests
|
|||
Selection,
|
||||
Interaction,
|
||||
Split,
|
||||
static (_, _, _, _, _) => 0u,
|
||||
static (_, _, _, _, _) => 0u,
|
||||
static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
Uses.Add,
|
||||
(item, container, placement) => Puts.Add((item, container, placement)),
|
||||
(item, container, placement, amount) =>
|
||||
|
|
@ -285,7 +286,7 @@ public sealed class ExternalContainerControllerTests
|
|||
h.Selection.Select(Item, SelectionChangeSource.Inventory);
|
||||
h.Split.Reset(5u, 2u);
|
||||
var source = new UiItemSlot { SourceKind = ItemDragSource.Inventory };
|
||||
source.SetItem(Item, 0u);
|
||||
source.SetItem(Item, GpuTextureSlot.Unassigned);
|
||||
var payload = new ItemDragPayload(Item, ItemDragSource.Inventory, 0, source);
|
||||
UiItemSlot target = h.Contents.GetItem(0)!;
|
||||
|
||||
|
|
@ -304,7 +305,7 @@ public sealed class ExternalContainerControllerTests
|
|||
h.Objects.AddOrUpdate(new ClientObject { ObjectId = Item, Type = ItemType.Misc });
|
||||
h.Objects.MoveItem(Item, Player, 0);
|
||||
var source = new UiItemSlot { SourceKind = ItemDragSource.Inventory };
|
||||
source.SetItem(Item, 0u);
|
||||
source.SetItem(Item, GpuTextureSlot.Unassigned);
|
||||
|
||||
Assert.True(h.Interaction.PlaceWorldItemInBackpack(0x70000A01u));
|
||||
h.Controller.HandleDropRelease(
|
||||
|
|
@ -333,7 +334,7 @@ public sealed class ExternalContainerControllerTests
|
|||
h.Selection.Select(Item, SelectionChangeSource.Inventory);
|
||||
h.Split.Reset(5u, 2u);
|
||||
var source = new UiItemSlot { SourceKind = ItemDragSource.Inventory };
|
||||
source.SetItem(Item, 0u);
|
||||
source.SetItem(Item, GpuTextureSlot.Unassigned);
|
||||
|
||||
Assert.True(h.Interaction.PlaceWorldItemInBackpack(0x70000A02u));
|
||||
h.Controller.HandleDropRelease(
|
||||
|
|
@ -355,7 +356,7 @@ public sealed class ExternalContainerControllerTests
|
|||
h.Objects.AddOrUpdate(new ClientObject { ObjectId = Item, Type = ItemType.Misc });
|
||||
h.Objects.MoveItem(Item, Player, 0);
|
||||
var source = new UiItemSlot { SourceKind = ItemDragSource.Inventory };
|
||||
source.SetItem(Item, 0u);
|
||||
source.SetItem(Item, GpuTextureSlot.Unassigned);
|
||||
|
||||
h.Controller.HandleDropRelease(
|
||||
h.Contents,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
|
@ -9,7 +10,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
/// no dats required. Fixtures were generated from the real portal.dat and
|
||||
/// serialized with <see cref="System.Text.Json"/>.
|
||||
/// </summary>
|
||||
public static class FixtureLoader
|
||||
internal static class FixtureLoader
|
||||
{
|
||||
private static readonly JsonSerializerOptions _opts = new()
|
||||
{
|
||||
|
|
@ -26,7 +27,7 @@ public static class FixtureLoader
|
|||
public static ImportedLayout LoadVitals()
|
||||
{
|
||||
var root = LoadVitalsInfos();
|
||||
return LayoutImporter.Build(root, _ => (0u, 0, 0), null);
|
||||
return LayoutImporter.Build(root, _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -46,7 +47,7 @@ public static class FixtureLoader
|
|||
/// conformance checks on tree structure and resolved types.
|
||||
/// </summary>
|
||||
public static ImportedLayout LoadChat()
|
||||
=> LayoutImporter.Build(LoadChatInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadChatInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the committed <c>chat_21000006.json</c> fixture into a raw
|
||||
|
|
@ -59,44 +60,44 @@ public static class FixtureLoader
|
|||
|
||||
/// <summary>Builds the committed retail radar LayoutDesc 0x21000074 fixture.</summary>
|
||||
public static ImportedLayout LoadRadar()
|
||||
=> LayoutImporter.Build(LoadRadarInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadRadarInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
/// <summary>Returns the resolved ElementInfo tree for retail radar LayoutDesc 0x21000074.</summary>
|
||||
public static AcDream.App.UI.Layout.ElementInfo LoadRadarInfos()
|
||||
=> LoadInfos("radar_21000074.json");
|
||||
|
||||
public static ImportedLayout LoadToolbar()
|
||||
=> LayoutImporter.Build(LoadToolbarInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadToolbarInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadToolbarInfos()
|
||||
=> LoadInfos("toolbar_21000016.json");
|
||||
|
||||
public static ImportedLayout LoadInventory()
|
||||
=> LayoutImporter.Build(LoadInventoryInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadInventoryInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadInventoryInfos()
|
||||
=> LoadInfos("inventory_21000023.json");
|
||||
|
||||
public static ImportedLayout LoadPaperdoll()
|
||||
=> LayoutImporter.Build(LoadPaperdollInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadPaperdollInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadPaperdollInfos()
|
||||
=> LoadInfos("paperdoll_21000024.json");
|
||||
|
||||
public static ImportedLayout LoadCharacter()
|
||||
=> LayoutImporter.Build(LoadCharacterInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadCharacterInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadCharacterInfos()
|
||||
=> LoadInfos("character_2100002E.json");
|
||||
|
||||
public static ImportedLayout LoadCombat()
|
||||
=> LayoutImporter.Build(LoadCombatInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadCombatInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadCombatInfos()
|
||||
=> LoadInfos("combat_21000073.json");
|
||||
|
||||
public static ImportedLayout LoadSpellbook()
|
||||
=> LayoutImporter.Build(LoadSpellbookInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadSpellbookInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadSpellbookInfos()
|
||||
=> LoadInfos("spellbook_21000034.json");
|
||||
|
|
@ -108,7 +109,7 @@ public static class FixtureLoader
|
|||
=> LoadInfos("component_row_21000033_10000467.json");
|
||||
|
||||
public static ImportedLayout LoadExamination()
|
||||
=> LayoutImporter.Build(LoadExaminationInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadExaminationInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadExaminationInfos()
|
||||
=> LoadInfos("examine_2100006B_100005F2.json");
|
||||
|
|
@ -120,31 +121,31 @@ public static class FixtureLoader
|
|||
=> LoadInfos("examine_component_2100006B_1000032E.json");
|
||||
|
||||
public static ImportedLayout LoadPowerbar()
|
||||
=> LayoutImporter.Build(LoadPowerbarInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadPowerbarInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadPowerbarInfos()
|
||||
=> LoadInfos("powerbar_21000072.json");
|
||||
|
||||
public static ImportedLayout LoadConfirmationDialog()
|
||||
=> LayoutImporter.Build(LoadConfirmationDialogInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadConfirmationDialogInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadConfirmationDialogInfos()
|
||||
=> LoadInfos("dialogs_2100003C.json");
|
||||
|
||||
public static ImportedLayout LoadFpsDisplay()
|
||||
=> LayoutImporter.Build(LoadFpsDisplayInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadFpsDisplayInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadFpsDisplayInfos()
|
||||
=> LoadInfos("smartbox_fps_2100000F.json");
|
||||
|
||||
public static ImportedLayout LoadPositiveEffects()
|
||||
=> LayoutImporter.Build(LoadPositiveEffectsInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadPositiveEffectsInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadPositiveEffectsInfos()
|
||||
=> LoadInfos("effects_positive_2100001B.json");
|
||||
|
||||
public static ImportedLayout LoadNegativeEffects()
|
||||
=> LayoutImporter.Build(LoadNegativeEffectsInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadNegativeEffectsInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadNegativeEffectsInfos()
|
||||
=> LoadInfos("effects_negative_2100001B.json");
|
||||
|
|
@ -154,31 +155,31 @@ public static class FixtureLoader
|
|||
|
||||
public static ImportedLayout LoadCharacterInformation()
|
||||
=> LayoutImporter.Build(
|
||||
LoadCharacterInformationInfos(), _ => (0u, 0, 0), null);
|
||||
LoadCharacterInformationInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadCharacterInformationInfos()
|
||||
=> LoadInfos("character_info_2100006E_10000183.json");
|
||||
|
||||
public static ImportedLayout LoadIndicators()
|
||||
=> LayoutImporter.Build(LoadIndicatorsInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadIndicatorsInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadIndicatorsInfos()
|
||||
=> LoadInfos("indicators_21000071.json");
|
||||
|
||||
public static ImportedLayout LoadLinkStatus()
|
||||
=> LayoutImporter.Build(LoadLinkStatusInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadLinkStatusInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadLinkStatusInfos()
|
||||
=> LoadInfos("link_status_2100001D.json");
|
||||
|
||||
public static ImportedLayout LoadVitae()
|
||||
=> LayoutImporter.Build(LoadVitaeInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadVitaeInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadVitaeInfos()
|
||||
=> LoadInfos("vitae_21000020.json");
|
||||
|
||||
public static ImportedLayout LoadMiniGame()
|
||||
=> LayoutImporter.Build(LoadMiniGameInfos(), _ => (0u, 0, 0), null);
|
||||
=> LayoutImporter.Build(LoadMiniGameInfos(), _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
|
||||
public static ElementInfo LoadMiniGameInfos()
|
||||
=> LoadInfos("mini_game_2100001E.json");
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
using AcDream.Core.Items;
|
||||
|
|
@ -9,7 +10,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
public sealed class IndicatorBarControllerTests
|
||||
{
|
||||
private const uint Player = 0x50000001u;
|
||||
private static (uint, int, int) NoTex(uint _) => (0u, 0, 0);
|
||||
private static (GpuTextureSlot, int, int) NoTex(uint _) => (GpuTextureSlot.Unassigned, 0, 0);
|
||||
|
||||
[Fact]
|
||||
public void AuthoredFixture_BuildsAllSevenRetailIndicatorButtons()
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using System.Collections.Generic;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
|
@ -65,7 +66,7 @@ public class InventoryControllerTests
|
|||
StackSplitQuantityState? stackSplitQuantity = null,
|
||||
ItemInteractionController? itemInteraction = null)
|
||||
=> InventoryController.Bind(layout, objects, () => Player,
|
||||
iconIds: (_, _, _, _, _) => 0u,
|
||||
iconIds: (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: () => strength, datFont: null,
|
||||
ownerName: ownerName is null ? null : () => ownerName,
|
||||
sendUse: uses is null ? null : g => uses.Add(g),
|
||||
|
|
@ -83,7 +84,7 @@ public class InventoryControllerTests
|
|||
private static UiButton MakeButton(uint id)
|
||||
{
|
||||
var info = new ElementInfo { Id = id, Type = 1 };
|
||||
return new UiButton(info, static _ => (0u, 0, 0)) { Width = 16, Height = 16 };
|
||||
return new UiButton(info, static _ => (GpuTextureSlot.Unassigned, 0, 0)) { Width = 16, Height = 16 };
|
||||
}
|
||||
|
||||
// Seed a side bag (a container) in the player's pack, plus optionally its own contents.
|
||||
|
|
@ -379,7 +380,7 @@ public class InventoryControllerTests
|
|||
{
|
||||
var (layout, grid, containers, top, _, _, _, _) = BuildLayout();
|
||||
InventoryController.Bind(layout, new ClientObjectTable(), () => Player,
|
||||
iconIds: (_, _, _, _, _) => 0u, strength: () => 100,
|
||||
iconIds: (_, _, _, _, _) => GpuTextureSlot.Unassigned, strength: () => 100,
|
||||
selection: new SelectionState(), datFont: null,
|
||||
contentsEmptySprite: 0x06004D20u, sideBagEmptySprite: 0x06005D9Cu, mainPackEmptySprite: 0x06005D9Cu);
|
||||
|
||||
|
|
@ -556,7 +557,7 @@ public class InventoryControllerTests
|
|||
nowMs: () => 1_000);
|
||||
|
||||
InventoryController.Bind(layout, objects, () => Player,
|
||||
iconIds: (_, _, _, _, _) => 0u,
|
||||
iconIds: (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: () => 100,
|
||||
selection: new SelectionState(),
|
||||
datFont: null,
|
||||
|
|
@ -589,7 +590,7 @@ public class InventoryControllerTests
|
|||
objects.AddOrUpdate(new ClientObject { ObjectId = Player, IconId = 0x06001234u });
|
||||
(ItemType type, uint icon)? mainPackCall = null;
|
||||
InventoryController.Bind(layout, objects, () => Player,
|
||||
iconIds: (t, icon, _, _, _) => { if (icon == 0x0600127Eu) mainPackCall = (t, icon); return 0u; },
|
||||
iconIds: (t, icon, _, _, _) => { if (icon == 0x0600127Eu) mainPackCall = (t, icon); return GpuTextureSlot.Unassigned; },
|
||||
strength: () => 100, selection: new SelectionState(), datFont: null);
|
||||
|
||||
// Retail draws a constant backpack over the Container type-underlay (IconData::RenderIcons
|
||||
|
|
@ -682,7 +683,7 @@ public class InventoryControllerTests
|
|||
var puts = new List<(uint item, uint container, int placement)>();
|
||||
using var ctrl = Bind(layout, objects, puts: puts, selection: selection);
|
||||
var source = new UiItemSlot { SourceKind = ItemDragSource.Ground };
|
||||
source.SetItem(loot, 0u);
|
||||
source.SetItem(loot, GpuTextureSlot.Unassigned);
|
||||
var payload = new ItemDragPayload(loot, ItemDragSource.Ground, 0, source);
|
||||
|
||||
ctrl.HandleDropRelease(grid, grid.GetItem(1)!, payload);
|
||||
|
|
@ -732,7 +733,7 @@ public class InventoryControllerTests
|
|||
layout,
|
||||
objects,
|
||||
() => Player,
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: () => 100,
|
||||
selection: new SelectionState(),
|
||||
datFont: null,
|
||||
|
|
@ -781,7 +782,7 @@ public class InventoryControllerTests
|
|||
layout,
|
||||
objects,
|
||||
() => Player,
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: () => 100,
|
||||
selection: new SelectionState(),
|
||||
datFont: null,
|
||||
|
|
@ -834,7 +835,7 @@ public class InventoryControllerTests
|
|||
layout,
|
||||
objects,
|
||||
() => Player,
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: () => 100,
|
||||
selection: new SelectionState(),
|
||||
datFont: null,
|
||||
|
|
@ -842,7 +843,7 @@ public class InventoryControllerTests
|
|||
puts.Add((item, container, placement)),
|
||||
itemInteraction: interaction);
|
||||
var source = new UiItemSlot { SourceKind = ItemDragSource.Ground };
|
||||
source.SetItem(draggedLoot, 0u);
|
||||
source.SetItem(draggedLoot, GpuTextureSlot.Unassigned);
|
||||
|
||||
inventory.HandleDropRelease(
|
||||
grid,
|
||||
|
|
@ -894,7 +895,7 @@ public class InventoryControllerTests
|
|||
layout,
|
||||
objects,
|
||||
() => Player,
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: () => 100,
|
||||
selection: new SelectionState(),
|
||||
datFont: null,
|
||||
|
|
@ -902,7 +903,7 @@ public class InventoryControllerTests
|
|||
puts.Add((item, container, placement)),
|
||||
itemInteraction: interaction);
|
||||
var source = new UiItemSlot { SourceKind = ItemDragSource.Ground };
|
||||
source.SetItem(draggedLoot, 0u);
|
||||
source.SetItem(draggedLoot, GpuTextureSlot.Unassigned);
|
||||
|
||||
Assert.True(interaction.PlaceWorldItemInBackpack(directLoot));
|
||||
Assert.Equal(
|
||||
|
|
@ -959,7 +960,7 @@ public class InventoryControllerTests
|
|||
layout,
|
||||
objects,
|
||||
() => Player,
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: () => 100,
|
||||
selection: new SelectionState(),
|
||||
datFont: null,
|
||||
|
|
@ -1022,7 +1023,7 @@ public class InventoryControllerTests
|
|||
layout,
|
||||
objects,
|
||||
() => Player,
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: () => 100,
|
||||
selection: new SelectionState(),
|
||||
datFont: null,
|
||||
|
|
@ -1030,7 +1031,7 @@ public class InventoryControllerTests
|
|||
merges.Add((source, target, amount)),
|
||||
itemInteraction: interaction);
|
||||
var sourceCell = new UiItemSlot { SourceKind = ItemDragSource.Ground };
|
||||
sourceCell.SetItem(sourceStack, 0u);
|
||||
sourceCell.SetItem(sourceStack, GpuTextureSlot.Unassigned);
|
||||
|
||||
Assert.True(interaction.PlaceWorldItemInBackpack(pendingLoot));
|
||||
UiItemSlot targetCell = Enumerable.Range(0, grid.GetNumUIItems())
|
||||
|
|
@ -1083,7 +1084,7 @@ public class InventoryControllerTests
|
|||
layout,
|
||||
objects,
|
||||
() => Player,
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: () => 100,
|
||||
selection: selection,
|
||||
datFont: null,
|
||||
|
|
@ -1092,7 +1093,7 @@ public class InventoryControllerTests
|
|||
itemInteraction: interaction,
|
||||
stackSplitQuantity: splitQuantity);
|
||||
var sourceCell = new UiItemSlot { SourceKind = ItemDragSource.Ground };
|
||||
sourceCell.SetItem(sourceStack, 0u);
|
||||
sourceCell.SetItem(sourceStack, GpuTextureSlot.Unassigned);
|
||||
|
||||
Assert.True(interaction.PlaceWorldItemInBackpack(pendingLoot));
|
||||
inventory.HandleDropRelease(
|
||||
|
|
@ -1131,7 +1132,7 @@ public class InventoryControllerTests
|
|||
layout,
|
||||
objects,
|
||||
() => Player,
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: () => 100,
|
||||
selection: new SelectionState(),
|
||||
datFont: null,
|
||||
|
|
@ -1172,7 +1173,7 @@ public class InventoryControllerTests
|
|||
layout,
|
||||
objects,
|
||||
() => Player,
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: () => 100,
|
||||
selection: new SelectionState(),
|
||||
datFont: null,
|
||||
|
|
@ -1212,7 +1213,7 @@ public class InventoryControllerTests
|
|||
layout,
|
||||
objects,
|
||||
() => Player,
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: () => 100,
|
||||
selection: new SelectionState(),
|
||||
datFont: null,
|
||||
|
|
@ -1239,7 +1240,7 @@ public class InventoryControllerTests
|
|||
var puts = new List<(uint item, uint container, int placement)>();
|
||||
using var ctrl = Bind(layout, objects, puts: puts);
|
||||
var source = new UiItemSlot { SourceKind = ItemDragSource.Ground };
|
||||
source.SetItem(loot, 0u);
|
||||
source.SetItem(loot, GpuTextureSlot.Unassigned);
|
||||
var payload = new ItemDragPayload(loot, ItemDragSource.Ground, 0, source);
|
||||
|
||||
ctrl.HandleDropRelease(grid, grid.GetItem(1)!, payload);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using System;
|
||||
using System.IO;
|
||||
using AcDream.App.UI;
|
||||
|
|
@ -43,7 +44,7 @@ public class InventoryFrameImportProbe
|
|||
if (datDir is null) return; // CI: no live dat — skip
|
||||
|
||||
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||
var layout = LayoutImporter.Import(dats, Frame, _ => (0u, 0, 0), null);
|
||||
var layout = LayoutImporter.Import(dats, Frame, _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
Assert.NotNull(layout);
|
||||
|
||||
// A representative spread across the slot grid (head, shield, the weapon composite, cloak,
|
||||
|
|
@ -63,7 +64,7 @@ public class InventoryFrameImportProbe
|
|||
if (datDir is null) return; // CI: no live dat — skip (this is a smoke test)
|
||||
|
||||
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||
var layout = LayoutImporter.Import(dats, Frame, _ => (0u, 0, 0), null);
|
||||
var layout = LayoutImporter.Import(dats, Frame, _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
Assert.NotNull(layout);
|
||||
|
||||
var backdrop = layout!.FindElement(Backdrop);
|
||||
|
|
@ -95,7 +96,7 @@ public class InventoryFrameImportProbe
|
|||
if (datDir is null) return; // CI: no live dat - skip
|
||||
|
||||
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||
var layout = LayoutImporter.Import(dats, Frame, _ => (0u, 0, 0), null);
|
||||
var layout = LayoutImporter.Import(dats, Frame, _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
Assert.NotNull(layout);
|
||||
|
||||
var close = layout!.FindElement(WindowChromeController.InventoryCloseButtonId);
|
||||
|
|
@ -108,7 +109,7 @@ public class InventoryFrameImportProbe
|
|||
layout,
|
||||
new ClientObjectTable(),
|
||||
playerGuid: static () => 0u,
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
strength: static () => 100,
|
||||
selection: new AcDream.Core.Selection.SelectionState(),
|
||||
datFont: null,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
using AcDream.Core.Items;
|
||||
|
|
@ -30,7 +31,7 @@ public sealed class ItemCooldownUiControllerTests
|
|||
double now = 112.5d;
|
||||
var root = new UiPanel();
|
||||
var list = new UiItemList();
|
||||
list.Cell.SetItem(0x5001u, 99u);
|
||||
list.Cell.SetItem(0x5001u, new GpuTextureSlot(99u));
|
||||
root.AddChild(list);
|
||||
uint[] sprites = Enumerable.Range(1, 10)
|
||||
.Select(index => 0x06000000u + (uint)index)
|
||||
|
|
@ -46,7 +47,7 @@ public sealed class ItemCooldownUiControllerTests
|
|||
Assert.Equal(sprites[5], list.Cell.ActiveCooldownSprite());
|
||||
|
||||
var future = new UiItemSlot();
|
||||
future.SetItem(0x5001u, 100u);
|
||||
future.SetItem(0x5001u, new GpuTextureSlot(100u));
|
||||
list.AddItem(future);
|
||||
Assert.Equal(sprites[5], future.ActiveCooldownSprite());
|
||||
|
||||
|
|
@ -81,7 +82,7 @@ public sealed class ItemCooldownUiControllerTests
|
|||
var root = new UiPanel();
|
||||
var window = new UiPanel();
|
||||
var list = new UiItemList();
|
||||
list.Cell.SetItem(0x5001u, 99u);
|
||||
list.Cell.SetItem(0x5001u, new GpuTextureSlot(99u));
|
||||
root.AddChild(window);
|
||||
window.AddChild(list);
|
||||
uint[] sprites = Enumerable.Range(1, 10)
|
||||
|
|
@ -117,7 +118,7 @@ public sealed class ItemCooldownUiControllerTests
|
|||
var spellbook = new Spellbook();
|
||||
var root = new UiPanel();
|
||||
var list = new UiItemList();
|
||||
list.Cell.SetItem(0x5001u, 99u);
|
||||
list.Cell.SetItem(0x5001u, new GpuTextureSlot(99u));
|
||||
root.AddChild(list);
|
||||
int clockReads = 0;
|
||||
ItemCooldownUiController controller = ItemCooldownUiController.Bind(
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
||||
|
|
@ -9,7 +10,7 @@ public sealed class JumpPowerbarLayoutConformanceTests
|
|||
public void RetailFixture_UsesExactFloatyGeometryTrackAndJumpFill()
|
||||
{
|
||||
ElementInfo info = FixtureLoader.LoadPowerbarInfos();
|
||||
ImportedLayout layout = LayoutImporter.Build(info, _ => (0u, 0, 0), null);
|
||||
ImportedLayout layout = LayoutImporter.Build(info, _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
var meter = Assert.IsType<UiMeter>(
|
||||
layout.FindElement(JumpPowerbarController.MeterId));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
||||
|
|
@ -9,7 +10,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
/// </summary>
|
||||
public class LayoutImporterTests
|
||||
{
|
||||
private static (uint, int, int) NoTex(uint _) => (0, 0, 0);
|
||||
private static (GpuTextureSlot, int, int) NoTex(uint _) => (GpuTextureSlot.Unassigned, 0, 0);
|
||||
|
||||
// ── Test 1: Health meter element → UiMeter with correct rect ─────────────
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
using AcDream.Core.Items;
|
||||
|
|
@ -59,7 +60,7 @@ public sealed class PaperdollClickMapTests
|
|||
ImportedLayout layout = Assert.IsType<ImportedLayout>(LayoutImporter.Import(
|
||||
dats,
|
||||
0x21000023u,
|
||||
static _ => (0u, 0, 0),
|
||||
static _ => (GpuTextureSlot.Unassigned, 0, 0),
|
||||
null));
|
||||
UiElement dragMask = Assert.IsAssignableFrom<UiElement>(
|
||||
layout.FindElement(PaperdollController.DollDragMaskId));
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using System.Collections.Generic;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
|
@ -66,7 +67,7 @@ public class PaperdollControllerTests
|
|||
systemMessage: systemMessages is null ? null : systemMessages.Add);
|
||||
configureInteraction?.Invoke(itemInteraction);
|
||||
return PaperdollController.Bind(layout, objects, () => Player,
|
||||
iconIds: (_, _, _, _, _) => 0x1234u,
|
||||
iconIds: (_, _, _, _, _) => new GpuTextureSlot(0x1234u),
|
||||
itemInteraction: itemInteraction,
|
||||
emptySlotSprite: emptySlot,
|
||||
selection: selection ?? new SelectionState(),
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using System.Numerics;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
|
@ -132,7 +133,7 @@ public sealed class RadarControllerTests
|
|||
root.Children.Add(lockButton);
|
||||
|
||||
root.Children.Add(Sprite(RadarController.DragButtonId, 87, 6, 27, 27, 0x060074C9u, type: 2));
|
||||
return LayoutImporter.Build(root, _ => (0u, 0, 0), null);
|
||||
return LayoutImporter.Build(root, _ => (GpuTextureSlot.Unassigned, 0, 0), null);
|
||||
}
|
||||
|
||||
private static ElementInfo Sprite(
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
||||
|
|
@ -180,7 +181,7 @@ public sealed class RetailPanelUiControllerTests
|
|||
return RetailWindowFrame.Mount(
|
||||
root,
|
||||
content,
|
||||
_ => (0u, 0, 0),
|
||||
_ => (GpuTextureSlot.Unassigned, 0, 0),
|
||||
new RetailWindowFrame.Options
|
||||
{
|
||||
WindowName = name,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
||||
|
|
@ -5,7 +6,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
|
||||
public sealed class RetailWindowFrameTests
|
||||
{
|
||||
private static (uint, int, int) NoTex(uint _) => (0u, 0, 0);
|
||||
private static (GpuTextureSlot, int, int) NoTex(uint _) => (GpuTextureSlot.Unassigned, 0, 0);
|
||||
|
||||
[Theory]
|
||||
[InlineData(9, 459f, 288f)]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
|
@ -52,7 +53,7 @@ public class SelectedObjectControllerTests
|
|||
["StackedItemSelected"] = (0x06004CF4u, 3),
|
||||
},
|
||||
};
|
||||
var overlayEl = new UiDatElement(overlayInfo, _ => (0u, 0, 0));
|
||||
var overlayEl = new UiDatElement(overlayInfo, _ => (GpuTextureSlot.Unassigned, 0, 0));
|
||||
dict[SelectedObjectController.OverlayId] = overlayEl;
|
||||
root.AddChild(overlayEl);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
||||
|
|
@ -16,16 +17,16 @@ public sealed class SpellExamineComponentTemplateFactoryTests
|
|||
FixtureLoader.LoadExaminationComponentTemplateInfos();
|
||||
var factory = new SpellExamineComponentTemplateFactory(
|
||||
template,
|
||||
did => (did + 1_000u, 32, 32),
|
||||
did => (new GpuTextureSlot(did + 1_000u), 32, 32),
|
||||
defaultFont: null);
|
||||
|
||||
UiDatElement root = Assert.IsType<UiDatElement>(
|
||||
factory.Create(0xABCDu, owned));
|
||||
factory.Create(new GpuTextureSlot(0xABCDu), owned));
|
||||
UiDatElement missing = Assert.IsType<UiDatElement>(
|
||||
Assert.Single(root.Children));
|
||||
|
||||
Assert.Equal(SpellExamineComponentTemplateFactory.TemplateId, root.ElementId);
|
||||
Assert.Equal(0xABCDu, root.RuntimeImageTexture);
|
||||
Assert.Equal(new GpuTextureSlot(0xABCDu), root.RuntimeImageTexture);
|
||||
Assert.Empty(root.Children.OfType<UiTextureElement>());
|
||||
Assert.Equal(
|
||||
SpellExamineComponentTemplateFactory.MissingOverlayId,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.Spells;
|
||||
using AcDream.Content;
|
||||
using AcDream.App.UI;
|
||||
|
|
@ -30,7 +31,7 @@ public sealed class SpellbookWindowControllerTests
|
|||
{
|
||||
ImportedLayout layout = LayoutImporter.Build(
|
||||
FixtureLoader.LoadSpellbookInfos(),
|
||||
_ => (0u, 0, 0),
|
||||
_ => (GpuTextureSlot.Unassigned, 0, 0),
|
||||
datFont: null,
|
||||
stringResolve: value => value.StringId switch
|
||||
{
|
||||
|
|
@ -81,7 +82,7 @@ public sealed class SpellbookWindowControllerTests
|
|||
{
|
||||
ImportedLayout layout = LayoutImporter.Build(
|
||||
FixtureLoader.LoadSpellbookInfos(),
|
||||
_ => (0u, 0, 0),
|
||||
_ => (GpuTextureSlot.Unassigned, 0, 0),
|
||||
datFont: null,
|
||||
stringResolve: value => value.StringId == 164868556u ? "Delete" : "Filter");
|
||||
|
||||
|
|
@ -302,7 +303,7 @@ public sealed class SpellbookWindowControllerTests
|
|||
selection.Select(objectId, SelectionChangeSource.Inventory);
|
||||
},
|
||||
setDesiredComponent: (component, amount) => desired.Add((component, amount)),
|
||||
resolveComponentIcon: icon => icon + 0x1000u)!;
|
||||
resolveComponentIcon: icon => new GpuTextureSlot(icon + 0x1000u))!;
|
||||
controller.ShowPage(SpellbookWindowPage.Components);
|
||||
|
||||
UiItemList list = Assert.IsType<UiItemList>(
|
||||
|
|
@ -339,7 +340,7 @@ public sealed class SpellbookWindowControllerTests
|
|||
UiElement iconHost = Assert.IsAssignableFrom<UiElement>(copper.Content.FindElement(
|
||||
ComponentBookTemplateFactory.IconId));
|
||||
Assert.Equal(
|
||||
0x06001100u,
|
||||
new GpuTextureSlot(0x06001100u),
|
||||
Assert.IsType<UiTextureElement>(Assert.Single(iconHost.Children)).Texture);
|
||||
|
||||
copper.OnEvent(new UiEvent(0u, copper, UiEventType.Click));
|
||||
|
|
@ -401,7 +402,7 @@ public sealed class SpellbookWindowControllerTests
|
|||
SelectionState? selection = null,
|
||||
Action<uint>? selectObject = null,
|
||||
Action<uint, uint>? setDesiredComponent = null,
|
||||
Func<uint, uint>? resolveComponentIcon = null)
|
||||
Func<uint, GpuTextureSlot>? resolveComponentIcon = null)
|
||||
=> SpellbookWindowController.Bind(
|
||||
layout,
|
||||
spellbook,
|
||||
|
|
@ -409,8 +410,8 @@ public sealed class SpellbookWindowControllerTests
|
|||
() => 1u,
|
||||
components ?? new Dictionary<uint, SpellComponentDescriptor>(),
|
||||
selection ?? new SelectionState(),
|
||||
spellId => spellId + 1000u,
|
||||
resolveComponentIcon ?? (iconId => iconId),
|
||||
spellId => new GpuTextureSlot(spellId + 1000u),
|
||||
resolveComponentIcon ?? (iconId => new GpuTextureSlot(iconId)),
|
||||
spellId => spellId == 103u ? 8 : 1,
|
||||
selectObject ?? (_ => { }),
|
||||
addFavorite ?? (_ => { }),
|
||||
|
|
@ -430,7 +431,7 @@ public sealed class SpellbookWindowControllerTests
|
|||
new ComponentBookTemplateFactory(
|
||||
FixtureLoader.LoadComponentCategoryTemplateInfos(),
|
||||
FixtureLoader.LoadComponentRowTemplateInfos(),
|
||||
_ => (0u, 0, 0),
|
||||
_ => (GpuTextureSlot.Unassigned, 0, 0),
|
||||
defaultFont: null),
|
||||
RowStyle,
|
||||
rowFont: null);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.Spells;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
|
@ -10,7 +11,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
|
||||
public sealed class SpellcastingUiControllerTests
|
||||
{
|
||||
private static (uint, int, int) NoTex(uint _) => (0u, 0, 0);
|
||||
private static (GpuTextureSlot, int, int) NoTex(uint _) => (GpuTextureSlot.Unassigned, 0, 0);
|
||||
|
||||
[Fact]
|
||||
public void ImportedFixture_UsesRetailEmptyCells_ShortcutDigits_AndCompleteCastButton()
|
||||
|
|
@ -160,8 +161,8 @@ public sealed class SpellcastingUiControllerTests
|
|||
Assert.True(host.Visible);
|
||||
UiCatalogSlot slot = Assert.IsType<UiCatalogSlot>(host.Children[^1]);
|
||||
Assert.Equal(2u, slot.EntryId);
|
||||
Assert.Equal(2670u, slot.CatalogIconTexture);
|
||||
Assert.Equal(2u, slot.CatalogOverlayTexture);
|
||||
Assert.Equal(new GpuTextureSlot(2670u), slot.CatalogIconTexture);
|
||||
Assert.Equal(new GpuTextureSlot(2u), slot.CatalogOverlayTexture);
|
||||
|
||||
slot.OnEvent(new UiEvent(0, slot, UiEventType.Click));
|
||||
var cast = Assert.IsType<UiButton>(
|
||||
|
|
@ -338,8 +339,8 @@ public sealed class SpellcastingUiControllerTests
|
|||
new NoopSpellCastOperations());
|
||||
return SpellcastingUiController.Bind(
|
||||
layout, spellbook, casting, objects, () => 1u,
|
||||
spellId => spellId,
|
||||
item => item.ObjectId,
|
||||
spellId => new GpuTextureSlot(spellId),
|
||||
item => new GpuTextureSlot(item.ObjectId),
|
||||
useItem,
|
||||
selectionState,
|
||||
(tab, position, spellId) =>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AcDream.App.UI;
|
||||
|
|
@ -66,7 +67,7 @@ public class ToolbarControllerTests
|
|||
|
||||
void AddSlot(uint id)
|
||||
{
|
||||
var list = new UiItemList(_ => (0u, 0, 0)) { Width = 32, Height = 32 };
|
||||
var list = new UiItemList(_ => (GpuTextureSlot.Unassigned, 0, 0)) { Width = 32, Height = 32 };
|
||||
dict[id] = list; slots[id] = list; root.AddChild(list);
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +102,7 @@ public class ToolbarControllerTests
|
|||
},
|
||||
};
|
||||
}
|
||||
var button = new UiButton(info, _ => (0u, 0, 0)) { Width = 32, Height = 32 };
|
||||
var button = new UiButton(info, _ => (GpuTextureSlot.Unassigned, 0, 0)) { Width = 32, Height = 32 };
|
||||
dict[id] = button;
|
||||
root.AddChild(button);
|
||||
}
|
||||
|
|
@ -117,10 +118,10 @@ public class ToolbarControllerTests
|
|||
{ new(Index: 0, ObjectId: 0x5001u, SpellId: 0) };
|
||||
|
||||
ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_,_,_,_,_) => 0x77u, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => new GpuTextureSlot(0x77u), useItem: _ => { });
|
||||
|
||||
Assert.Equal(0x5001u, slots[Row1[0]].Cell.ItemId);
|
||||
Assert.Equal(0x77u, slots[Row1[0]].Cell.IconTexture);
|
||||
Assert.Equal(new GpuTextureSlot(0x77u), slots[Row1[0]].Cell.IconTexture);
|
||||
Assert.Equal(0u, slots[Row1[1]].Cell.ItemId); // others empty
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +144,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
Store(shortcuts),
|
||||
iconIds: (_, _, _, _, _) => 0x77u,
|
||||
iconIds: (_, _, _, _, _) => new GpuTextureSlot(0x77u),
|
||||
useItem: _ => { });
|
||||
Assert.Equal(0x5001u, slots[Row1[0]].Cell.ItemId);
|
||||
|
||||
|
|
@ -161,7 +162,7 @@ public class ToolbarControllerTests
|
|||
{ new(Index: 2, ObjectId: 0x5002u, SpellId: 0) };
|
||||
|
||||
ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_,_,_,_,_) => 0x88u, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => new GpuTextureSlot(0x88u), useItem: _ => { });
|
||||
Assert.Equal(0u, slots[Row1[2]].Cell.ItemId); // not bound yet
|
||||
|
||||
repo.AddOrUpdate(new ClientObject { ObjectId = 0x5002u, WeenieClassId = 1u, IconId = 0x06005678u });
|
||||
|
|
@ -177,7 +178,7 @@ public class ToolbarControllerTests
|
|||
var shortcuts = new List<ShortcutEntry>
|
||||
{ new(Index: 2, ObjectId: 0x5002u, SpellId: 0) };
|
||||
var controller = ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_,_,_,_,_) => 0x88u, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => new GpuTextureSlot(0x88u), useItem: _ => { });
|
||||
|
||||
controller.Dispose();
|
||||
controller.Dispose();
|
||||
|
|
@ -203,7 +204,7 @@ public class ToolbarControllerTests
|
|||
var selection = new SelectionState();
|
||||
|
||||
ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_,_,_,_,_) => 0x77u,
|
||||
iconIds: (_,_,_,_,_) => new GpuTextureSlot(0x77u),
|
||||
useItem: g => used = g,
|
||||
selection: selection);
|
||||
UiItemSlot cell = slots[Row1[0]].Cell;
|
||||
|
|
@ -226,7 +227,7 @@ public class ToolbarControllerTests
|
|||
|
||||
var ctrl = ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { });
|
||||
ctrl.BindPanelButtons(
|
||||
panelId => panelId is RetailPanelCatalog.Inventory or RetailPanelCatalog.Character,
|
||||
toggles.Add);
|
||||
|
|
@ -277,7 +278,7 @@ public class ToolbarControllerTests
|
|||
|
||||
var ctrl = ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u,
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned,
|
||||
useItem: _ => { },
|
||||
itemInteraction: interaction);
|
||||
ctrl.BindPanelButtons(
|
||||
|
|
@ -304,7 +305,7 @@ public class ToolbarControllerTests
|
|||
var puts = new List<(uint Item, uint Container, int Placement)>();
|
||||
ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_, _, _, _, _) => 0u,
|
||||
iconIds: (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
useItem: _ => { },
|
||||
playerGuid: () => player,
|
||||
sendPutItemInContainer: (i, c, p) => puts.Add((i, c, p)));
|
||||
|
|
@ -344,7 +345,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
useItem: static _ => { },
|
||||
itemInteraction: interaction,
|
||||
playerGuid: () => player,
|
||||
|
|
@ -394,7 +395,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: static (_, _, _, _, _) => 0u,
|
||||
iconIds: static (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
useItem: static _ => { },
|
||||
itemInteraction: interaction,
|
||||
playerGuid: () => player,
|
||||
|
|
@ -426,7 +427,7 @@ public class ToolbarControllerTests
|
|||
var puts = new List<(uint Item, uint Container, int Placement)>();
|
||||
ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_, _, _, _, _) => 0u,
|
||||
iconIds: (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
useItem: _ => { },
|
||||
playerGuid: () => player,
|
||||
sendPutItemInContainer: (i, c, p) => puts.Add((i, c, p)));
|
||||
|
|
@ -447,7 +448,7 @@ public class ToolbarControllerTests
|
|||
var repo = new ClientObjectTable();
|
||||
var ctrl = ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { });
|
||||
var inventoryButton = (UiButton)layout.FindElement(InventoryButtonId)!;
|
||||
var characterButton = (UiButton)layout.FindElement(CharacterButtonId)!;
|
||||
|
||||
|
|
@ -524,7 +525,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_, _, _, _, _) => 0u,
|
||||
iconIds: (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
useItem: _ => { },
|
||||
itemInteraction: interaction,
|
||||
selectedObjectId: () => selected);
|
||||
|
|
@ -582,7 +583,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_, _, _, _, _) => 0u,
|
||||
iconIds: (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
useItem: _ => { },
|
||||
itemInteraction: interaction,
|
||||
selectedObjectId: () => selection.SelectedObjectId ?? 0u,
|
||||
|
|
@ -648,7 +649,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_, _, _, _, _) => 0u,
|
||||
iconIds: (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
useItem: _ => { },
|
||||
itemInteraction: interaction,
|
||||
selectedObjectId: () => selection.SelectedObjectId ?? 0u,
|
||||
|
|
@ -691,7 +692,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_, _, _, _, _) => 0u,
|
||||
iconIds: (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
useItem: _ => { },
|
||||
playerGuid: () => player);
|
||||
var ammoButton = (UiButton)layout.FindElement(0x10000194u)!;
|
||||
|
|
@ -730,7 +731,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_, _, _, _, _) => 0u,
|
||||
iconIds: (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
useItem: _ => { },
|
||||
playerGuid: () => player);
|
||||
var ammoButton = (UiButton)layout.FindElement(0x10000194u)!;
|
||||
|
|
@ -752,7 +753,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_, _, _, _, _) => 0u,
|
||||
iconIds: (_, _, _, _, _) => GpuTextureSlot.Unassigned,
|
||||
useItem: _ => { },
|
||||
toggleCombat: () => toggles++);
|
||||
|
||||
|
|
@ -779,7 +780,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
Store(shortcuts),
|
||||
iconIds: (_, _, _, _, _) => 1u,
|
||||
iconIds: (_, _, _, _, _) => new GpuTextureSlot(1u),
|
||||
useItem: id => used = id,
|
||||
selectItem: id => selected = id);
|
||||
|
||||
|
|
@ -816,7 +817,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
Store(shortcuts),
|
||||
iconIds: (_, _, _, _, _) => 1u,
|
||||
iconIds: (_, _, _, _, _) => new GpuTextureSlot(1u),
|
||||
useItem: _ => { },
|
||||
itemInteraction: interaction,
|
||||
selectItem: id => selection.Select(id, SelectionChangeSource.Toolbar),
|
||||
|
|
@ -870,7 +871,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
Store(shortcuts),
|
||||
iconIds: (_, _, _, _, _) => 1u,
|
||||
iconIds: (_, _, _, _, _) => new GpuTextureSlot(1u),
|
||||
useItem: _ => { },
|
||||
itemInteraction: interaction);
|
||||
|
||||
|
|
@ -909,7 +910,7 @@ public class ToolbarControllerTests
|
|||
layout,
|
||||
repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_, _, _, _, _) => 1u,
|
||||
iconIds: (_, _, _, _, _) => new GpuTextureSlot(1u),
|
||||
useItem: _ => { },
|
||||
itemInteraction: interaction,
|
||||
sendAddShortcut: entry => sends.Add(((uint)entry.Index, entry.ObjectId)));
|
||||
|
|
@ -935,7 +936,7 @@ public class ToolbarControllerTests
|
|||
|
||||
ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) =>0u, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { });
|
||||
|
||||
// Only peace indicator (index 0 = 0x10000192) is visible.
|
||||
Assert.True (indicators[0x10000192u].Visible, "peace indicator should be visible after bind");
|
||||
|
|
@ -955,7 +956,7 @@ public class ToolbarControllerTests
|
|||
|
||||
var ctrl = ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) =>0u, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { });
|
||||
|
||||
ctrl.SetCombatMode(CombatMode.Melee);
|
||||
|
||||
|
|
@ -977,7 +978,7 @@ public class ToolbarControllerTests
|
|||
|
||||
ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) =>0u, useItem: _ => { },
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { },
|
||||
combatState: combat);
|
||||
|
||||
// Initially NonCombat after bind.
|
||||
|
|
@ -1016,7 +1017,7 @@ public class ToolbarControllerTests
|
|||
|
||||
ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u, useItem: _ => { },
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { },
|
||||
regularDigits: FakeRegular, ghostedDigits: FakeGhosted);
|
||||
|
||||
// Top row: ShortcutNum == slot index, ghosted == false.
|
||||
|
|
@ -1045,7 +1046,7 @@ public class ToolbarControllerTests
|
|||
var repo = new ClientObjectTable();
|
||||
var ctrl = ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u, useItem: _ => { },
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { },
|
||||
regularDigits: FakeRegular, ghostedDigits: FakeGhosted);
|
||||
|
||||
ctrl.SetCombatMode(mode);
|
||||
|
|
@ -1055,7 +1056,7 @@ public class ToolbarControllerTests
|
|||
var cell = slots[Row1[i]].Cell;
|
||||
Assert.Equal(i, cell.ShortcutNum);
|
||||
Assert.False(cell.ShortcutGhosted, $"top-row slot {i} should be regular in {mode}");
|
||||
cell.SetItem((uint)(0x5000 + i), 0x99u);
|
||||
cell.SetItem((uint)(0x5000 + i), new GpuTextureSlot(0x99u));
|
||||
Assert.Same(FakeRegular, cell.ActiveDigitArray());
|
||||
}
|
||||
// Bottom row still has no number.
|
||||
|
|
@ -1073,13 +1074,13 @@ public class ToolbarControllerTests
|
|||
var repo = new ClientObjectTable();
|
||||
var ctrl = ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u, useItem: _ => { },
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { },
|
||||
regularDigits: FakeRegular, ghostedDigits: FakeGhosted);
|
||||
|
||||
ctrl.SetCombatMode(CombatMode.Magic);
|
||||
foreach (var id in Row1)
|
||||
{
|
||||
slots[id].Cell.SetItem(id, 0x99u);
|
||||
slots[id].Cell.SetItem(id, new GpuTextureSlot(0x99u));
|
||||
Assert.True(slots[id].Cell.ShortcutGhosted);
|
||||
Assert.Same(FakeGhosted, slots[id].Cell.ActiveDigitArray());
|
||||
}
|
||||
|
|
@ -1105,7 +1106,7 @@ public class ToolbarControllerTests
|
|||
|
||||
ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u, useItem: _ => { },
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { },
|
||||
regularDigits: FakeRegular, ghostedDigits: FakeGhosted);
|
||||
|
||||
foreach (var id in Row1)
|
||||
|
|
@ -1127,7 +1128,7 @@ public class ToolbarControllerTests
|
|||
|
||||
ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u, useItem: _ => { },
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { },
|
||||
regularDigits: FakeRegular, ghostedDigits: FakeGhosted, emptyDigits: FakeEmpty);
|
||||
|
||||
foreach (var id in Row1)
|
||||
|
|
@ -1148,7 +1149,7 @@ public class ToolbarControllerTests
|
|||
|
||||
ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u, useItem: _ => { },
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { },
|
||||
regularDigits: FakeRegular, ghostedDigits: FakeGhosted, emptyDigits: null);
|
||||
|
||||
foreach (var id in Row1)
|
||||
|
|
@ -1174,7 +1175,7 @@ public class ToolbarControllerTests
|
|||
|
||||
int iconCallCount = 0;
|
||||
ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_,_,_,_,_) => { iconCallCount++; return 0x77u; }, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => { iconCallCount++; return new GpuTextureSlot(0x77u); }, useItem: _ => { });
|
||||
|
||||
int callsAfterBind = iconCallCount; // 1 call from initial Populate
|
||||
|
||||
|
|
@ -1199,7 +1200,7 @@ public class ToolbarControllerTests
|
|||
|
||||
int iconCallCount = 0;
|
||||
ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_,_,_,_,_) => { iconCallCount++; return 0x99u; }, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => { iconCallCount++; return new GpuTextureSlot(0x99u); }, useItem: _ => { });
|
||||
|
||||
Assert.Equal(0, iconCallCount); // not called — item absent during initial Populate
|
||||
Assert.Equal(0u, slots[Row1[1]].Cell.ItemId);
|
||||
|
|
@ -1225,7 +1226,7 @@ public class ToolbarControllerTests
|
|||
{ new(Index: 3, ObjectId: 0x5004u, SpellId: 0) };
|
||||
|
||||
ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_,_,_,_,_) => 0xAAu, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => new GpuTextureSlot(0xAAu), useItem: _ => { });
|
||||
|
||||
Assert.Equal(0x5004u, slots[Row1[3]].Cell.ItemId); // bound
|
||||
|
||||
|
|
@ -1252,7 +1253,7 @@ public class ToolbarControllerTests
|
|||
|
||||
int iconCallCount = 0;
|
||||
ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_,_,_,_,_) => { iconCallCount++; return 0xBBu; }, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => { iconCallCount++; return new GpuTextureSlot(0xBBu); }, useItem: _ => { });
|
||||
|
||||
int callsAfterBind = iconCallCount; // 1 call for the shortcut item
|
||||
|
||||
|
|
@ -1274,7 +1275,7 @@ public class ToolbarControllerTests
|
|||
|
||||
var ctrl = ToolbarController.Bind(layout, repo,
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { });
|
||||
|
||||
for (int i = 0; i < Row1.Length; i++)
|
||||
{
|
||||
|
|
@ -1299,7 +1300,7 @@ public class ToolbarControllerTests
|
|||
var (layout, slots, _) = FakeToolbar();
|
||||
var ctrl = ToolbarController.Bind(layout, new ClientObjectTable(),
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { });
|
||||
|
||||
var list = slots[Row1[0]];
|
||||
var payload = new ItemDragPayload(0x5001u, ItemDragSource.Inventory, 0, new UiItemSlot());
|
||||
|
|
@ -1314,7 +1315,7 @@ public class ToolbarControllerTests
|
|||
var (layout, slots, _) = FakeToolbar();
|
||||
var ctrl = ToolbarController.Bind(layout, new ClientObjectTable(),
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { });
|
||||
var list = slots[Row1[0]];
|
||||
var payload = new ItemDragPayload(0u, ItemDragSource.Inventory, 0, new UiItemSlot());
|
||||
Assert.Equal(ItemDragAcceptance.None, ctrl.OnDragOver(list, list.Cell, payload));
|
||||
|
|
@ -1343,7 +1344,7 @@ public class ToolbarControllerTests
|
|||
uint selected = 0;
|
||||
|
||||
var ctrl = ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_,_,_,_,_) => 0x77u, useItem: _ => { },
|
||||
iconIds: (_,_,_,_,_) => new GpuTextureSlot(0x77u), useItem: _ => { },
|
||||
sendAddShortcut: add, sendRemoveShortcut: rem,
|
||||
selectItem: item => selected = item, selectedObjectId: () => selected);
|
||||
Assert.Equal(0x5001u, slots[Row1[3]].Cell.ItemId);
|
||||
|
|
@ -1368,7 +1369,7 @@ public class ToolbarControllerTests
|
|||
new(Index: 5, ObjectId: 0x5002u, SpellId: 0) };
|
||||
var (adds, removes) = NewSpies(out var add, out var rem);
|
||||
var ctrl = ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_,_,_,_,_) => 0x77u, useItem: _ => { },
|
||||
iconIds: (_,_,_,_,_) => new GpuTextureSlot(0x77u), useItem: _ => { },
|
||||
sendAddShortcut: add, sendRemoveShortcut: rem);
|
||||
|
||||
var payload = new ItemDragPayload(0x5001u, ItemDragSource.ShortcutBar, 3, slots[Row1[3]].Cell);
|
||||
|
|
@ -1397,7 +1398,7 @@ public class ToolbarControllerTests
|
|||
var (adds, _) = NewSpies(out var add, out var remove);
|
||||
var controller = ToolbarController.Bind(
|
||||
layout, repo, Store(shortcuts),
|
||||
iconIds: (_, _, _, _, _) => 1u,
|
||||
iconIds: (_, _, _, _, _) => new GpuTextureSlot(1u),
|
||||
useItem: _ => { },
|
||||
sendAddShortcut: add,
|
||||
sendRemoveShortcut: remove);
|
||||
|
|
@ -1420,7 +1421,7 @@ public class ToolbarControllerTests
|
|||
{ new(Index: 3, ObjectId: 0x5001u, SpellId: 0) };
|
||||
var (adds, removes) = NewSpies(out var add, out var rem);
|
||||
var ctrl = ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_,_,_,_,_) => 0x77u, useItem: _ => { },
|
||||
iconIds: (_,_,_,_,_) => new GpuTextureSlot(0x77u), useItem: _ => { },
|
||||
sendAddShortcut: add, sendRemoveShortcut: rem);
|
||||
|
||||
var payload = new ItemDragPayload(0x5001u, ItemDragSource.ShortcutBar, 3, slots[Row1[3]].Cell);
|
||||
|
|
@ -1446,7 +1447,7 @@ public class ToolbarControllerTests
|
|||
};
|
||||
var wire = new List<string>();
|
||||
var ctrl = ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_, _, _, _, _) => 1u,
|
||||
iconIds: (_, _, _, _, _) => new GpuTextureSlot(1u),
|
||||
useItem: _ => { },
|
||||
sendAddShortcut: entry => wire.Add($"add:{entry.Index}:{entry.ObjectId:X8}:{entry.SpellId:X8}"),
|
||||
sendRemoveShortcut: slot => wire.Add($"remove:{slot}"));
|
||||
|
|
@ -1479,7 +1480,7 @@ public class ToolbarControllerTests
|
|||
};
|
||||
var wire = new List<string>();
|
||||
var ctrl = ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_, _, _, _, _) => 1u,
|
||||
iconIds: (_, _, _, _, _) => new GpuTextureSlot(1u),
|
||||
useItem: _ => { },
|
||||
sendAddShortcut: entry => wire.Add($"add:{entry.Index}:{entry.ObjectId:X8}:{entry.SpellId:X8}"),
|
||||
sendRemoveShortcut: slot => wire.Add($"remove:{slot}"));
|
||||
|
|
@ -1504,7 +1505,7 @@ public class ToolbarControllerTests
|
|||
{ new(Index: 3, ObjectId: 0x5001u, SpellId: 0) };
|
||||
var (adds, removes) = NewSpies(out var add, out var rem);
|
||||
var ctrl = ToolbarController.Bind(layout, repo, Store(shortcuts),
|
||||
iconIds: (_,_,_,_,_) => 0x77u, useItem: _ => { },
|
||||
iconIds: (_,_,_,_,_) => new GpuTextureSlot(0x77u), useItem: _ => { },
|
||||
sendAddShortcut: add, sendRemoveShortcut: rem);
|
||||
|
||||
var payload = new ItemDragPayload(0x5001u, ItemDragSource.ShortcutBar, 3, slots[Row1[3]].Cell);
|
||||
|
|
@ -1523,7 +1524,7 @@ public class ToolbarControllerTests
|
|||
var (layout, slots, _) = FakeToolbar();
|
||||
ToolbarController.Bind(layout, new ClientObjectTable(),
|
||||
new ShortcutStore(),
|
||||
iconIds: (_,_,_,_,_) => 0u, useItem: _ => { });
|
||||
iconIds: (_,_,_,_,_) => GpuTextureSlot.Unassigned, useItem: _ => { });
|
||||
Assert.Equal(0x060011FAu, slots[Row1[0]].Cell.DragAcceptSprite); // green cross, not the ring F9
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
namespace AcDream.App.Tests.UI.Layout;
|
||||
|
|
@ -10,7 +11,7 @@ public class UiDatElementTests
|
|||
var info = new ElementInfo();
|
||||
info.StateMedia[""] = (0x06000001, 1); // DirectState (DrawMode Normal=1)
|
||||
info.StateMedia["ShowDetail"] = (0x06000002, 3); // named (Alphablend=3)
|
||||
var e = new UiDatElement(info, _ => (0, 0, 0)) { ActiveState = "ShowDetail" };
|
||||
var e = new UiDatElement(info, _ => (GpuTextureSlot.Unassigned, 0, 0)) { ActiveState = "ShowDetail" };
|
||||
Assert.Equal(0x06000002u, e.ActiveMedia().File);
|
||||
Assert.Equal(3, e.ActiveMedia().DrawMode);
|
||||
e.ActiveState = "";
|
||||
|
|
@ -21,7 +22,7 @@ public class UiDatElementTests
|
|||
[Fact]
|
||||
public void ActiveMedia_NoMedia_ReturnsZero()
|
||||
{
|
||||
var e = new UiDatElement(new ElementInfo(), _ => (0, 0, 0));
|
||||
var e = new UiDatElement(new ElementInfo(), _ => (GpuTextureSlot.Unassigned, 0, 0));
|
||||
Assert.Equal(0u, e.ActiveMedia().File);
|
||||
Assert.Equal(0, e.ActiveMedia().DrawMode);
|
||||
}
|
||||
|
|
@ -31,7 +32,7 @@ public class UiDatElementTests
|
|||
{
|
||||
var info = new ElementInfo();
|
||||
info.StateMedia[""] = (0x06000005, 1);
|
||||
var e = new UiDatElement(info, _ => (0, 0, 0)) { ActiveState = "NoSuchState" };
|
||||
var e = new UiDatElement(info, _ => (GpuTextureSlot.Unassigned, 0, 0)) { ActiveState = "NoSuchState" };
|
||||
Assert.Equal(0x06000005u, e.ActiveMedia().File);
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +50,7 @@ public class UiDatElementTests
|
|||
info.StateMedia["Normal"] = (0x0000AAAAu, 1);
|
||||
info.StateMedia["Hover"] = (0x0000BBBBu, 1);
|
||||
|
||||
var e = new UiDatElement(info, _ => (0, 0, 0));
|
||||
var e = new UiDatElement(info, _ => (GpuTextureSlot.Unassigned, 0, 0));
|
||||
|
||||
// Should have defaulted to "Normal" state.
|
||||
Assert.Equal(0x0000AAAAu, e.ActiveMedia().File);
|
||||
|
|
@ -67,7 +68,7 @@ public class UiDatElementTests
|
|||
info.StateMedia["Maximized"] = (0x0000CCCCu, 1);
|
||||
info.StateMedia["Normal"] = (0x0000DDDDu, 1);
|
||||
|
||||
var e = new UiDatElement(info, _ => (0, 0, 0));
|
||||
var e = new UiDatElement(info, _ => (GpuTextureSlot.Unassigned, 0, 0));
|
||||
|
||||
// DefaultStateName "Minimized" wins over "Normal" implicit default.
|
||||
Assert.Equal(0x0000BBBBu, e.ActiveMedia().File);
|
||||
|
|
@ -83,7 +84,7 @@ public class UiDatElementTests
|
|||
var info = new ElementInfo();
|
||||
info.StateMedia[""] = (0x06007777u, 1); // DirectState only (e.g. vitals chrome corner)
|
||||
|
||||
var e = new UiDatElement(info, _ => (0, 0, 0));
|
||||
var e = new UiDatElement(info, _ => (GpuTextureSlot.Unassigned, 0, 0));
|
||||
|
||||
// No DefaultStateName, no "Normal" state → ActiveState stays "" (DirectState).
|
||||
Assert.Equal(0x06007777u, e.ActiveMedia().File);
|
||||
|
|
@ -100,7 +101,7 @@ public class UiDatElementTests
|
|||
Image = new UiImageMedia(0x06000009u, 3),
|
||||
};
|
||||
info.StateMedia["ShowDetail"] = (0x06000009u, 3);
|
||||
var element = new UiDatElement(info, _ => (0u, 0, 0))
|
||||
var element = new UiDatElement(info, _ => (GpuTextureSlot.Unassigned, 0, 0))
|
||||
{
|
||||
Left = info.X,
|
||||
Top = info.Y,
|
||||
|
|
@ -121,7 +122,7 @@ public class UiDatElementTests
|
|||
{
|
||||
var info = new ElementInfo { DefaultStateName = "Normal" };
|
||||
info.StateMedia["Normal"] = (0x06000001u, 1);
|
||||
var element = new UiDatElement(info, _ => (0u, 0, 0));
|
||||
var element = new UiDatElement(info, _ => (GpuTextureSlot.Unassigned, 0, 0));
|
||||
|
||||
Assert.False(element.TrySetRetailState(RetailUiStateIds.ShowDetail));
|
||||
Assert.Equal("Normal", element.ActiveState);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
|
||||
|
|
@ -5,7 +6,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
|
||||
public class UiViewportFactoryTests
|
||||
{
|
||||
private static (uint, int, int) NoTex(uint _) => (0, 0, 0);
|
||||
private static (GpuTextureSlot, int, int) NoTex(uint _) => (GpuTextureSlot.Unassigned, 0, 0);
|
||||
|
||||
[Fact]
|
||||
public void Factory_builds_UiViewport_for_dat_type_0xD()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue