From 06c9b95222c2d1d2242bdec4c412a03c624ff6f4 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2026 12:05:27 +0200 Subject: [PATCH] =?UTF-8?q?feat(vtank):=20slice=207=20fix=20round=20B=20it?= =?UTF-8?q?em=205=20=E2=80=94=20Meta=20tab=20down=20to=20VTank's=20real=20?= =?UTF-8?q?5=20controls,=20rule=20editor=20as=20a=20popup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VTank's own Meta tab (docs/research/vtank-kb/08-ui-views.md §1 "Tab: Meta") is only 5 controls: the lstMetaRules grid, cmdMetaCreate ("Create"), a bold "Current State:" caption, and a SETTABLE cmbMetaCurrentState choice — no profile toolbar, no "Enable Meta" checkbox, no inline editor at all. - Removed from the Meta tab entirely: the profile menu/name-draft field/ New/CopyTo/Clear/Delete row (Profiles already carries the Meta combo/ CopyTo/Delete) and the "Enable Meta" toggle (already on Options) — same accepted-regression shape as fix round A's Macro/Nav CopyTo-name-field loss (no Profiles-tab equivalent exists for these, and VTank's own tab has none either). - Moved the inline State/Condition/Action editor (fields, condition/action menus, numeric steppers, Apply/Remove/MoveUp/MoveDown) into a new popup, mosstank-metaeditor.xml, registered the same StartVisible=true/ ShowInSidePanel=false way as the buff picker. Opened by a grid text-cell click (SelectMetaRule, still populating the draft via SelectMetaRuleCore) or the tab's own "Create" button (CreateMetaRule — new, distinct from the still-existing AddMetaRule the tests call directly); Apply and Cancel (HideMetaEditor) both close it. DeleteMetaRuleAt/MoveMetaRuleUpAt/ MoveMetaRuleDownAt call SelectMetaRuleCore directly and do NOT open the popup. - "Add" -> "Create": CreateMetaRule adds a default rule (delegating to the existing AddMetaRuleCore) and opens the editor so it isn't left silently default-valued. - Added the settable current-state menu: MetaCurrentStateNames/ SelectedMetaCurrentState/SetMetaCurrentState expose MetaEngine's own already-public States/Transition(string) — choosing a state here forces the live engine into it, matching VTank's own manual override. - The grid returns to VTank's full-width 856x116 proportion (848x116 here) now nothing else shares the tab. - Bold text isn't representable in the plain retail UI font (0x40000000 has no bold face); "Current State:" uses the same bright caption color other tab headers use instead — documented in mosstank.xml's own comment, not silently dropped. New tests: MetaEditorPopupOpensOnCellClickOrCreateAndClosesOnApplyOrCancel, MetaCurrentStateMenuForcesTheLiveEngineIntoTheChosenState. Both mutation- checked: commenting out SelectMetaRule's `_metaEditorVisible = true` turned the first red ("Expected: True, Actual: False"); commenting out SetMetaCurrentState's `_meta.Transition(value)` turned the second red ("Expected: Hunt, Actual: Default"). Restoring both turns them green. EveryInteractiveControlDeclaresARealHandlerBinding's pinned control count: 186 -> 166 (-7 controls removed for good, -14 moved into the new popup file this scan doesn't cover, +1 the new current-state menu). SecondaryPopupPanelsFitTheirOwnBoundsAndEveryBindingResolves gained mosstank-metaeditor.xml (630x236... — 630x160, corrected below). tests/AcDream.Plugins.MossTank.Tests: 665/665 (was 663/663, +2 new tests). tests/AcDream.App.Tests --filter Markup|Plugin|UiMenu|Slider: 276/3 skipped/279 (unchanged). Screenshot with at least two rules (item 17) is owed with the round's other live captures. Co-Authored-By: Claude Fable 5.1 --- src/AcDream.Plugins.MossTank/MossTankPanel.cs | 49 +++++++- .../MossTankPlugin.cs | 11 ++ .../mosstank-metaeditor.xml | 73 ++++++++++++ src/AcDream.Plugins.MossTank/mosstank.xml | 109 +++++------------- .../MossTankMarkupContractTests.cs | 15 ++- .../MossTankPanelTests.cs | 62 ++++++++++ 6 files changed, 238 insertions(+), 81 deletions(-) create mode 100644 src/AcDream.Plugins.MossTank/mosstank-metaeditor.xml diff --git a/src/AcDream.Plugins.MossTank/MossTankPanel.cs b/src/AcDream.Plugins.MossTank/MossTankPanel.cs index 45075ab2c..46a7aa3d8 100644 --- a/src/AcDream.Plugins.MossTank/MossTankPanel.cs +++ b/src/AcDream.Plugins.MossTank/MossTankPanel.cs @@ -216,6 +216,13 @@ internal sealed partial class MossTankPanel private int _metaNumber; private int _metaSecondaryNumber; private string _metaNotice = "Add a rule or select one to edit."; + // Fix round B item 5: the rule editor (State/Condition/Action drafts, + // Apply/Remove/Move) moved off the Meta tab into its own popup + // (mosstank-metaeditor.xml), opened by a grid text-cell click or the + // tab's own "Create" button, closed by the popup's own Apply/Cancel — + // same StartVisible=true/ShowInSidePanel=false pattern as the buff + // picker (MossTankPlugin.cs). + private bool _metaEditorVisible; private bool _applyingProfileOptions; private bool _initialized; private bool _firstRunGuidancePending; @@ -982,7 +989,30 @@ internal sealed partial class MossTankPanel _meta.SetEnabled(!_meta.Enabled); _combatSettings.MetaState = _meta.CurrentState; }; - public Action SelectMetaRule => SelectMetaRuleCore; + // Fix round B item 5: clicking a State/Condition/Action grid cell opens + // the rule editor popup (SelectMetaRuleCore alone still populates the + // draft fields for DeleteMetaRuleAt/MoveMetaRuleUpAt/MoveMetaRuleDownAt, + // which call it directly and must NOT pop the editor open). + public Action SelectMetaRule => row => + { + SelectMetaRuleCore(row); + _metaEditorVisible = true; + }; + public bool MetaEditorVisible => _metaEditorVisible; + public Action HideMetaEditor => () => _metaEditorVisible = false; + // VTank's own cmbMetaCurrentState (docs/research/vtank-kb/08-ui-views.md + // §1 "Tab: Meta") is a SETTABLE current-state choice, not a read-only + // label — MetaEngine.Transition(string) and .States already existed + // (used internally for state-machine transitions), so this just exposes + // them: choosing a state here forces the live engine into it, exactly + // like retail's own manual state override. + public IReadOnlyList MetaCurrentStateNames => _meta.States.ToArray(); + public string SelectedMetaCurrentState => _meta.CurrentState; + public Action SetMetaCurrentState => value => + { + _meta.Transition(value); + _combatSettings.MetaState = _meta.CurrentState; + }; public Action SelectMetaCondition => value => { if (Enum.TryParse(value, ignoreCase: true, out MetaConditionKind parsed)) @@ -1005,7 +1035,22 @@ internal sealed partial class MossTankPanel public Action MetaSecondaryNumberDown => () => _metaSecondaryNumber--; public Action MetaSecondaryNumberUp => () => _metaSecondaryNumber++; public Action AddMetaRule => AddMetaRuleCore; - public Action ApplyMetaRule => ApplyMetaRuleCore; + // The Meta tab's own "Create" button (VTank's cmdMetaCreate, renamed + // from "Add" — item 5): appends a default rule exactly like AddMetaRule + // and immediately opens the editor popup so the new rule isn't left + // silently default-valued in the grid. + public Action CreateMetaRule => () => + { + AddMetaRuleCore(); + _metaEditorVisible = true; + }; + // Apply/Cancel both close the popup (item 5) — Apply persists first, + // Cancel (HideMetaEditor) discards the in-progress draft. + public Action ApplyMetaRule => () => + { + ApplyMetaRuleCore(); + _metaEditorVisible = false; + }; public Action RemoveMetaRule => RemoveMetaRuleCore; public Action MoveMetaRuleUp => () => MoveMetaRule(-1); public Action MoveMetaRuleDown => () => MoveMetaRule(1); diff --git a/src/AcDream.Plugins.MossTank/MossTankPlugin.cs b/src/AcDream.Plugins.MossTank/MossTankPlugin.cs index 51e3c064e..3b150a4d2 100644 --- a/src/AcDream.Plugins.MossTank/MossTankPlugin.cs +++ b/src/AcDream.Plugins.MossTank/MossTankPlugin.cs @@ -113,6 +113,17 @@ public sealed class MossTankPlugin : IAcDreamPlugin }, Path.Combine(directory, "mosstank-buffpicker.xml"), _panel); + // Fix round B item 5: the Meta tab's inline rule editor moved to its + // own popup, same StartVisible=true/ShowInSidePanel=false pattern + // as the three panels above. + _host.Ui.AddPanel( + new PluginPanelDescriptor("meta-editor", "MossTank Meta Rule Editor") + { + StartVisible = true, + ShowInSidePanel = false, + }, + Path.Combine(directory, "mosstank-metaeditor.xml"), + _panel); _commandRegistration = _host.Commands.Register( "vt", diff --git a/src/AcDream.Plugins.MossTank/mosstank-metaeditor.xml b/src/AcDream.Plugins.MossTank/mosstank-metaeditor.xml new file mode 100644 index 000000000..779cfaea3 --- /dev/null +++ b/src/AcDream.Plugins.MossTank/mosstank-metaeditor.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + +