Release v2.0.0#12
Merged
Merged
Conversation
Use Ctrl+Click (matching default UI) instead of Shift+Click to preview loot items. Fall through to EJ navigation when the item has no visual model. Clear stale tooltip IDs when recycling result buttons between mount/toy/pet/outfit and loot result types.
Search results include transmog appearance sets with class, collected, and PvE/PvP filters that sync both directions with the default UI's wardrobe filter. Ctrl+click a set to dress up the full outfit in the dressing room, or click to navigate to it in the wardrobe. Pinned sets and pinned loot now round-trip correctly through SavedVariables and hydrate from the live database when older pins are missing fields. Repopulate the set list when the filter dropdown opens and detects that the default UI's class filter changed since last populate.
Hook C_TransmogSets.SetTransmogSetsClassFilter so runtime class changes in the default wardrobe propagate to our search data without waiting for the user to open the filter dropdown. Listen for TRANSMOG_COLLECTION_UPDATED so the engine's deferred state restore on login triggers a resync, since the login-time sync can run before the wardrobe state is ready. Guard both paths against recursion when PopulateDynamicTransmogSets calls the setter itself, and invalidate the incremental search cache whenever uiSearchData is repopulated so stale prevCandidates don't hide the newly injected entries.
Filter search to base sets only (variants aren't navigable in the left list). Fix Sets tab scroll using SetScrollPercentage with data provider index instead of ScrollToElementData which silently fails for this ScrollBox type.
hideSearchBarsMaximized defaults to true. New installs get bars hidden on the maximized map; users who want fullscreen search uncheck the "Hide Fullscreen" option.
Replaces the ad-hoc rect- and mask-based border with a single createTutorialBox() helper that composes three custom TGAs (one corner + horizontal/vertical edges) into a chamfered, multi-layer, pulsing neon-yellow border. The corner chamfer is anti-aliased at 4x4 sub-pixel density while layer interiors and layer-to-transparent boundaries stay sharp, so the chamfer reads as a smooth diagonal without fuzzy ghosting where the bright band meets the dark interior. The bright band sits just outside the frame edge so the pulse animation doesn't reveal the interior gradient behind it. tools/gen_glow_tgas.py regenerates the three TGAs from a simple LAYERS list plus CHAMFER_OUTER/CHAMFER_INNER knobs; rerun it after tweaking parameters. Demo.lua's transition banner, minimap callout, and map-search callout all rebuild on top of the new helper.
Pull the chamfered glow-border tutorial box from Demo into its own TutorialBox module and add TutorialBox.AttachPointer for animated chevron arrows next to any tutorial box. The pointer handles direction-based rotation, trail-back-flush origin anchoring (invariant to box size and TGA tunables), count-staggered cascades, easing, fadeStart, a fixed-endpoint startOffset, onPhase sync callback, and an additive chevron-shaped glow layer. Replaces the bespoke mode-button chevron block in UI.lua with a single AttachPointer call.
Replaces the bouncing minimap arrow with chevron pointers attached to the callout boxes, uses a scrolling cross-fade to transition narration text in place, and snapshots WMF's mapID on demo start so navigating to an instance entrance doesn't leak into later demos. Adds a clear-button hint sequence with per-button chevrons, an adaptive tracking-state narration that keys off near/far mode, and multi-row hovers per typed prefix. Prefers the player's actual zone over WMF when picking diverse POIs so the demo works after a map-switching demo ran. Tutorial-box marker lets the cursor helper anchor its tip at the box's bottom border instead of covering text.
Deprecates the per-search-bar Fast/Guide toggle. Search bar icons are now static magnifying glasses; a result row's right-click context menu offers Pin/Unpin plus a Guide row (eye icon) that invokes the step-by-step walkthrough for that specific entry. Core: removes directOpen DB field, flips minimap FX defaults off. Options: removes Open-Panels-Directly and Navigate-Directly checkboxes. UI: rebuilds pin popup as a two-row menu (Guide on top, Pin/Unpin below). MapSearch: static icons, simplified placeholder tooltips. Demo: strips guide-mode branches from every demo, adds a dedicated Guide demo that shows right-click -> Guide on a Valorstones search. Archives the now-unused lightning-bolt.tga under archive/ (gitignored). Adds a new white eye.tga for the Guide menu row.
Creates EasyFindMapSearchTab as a 42x55 side tab below MapLegendTab matching the Blizzard quest log tab style (QuestLog-tab-side bg, Select and hover glows, magnifier icon). Clicking the tab swaps the QuestMapFrame side panel to an EasyFindMapSearchPanel containing a search box styled like QuestScrollFrame.SearchBox plus a settings cogwheel using QuestLog-icon-setting. Tab-switching state machine hides Blizzard's QuestsFrame / MapLegendFrame when our panel is active and vice versa, keeping Select glows in sync. Search engine wiring, results list with local/global sections, hover preview, Pin/Guide right-click menu, and cog filter dropdown are placeholders for the next commits.
Extracts the result-computation body from MapSearch:OnSearchTextChanged
into a pure MapSearch:BuildResults(text, isGlobal, skipPins) that
returns the ranked/filtered list without rendering. Exposes pin
helpers (IsMapItemPinned, PinMapItem, UnpinMapItem, GetMapPinKey) on
the MapSearch table.
MapTab now runs BuildResults twice per query (once local, once global,
both with skipPins) and renders two sections with gold category
headers ("In This Zone" / "Across Azeroth"). Pinned items show above
both sections when present, with a collapsible "Pinned" header.
Row interactions wired:
- Hover shows waypoint preview via MapSearch:GetPreviewCoords.
- Left-click dispatches to MapSearch:SelectResult.
- Right-click opens a Pin/Guide popup matching UI.lua's pattern;
Guide row appears only for global results (zones / entrances).
- Pin-header click toggles mapPinsCollapsed and refreshes.
Search is debounced 80ms per keystroke. Scratch tables inside
BuildResults are shallow-copied on the MapTab side because they're
reused across the two back-to-back searches.
MapSearch:Initialize no longer creates searchFrame, globalSearchFrame, or resultsFrame. HookWorldMap keeps waypoint restoration and breadcrumb positioning on map open/close/maximize but drops all bar-positioning, bar-focus, and bar-clear logic. Guarded the remaining direct editbox references in SelectResult and OnSearchTextChanged, ShowResults, and ShowPinnedItems so they early- return or skip when the floating bars are nil. ResetPosition becomes a pure SavedVariables wipe. Removed the three map demos (zone / current / UI-bar) from DEMO_LIST since their recorded flows click the retired bars. The demo bodies are left in Demo.lua for now but unreachable via the picker. Removed the "Resize Map Search" Options button (dead; Rescaler's map-mode targeted the retired bars).
Hides the EasyFindMapSearchTab when the world map is maximized, matching how Blizzard's QuestsTab and MapLegendTab behave. Restores the tab when the map returns to windowed mode. Adds MapTab:Focus() which opens the world map, selects our tab, and focuses the search box. The ToggleFocusSearchUI keybind dispatcher now routes to MapTab:Focus when the map is open, replacing the old floating-bar FocusLocalSearch call.
Tab frame: - Stack flush under MapLegendTab (removed the +2 vertical fudge). - Center the QuestLog-tab-side background, Select glow, and hover glow on the clickable area. They're 51x59 atop the 42x55 tab, so CENTER anchoring places the leather overhang symmetrically, matching Blizzard's own QuestsTab / MapLegendTab visual extent. - Center the magnifier icon on the tab (removed the -4 X offset). Panel: - Paint QuestLog-main-background atlas as the backdrop so the panel looks identical to the Blizzard quest-log scroll area. - Anchor to QuestScrollFrame's rect when available (exact same hitbox as Blizzard's quest list) with fallbacks to QuestsFrame / qmf. Tab-switching: - Stopped hiding Blizzard's QuestsFrame / MapLegendFrame when our panel opens. Clicking between tabs was leaving those panels Hidden, which made the quest log blank when the user clicked back to Quests. The MapTab panel is frame-level +5 with an opaque backdrop so it cleanly overlays Blizzard's content without disturbing its state.
Tab: - Added 6px vertical gap under MapLegendTab so the leather edges don't collide. - Shrunk the magnifier to 20x20 (native atlas is 24x24; smaller keeps it crisp instead of upscaled-blurry). - Tint the icon dim gold when inactive, bright gold (GOLD_COLOR) when our tab is selected, matching the other tabs' gold accent palette. RefreshSelectGlows toggles both the Select glow and the icon color. Panel layout: - Search box and cog now sit ABOVE the paper backdrop in the map frame's dark header area, mirroring where Blizzard's Search Quest Log field renders. Scroll area now covers the full paper rect. - Replaced UIPanelScrollFrameTemplate with a plain ScrollFrame + mouse-wheel handler so we don't inherit the blue/gold scroll decorations. A proper minimal scrollbar is a followup. Tab switching: - Brought back HideBlizzPanels when our panel opens, which stops the MapLegend header text bleeding through our overlay. - Blizzard tab click hooks now explicitly Show the correct panel and Hide the other (belt-and-suspenders in case Blizzard's internal tab switcher bailed on "already selected" state). Removed auto-focus of the search box on tab click. User can click the box when they want to type. MapTab:Focus (keybind path) still focuses explicitly.
Stopped hiding QuestsFrame / MapLegendFrame when our panel opens; the show/hide dance fought Blizzard's internal tab-state machine, and the "Map Legend" title fontstring lives on QuestMapFrame directly (not on MapLegendFrame), so hiding the panel never hid the title anyway. New approach: overlay everything. - Panel extends 42px up into QuestMapFrame's dark header bar. - Opaque dark ColorTexture covers that header region, occluding any Blizzard title text that would otherwise bleed through. - QuestLog-main-background atlas paints only the lower 468px (paper). - Panel frame level raised to qmf + 50 so it sits above any font strings Blizzard anchors to QuestMapFrame. - Search box + cog live in the header region. - Scroll area fills the paper region with a 14px right margin for a future minimal scrollbar. Blizzard tab-click hooks simplified: just HideOurPanel; Blizzard's own OnMouseUp handles showing the clicked panel since we no longer disturb their visibility state.
Dark header issue: panel was anchored to QuestScrollFrame with a +42 y-offset that pushed the top edge outside QuestMapFrame's visible bounds, so the opaque header backdrop extended past the map window. Panel now anchors to QuestsFrame (the right-column container that already spans both the header + paper areas), reducing header extent to an internal 34px block that stays within QuestMapFrame. Scrollbar-bleeding issue: Blizzard's scrollbars / content in QuestsFrame or MapLegendFrame were drawing above our backdrop because nested children can sit at frame sublevels above our +50. We can't just Hide those panels (breaks Blizzard's tab state). Instead we SetAlpha(0) on them while our panel is active — children inherit alpha 0 so nothing renders, but frames stay Shown so Blizzard's tab logic is undisturbed. HideOurPanel restores alpha 1 on close. Panel right edge extended 8px past QuestsFrame to cover any scrollbar child that might anchor just outside.
Search panel rewrite layered on the prior MapTab scaffold.
- Inline autocomplete via SetText + HighlightText: typed prefix plus
suggestion suffix shown as a selected range. Native caret stays at
the end of typed text. Tab/Enter confirm, backspace dismisses
without re-conjuring the suggestion, typing replaces the selection
to advance through it.
- Group headers with collapse/expand by continent and zone. Display
paths collapse to the immediate parent. World/Azeroth/Cosmic
stripped as virtual roots that add no disambiguation.
- Multi-token queries ("northrend raid") match ancestor names so
category-style filtering works without a literal substring.
- Recent searches list (capped, dedupe, show/hide toggle) and pinned
items section with right-click pin/unpin/guide popup.
- Keyboard nav: arrow keys / Ctrl+J/K / Enter / Esc with hold-to-step
acceleration; navFrame keyboard capture flips between editbox and
result list as focus moves.
- One-click row activation: rows, group headers, and toggle buttons
register clicks for ButtonDown so OnClick fires on press, bypassing
WoW's focus-transition machinery that was absorbing the mouseUp on
the first click and forcing a second.
- Hover preview throttled during typing so re-rendered rows landing
under a stationary cursor don't spawn spurious map pins.
- Database: CouldMatch pre-filter for ScoreName drops candidates whose text doesn't contain every char of the query before they reach the DamerauLevenshtein DP. Eliminates the bulk of scoring work on the ~90%+ of entries that obviously don't match. - Utils: extract CreateKeyRepeat as a shared hold-to-step helper used by both UI search and MapTab navigation. Action fires immediately, then ticks at an accelerating cadence (0.30s -> 0.05s over 1.5s). - UI: defer the search work to the next frame on each keystroke so multiple keys within one frame coalesce to a single search; make the clear button focus-aware (visible while focused even if empty).
- Bindings / Core / luacheckrc: drop EASYFIND_TOGGLE and EASYFIND_FOCUS (the unified EASYFIND_TOGGLE_FOCUS replaces both); add EASYFIND_MAP_FOCUS bound to EasyFind:FocusMapSearch -> MapTab:Focus. - Core: db migration v4 flips stale localMapDirectOpen and globalMapDirectOpen defaults to true. The prior "Make Fast Mode default" change didn't run a migration, so existing saves carried false through and routed every zone click into the multi-step teach path, making clicks feel like they needed two presses. - Options: replace the legacy Map Search Bars section with a Map Tab section (recent-search count slider, show-recent toggle); refresh the keyboard shortcut help text to match the consolidated bindings. - MapSearch: expose GetFilterBucket and GetCategoryIcon for MapTab; CreateFilterDropdown gains an onChanged callback so MapTab can refresh its own panel without going through the legacy editbox refresh path; highlight / indicator / zone-highlight frames now EnableMouse(false) so decorative chrome can never absorb clicks. - MapSearch: SelectResult tracks pinHoverClearsOverride so guide-mode terminal pins teach hover-to-clear the same way global pins do.
Pressing an arrow key (or Ctrl+J/K) while the autocomplete suffix was highlighted in the search box did not move into the results. WoW's default arrow-key handling on a highlighted selection collapses it synchronously, firing OnTextChanged with the typed prefix unchanged. The OnTextChanged hook rescheduled the search timer, which fired one frame later and re-rendered the rows -- resetting navRowIndex to 0 and erasing the move HandleNavKey had just made. - OnTextChanged: bail when the typed prefix is unchanged. Selection- collapse edits don't change what the user is searching for. - OnKeyDown: also cancel any pending search timer when a nav key is pressed. Defends against a timer scheduled by an OnTextChanged that fired before our hook (timer would otherwise fire next frame and wipe nav state regardless of the typed-prefix guard). While here, drop the navKeyRepeat hold-to-step ticker. The press that fires from the editbox has no paired OnKeyUp on navFrame, so a dropped release would leave repeatActive stuck and resume auto- scrolling the next time the panel was shown. WoW delivers repeated OnKeyDown events at the OS auto-repeat cadence while a key is held, so single-stepping per event preserves hold-to-walk without owning the timer.
MapTab list:
- World hierarchy children with Dungeon mapType render with the
dungeon-portal icon instead of the generic continent texture.
- BuildFullBreadcrumb prints root-first ("World > Continent > Zone
> Name"), and surfaces mapID 946 ("Cosmic") as "World".
- Duplicate-named zones (Dalaran in Northrend vs Broken Isles)
collapse into a single "version" header that lists each variant
on expand. Header navigates to the highest-mapID variant.
- Auto-expand checkbox under the recent-search toggle. When on
(default), a matched parent zone lists every child the world
hierarchy says lives under it; when off, only matched names show.
- Continent-type zone matches that EXCLUDE_FROM_LOCAL_MAPTYPES
drops from the local section now have their synthesized "This
Zone" header promoted back to the real result, so auto-expand
fires for them too.
- Drop any global group whose ancestor matches the currently-viewed
map -- the "This Zone" section already covers it.
MapTab pin popup:
- Cursor offset by 8px inside the popup at open time. Without it,
IsMouseOver flickered at the boundary pixel and the auto-dismiss
hid the popup on the same frame it appeared.
- 0.15s grace period in the auto-dismiss OnUpdate so the right-
click that opens the popup doesn't immediately close it.
- Right-click guide menu always shows (was previously gated on
isZone or isDungeonEntrance).
MapSearch zone hover preview:
- Indicator frame is parented to the canvas (sibling of waypointPin
/ highlightFrame) and anchored explicitly on every show. Reparent
on every hover had inconsistent timing on some result rows.
- New arrow-only mode for plain zone hovers: just the bouncing
arrow over the zone center plus the zone outline; no pin
icon/glow/box clutter that would compete with the outline.
- PreviewZoneHighlight uses a strict direct-child gate
(parentMapID == currently-viewed map). Ancestor / sibling /
distant-descendant rects all read as glitches and are skipped.
- ClearZoneHighlight gains a preserveBreadcrumb flag so the hover
cleanup leaves the click-driven gold breadcrumb intact.
- Newly-pinned parent zones default to collapsed.
Demo: pin popup is now a structured frame (pinRow, guideRow); the
demo flow's auto-pin clicks pinRow:Click() instead of the old
popup:Click() that no longer applies.
Group the two keybind buttons under a "Keybindings" header with a thin divider so they read as a labeled subsection rather than two loose buttons. Move "See demo" / "Got it" outside the panel: anchor TOP to the panel's BOTTOM rather than BOTTOM/BOTTOM with a positive y offset. Buttons no longer crowd the keybind section above.
StaticPopupDialogs = StaticPopupDialogs or {} writes the global slot
even when the table already exists, which taints it. Blizzard's
ShowUIPanel reads StaticPopupDialogs[name] during panel-manager work,
inheriting the taint and crashing TextStatusBar comparisons on later
panel opens. Guard the popup registration on the existing global
without writing it back.
Replace hardcoded achievement and statistics category trees in uiTree with runtime walks of GetCategoryList / GetStatisticsCategoryList + GetCategoryInfo so the search index always matches the live AchievementFrame sidebar for the current build. Statistics get a separate filter (Statistics, distinct from Achievements) and one entry per stat row via GetCategoryNumAchievements + GetAchievementInfo. Each row carries the stat ID so the result shows the live GetStatistic value inline (similar to currency quantity) and the highlight engine drives the AchievementFrameStats ScrollBox to scroll-and-select the exact row. The per-row enumeration runs synchronously at PLAYER_LOGIN before the staggered dynamic-provider chain so the ~400 API calls land during the load screen rather than as a post-login hitch. The provider machinery's loaded flag prevents re-running.
Two leak paths were emitting stat-tracker rows under the Achievements filter alongside the dedicated Statistics rows: 1. PopulateDynamicAchievements walked GetCategoryList(), which in 12.0 contains every individual stat-row achievement ID using the stat name as its "category" name. Extend the exclusion set to cover the per-stat IDs inside each statistics category, not just the sidebar categories themselves. 2. UI.lua's inline achievement search (SetAchievementSearchString) surfaces every achievement matching the query, including stat trackers. Filter results against Database.statisticIDs so they appear only as book-icon Statistics rows. Also wires the missing filters.statistics check into the bucket-aware filter guard so toggling the Statistics chip off actually drops the stat entries.
ESC and click-outside both now route through ShowUnappliedSettingsPopup, a shared helper that finds the popup's actual StaticPopup slot (1..4) and lifts its strata to TOOLTIP so it renders above the FULLSCREEN_DIALOG results panel. The popup preempts text-clear and panel-close on ESC so Cancel preserves the exact pre-ESC state (text, scroll, pending change). StaticPopup1..4 added to the click-outside guards so clicking the popup buttons doesn't register as outside-the-results. ApplyPendingChanges now reuses ApplyVariable per pending setting (the same proven path the per-row Apply button uses) instead of the SettingsPanel.modified + CommitSettings approach which silently no-oped from addon code. Apply and Exit / Apply now actually apply. Per-row Apply / Reset buttons refocus the search editbox after running so the click doesn't steal focus. Inline setting dropdown button toggles -- a second click on the same dropdown closes the popup instead of being a no-op.
Replace the 60-entry FRESH_SETTINGS_KEYS allowlist with a 6-entry PRESERVED_KEYS denylist and iterate DB_DEFAULTS, so the reset stays correct automatically when new defaults are added. Drop the redundant FRESH_SETTINGS_VERSION constant and freshSettingsVersion DB field since the migration framework already gates run-once. Flatten the nested version check in OnPlayerLogin and use the REVAMPED_TUTORIAL_VERSION constant instead of the "2.0.0" literal.
Add missing WoW API globals (securecallfunction, IsKeyDown, GetCurrentKeyBoardFocus, GetCVarBool, OpenBackpack/Bag, GetItemSpell, StaticPopup_Visible, IsGraphicsSettingValueSupported, QuestScrollFrame, LibStub, CURRENCY_FILTER_TYPE_*, SETTINGS_*, FACTION_ALLIANCE/HORDE, GameFontHighlightLarge) to read_globals. Move SettingsPanel and TokenFrame to globals so field writes pass. Remove dead code: BuildPage4 and BulletRow in Wizard.lua, ClearBinding in Options.lua, FlagsFor in BlizzOptionsSearch.lua, unused willScroll local in UI.lua. Drop unused imports (sformat, tonumber, tconcat in Options.lua; tinsert in Rescaler.lua). Branch luacheck now reports 0 warnings (was 47).
Project style forbids em/en dashes in prose and comments. Sweep all remaining hits and replace each with a context-appropriate colon, comma, period, or parentheses. All edits are comment-only; no code behavior changes. Branch luacheck still reports 0 warnings.
Default to zero comments per project style. Remove WHAT-narration, section banners, restated-name comments, and pre-function description blocks. Keep load-bearing WHY: WoW API quirks, taint and combat-lockdown rationale, bug workarounds, performance invariants, non-obvious algorithmic choices. 3142 comment lines removed across 15 files. Luacheck and lua syntax both clean.
Utils loads before MapTab and Wizard per .toc order, so the `Utils.SafeAfter or function(...)` fallbacks are dead code that would silently bypass xpcall safety if ever taken. Replace with direct references. Remove MapTab.GetTopAncestor (no callers) and MapSearch:GetMapPath (pure forwarding shim around the file-scope local; collapse its four self:GetMapPath sites to the direct call).
Replace bare EnableKeyboard / SetPropagateKeyboardInput calls with Utils.SafeCallMethod so they no-op under combat lockdown instead of tainting. Replace guarded C_Timer.After patterns with Utils.SafeAfter (xpcall-wrapped). Wrap user-interaction OnUpdate handlers (calculator copy watcher, pending search frames, dropdown dismissers, map tab pending, setup glow, resizer) with Utils.SafeOnUpdate so a crash self-cancels the ticker instead of spamming and freezing the UI. Hoist three inline tsort comparators in MapSearch.lua and four in MapTab.lua to module-scope locals to avoid per-call closure allocation in per-keystroke and per-pin hot paths. Branch luacheck and lua syntax remain clean.
Add ns.SetRoundedRectFill (color + alpha + optional pixel-snap-off), ns.SetRoundedRectBorderColor, and ns.SetRoundedRectBorderEdgeShown to Utils.lua. Replace per-file iteration over frame.combinedBorder in UI, Options, Wizard, and Rescaler (SetCalculatorRoundedFill, HideCalculatorRoundedBorder, PaintRoundedFill, TintRoundedFill, SetModernButtonFill, SetModernButtonAlpha, HideRoundedFrameBorder, HideRoundedBorder, MakeButton/FeatureTile/footer/page-frame inline loops) with the shared helpers. All combinedBorder pairs() iteration now lives in Utils.lua. Branch luacheck and lua syntax remain clean.
Drop two dead defensive `if ns.SetRoundedRectBorderFillColor then` guards (Utils loads before UI/Rescaler per .toc, the check can't fire). Extract a local DisablePixelSnap helper from the two new ns.SetRoundedRectFill / ns.SetRoundedRectBorderColor bodies that called the same two methods inline.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ships the v2.0.0 tag (already created).