map: clamp the canvas onto whatever zoom ladder is in force

CreateZoomLevels is the extension point a canvas addon replaces
wholesale, and OnLoad seeds a scale (1) before any addon has run.
OpenMapClassic's ladder is 27 steps from 0.0125 to 0.899 -- its whole
range below this file's own 1, because its stitched world is reached by
zooming out past a single zone -- so the canvas sat above its own
ceiling, and ZoomIn, which walks the ladder by value, found no step at
all above it.

ClampZoomToLevels is called from GetCanvasScale rather than from
CreateZoomLevels, because CreateZoomLevels is exactly the function the
addon will not have.

Also records where OpenMapClassic stands, measured: 808 textures in the
canvas subtree, 166 placed, spanning ~4600x3270 units of a 1002x668
canvas, with a ladder floor implying a world ~80000 units wide. The Era
map tree under it answers correctly; GetMapArtLayers answering one
constant for every map is the thread to pull next.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
2026-11-03 15:05:14 -07:00
co-authored by Claude Opus 5
parent 07dd5ba7e1
commit 3e8c995e27
2 changed files with 111 additions and 20 deletions
+64
View File
@@ -2728,3 +2728,67 @@ Two consequences had to follow it:
The no-art-layer fallback changed with them: the canvas used to take the **container's** size when
a map had no art layer, which was safe only while the container was 1002x668. It is 1.12's own art
rect now in every case, and the fitted floor is what keeps it visible in a smaller window.
## A canvas addon's zoom ladder, and the scale that was set before it existed
`MapCanvasScrollControllerMixin:OnLoad` seeds `currentScale = 1`, and `CreateZoomLevels` is the
documented extension point a canvas addon replaces **wholesale**. OpenMapClassic's ladder is 27
steps from **0.0125 to 0.899** — its whole range below this file's own 1, because its stitched
world is reached by zooming *out* far past a single zone. Measured with it loaded:
```
zoom: fit=1.0000 min=0.0125 max=0.8990 cur=1.0000 levels=27
```
The canvas sat above its own ceiling, and `ZoomIn`/`ZoomOut` walk the ladder **by value** — the
first step above or below the current scale — so from 1.0 `ZoomIn` found nothing at all. The clamp
is in `ClampZoomToLevels`, called from `GetCanvasScale`, because `CreateZoomLevels` is exactly the
function the addon will have replaced.
### Where OpenMapClassic actually stands, measured
With it enabled and the map open, the canvas subtree holds **808 textures, 263 shown, 166 with a
resolved rect**, spanning roughly 4600x3270 canvas units of a 1002x668 canvas — and that is only
the part built so far, because the stitch is lazy per zone. Its ladder's floor of 0.0125 implies a
world about **80 000 units wide**: 1002 / 0.0125. So what a player sees is a correct crop of a
world far larger than the canvas, at whatever scale the view is on — which is why grom's
screenshot is a band of zone art with grey around it rather than misplaced art.
The Era map tree underneath it answers correctly, which rules out the obvious suspects:
```
children of 947: 2
1414 Kalimdor rect=0.0888,0.4002,0.0791,0.8695 art=1002x668
zone 1440 Ashenvale rectOnParent=0.4176,0.5743,0.3313,0.4879
1415 Eastern Kingdoms rect=0.6238,0.9232,0.0269,0.8713 art=1002x668
```
`C_Map.GetMapArtLayers` answers a constant 1002x668 for **every** map, which is faithful for 1.12
— every zone, continent and world sheet is 1002x668 of art in twelve 256 tiles — but it is the one
number OpenMapClassic's stitch is built on (`Map/Stitch.lua`'s `ArtSize`), together with
`GetMapRectOnMap`. That is where the next session starts.
## Two port edits to BetterCharacterPanel
Mirrored at `Addon_Ports/bettercharacterpanel_port/`, both one-liners, both the addon's own bug:
- **`skins/paperdoll/BetterCharacterPanel-paperdoll-pfUI.lua:127`** — `SetCustomPositionCloseButton`
indexes `BCPPFUIUnifiedBackdrop` unguarded, where line 121 guards the same global three lines
up. FrameXML's own `ToggleCharacter` runs `ShowUIPanel(CharacterFrame)` — and so
`CharacterFrame_OnShow`, and so this — **before** `CharacterFrame_ShowSubFrame`, and the
backdrop is built only in `OnPaperDollShow`. So the first character-panel open of every session
raised, on any 1.12 client; it healed a moment later when `OnPaperDollShow` built the backdrop
and called `ChangeFrameValues` again. It was the only runtime error in grom's whole session log.
- **`BetterCharacterPanel-paperdoll.lua:581`** — `SetMinMaxValues(0, contentH - frameH - 20)`. The
stats content is 699 in a 451 window, so the range has to be 248 and the bar stopped at 228:
twenty units of the last card that no amount of scrolling could reach. The engine's own
`GetVerticalScrollRange()` answers 296 here and is not wrong — it measures the scroll child's
whole **subtree** (`0x786e30` → `0x786f80`), and the cards' pfUI shadows hang past
`contentFrame:SetHeight(yOffset)`. The edit keeps the addon's own measure and drops only the
fudge.
What is left of "the info is bigger than the frame" is the addon's own arithmetic and is not a
client fault: `BCPPFUICharacterInformationFrame` is `PaperDollFrame:GetHeight() + 19 - padding` =
**522**, while `BCPPFUIUnifiedBackdrop.backdrop` is `512 - 10 - 72` = **430**, so the stats column
stands 46 units proud of the panel at the top and 46 at the bottom. `PaperDollFrame` is
`setAllPoints` to `CharacterFrame` in the realm's own XML, so the 512 it is derived from is right.