feat(vtank): slice 7 fix round A — grid scaling, Profiles cleanup, popups as own panels
Owner's live-client report (2026-09-07 08:05): "The Options tab labels
overlap, fix that" and "Those BIG gold/yellow buttons HAS to go" (the
gold-button half already landed upstream at cfa703065, merged into this
branch first). This commit is the geometry half of that fix round plus
the lead's 07:55 read (docs/plans/2026-09-07-campaign-vt-slice7-tabs.md).
Grid scaling: measured acdream's actual retail DAT font (0x40000000) via
AcDream.Cli's dump-font-atlas against a real installed DAT rather than
guessing — MaxCharHeight=16 matches VVS's own assumed row height exactly,
so no vertical scale was needed, but several captions render wider than
VVS's narrow font assumed ("Follow/Nav Min Distance:" measures 134px real
width vs an 80px-wide retail label column). <label>/<toggle> never clip or
use their declared "w" (UiLabel.OnDraw/UiMarkupToggle.OnDraw draw raw,
unclipped text), so the fix is a plain rightward SHIFT of the columns after
the overflowing captions rather than a width change: Options' columns 2-5
move +62px (90/220/386/552/611 -> 152/282/448/614/673, with the rightmost
Advanced Options/Run Macro/status sub-block also shrinking its declared
width 233->175 to stay inside the group's 848 budget), Profiles' columns
2-5 move +16px (140/280/330/440/530 -> 156/296/346/456/546). Both are pure
translations, so every original inter-column gap is preserved exactly.
Vitals needed no shift (its worst caption already clears its slider by 3px)
but got a small +4px safety margin anyway since it was the tightest
already-OK case measured.
Profiles leftovers deleted (owner + lead, "legacy controls"): the three
stacked ProfileNameDraft/RouteProfileNameDraft/MetaProfileNameDraft
field+"New"-button rows (three 20-tall fields at zero vertical gap that
rendered as one solid black bar behind three stacked "New" buttons — the
owner's screenshot), the acdream-only "Loot engine" classifier row
(no VTank equivalent), and the ProfileLifecycleNotice label (the raw
macro-profile recovery path the owner saw rendered). Deviation: Macro/Nav
CopyTo lose their only in-UI target-name entry point (Meta's naming
already exists on the Meta tab itself, so only Macro/Nav are affected) —
an accepted trade for matching VTank's own Profiles table, which has no
name-draft control at all (VVS's own combo is presumably editable
in-place; acdream's <menu> is not). LootStatus is kept (general feedback,
not itself a reported leftover) but repositioned into the freed space.
Window: Advanced Options and Loot Editor move out of mosstank.xml into
their own top-level plugin panels (mosstank-advanced.xml,
mosstank-loot-editor.xml, MossTankPlugin.cs registers a second and third
AddPanel with ShowInSidePanel=false since VTank's own popups have no
shelf entry). No new IUiRegistry show/hide API was needed: a root <panel>
already supports a data-bound visible="{Prop}" attribute
(MarkupDocument.Build re-evaluates VisibleSource every frame, proven by
the main panel's own visible="{WindowAvailable}"), so each popup's own
visible="{AdvancedOptionsVisible}"/"{LootEditorVisible}" is the SAME flag
the Options/Profiles checkbox flips and the popup's own "Back" button
clears — closing the popup unchecks the box for free. The main window
returns to VTank's 210-ish proportion (236 = 42px header/tab-strip +
194px per-tab content, both unchanged since S7.1) with no dead space
below the tabs. The eight tab-content *Visible getters (MossTankPanel.cs)
drop their `&& !_lootEditorVisible`/`&& !_advancedOptionsVisible` guards,
which only existed because the popups used to share screen space with the
tab content in the same window.
Trailing blank button slots (Route waypoint reorder, Meta rule reorder,
Loot Editor rule reorder): the retail default UI font (0x40000000) has no
glyph for U+2191/U+2193, so the "↑"/"↓" text buttons rendered as blank
slots (owner's screenshot). Replaced with the same DAT move-up/move-down
icons (0x060028FC/0x060028FD) the Monsters grid's own reorder columns
already use.
No remaining <menu style="retail"> in any of the three files (verified).
Pins updated (shown to fail against the old numbers first): the markup
contract's interactive-control count (202 -> 167, the two popups leaving
the file plus the Profiles deletions) and the authored-shell height pin
(350 -> 236). Added SecondaryPopupPanelsFitTheirOwnBoundsAndEveryBindingResolves
(parses both new files, checks their declared 392x300/268x300 footprint,
AssertWithinParent, and every markup binding resolves) and
NoButtonAnywhereUsesTheUnrenderableArrowGlyphs (no <button text="↑"|"↓">
survives anywhere) as new coverage for this fix round.
MossTank suite 651 -> 654 (the two new SecondaryPopupPanels theory cases
+ NoButtonAnywhereUsesTheUnrenderableArrowGlyphs); App markup/plugin/menu
filter stays 237/237.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
045cd0a195
commit
565a33d789
8 changed files with 434 additions and 231 deletions
|
|
@ -22,6 +22,12 @@
|
|||
<None Update="mosstank.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="mosstank-advanced.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="mosstank-loot-editor.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<EmbeddedResource Include="VtankCraftRecipes.tsv" />
|
||||
<EmbeddedResource Include="VtankAmmunitionOptions.tsv" />
|
||||
<EmbeddedResource Include="VtankDefaultSettings.usd" />
|
||||
|
|
|
|||
|
|
@ -347,17 +347,23 @@ internal sealed partial class MossTankPanel
|
|||
public bool RouteTabEnabled => true;
|
||||
public bool MetaTabEnabled => true;
|
||||
|
||||
public bool OptionsVisible => OptionsSelected
|
||||
&& !_lootEditorVisible
|
||||
&& !_advancedOptionsVisible;
|
||||
public bool ProfilesVisible => ProfilesSelected && !_lootEditorVisible;
|
||||
public bool VitalsVisible => VitalsSelected && !_lootEditorVisible;
|
||||
public bool MonstersVisible => MonstersSelected && !_lootEditorVisible;
|
||||
public bool ItemsVisible => ItemsSelected && !_lootEditorVisible;
|
||||
public bool ConsumablesVisible => ConsumablesSelected && !_lootEditorVisible;
|
||||
public bool BuffsVisible => BuffsSelected && !_lootEditorVisible;
|
||||
public bool RouteVisible => RouteSelected && !_lootEditorVisible;
|
||||
public bool MetaVisible => MetaSelected && !_lootEditorVisible;
|
||||
// Fix round A (2026-09-07): Advanced Options / Loot Editor used to be
|
||||
// in-panel groups sharing this SAME window with the nine normal tabs,
|
||||
// so a tab's own content had to hide while a popup was open to avoid
|
||||
// drawing both at once. Now that both popups are their own separate
|
||||
// plugin panels (MossTankPlugin.cs, mosstank-advanced.xml /
|
||||
// mosstank-loot-editor.xml), they no longer share screen space with
|
||||
// any tab body, so these guards are gone — a tab stays visible
|
||||
// (or not) purely by tab selection again.
|
||||
public bool OptionsVisible => OptionsSelected;
|
||||
public bool ProfilesVisible => ProfilesSelected;
|
||||
public bool VitalsVisible => VitalsSelected;
|
||||
public bool MonstersVisible => MonstersSelected;
|
||||
public bool ItemsVisible => ItemsSelected;
|
||||
public bool ConsumablesVisible => ConsumablesSelected;
|
||||
public bool BuffsVisible => BuffsSelected;
|
||||
public bool RouteVisible => RouteSelected;
|
||||
public bool MetaVisible => MetaSelected;
|
||||
public bool LootEditorVisible => _lootEditorVisible;
|
||||
public bool AdvancedOptionsVisible => _advancedOptionsVisible;
|
||||
public IReadOnlyList<string> AdvancedOptionNames => VtankOptionCatalog.Names;
|
||||
|
|
|
|||
|
|
@ -52,6 +52,38 @@ public sealed class MossTankPlugin : IAcDreamPlugin
|
|||
Path.Combine(directory, "mosstank.xml"),
|
||||
_panel);
|
||||
|
||||
// Fix round A (2026-09-07): Advanced Options / Loot Editor were
|
||||
// in-panel groups sharing the main window (forcing it to 350px
|
||||
// tall with dead space under the nine normal tabs); they are now
|
||||
// their own plugin panels, matching VTank's own separate popup
|
||||
// windows (docs/research/vtank-kb/08-ui-views.md §1's secondary-
|
||||
// view table). ShowInSidePanel=false — VTank's popups have no
|
||||
// independent shelf/taskbar entry, they only exist while opened
|
||||
// from the Options/Profiles tab checkbox
|
||||
// (AdvancedOptionsVisible/LootEditorVisible). Each popup's own
|
||||
// <panel visible="{...}"> binding is the SAME flag the checkbox
|
||||
// flips and the popup's own "Back" button clears, so closing the
|
||||
// popup unchecks the box for free — no new IUiRegistry show/hide
|
||||
// API needed (MarkupDocument.Build already re-evaluates a root
|
||||
// <panel>'s VisibleSource every frame; see the two files' own
|
||||
// header comments).
|
||||
_host.Ui.AddPanel(
|
||||
new PluginPanelDescriptor("advanced-options", "MossTank Advanced Options")
|
||||
{
|
||||
StartVisible = false,
|
||||
ShowInSidePanel = false,
|
||||
},
|
||||
Path.Combine(directory, "mosstank-advanced.xml"),
|
||||
_panel);
|
||||
_host.Ui.AddPanel(
|
||||
new PluginPanelDescriptor("loot-editor", "MossTank Loot Editor")
|
||||
{
|
||||
StartVisible = false,
|
||||
ShowInSidePanel = false,
|
||||
},
|
||||
Path.Combine(directory, "mosstank-loot-editor.xml"),
|
||||
_panel);
|
||||
|
||||
_commandRegistration = _host.Commands.Register(
|
||||
"vt",
|
||||
_panel.ExecuteVtankCommand);
|
||||
|
|
|
|||
44
src/AcDream.Plugins.MossTank/mosstank-advanced.xml
Normal file
44
src/AcDream.Plugins.MossTank/mosstank-advanced.xml
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Advanced Options popup — VTank's own AdvancedOptionsView is a separate
|
||||
392x300 OS-level window (docs/research/vtank-kb/08-ui-views.md §1's
|
||||
secondary-view table), opened/closed by the Options tab's own
|
||||
"Advanced Options" checkbox (mosstank.xml, cShowAdvanced/
|
||||
ToggleAdvancedOptionsVisible). Fix round A (2026-09-07) moved this OUT of
|
||||
the main mosstank.xml panel (where it used to live as an in-panel group
|
||||
sharing the main window, forcing the whole window to grow to 350px tall
|
||||
with ~180px of dead space under the nine normal tabs) into its own
|
||||
top-level plugin panel, registered as a SECOND AddPanel call from
|
||||
MossTankPlugin.cs with ShowInSidePanel=false (VTank's popup has no
|
||||
independent shelf/taskbar entry — it only exists while opened from the
|
||||
checkbox). This panel's own visible="{AdvancedOptionsVisible}" binding is
|
||||
the SAME flag the checkbox flips and this popup's own "Back" button clears
|
||||
(HideAdvancedOptions => _advancedOptionsVisible = false) — closing the
|
||||
popup unchecks the box for free, no new host show/hide API needed:
|
||||
MarkupDocument.Build already re-evaluates a root <panel>'s VisibleSource
|
||||
every frame (proven by the main panel's own visible="{WindowAvailable}").
|
||||
|
||||
VTank's own popup has no Apply/Back buttons at all (edits are
|
||||
destructive-live in retail); acdream keeps its own explicit Apply/Back
|
||||
pair since our draft-then-submit editing flow needs them.
|
||||
-->
|
||||
<panel x="440" y="60" w="392" h="300" title="MossTank Advanced Options"
|
||||
visible="{AdvancedOptionsVisible}" resize="none">
|
||||
<label x="4" y="4" w="384" h="16"
|
||||
text="Advanced Options — complete VTank settings table"
|
||||
color="#FFE8DEC3" />
|
||||
<list x="4" y="22" w="260" h="160" rowheight="17"
|
||||
items="{AdvancedOptionNames}" selected="{SelectedAdvancedOptionIndex}"
|
||||
onchange="{SelectAdvancedOption}"
|
||||
tooltip="Select one of Virindi Tank's 137 advanced options." />
|
||||
<label x="272" y="22" w="116" h="16" text="{AdvancedOptionName}" color="#FFE8DEC3" />
|
||||
<button x="272" y="42" w="116" h="23" text="Apply"
|
||||
onclick="{ApplyAdvancedOption}" />
|
||||
<button x="272" y="70" w="116" h="23" text="Back"
|
||||
onclick="{HideAdvancedOptions}" />
|
||||
<field x="4" y="188" w="260" h="23" text="{AdvancedOptionValueDraft}"
|
||||
onchange="{SetAdvancedOptionValueDraft}" onsubmit="{SubmitAdvancedOption}"
|
||||
maxlength="160" clearonsubmit="false" background="#E6000000"
|
||||
tooltip="Edit the selected advanced-option value and press Enter or Apply." />
|
||||
<label x="4" y="216" w="384" h="16" text="{AdvancedOptionNotice}" color="#FFC7B98F" />
|
||||
</panel>
|
||||
101
src/AcDream.Plugins.MossTank/mosstank-loot-editor.xml
Normal file
101
src/AcDream.Plugins.MossTank/mosstank-loot-editor.xml
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Loot Editor popup — VTank's own FriendlyLootEditorView is a separate
|
||||
268x300 OS-level window (docs/research/vtank-kb/08-ui-views.md §1's
|
||||
secondary-view table) whose retail "Rules" page is a literal stub ("This
|
||||
page not yet completed"); our own editor is genuinely more complete
|
||||
(KB §5). Opened/closed by the Profiles tab's own "Show Editor" checkbox
|
||||
(mosstank.xml, cShowLootEditor/ToggleLootEditorVisible).
|
||||
|
||||
Fix round A (2026-09-07) moved this OUT of the main mosstank.xml panel
|
||||
(an in-panel group forcing the whole window to grow to 350px tall with
|
||||
dead space under the nine normal tabs) into its own top-level plugin
|
||||
panel, registered as a THIRD AddPanel call from MossTankPlugin.cs with
|
||||
ShowInSidePanel=false (VTank's popup has no independent shelf entry). This
|
||||
panel's own visible="{LootEditorVisible}" binding is the SAME flag the
|
||||
checkbox flips and this popup's own "Back" button clears
|
||||
(CloseLootEditor => _lootEditorVisible = false) — closing the popup
|
||||
unchecks the box for free (see mosstank-advanced.xml's comment for why no
|
||||
new host show/hide API was needed).
|
||||
|
||||
Fix round A also replaced the "↑"/"↓" text buttons (MoveLootRuleUp/Down)
|
||||
with the same DAT move-up/move-down icon glyphs the Monsters grid already
|
||||
uses (0x060028FC / 0x060028FD) — the retail default UI font (0x40000000)
|
||||
has no glyph for U+2191/U+2193, so these rendered as blank button slots
|
||||
(owner's 07:55 screenshot read).
|
||||
|
||||
LootEditorNotice (a status label, not an action) is the one control
|
||||
dropped to make everything else fit without clipping — a deliberate,
|
||||
narrow trim given how much richer this editor is than the 268-wide popup
|
||||
VTank itself budgets for.
|
||||
-->
|
||||
<panel x="440" y="60" w="268" h="300" title="MossTank Loot Editor"
|
||||
visible="{LootEditorVisible}" resize="none">
|
||||
<label x="4" y="2" w="190" h="16" text="Loot profile rules (first match wins)"
|
||||
color="#FFE8DEC3" />
|
||||
<button x="198" y="2" w="64" h="18" text="Back"
|
||||
onclick="{CloseLootEditor}" />
|
||||
<field x="4" y="22" w="260" h="18" text="{LootProfileNameDraft}"
|
||||
onchange="{SetLootProfileNameDraft}"
|
||||
onsubmit="{CreateNamedLootProfile}" maxlength="64"
|
||||
background="#E6000000" color="#FFE8DEC3"
|
||||
tooltip="Name a new or copied loot profile." />
|
||||
<button x="4" y="44" w="58" h="18" text="New"
|
||||
onclick="{CreateLootProfile}" />
|
||||
<button x="66" y="44" w="58" h="18" text="CopyTo"
|
||||
onclick="{CopyLootProfile}" />
|
||||
<button x="128" y="44" w="58" h="18" text="Clear"
|
||||
onclick="{ClearLootProfile}" />
|
||||
<button x="190" y="44" w="70" h="18" text="Delete"
|
||||
onclick="{DeleteLootProfile}"
|
||||
tooltip="Delete the selected named loot profile's real .utl file. Not available for By char." />
|
||||
<list x="4" y="66" w="260" h="68" rowheight="17"
|
||||
items="{LootRuleRows}" selected="{SelectedLootRuleIndex}"
|
||||
onchange="{SelectLootRule}" tooltip="Select an ordered loot rule to edit." />
|
||||
|
||||
<menu x="4" y="138" w="260" h="18" items="{LootActionNames}"
|
||||
selected="{SelectedLootAction}" onchange="{SelectLootAction}"
|
||||
rows="9" scroll="true" tooltip="Choose the action for matching loot." />
|
||||
<label x="4" y="160" w="140" h="16" text="{LootPriorityText}" color="#FFC7B98F" />
|
||||
<button x="148" y="160" w="22" h="18" text="-"
|
||||
onclick="{LootPriorityDown}" tooltip="Decrease loot rule priority." />
|
||||
<button x="174" y="160" w="22" h="18" text="+"
|
||||
onclick="{LootPriorityUp}" tooltip="Increase loot rule priority." />
|
||||
<label x="4" y="180" w="140" h="16" text="{LootKeepCountText}" color="#FFC7B98F" />
|
||||
<button x="148" y="180" w="22" h="18" text="-"
|
||||
onclick="{LootKeepCountDown}" tooltip="Decrease the KeepUpTo count." />
|
||||
<button x="174" y="180" w="22" h="18" text="+"
|
||||
onclick="{LootKeepCountUp}" tooltip="Increase the KeepUpTo count." />
|
||||
|
||||
<field x="4" y="200" w="190" h="18" text="{LootExpressionDraft}"
|
||||
onchange="{SetLootExpressionDraft}" onsubmit="{ApplyLootExpression}"
|
||||
maxlength="256" background="#E6000000" color="#FFE8DEC3"
|
||||
tooltip="VTClassic or UtilityBelt-compatible loot match expression." />
|
||||
<button x="198" y="200" w="64" h="18" text="Apply"
|
||||
onclick="{ApplyLootRule}" />
|
||||
<button x="4" y="222" w="54" h="18" text="Add"
|
||||
onclick="{AddLootRule}" />
|
||||
<button x="60" y="222" w="64" h="18" text="Remove"
|
||||
onclick="{RemoveLootRule}" />
|
||||
<button x="128" y="222" w="26" h="18" icon="0x060028FC" iconkind="did"
|
||||
onclick="{MoveLootRuleUp}" tooltip="Move the selected loot rule up." />
|
||||
<button x="158" y="222" w="26" h="18" icon="0x060028FD" iconkind="did"
|
||||
onclick="{MoveLootRuleDown}" tooltip="Move the selected loot rule down." />
|
||||
|
||||
<toggle x="4" y="244" w="128" h="18" text="Loot All Corpses"
|
||||
checked="{LootAllCorpsesEnabled}" onclick="{ToggleLootAllCorpses}" />
|
||||
<toggle x="136" y="244" w="128" h="18" text="Loot Fellow Corpses"
|
||||
checked="{LootFellowCorpsesEnabled}"
|
||||
onclick="{ToggleLootFellowCorpses}" />
|
||||
<toggle x="4" y="264" w="128" h="18" text="Loot Only Rare Corpses"
|
||||
checked="{LootOnlyRareCorpsesEnabled}"
|
||||
onclick="{ToggleLootOnlyRareCorpses}" />
|
||||
<toggle x="136" y="264" w="128" h="18" text="Read Unknown Scrolls"
|
||||
checked="{ReadUnknownScrollsEnabled}"
|
||||
onclick="{ToggleReadUnknownScrolls}" />
|
||||
<label x="4" y="282" w="140" h="16" text="{LootRangeText}" color="#FFC7B98F" />
|
||||
<button x="148" y="282" w="22" h="16" text="-"
|
||||
onclick="{LootRangeDown}" tooltip="Decrease corpse-looting range." />
|
||||
<button x="174" y="282" w="22" h="16" text="+"
|
||||
onclick="{LootRangeUp}" tooltip="Increase corpse-looting range." />
|
||||
</panel>
|
||||
|
|
@ -7,16 +7,50 @@
|
|||
<!--
|
||||
Campaign VT slice 7 S7.1: the content area is 856 wide, matching VTank's
|
||||
own mainView.xml (856x210, docs/research/vtank-kb/08-ui-views.md §0). The
|
||||
panel is taller than VTank's own 210 (350, not 210) ONLY because the
|
||||
Advanced Options and Loot Editor pages moved to VTank's own POPUP
|
||||
geometry (392x300 / 268x300, KB §1's secondary-view tables) as separate
|
||||
groups within this same window (KB §5's documented in-panel-popup design
|
||||
choice) rather than VTank's own separate OS-level popup windows — the
|
||||
nine normal tab bodies below keep their existing 194-tall content
|
||||
(== VTank's 210 minus its own 16px HudTabView tab strip, Float_Theme.cs's
|
||||
TabHeight) and simply don't fill the extra vertical room the popups need.
|
||||
Advanced Options and Loot Editor pages now live in their OWN plugin panels
|
||||
(mosstank-advanced.xml / mosstank-loot-editor.xml, registered by
|
||||
MossTankPlugin.cs at VTank's own 392x300 / 268x300 popup geometry — KB §1's
|
||||
secondary-view tables), toggled by the SAME AdvancedOptionsVisible /
|
||||
LootEditorVisible flags this panel's own checkboxes flip, via each popup's
|
||||
own <c><panel visible="{...}"></c> binding — so the main window is
|
||||
back to VTank's 210-tall proportion (42 header/tab-strip + 194 content,
|
||||
unchanged since S7.1) with no dead space below the tabs.
|
||||
|
||||
Fix round A (2026-09-07, owner: "Options tab labels overlap" + lead's
|
||||
07:55/08:05 read): VTank's literal L,T,W,H assume an ~11px VVS font;
|
||||
measured against acdream's actual retail DAT font 0x40000000
|
||||
(built via `AcDream.Cli`'s `dump-font-atlas` command against a real
|
||||
installed DAT: MaxCharHeight=16, matching VVS's own assumed row
|
||||
height exactly, so no VERTICAL scale is needed) some captions render wider
|
||||
than VVS's box: "Follow/Nav Min Distance:" measures 134px real width vs
|
||||
an 80px-wide retail label column, overflowing into the checkbox column 2px
|
||||
to its right. <label>/<toggle> never clip or use their declared "w" for
|
||||
rendering (UiLabel.OnDraw/UiMarkupToggle.OnDraw both draw raw, unclipped
|
||||
text — only <list>/<field>/<menu> boxes are real containers), so the fix
|
||||
is a plain rightward SHIFT of every column after the labels, not a width
|
||||
change: OPTIONS_COL_SHIFT = 62px moves every Options control whose retail
|
||||
x >= 90 to x+62 (90->152, 220->282, 386->448, 552->614, 611->673),
|
||||
clearing the widest real caption (134px @ x=8, ends 142; column 2 now
|
||||
starts 152) while preserving every original inter-column gap exactly (a
|
||||
uniform translation, not a scale, so "Boost Nav. Priority" et al keep the
|
||||
identical spacing to their neighbors). The rightmost sub-block (Advanced
|
||||
Options / Run Macro / Combat status, retail x=611 w=233, offset +59 from
|
||||
its column) shrinks its declared width from 233 to 175 (real content only
|
||||
needs ~110px) so 673+175=848 still fits the group's own 848-wide box
|
||||
(contract test AuthoredShellFitsTheMinimumCanvasAndEverySizedChildFitsItsParent
|
||||
enforces x+w<=parent w recursively). PROFILES_COL_SHIFT = 16px applies the
|
||||
same fix to Profiles' one overlap ("Enable Auto-Navigation", real width
|
||||
137px @ x=8 ends 145, over the original menu start at 140) by shifting
|
||||
every Profiles column after the checkboxes (menu/CopyTo-or-New/
|
||||
Clear-or-Delete/toggle/Delete) from 140/280/330/440/530 to
|
||||
156/296/346/456/546 — again a pure translation preserving every original
|
||||
gap. Vitals needed no shift for its widest caption ("Restam others at:",
|
||||
85px @ x=8 ends 93 vs the slider at x=96, a 3px clearance) but its two
|
||||
left-column elements (slider, percent label) move 4px right (96->100,
|
||||
248->252) as a small safety margin since it was the tightest already-OK
|
||||
case measured.
|
||||
-->
|
||||
<panel x="28" y="42" w="856" h="350" title="MossTank v0.1.0"
|
||||
<panel x="28" y="42" w="856" h="236" title="MossTank v0.1.0"
|
||||
visible="{WindowAvailable}" resize="none">
|
||||
<!-- Virindi Tank tab order and compact text-strip presentation. -->
|
||||
<tab x="8" y="22" w="58" h="18" text="Options"
|
||||
|
|
@ -64,94 +98,66 @@
|
|||
onchange="{SetFollowNavMinimumText}" maxlength="6" background="#E6000000"
|
||||
tooltip="Minimum distance maintained while following or navigating." />
|
||||
|
||||
<button x="90" y="8" w="112" h="25" text="Force Buff" onclick="{ForceBuff}" />
|
||||
<button x="90" y="38" w="112" h="25" text="Cancel Force Buff"
|
||||
<button x="152" y="8" w="112" h="25" text="Force Buff" onclick="{ForceBuff}" />
|
||||
<button x="152" y="38" w="112" h="25" text="Cancel Force Buff"
|
||||
onclick="{CancelForceBuff}" />
|
||||
<toggle x="90" y="68" w="120" h="20" text="Enable Buffing"
|
||||
<toggle x="152" y="68" w="120" h="20" text="Enable Buffing"
|
||||
checked="{BuffingEnabled}" onclick="{ToggleBuffing}" />
|
||||
<toggle x="90" y="88" w="120" h="20" text="Enable Combat"
|
||||
<toggle x="152" y="88" w="120" h="20" text="Enable Combat"
|
||||
checked="{CombatEnabled}" onclick="{ToggleCombatEnabled}" />
|
||||
<toggle x="90" y="108" w="120" h="20" text="Enable Navigation"
|
||||
<toggle x="152" y="108" w="120" h="20" text="Enable Navigation"
|
||||
checked="{NavigationEnabled}" onclick="{ToggleNavigation}" />
|
||||
<toggle x="90" y="128" w="120" h="20" text="Enable Looting"
|
||||
<toggle x="152" y="128" w="120" h="20" text="Enable Looting"
|
||||
checked="{LootEnabled}" onclick="{ToggleLooting}" />
|
||||
<toggle x="90" y="148" w="120" h="20" text="Enable Meta"
|
||||
<toggle x="152" y="148" w="120" h="20" text="Enable Meta"
|
||||
checked="{MetaEnabled}" onclick="{ToggleMeta}" />
|
||||
|
||||
<toggle x="220" y="8" w="160" h="20" text="Enable Autostack"
|
||||
<toggle x="282" y="8" w="160" h="20" text="Enable Autostack"
|
||||
checked="{AutoStackEnabled}" onclick="{ToggleAutoStack}" />
|
||||
<toggle x="220" y="28" w="160" h="20" text="Enable Autocram"
|
||||
<toggle x="282" y="28" w="160" h="20" text="Enable Autocram"
|
||||
checked="{AutoCramEnabled}" onclick="{ToggleAutoCram}" />
|
||||
<toggle x="220" y="48" w="120" h="20" text="Use Dispel Items"
|
||||
<toggle x="282" y="48" w="120" h="20" text="Use Dispel Items"
|
||||
checked="{UseDispelItemsEnabled}" onclick="{ToggleUseDispelItems}" />
|
||||
<toggle x="220" y="68" w="120" h="20" text="Cast Dispel Self"
|
||||
<toggle x="282" y="68" w="120" h="20" text="Cast Dispel Self"
|
||||
checked="{CastDispelSelfEnabled}" onclick="{ToggleCastDispelSelf}" />
|
||||
<toggle x="220" y="128" w="120" h="20" text="Auto Fellow Mgmt."
|
||||
<toggle x="282" y="128" w="120" h="20" text="Auto Fellow Mgmt."
|
||||
checked="{AutoFellowManagementEnabled}" onclick="{ToggleAutoFellowManagement}" />
|
||||
<toggle x="220" y="148" w="160" h="20" text="M. Charges When Off"
|
||||
<toggle x="282" y="148" w="160" h="20" text="M. Charges When Off"
|
||||
checked="{ManaChargesWhenOffEnabled}" onclick="{ToggleManaChargesWhenOff}" />
|
||||
|
||||
<toggle x="386" y="8" w="160" h="20" text="Boost Nav. Priority"
|
||||
<toggle x="448" y="8" w="160" h="20" text="Boost Nav. Priority"
|
||||
checked="{NavigationPriorityEnabled}" onclick="{ToggleNavigationPriority}" />
|
||||
<toggle x="386" y="28" w="160" h="20" text="Boost Loot Priority"
|
||||
<toggle x="448" y="28" w="160" h="20" text="Boost Loot Priority"
|
||||
checked="{LootPriorityBoostEnabled}" onclick="{ToggleLootPriorityBoost}" />
|
||||
<toggle x="386" y="48" w="160" h="20" text="Loot Only Rare Corpses"
|
||||
<toggle x="448" y="48" w="160" h="20" text="Loot Only Rare Corpses"
|
||||
checked="{LootOnlyRareCorpsesEnabled}" onclick="{ToggleLootOnlyRareCorpses}" />
|
||||
<toggle x="386" y="68" w="160" h="20" text="Peace Mode When Idle"
|
||||
<toggle x="448" y="68" w="160" h="20" text="Peace Mode When Idle"
|
||||
checked="{IdlePeaceModeEnabled}" onclick="{ToggleIdlePeaceMode}" />
|
||||
<toggle x="386" y="88" w="160" h="20" text="Rebuff When Idle"
|
||||
<toggle x="448" y="88" w="160" h="20" text="Rebuff When Idle"
|
||||
checked="{IdleBuffTopoffEnabled}" onclick="{ToggleIdleBuffTopoff}" />
|
||||
<toggle x="386" y="108" w="160" h="20" text="Fastcast Buffs"
|
||||
<toggle x="448" y="108" w="160" h="20" text="Fastcast Buffs"
|
||||
checked="{FastCastBuffsEnabled}" onclick="{ToggleFastCastBuffs}" />
|
||||
<toggle x="386" y="128" w="160" h="20" text="Don't Shoot at Walls"
|
||||
<toggle x="448" y="128" w="160" h="20" text="Don't Shoot at Walls"
|
||||
checked="{DontShootAtWallsEnabled}" onclick="{ToggleDontShootAtWalls}" />
|
||||
<toggle x="386" y="148" w="160" h="20" text="Fallback Debuffs if Blocked"
|
||||
<toggle x="448" y="148" w="160" h="20" text="Fallback Debuffs if Blocked"
|
||||
checked="{DebuffFallbackEnabled}" onclick="{ToggleDebuffFallback}" />
|
||||
|
||||
<toggle x="552" y="8" w="160" h="20" text="Summon Pets"
|
||||
<toggle x="614" y="8" w="160" h="20" text="Summon Pets"
|
||||
checked="{SummonPetsEnabled}" onclick="{ToggleSummonPets}" />
|
||||
<toggle x="552" y="28" w="120" h="20" text="Custom Pet Range:"
|
||||
<toggle x="614" y="28" w="120" h="20" text="Custom Pet Range:"
|
||||
checked="{CustomPetRangeEnabled}" onclick="{TogglePetRangeMode}" />
|
||||
<field x="672" y="28" w="40" h="16" text="{PetCustomRangeValueText}"
|
||||
<field x="734" y="28" w="40" h="16" text="{PetCustomRangeValueText}"
|
||||
onchange="{SetPetCustomRangeText}" maxlength="6" background="#E6000000"
|
||||
tooltip="Custom pet summon range in meters." />
|
||||
<label x="552" y="48" w="125" h="16" text="Pet Min. Monsters:" color="#FFE8DEC3" />
|
||||
<field x="672" y="48" w="40" h="16" text="{PetDensityValueText}"
|
||||
<label x="614" y="48" w="125" h="16" text="Pet Min. Monsters:" color="#FFE8DEC3" />
|
||||
<field x="734" y="48" w="40" h="16" text="{PetDensityValueText}"
|
||||
onchange="{SetPetDensityText}" maxlength="3" background="#E6000000"
|
||||
tooltip="Minimum nearby monsters required before summoning a pet." />
|
||||
<toggle x="611" y="128" w="233" h="20" text="Advanced Options"
|
||||
<toggle x="673" y="128" w="175" h="20" text="Advanced Options"
|
||||
checked="{AdvancedOptionsVisible}" onclick="{ToggleAdvancedOptionsVisible}" />
|
||||
<toggle x="611" y="148" w="233" h="20" text="Run Macro"
|
||||
<toggle x="673" y="148" w="175" h="20" text="Run Macro"
|
||||
checked="{CombatMacroRunning}" onclick="{ToggleCombat}" />
|
||||
<label x="611" y="170" w="233" h="16" text="{CombatStatus}" color="#FFC7B98F" />
|
||||
</group>
|
||||
|
||||
<!-- Advanced Options popup: VTank's own AdvancedOptionsView is a
|
||||
separate 392x300 OS-level window (docs/research/vtank-kb/08-ui-views.md
|
||||
§1's secondary-view table); this stays in-panel (KB §5) but now uses
|
||||
that exact footprint instead of the full 848x194 tab canvas, so
|
||||
nothing is clipped when it opens. Controls repositioned to fit —
|
||||
VTank's own popup has no Apply/Back buttons at all (edits are
|
||||
destructive-live in retail); acdream keeps its own explicit
|
||||
Apply/Back pair since our draft-then-submit editing flow needs them. -->
|
||||
<group x="8" y="42" w="392" h="300" visible="{AdvancedOptionsVisible}">
|
||||
<label x="4" y="4" w="384" h="16"
|
||||
text="Advanced Options — complete VTank settings table"
|
||||
color="#FFE8DEC3" />
|
||||
<list x="4" y="22" w="260" h="160" rowheight="17"
|
||||
items="{AdvancedOptionNames}" selected="{SelectedAdvancedOptionIndex}"
|
||||
onchange="{SelectAdvancedOption}"
|
||||
tooltip="Select one of Virindi Tank's 137 advanced options." />
|
||||
<label x="272" y="22" w="116" h="16" text="{AdvancedOptionName}" color="#FFE8DEC3" />
|
||||
<button x="272" y="42" w="116" h="23" text="Apply"
|
||||
onclick="{ApplyAdvancedOption}" />
|
||||
<button x="272" y="70" w="116" h="23" text="Back"
|
||||
onclick="{HideAdvancedOptions}" />
|
||||
<field x="4" y="188" w="260" h="23" text="{AdvancedOptionValueDraft}"
|
||||
onchange="{SetAdvancedOptionValueDraft}" onsubmit="{SubmitAdvancedOption}"
|
||||
maxlength="160" clearonsubmit="false" background="#E6000000"
|
||||
tooltip="Edit the selected advanced-option value and press Enter or Apply." />
|
||||
<label x="4" y="216" w="384" h="16" text="{AdvancedOptionNotice}" color="#FFC7B98F" />
|
||||
<label x="673" y="170" w="175" h="16" text="{CombatStatus}" color="#FFC7B98F" />
|
||||
</group>
|
||||
|
||||
<!-- Profiles: transcribed control-for-control from VTank's own Profiles
|
||||
|
|
@ -163,84 +169,79 @@
|
|||
meta-debug windows to close — so that slot is repurposed for our own
|
||||
per-type Delete (slice 1), keeping VTank's row rhythm undisturbed;
|
||||
Delete for Settings/Nav sits just past "Mine only"/past the row's
|
||||
last VTank control instead. The name-draft field each CopyTo/New
|
||||
needs a target for (VTank's own combos are presumably editable
|
||||
in-place; acdream's <menu> is not) lives in its own row below the
|
||||
four VTank rows, alongside the acdream-only loot-engine selector
|
||||
(KB §5: no VTank equivalent) and the profile/loot status notices. -->
|
||||
last VTank control instead.
|
||||
|
||||
Fix round A (2026-09-07, owner: legacy leftovers deleted): the
|
||||
stacked ProfileNameDraft/RouteProfileNameDraft/MetaProfileNameDraft
|
||||
field+"New"-button trio below the four VTank rows (three 20-tall
|
||||
fields at zero vertical gap rendered as one solid black bar behind
|
||||
three stacked "New" buttons — the owner's screenshot) is REMOVED;
|
||||
Meta's naming already has a live field+button pair on the Meta tab
|
||||
itself (mosstank.xml's Meta group), and Macro/Nav lose their only
|
||||
in-UI CopyTo target-name entry as a result (a real, accepted
|
||||
regression — see the commit body). The acdream-only "Loot engine"
|
||||
classifier row (LootClassifierNames/SelectedLootClassifier, no VTank
|
||||
equivalent per KB §5) and the ProfileLifecycleNotice label (the raw
|
||||
macro-profile recovery path the owner saw rendered) are also
|
||||
REMOVED — VTank's own Profiles tab has no notice/status control at
|
||||
all. LootStatus is kept (general loot-load feedback, not itself the
|
||||
reported leftover) but repositioned into the space this freed.
|
||||
PROFILES_COL_SHIFT = 16px moves every column after the leftmost
|
||||
checkbox/label (menu 140->156, CopyTo/New 280->296,
|
||||
Clear/Delete-as-button 330->346, Mine-only/Show-Editor 440->456,
|
||||
per-family Delete 530->546) — see the panel-level comment for why
|
||||
(fixes "Enable Auto-Navigation" running into its dropdown). Every
|
||||
gap between these columns is preserved exactly (a translation, not a
|
||||
scale). -->
|
||||
<group x="8" y="42" w="848" h="194" visible="{ProfilesVisible}">
|
||||
<label x="8" y="8" w="142" h="16" text="Macro Settings" color="#FFE8DEC3" />
|
||||
<menu x="140" y="8" w="140" h="20" items="{MacroProfileNames}"
|
||||
<menu x="156" y="8" w="140" h="20" items="{MacroProfileNames}"
|
||||
selected="{SelectedMacroProfile}" onchange="{SelectMacroProfile}"
|
||||
rows="7" scroll="true" tooltip="Select the active macro profile." />
|
||||
<button x="280" y="8" w="40" h="20" text="CopyTo" onclick="{CopyProfile}" />
|
||||
<button x="330" y="8" w="100" h="20" text="Clear profile!"
|
||||
<button x="296" y="8" w="40" h="20" text="CopyTo" onclick="{CopyProfile}" />
|
||||
<button x="346" y="8" w="100" h="20" text="Clear profile!"
|
||||
onclick="{ClearProfile}" />
|
||||
<toggle x="440" y="8" w="80" h="20" text="Mine only"
|
||||
<toggle x="456" y="8" w="80" h="20" text="Mine only"
|
||||
checked="{MineOnlyEnabled}" onclick="{ToggleMineOnly}" />
|
||||
<button x="530" y="8" w="76" h="20" text="Delete"
|
||||
<button x="546" y="8" w="76" h="20" text="Delete"
|
||||
onclick="{DeleteProfile}"
|
||||
tooltip="Delete the selected named profile's real .usd file. Not available for By char." />
|
||||
|
||||
<toggle x="8" y="32" w="142" h="20" text="Enable Auto-Navigation"
|
||||
checked="{NavigationEnabled}" onclick="{ToggleNavigation}" />
|
||||
<menu x="140" y="32" w="140" h="20" items="{RouteProfileNames}"
|
||||
<menu x="156" y="32" w="140" h="20" items="{RouteProfileNames}"
|
||||
selected="{SelectedRouteProfile}" onchange="{SelectRouteProfile}"
|
||||
rows="7" scroll="true" tooltip="Select the active navigation profile." />
|
||||
<button x="280" y="32" w="40" h="20" text="CopyTo" onclick="{CopyRouteProfile}" />
|
||||
<button x="330" y="32" w="100" h="20" text="Clear nav profile!"
|
||||
<button x="296" y="32" w="40" h="20" text="CopyTo" onclick="{CopyRouteProfile}" />
|
||||
<button x="346" y="32" w="100" h="20" text="Clear nav profile!"
|
||||
onclick="{ClearRouteProfile}" />
|
||||
<button x="440" y="32" w="76" h="20" text="Delete"
|
||||
<button x="456" y="32" w="76" h="20" text="Delete"
|
||||
onclick="{DeleteRouteProfile}"
|
||||
tooltip="Delete the selected named route's real .af file. Not available for By char." />
|
||||
|
||||
<toggle x="8" y="56" w="142" h="20" text="Enable Looting"
|
||||
checked="{LootEnabled}" onclick="{ToggleLooting}" />
|
||||
<menu x="140" y="56" w="140" h="20" items="{LootProfileNames}"
|
||||
<menu x="156" y="56" w="140" h="20" items="{LootProfileNames}"
|
||||
selected="{LootProfileName}" onchange="{SelectLootProfile}"
|
||||
rows="7" scroll="true" tooltip="Select the active loot profile." />
|
||||
<button x="280" y="56" w="40" h="20" text="New" onclick="{CreateLootProfile}" />
|
||||
<button x="330" y="56" w="100" h="20" text="Delete"
|
||||
<button x="296" y="56" w="40" h="20" text="New" onclick="{CreateLootProfile}" />
|
||||
<button x="346" y="56" w="100" h="20" text="Delete"
|
||||
onclick="{DeleteLootProfile}"
|
||||
tooltip="Delete the selected named loot profile's real .utl file. Not available for By char." />
|
||||
<toggle x="440" y="56" w="80" h="20" text="Show Editor"
|
||||
<toggle x="456" y="56" w="80" h="20" text="Show Editor"
|
||||
checked="{LootEditorVisible}" onclick="{ToggleLootEditorVisible}" />
|
||||
|
||||
<toggle x="8" y="80" w="142" h="20" text="Enable Meta Actions"
|
||||
checked="{MetaEnabled}" onclick="{ToggleMeta}" />
|
||||
<menu x="140" y="80" w="140" h="20" items="{MetaProfileNames}"
|
||||
<menu x="156" y="80" w="140" h="20" items="{MetaProfileNames}"
|
||||
selected="{SelectedMetaProfile}" onchange="{SelectMetaProfile}"
|
||||
rows="7" scroll="true" tooltip="Select the active meta profile." />
|
||||
<button x="280" y="80" w="40" h="20" text="CopyTo" onclick="{CopyMetaProfile}" />
|
||||
<button x="330" y="80" w="100" h="20" text="Delete"
|
||||
<button x="296" y="80" w="40" h="20" text="CopyTo" onclick="{CopyMetaProfile}" />
|
||||
<button x="346" y="80" w="100" h="20" text="Delete"
|
||||
onclick="{DeleteMetaProfile}"
|
||||
tooltip="Delete the selected named Meta profile's real .af file. Not available for By char." />
|
||||
|
||||
<field x="8" y="104" w="160" h="20" text="{ProfileNameDraft}"
|
||||
onchange="{SetProfileNameDraft}" onsubmit="{CreateNamedProfile}"
|
||||
maxlength="64" clearonsubmit="false" background="#E6000000"
|
||||
color="#FFE8DEC3" tooltip="Name a new or copied macro profile." />
|
||||
<button x="176" y="104" w="56" h="20" text="New" onclick="{CreateProfile}" />
|
||||
<field x="8" y="124" w="160" h="20" text="{RouteProfileNameDraft}"
|
||||
onchange="{SetRouteProfileNameDraft}"
|
||||
onsubmit="{CreateNamedRouteProfile}" maxlength="64"
|
||||
clearonsubmit="false" background="#E6000000" color="#FFE8DEC3"
|
||||
tooltip="Name a new or copied navigation profile." />
|
||||
<button x="176" y="124" w="56" h="20" text="New" onclick="{CreateRouteProfile}" />
|
||||
<field x="8" y="144" w="160" h="20" text="{MetaProfileNameDraft}"
|
||||
onchange="{SetMetaProfileNameDraft}"
|
||||
onsubmit="{CreateNamedMetaProfile}" maxlength="64"
|
||||
clearonsubmit="false" background="#E6000000" color="#FFE8DEC3"
|
||||
tooltip="Name a new or copied meta profile." />
|
||||
<button x="176" y="144" w="56" h="20" text="New" onclick="{CreateMetaProfile}" />
|
||||
|
||||
<label x="8" y="166" w="70" h="16" text="Loot engine" color="#FFC7B98F" />
|
||||
<menu x="82" y="164" w="180" h="20" items="{LootClassifierNames}"
|
||||
selected="{SelectedLootClassifier}" onchange="{SelectLootClassifier}"
|
||||
rows="7" scroll="true" tooltip="Select the loot-rule engine for this profile." />
|
||||
<label x="270" y="166" w="290" h="16" text="{ProfileLifecycleNotice}"
|
||||
color="#FFC7B98F" />
|
||||
<label x="566" y="166" w="180" h="16" text="{LootStatus}" color="#FF9B9072" />
|
||||
<label x="8" y="108" w="400" h="16" text="{LootStatus}" color="#FF9B9072" />
|
||||
</group>
|
||||
|
||||
<!-- Vitals: transcribed control-for-control from VTank's own Vitals tab
|
||||
|
|
@ -253,52 +254,52 @@
|
|||
the right of that, in space VTank's own layout never uses. -->
|
||||
<group x="8" y="42" w="848" h="194" visible="{VitalsVisible}">
|
||||
<label x="8" y="0" w="80" h="16" text="Heal at:" color="#FFE8DEC3" />
|
||||
<slider x="96" y="0" w="144" h="16" min="0" max="100"
|
||||
<slider x="100" y="0" w="144" h="16" min="0" max="100"
|
||||
value="{NormalHealthPercent}" onchange="{SetNormalHealthPercent}"
|
||||
tooltip="Combat health recharge threshold." />
|
||||
<label x="248" y="0" w="80" h="16" text="{NormalHealthText}" color="#FFC7B98F" />
|
||||
<label x="252" y="0" w="80" h="16" text="{NormalHealthText}" color="#FFC7B98F" />
|
||||
<label x="8" y="16" w="80" h="16" text="Restam at:" color="#FFE8DEC3" />
|
||||
<slider x="96" y="16" w="144" h="16" min="0" max="100"
|
||||
<slider x="100" y="16" w="144" h="16" min="0" max="100"
|
||||
value="{NormalStaminaPercent}" onchange="{SetNormalStaminaPercent}"
|
||||
tooltip="Combat stamina recharge threshold." />
|
||||
<label x="248" y="16" w="80" h="16" text="{NormalStaminaText}" color="#FFC7B98F" />
|
||||
<label x="252" y="16" w="80" h="16" text="{NormalStaminaText}" color="#FFC7B98F" />
|
||||
<label x="8" y="32" w="80" h="16" text="Get Mana at:" color="#FFE8DEC3" />
|
||||
<slider x="96" y="32" w="144" h="16" min="0" max="100"
|
||||
<slider x="100" y="32" w="144" h="16" min="0" max="100"
|
||||
value="{NormalManaPercent}" onchange="{SetNormalManaPercent}"
|
||||
tooltip="Combat mana recharge threshold." />
|
||||
<label x="248" y="32" w="80" h="16" text="{NormalManaText}" color="#FFC7B98F" />
|
||||
<label x="252" y="32" w="80" h="16" text="{NormalManaText}" color="#FFC7B98F" />
|
||||
|
||||
<label x="8" y="56" w="80" h="16" text="Top-off HP:" color="#FFE8DEC3" />
|
||||
<slider x="96" y="56" w="144" h="16" min="0" max="100"
|
||||
<slider x="100" y="56" w="144" h="16" min="0" max="100"
|
||||
value="{NoTargetHealthPercent}" onchange="{SetNoTargetHealthPercent}"
|
||||
tooltip="Idle health top-off threshold." />
|
||||
<label x="248" y="56" w="80" h="16" text="{NoTargetHealthText}" color="#FFC7B98F" />
|
||||
<label x="252" y="56" w="80" h="16" text="{NoTargetHealthText}" color="#FFC7B98F" />
|
||||
<label x="8" y="72" w="80" h="16" text="Top-off Stam:" color="#FFE8DEC3" />
|
||||
<slider x="96" y="72" w="144" h="16" min="0" max="100"
|
||||
<slider x="100" y="72" w="144" h="16" min="0" max="100"
|
||||
value="{NoTargetStaminaPercent}" onchange="{SetNoTargetStaminaPercent}"
|
||||
tooltip="Idle stamina top-off threshold." />
|
||||
<label x="248" y="72" w="80" h="16" text="{NoTargetStaminaText}" color="#FFC7B98F" />
|
||||
<label x="252" y="72" w="80" h="16" text="{NoTargetStaminaText}" color="#FFC7B98F" />
|
||||
<label x="8" y="88" w="80" h="16" text="Top-off Mana:" color="#FFE8DEC3" />
|
||||
<slider x="96" y="88" w="144" h="16" min="0" max="100"
|
||||
<slider x="100" y="88" w="144" h="16" min="0" max="100"
|
||||
value="{NoTargetManaPercent}" onchange="{SetNoTargetManaPercent}"
|
||||
tooltip="Idle mana top-off threshold." />
|
||||
<label x="248" y="88" w="80" h="16" text="{NoTargetManaText}" color="#FFC7B98F" />
|
||||
<label x="252" y="88" w="80" h="16" text="{NoTargetManaText}" color="#FFC7B98F" />
|
||||
|
||||
<label x="8" y="112" w="80" h="16" text="Heal others at:" color="#FFE8DEC3" />
|
||||
<slider x="96" y="112" w="144" h="16" min="0" max="100"
|
||||
<slider x="100" y="112" w="144" h="16" min="0" max="100"
|
||||
value="{HelperHealthPercent}" onchange="{SetHelperHealthPercent}"
|
||||
tooltip="Fellowship healing threshold." />
|
||||
<label x="248" y="112" w="80" h="16" text="{HelperHealthText}" color="#FFC7B98F" />
|
||||
<label x="252" y="112" w="80" h="16" text="{HelperHealthText}" color="#FFC7B98F" />
|
||||
<label x="8" y="128" w="80" h="16" text="Restam others at:" color="#FFE8DEC3" />
|
||||
<slider x="96" y="128" w="144" h="16" min="0" max="100"
|
||||
<slider x="100" y="128" w="144" h="16" min="0" max="100"
|
||||
value="{HelperStaminaPercent}" onchange="{SetHelperStaminaPercent}"
|
||||
tooltip="Fellowship stamina-restoration threshold." />
|
||||
<label x="248" y="128" w="80" h="16" text="{HelperStaminaText}" color="#FFC7B98F" />
|
||||
<label x="252" y="128" w="80" h="16" text="{HelperStaminaText}" color="#FFC7B98F" />
|
||||
<label x="8" y="144" w="80" h="16" text="Infuse others at:" color="#FFE8DEC3" />
|
||||
<slider x="96" y="144" w="144" h="16" min="0" max="100"
|
||||
<slider x="100" y="144" w="144" h="16" min="0" max="100"
|
||||
value="{HelperManaPercent}" onchange="{SetHelperManaPercent}"
|
||||
tooltip="Fellowship mana-infusion threshold." />
|
||||
<label x="248" y="144" w="80" h="16" text="{HelperManaText}" color="#FFC7B98F" />
|
||||
<label x="252" y="144" w="80" h="16" text="{HelperManaText}" color="#FFC7B98F" />
|
||||
|
||||
<toggle x="360" y="4" w="190" h="20" text="Enable vital recharge"
|
||||
checked="{VitalUpkeepEnabled}" onclick="{ToggleVitalUpkeep}" />
|
||||
|
|
@ -503,9 +504,9 @@
|
|||
onclick="{AddRouteJump}" />
|
||||
<button x="556" y="126" w="72" h="21" text="Remove"
|
||||
onclick="{RemoveRouteWaypoint}" />
|
||||
<button x="636" y="126" w="28" h="21" text="↑"
|
||||
<button x="636" y="126" w="28" h="21" icon="0x060028FC" iconkind="did"
|
||||
onclick="{MoveRouteWaypointUp}" tooltip="Move the selected waypoint up." />
|
||||
<button x="670" y="126" w="28" h="21" text="↓"
|
||||
<button x="670" y="126" w="28" h="21" icon="0x060028FD" iconkind="did"
|
||||
onclick="{MoveRouteWaypointDown}" tooltip="Move the selected waypoint down." />
|
||||
|
||||
<menu x="4" y="148" w="90" h="22" items="{RouteModeNames}"
|
||||
|
|
@ -603,92 +604,12 @@
|
|||
onclick="{AddMetaRule}" />
|
||||
<button x="414" y="151" w="62" h="21" text="Remove"
|
||||
onclick="{RemoveMetaRule}" />
|
||||
<button x="482" y="151" w="28" h="21" text="↑"
|
||||
<button x="482" y="151" w="28" h="21" icon="0x060028FC" iconkind="did"
|
||||
onclick="{MoveMetaRuleUp}" tooltip="Move the selected meta rule up." />
|
||||
<button x="516" y="151" w="28" h="21" text="↓"
|
||||
<button x="516" y="151" w="28" h="21" icon="0x060028FD" iconkind="did"
|
||||
onclick="{MoveMetaRuleDown}" tooltip="Move the selected meta rule down." />
|
||||
<label x="558" y="156" text="{MetaStatus}" color="#FFC7B98F" />
|
||||
<label x="4" y="178" text="{MetaNotice}" color="#FF9B9072" />
|
||||
</group>
|
||||
|
||||
<!-- Loot Editor popup: VTank's own FriendlyLootEditorView is a separate
|
||||
268x300 OS-level window (docs/research/vtank-kb/08-ui-views.md §1's
|
||||
secondary-view table) whose retail "Rules" page is a literal stub
|
||||
("This page not yet completed") — our own editor is genuinely more
|
||||
complete (KB §5). Stays in-panel (KB §5) but now uses VTank's exact
|
||||
268x300 footprint instead of the full 848x194 tab canvas. Every
|
||||
control from before is repositioned to fit that narrower footprint;
|
||||
LootEditorNotice (a status label, not an action) is the one control
|
||||
dropped to make everything else fit without clipping — a deliberate,
|
||||
narrow trim given how much richer this editor is than the 268-wide
|
||||
popup VTank itself budgets for. -->
|
||||
<group x="8" y="42" w="268" h="300" visible="{LootEditorVisible}">
|
||||
<label x="4" y="2" w="190" h="16" text="Loot profile rules (first match wins)"
|
||||
color="#FFE8DEC3" />
|
||||
<button x="198" y="2" w="64" h="18" text="Back"
|
||||
onclick="{CloseLootEditor}" />
|
||||
<field x="4" y="22" w="260" h="18" text="{LootProfileNameDraft}"
|
||||
onchange="{SetLootProfileNameDraft}"
|
||||
onsubmit="{CreateNamedLootProfile}" maxlength="64"
|
||||
background="#E6000000" color="#FFE8DEC3"
|
||||
tooltip="Name a new or copied loot profile." />
|
||||
<button x="4" y="44" w="58" h="18" text="New"
|
||||
onclick="{CreateLootProfile}" />
|
||||
<button x="66" y="44" w="58" h="18" text="CopyTo"
|
||||
onclick="{CopyLootProfile}" />
|
||||
<button x="128" y="44" w="58" h="18" text="Clear"
|
||||
onclick="{ClearLootProfile}" />
|
||||
<button x="190" y="44" w="70" h="18" text="Delete"
|
||||
onclick="{DeleteLootProfile}"
|
||||
tooltip="Delete the selected named loot profile's real .utl file. Not available for By char." />
|
||||
<list x="4" y="66" w="260" h="68" rowheight="17"
|
||||
items="{LootRuleRows}" selected="{SelectedLootRuleIndex}"
|
||||
onchange="{SelectLootRule}" tooltip="Select an ordered loot rule to edit." />
|
||||
|
||||
<menu x="4" y="138" w="260" h="18" items="{LootActionNames}"
|
||||
selected="{SelectedLootAction}" onchange="{SelectLootAction}"
|
||||
rows="9" scroll="true" tooltip="Choose the action for matching loot." />
|
||||
<label x="4" y="160" w="140" h="16" text="{LootPriorityText}" color="#FFC7B98F" />
|
||||
<button x="148" y="160" w="22" h="18" text="-"
|
||||
onclick="{LootPriorityDown}" tooltip="Decrease loot rule priority." />
|
||||
<button x="174" y="160" w="22" h="18" text="+"
|
||||
onclick="{LootPriorityUp}" tooltip="Increase loot rule priority." />
|
||||
<label x="4" y="180" w="140" h="16" text="{LootKeepCountText}" color="#FFC7B98F" />
|
||||
<button x="148" y="180" w="22" h="18" text="-"
|
||||
onclick="{LootKeepCountDown}" tooltip="Decrease the KeepUpTo count." />
|
||||
<button x="174" y="180" w="22" h="18" text="+"
|
||||
onclick="{LootKeepCountUp}" tooltip="Increase the KeepUpTo count." />
|
||||
|
||||
<field x="4" y="200" w="190" h="18" text="{LootExpressionDraft}"
|
||||
onchange="{SetLootExpressionDraft}" onsubmit="{ApplyLootExpression}"
|
||||
maxlength="256" background="#E6000000" color="#FFE8DEC3"
|
||||
tooltip="VTClassic or UtilityBelt-compatible loot match expression." />
|
||||
<button x="198" y="200" w="64" h="18" text="Apply"
|
||||
onclick="{ApplyLootRule}" />
|
||||
<button x="4" y="222" w="54" h="18" text="Add"
|
||||
onclick="{AddLootRule}" />
|
||||
<button x="60" y="222" w="64" h="18" text="Remove"
|
||||
onclick="{RemoveLootRule}" />
|
||||
<button x="128" y="222" w="26" h="18" text="↑"
|
||||
onclick="{MoveLootRuleUp}" tooltip="Move the selected loot rule up." />
|
||||
<button x="158" y="222" w="26" h="18" text="↓"
|
||||
onclick="{MoveLootRuleDown}" tooltip="Move the selected loot rule down." />
|
||||
|
||||
<toggle x="4" y="244" w="128" h="18" text="Loot All Corpses"
|
||||
checked="{LootAllCorpsesEnabled}" onclick="{ToggleLootAllCorpses}" />
|
||||
<toggle x="136" y="244" w="128" h="18" text="Loot Fellow Corpses"
|
||||
checked="{LootFellowCorpsesEnabled}"
|
||||
onclick="{ToggleLootFellowCorpses}" />
|
||||
<toggle x="4" y="264" w="128" h="18" text="Loot Only Rare Corpses"
|
||||
checked="{LootOnlyRareCorpsesEnabled}"
|
||||
onclick="{ToggleLootOnlyRareCorpses}" />
|
||||
<toggle x="136" y="264" w="128" h="18" text="Read Unknown Scrolls"
|
||||
checked="{ReadUnknownScrollsEnabled}"
|
||||
onclick="{ToggleReadUnknownScrolls}" />
|
||||
<label x="4" y="282" w="140" h="16" text="{LootRangeText}" color="#FFC7B98F" />
|
||||
<button x="148" y="282" w="22" h="16" text="-"
|
||||
onclick="{LootRangeDown}" tooltip="Decrease corpse-looting range." />
|
||||
<button x="174" y="282" w="22" h="16" text="+"
|
||||
onclick="{LootRangeUp}" tooltip="Increase corpse-looting range." />
|
||||
</group>
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,12 @@
|
|||
<None Include="..\..\src\AcDream.Plugins.MossTank\mosstank.xml"
|
||||
Link="mosstank.xml"
|
||||
CopyToOutputDirectory="PreserveNewest" />
|
||||
<None Include="..\..\src\AcDream.Plugins.MossTank\mosstank-advanced.xml"
|
||||
Link="mosstank-advanced.xml"
|
||||
CopyToOutputDirectory="PreserveNewest" />
|
||||
<None Include="..\..\src\AcDream.Plugins.MossTank\mosstank-loot-editor.xml"
|
||||
Link="mosstank-loot-editor.xml"
|
||||
CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Fixtures\vtank\**\*.*" CopyToOutputDirectory="PreserveNewest" />
|
||||
|
|
|
|||
|
|
@ -187,7 +187,14 @@ public sealed class MossTankMarkupContractTests
|
|||
// buttons + 3 menus + 14 toggles + 3 equip buttons = 30 controls)
|
||||
// is gone, replaced by 1 list + 23 columns + 1 field + 2 buttons
|
||||
// (27) — net 205 -> 202.
|
||||
Assert.Equal(202, controls.Length);
|
||||
// Fix round A (2026-09-07) moved the Advanced Options and Loot
|
||||
// Editor groups OUT of mosstank.xml entirely into their own plugin
|
||||
// panels (mosstank-advanced.xml / mosstank-loot-editor.xml, this
|
||||
// contract only scans mosstank.xml) and deleted the Profiles tab's
|
||||
// three stacked name-draft field+"New"-button rows and the
|
||||
// acdream-only "Loot engine" classifier menu (owner: legacy
|
||||
// leftovers) — net 202 -> 167.
|
||||
Assert.Equal(167, controls.Length);
|
||||
|
||||
foreach (XElement control in controls)
|
||||
{
|
||||
|
|
@ -274,15 +281,95 @@ public sealed class MossTankMarkupContractTests
|
|||
|
||||
// Campaign VT slice 7 S7.1: 856 wide, matching VTank's own
|
||||
// mainView.xml content (856x210, docs/research/vtank-kb/
|
||||
// 08-ui-views.md §0). 350 tall (not 210) only because the
|
||||
// Advanced Options / Loot Editor popups moved to VTank's own
|
||||
// 392x300 / 268x300 popup geometry as separate in-panel groups —
|
||||
// see mosstank.xml's own panel-level comment.
|
||||
// 08-ui-views.md §0). Fix round A (2026-09-07) moved the Advanced
|
||||
// Options / Loot Editor popups OUT into their own plugin panels
|
||||
// (mosstank-advanced.xml / mosstank-loot-editor.xml), so the main
|
||||
// window is back to VTank's own proportion: 236 tall (42px header +
|
||||
// tab strip, unchanged since S7.1, + 194px per-tab content,
|
||||
// unchanged) with no dead space below the tabs — see mosstank.xml's
|
||||
// own panel-level comment.
|
||||
Assert.Equal(856f, Number(root, "w"));
|
||||
Assert.Equal(350f, Number(root, "h"));
|
||||
Assert.Equal(236f, Number(root, "h"));
|
||||
AssertWithinParent(root);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fix round A (2026-09-07): the Advanced Options and Loot Editor popups
|
||||
/// moved out of mosstank.xml into their own plugin panel files. This
|
||||
/// pins that both files still parse, still declare VTank's own popup
|
||||
/// footprint (392x300 / 268x300, docs/research/vtank-kb/08-ui-views.md
|
||||
/// §1's secondary-view table), every child fits its own declared bounds,
|
||||
/// and every markup binding still resolves against a real
|
||||
/// <see cref="MossTankPanel"/> property — the same three guarantees
|
||||
/// <see cref="VtankTabOrderAndEveryBindingResolveAgainstTheLivePanel"/>
|
||||
/// and <see cref="AuthoredShellFitsTheMinimumCanvasAndEverySizedChildFitsItsParent"/>
|
||||
/// give the main panel, now split across three files instead of one.
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData("mosstank-advanced.xml", 392f, 300f)]
|
||||
[InlineData("mosstank-loot-editor.xml", 268f, 300f)]
|
||||
public void SecondaryPopupPanelsFitTheirOwnBoundsAndEveryBindingResolves(
|
||||
string fileName, float expectedWidth, float expectedHeight)
|
||||
{
|
||||
XDocument document = XDocument.Load(
|
||||
Path.Combine(AppContext.BaseDirectory, fileName));
|
||||
XElement root = Assert.IsType<XElement>(document.Root);
|
||||
|
||||
Assert.Equal(expectedWidth, Number(root, "w"));
|
||||
Assert.Equal(expectedHeight, Number(root, "h"));
|
||||
AssertWithinParent(root);
|
||||
|
||||
PropertyInfo[] properties = typeof(MossTankPanel).GetProperties(
|
||||
BindingFlags.Instance | BindingFlags.Public);
|
||||
var byName = properties.ToDictionary(
|
||||
static property => property.Name,
|
||||
StringComparer.Ordinal);
|
||||
|
||||
foreach (XAttribute attribute in root.DescendantsAndSelf().Attributes())
|
||||
{
|
||||
string value = attribute.Value;
|
||||
if (!value.Contains('{', StringComparison.Ordinal))
|
||||
continue;
|
||||
Assert.Matches("^\\{[^{}]+\\}$", value);
|
||||
string name = value[1..^1];
|
||||
Assert.True(
|
||||
byName.ContainsKey(name),
|
||||
$"Markup binding {value} on <{attribute.Parent?.Name}> in "
|
||||
+ $"{fileName} has no public MossTankPanel property.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fix round A: neither popup's own "↑"/"↓" reorder buttons (Loot
|
||||
/// Editor's MoveLootRuleUp/Down) render as blank slots — the retail
|
||||
/// default UI font (0x40000000) has no glyph for those Unicode
|
||||
/// characters, so they now carry the same DAT move-up/move-down icons
|
||||
/// (0x060028FC/0x060028FD) the Monsters grid already uses, and no
|
||||
/// <c><button></c> anywhere is left with the literal arrow text.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void NoButtonAnywhereUsesTheUnrenderableArrowGlyphs()
|
||||
{
|
||||
foreach (string fileName in new[]
|
||||
{
|
||||
"mosstank.xml", "mosstank-advanced.xml",
|
||||
"mosstank-loot-editor.xml",
|
||||
})
|
||||
{
|
||||
XDocument document = XDocument.Load(
|
||||
Path.Combine(AppContext.BaseDirectory, fileName));
|
||||
XElement root = Assert.IsType<XElement>(document.Root);
|
||||
foreach (XElement button in root.Descendants("button"))
|
||||
{
|
||||
string? text = (string?)button.Attribute("text");
|
||||
Assert.False(
|
||||
text is "↑" or "↓",
|
||||
$"<button> in {fileName} still uses the unrenderable "
|
||||
+ $"'{text}' glyph instead of a DAT icon.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TextlessAndAbbreviatedControlsHaveAccessibleRetailTooltips()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue