feat(ui): centralize retail selection state
This commit is contained in:
parent
c7607f019c
commit
7983309d23
30 changed files with 591 additions and 108 deletions
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.Core.Selection;
|
||||
|
||||
namespace AcDream.App.UI.Layout;
|
||||
|
||||
|
|
@ -82,7 +83,7 @@ public sealed class SelectedObjectController : IRetainedPanelController
|
|||
private readonly Func<uint, bool> _hasHealth;
|
||||
private readonly Func<uint, uint> _stackSize;
|
||||
private readonly Action<uint> _sendQueryHealth;
|
||||
private readonly Action<Action<uint?>> _unsubscribeSelectionChanged;
|
||||
private readonly SelectionState _selection;
|
||||
private readonly Action<Action<uint, float>> _unsubscribeHealthChanged;
|
||||
|
||||
// ── Live state (read by closures on the per-frame draw path) ────────────
|
||||
|
|
@ -96,8 +97,7 @@ public sealed class SelectedObjectController : IRetainedPanelController
|
|||
|
||||
private SelectedObjectController(
|
||||
ImportedLayout layout,
|
||||
Action<Action<uint?>> subscribeSelectionChanged,
|
||||
Action<Action<uint?>> unsubscribeSelectionChanged,
|
||||
SelectionState selection,
|
||||
Action<Action<uint, float>> subscribeHealthChanged,
|
||||
Action<Action<uint, float>> unsubscribeHealthChanged,
|
||||
Func<uint, bool> isHealthTarget,
|
||||
|
|
@ -114,7 +114,7 @@ public sealed class SelectedObjectController : IRetainedPanelController
|
|||
_hasHealth = hasHealth;
|
||||
_stackSize = stackSize;
|
||||
_sendQueryHealth = sendQueryHealth;
|
||||
_unsubscribeSelectionChanged = unsubscribeSelectionChanged;
|
||||
_selection = selection ?? throw new ArgumentNullException(nameof(selection));
|
||||
_unsubscribeHealthChanged = unsubscribeHealthChanged;
|
||||
|
||||
// Find elements — silently skip absent ones (partial/test layouts).
|
||||
|
|
@ -171,8 +171,10 @@ public sealed class SelectedObjectController : IRetainedPanelController
|
|||
}
|
||||
|
||||
// Register the handlers LAST so the initial state is fully set up first.
|
||||
subscribeSelectionChanged(OnSelectionChanged);
|
||||
_selection.Changed += OnSelectionTransition;
|
||||
subscribeHealthChanged(OnHealthChanged);
|
||||
if (_selection.SelectedObjectId is { } initial)
|
||||
ApplySelection(initial);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -180,8 +182,7 @@ public sealed class SelectedObjectController : IRetainedPanelController
|
|||
/// Port of retail <c>gmToolbarUI::HandleSelectionChanged</c> + <c>RecvNotice_UpdateObjectHealth</c>.
|
||||
/// </summary>
|
||||
/// <param name="layout">Imported toolbar layout (LayoutDesc 0x21000016).</param>
|
||||
/// <param name="subscribeSelectionChanged">Called once with <see cref="OnSelectionChanged"/>
|
||||
/// (typical host: <c>h => SelectionChanged += h</c>).</param>
|
||||
/// <param name="selection">The single Core selected-object owner.</param>
|
||||
/// <param name="subscribeHealthChanged">Called once with <see cref="OnHealthChanged"/>
|
||||
/// (typical host: <c>h => Combat.HealthChanged += h</c>) — drives meter visibility.</param>
|
||||
/// <param name="isHealthTarget">Returns true for guids that may show a health meter
|
||||
|
|
@ -195,8 +196,7 @@ public sealed class SelectedObjectController : IRetainedPanelController
|
|||
/// <param name="datFont">Dat font for the name label; null = debug bitmap font fallback.</param>
|
||||
public static SelectedObjectController Bind(
|
||||
ImportedLayout layout,
|
||||
Action<Action<uint?>> subscribeSelectionChanged,
|
||||
Action<Action<uint?>> unsubscribeSelectionChanged,
|
||||
SelectionState selection,
|
||||
Action<Action<uint, float>> subscribeHealthChanged,
|
||||
Action<Action<uint, float>> unsubscribeHealthChanged,
|
||||
Func<uint, bool> isHealthTarget,
|
||||
|
|
@ -207,7 +207,7 @@ public sealed class SelectedObjectController : IRetainedPanelController
|
|||
Action<uint> sendQueryHealth,
|
||||
UiDatFont? datFont)
|
||||
=> new SelectedObjectController(
|
||||
layout, subscribeSelectionChanged, unsubscribeSelectionChanged,
|
||||
layout, selection,
|
||||
subscribeHealthChanged, unsubscribeHealthChanged,
|
||||
isHealthTarget, name, healthPercent, hasHealth, stackSize, sendQueryHealth, datFont);
|
||||
|
||||
|
|
@ -215,7 +215,7 @@ public sealed class SelectedObjectController : IRetainedPanelController
|
|||
/// Port of <c>gmToolbarUI::HandleSelectionChanged</c> (<c>:198635</c>):
|
||||
/// clear-then-populate the selected-object strip on any selection change.
|
||||
/// </summary>
|
||||
public void OnSelectionChanged(uint? guid)
|
||||
private void ApplySelection(uint? guid)
|
||||
{
|
||||
// ── 1. Clear first (retail: SetText("") + m_pSelObjectField->SetState(0)
|
||||
// + SetVisible(0) on the meters). ──────────────────────────────────────
|
||||
|
|
@ -279,11 +279,14 @@ public sealed class SelectedObjectController : IRetainedPanelController
|
|||
_overlay?.TrySetRetailState(state);
|
||||
}
|
||||
|
||||
private void OnSelectionTransition(SelectionTransition transition)
|
||||
=> ApplySelection(transition.SelectedObjectId);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
_unsubscribeSelectionChanged(OnSelectionChanged);
|
||||
_selection.Changed -= OnSelectionTransition;
|
||||
_unsubscribeHealthChanged(OnHealthChanged);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue