perf(ui): retain shaped report text

This commit is contained in:
Erik 2026-07-25 05:11:12 +02:00
parent c0bec56dfe
commit f2a015be8e
11 changed files with 525 additions and 38 deletions

View file

@ -87,6 +87,9 @@ public sealed class AppraisalUiController : IRetainedPanelController
private readonly UiElement _spellFormulaHost;
private readonly UiTextureElement _spellIcon;
private readonly List<UiElement> _spellFormulaCells = [];
private readonly Dictionary<UiText, UiTextLayoutCache<string>>
_textLayouts = new();
private UiTextLayoutCache<ItemAppraisalReport> _itemTextLayout = null!;
private readonly float _spellFormulaOriginX;
private readonly float _spellFormulaCellWidth;
private AppraisalView _activeView;
@ -173,8 +176,11 @@ public sealed class AppraisalUiController : IRetainedPanelController
layout.FindElement(InscriptionBackgroundId) as UiDatElement;
_close = layout.FindElement(CloseId) as UiButton;
_title.LinesProvider = () =>
[new UiText.Line(_titleValue, _title.DefaultColor)];
BindTextSource(
_title,
() => _titleValue,
static (target, value) =>
[new UiText.Line(value, target.DefaultColor)]);
// ItemExamineUI::AddItemInfo @ 0x004AC050 appends the freshly
// rebuilt report from the beginning of the authored text surface.
// LayoutDesc 0x2100006B carries Bottom here, which is appropriate for
@ -200,8 +206,13 @@ public sealed class AppraisalUiController : IRetainedPanelController
scrollbar.Model = _inscriptionField.Scroll;
}
if (_signature is not null)
_signature.LinesProvider = () =>
[new UiText.Line(_signatureValue, _signature.DefaultColor)];
{
BindTextSource(
_signature,
() => _signatureValue,
static (target, value) =>
[new UiText.Line(value, target.DefaultColor)]);
}
if (_close is not null)
_close.OnClick = close;
if (_inscriptionBackground is not null)
@ -717,11 +728,49 @@ public sealed class AppraisalUiController : IRetainedPanelController
text.PreserveEndOnLayout = false;
text.WheelScrollEnabled = true;
text.ClickThrough = false;
text.LinesProvider = () => IndicatorDetailText.Shape(text, value());
BindTextSource(
text,
value,
static (target, content) =>
IndicatorDetailText.Shape(target, content));
if (_layout.FindElement(scrollbarId) is UiScrollbar scrollbar)
scrollbar.Model = text.Scroll;
}
private void BindTextSource(
UiText text,
Func<string> source,
Func<UiText, string, IReadOnlyList<UiText.Line>> shape)
{
var cache = new UiTextLayoutCache<string>(
text,
shape,
source,
StringComparer.Ordinal);
_textLayouts.Add(text, cache);
text.LinesProvider = cache.Provider;
}
private UiTextLayoutCache<string> GetTextLayout(UiText text)
{
if (_textLayouts.TryGetValue(
text,
out UiTextLayoutCache<string>? cache))
{
return cache;
}
cache = new UiTextLayoutCache<string>(
text,
static (target, value) =>
IndicatorDetailText.Shape(target, value),
string.Empty,
StringComparer.Ordinal);
_textLayouts.Add(text, cache);
text.LinesProvider = cache.Provider;
return cache;
}
private void ConfigureScrollableItemText(
UiText text,
uint scrollbarId)
@ -729,8 +778,13 @@ public sealed class AppraisalUiController : IRetainedPanelController
text.PreserveEndOnLayout = false;
text.WheelScrollEnabled = true;
text.ClickThrough = false;
text.LinesProvider = () =>
ItemAppraisalTextLayout.Shape(text, _itemReport);
_itemTextLayout = new UiTextLayoutCache<ItemAppraisalReport>(
text,
static (target, report) =>
ItemAppraisalTextLayout.Shape(target, report),
() => _itemReport,
ReferenceEqualityComparer.Instance);
text.LinesProvider = _itemTextLayout.Provider;
if (_layout.FindElement(scrollbarId) is UiScrollbar scrollbar)
scrollbar.Model = text.Scroll;
}
@ -746,8 +800,8 @@ public sealed class AppraisalUiController : IRetainedPanelController
}
}
private static void SetSpellText(UiText text, string value)
=> text.LinesProvider = () => IndicatorDetailText.Shape(text, value);
private void SetSpellText(UiText text, string value)
=> GetTextLayout(text).SetValue(value);
private static string BuildSpellDisplay(
SpellMetadata metadata,
@ -811,7 +865,7 @@ public sealed class AppraisalUiController : IRetainedPanelController
text.PreserveEndOnLayout = false;
text.WheelScrollEnabled = scrollable;
text.ClickThrough = !scrollable;
text.LinesProvider = () => IndicatorDetailText.Shape(text, value);
GetTextLayout(text).SetValue(value);
if (scrollable)
{
UiScrollbar? scrollbar = Descendants(text.Parent)
@ -830,7 +884,7 @@ public sealed class AppraisalUiController : IRetainedPanelController
0x10000150u, 0x10000151u, 0x10000152u, 0x1000053Au,
})
if (_layout.FindElement(id) is UiText text)
text.LinesProvider = static () => Array.Empty<UiText.Line>();
GetTextLayout(text).SetValue(string.Empty);
_creatureStats?.Flush();
_creatureExtra?.Flush();
}