fix(ui): restore modern spell formula presentation

Resolve spell-examination component cells through their DAT icon DIDs, project scarab and prismatic-taper formulas when ACE disables component enforcement, and version authored window geometry so stale examination sizes reset once without losing user layout behavior.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-24 07:08:47 +02:00
parent 3e31b0ac70
commit d4ce64f56b
22 changed files with 307 additions and 41 deletions

View file

@ -717,6 +717,17 @@ public sealed class AppraisalUiControllerTests
new SpellComponentDescriptor(101u, "Malar Herb", 1u, 0x06000011u),
Owned: false),
};
var componentTemplate = new SpellExamineComponentTemplateFactory(
new ElementInfo
{
Id = SpellExamineComponentTemplateFactory.TemplateId,
Type = 3,
Width = 20,
Height = 20,
},
NoTexture,
defaultFont: null);
var resolvedComponentIcons = new List<uint>();
int shown = 0;
using AppraisalUiController controller = Bind(
layout,
@ -730,8 +741,14 @@ public sealed class AppraisalUiControllerTests
selection: selection,
spellbook: spellbook,
resolveSpellIcon: id => id + 1_000u,
resolveComponentIcon: did =>
{
resolvedComponentIcons.Add(did);
return did + 2_000u;
},
spellComponents: _ => components,
magicSkill: _ => 200u)!;
magicSkill: _ => 200u,
spellComponentTemplates: componentTemplate)!;
Assert.True(interaction.ExamineSelectedOrEnterMode(ObjectId));
Assert.Equal(1, interaction.BusyCount);
@ -784,6 +801,17 @@ public sealed class AppraisalUiControllerTests
UiTextureElement icon = Assert.Single(
iconHost.Children.OfType<UiTextureElement>());
Assert.Equal(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 },
formula.Children
.SelectMany(cell => cell.Children)
.OfType<UiTextureElement>()
.Select(texture => texture.Texture));
}
private static AppraisalUiController? Bind(

View file

@ -94,6 +94,87 @@ public sealed class RetailWindowLayoutPersistenceTests : IDisposable
Assert.True(state.Restored.Maximized);
}
[Fact]
public void Restore_OlderAuthoredGeometryRevision_ResetsOnlySavedExtent()
{
var store = new SettingsStore(PathName);
store.SaveWindowLayout(
"Alice",
"800x600",
WindowNames.Examination,
new UiWindowLayout(
44f,
55f,
310f,
545f,
true,
false,
false,
AuthoredGeometryRevision: 0));
var root = new UiRoot { Width = 800, Height = 600 };
RetailWindowHandle handle = Mount(
root,
WindowNames.Examination,
authoredGeometryRevision: 1,
width: 310f,
height: 400f);
using var persistence = new RetailWindowLayoutPersistence(
root.WindowManager,
store,
() => "Alice",
() => (800, 600));
persistence.RestoreAll();
Assert.Equal((44f, 55f), (handle.Left, handle.Top));
Assert.Equal((310f, 400f), (handle.Width, handle.Height));
UiWindowLayout migrated = Assert.IsType<UiWindowLayout>(
store.LoadWindowLayout(
"Alice",
"800x600",
WindowNames.Examination,
default));
Assert.Equal(1, migrated.AuthoredGeometryRevision);
}
[Fact]
public void RestoreNamed_OlderRevisionUsesMountedAuthoredExtent_NotCurrentSize()
{
var store = new SettingsStore(PathName);
store.SaveNamedWindowLayout(
"legacy",
WindowNames.Examination,
new UiWindowLayout(
44f,
55f,
310f,
545f,
true,
false,
false,
AuthoredGeometryRevision: 0));
var root = new UiRoot { Width = 800, Height = 600 };
RetailWindowHandle handle = Mount(
root,
WindowNames.Examination,
authoredGeometryRevision: 1,
width: 310f,
height: 400f);
handle.ResizeTo(500f, 300f);
using var persistence = new RetailWindowLayoutPersistence(
root.WindowManager,
store,
() => "Alice",
() => (800, 600));
persistence.RestoreNamed("legacy");
Assert.Equal((44f, 55f), (handle.Left, handle.Top));
Assert.Equal((310f, 400f), (handle.Width, handle.Height));
}
[Fact]
public void DefaultPreLoginKey_NeverOverwritesCharacterLayouts()
{
@ -169,14 +250,17 @@ public sealed class RetailWindowLayoutPersistenceTests : IDisposable
private static RetailWindowHandle Mount(
UiRoot root,
string name,
IRetainedWindowStateController? state = null)
IRetainedWindowStateController? state = null,
int authoredGeometryRevision = 0,
float width = 200f,
float height = 100f)
{
var frame = new UiPanel
{
Left = 10f,
Top = 20f,
Width = 200f,
Height = 100f,
Width = width,
Height = height,
MinWidth = 100f,
MinHeight = 80f,
MaxWidth = 600f,
@ -185,7 +269,11 @@ public sealed class RetailWindowLayoutPersistenceTests : IDisposable
Resizable = true,
};
root.AddChild(frame);
return root.RegisterWindow(name, frame, stateController: state);
return root.RegisterWindow(
name,
frame,
stateController: state,
authoredGeometryRevision: authoredGeometryRevision);
}
public void Dispose()