MoveItems() uses ClassicAPI's C_Container.MoveItem() when available (and
no move equips a bag): each round sends every move whose slots are free
and unlocked, then waits for BAG_UPDATE_DELAYED (1 s fallback) before the
next round. Restack() queues exact amounts; EmptyBag()/FillBag() move
whole stacks. Locked slots are retried up to 5 times, stock-state
handling matches ProcessMoveQueue(), and the cursor-based queue remains
the fallback. Approach taken from brues-code/pfUI libs/libbagsort.lua.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019W3rwt5PZSpEDkXYzRuRhH
- UiFrame_OnShow requests a full categorization pass only if the last one
was more than 60 seconds ago.
- Lock-only cache updates refresh just the affected item buttons
(AssignItemToItemButton) instead of running UpdateWindow().
- SortGroups() reuses a group's previous sorted order when none of its
items were re-categorized and it holds exactly the same items; any
full categorization pass invalidates all sorted orders.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019W3rwt5PZSpEDkXYzRuRhH
- CategorizeItems() keeps each item's category unless something it was
based on changed (item, bag/slot, bag type, count, charges, stock
state, tooltip). A full pass runs on window open, forced resort,
rebuilt lookup tables, character switch and any non-bag event.
- ActiveQuestItems: raise BAGSHUI_ACTIVE_QUEST_ITEM_UPDATE only when the
quest item list or counts changed, not after every QUEST_LOG_UPDATE.
- Item buttons: OnUpdate is set on mouse enter and removes itself after
the mouse leaves; the base template OnUpdate is cleared. Stock badges
are refreshed once a minute from the window's OnUpdate.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019W3rwt5PZSpEDkXYzRuRhH
- Normalize the locked flag from GetContainerItemInfo (1/nil) to the
cached 1/0, so `preLocked ~= nowLocked` no longer treats every unlocked
slot as changed. Every cache update was re-running ItemInfo:Get() and
the tooltip scan for every slot.
- When only the locked state changes, record it directly and don't flag
the cache for re-categorization; the window still redraws.
- Update() re-categorizes only when items changed (cacheNeedsCategorize),
not for cosmetic lock changes.
- Build emptyGenericContainerSlots for every empty slot on each update,
since unchanged slots no longer pass through the change branch.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019W3rwt5PZSpEDkXYzRuRhH
- Rules: collect rule function arguments with inline nil checks instead
of 50 BsUtil.TableInsertNonNil() calls per rule call. Profiling showed
this was the biggest single cost of re-categorizing on every bag change.
- Item click: queue the window update instead of running it immediately,
so it merges with the update from the bag/lock events that follow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019W3rwt5PZSpEDkXYzRuRhH
Moving the real window made the client re-lay out every item button,
texture and cooldown model on each mouse movement, freezing the game for
seconds with the Bags and Bank open (profiling showed almost no Lua time
during the freezes). A single empty outline frame now follows the mouse,
and the window is moved once on drop. Clicking the outline finishes a
move whose drop was missed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019W3rwt5PZSpEDkXYzRuRhH
ClassicAPI's frame CPU numbers exceeded wall-clock time, so they are no
longer shown. `/bs cpu clamp on|off` toggles SetClampedToScreen on the
inventory windows for the session to test the engine-side drag stalls.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019W3rwt5PZSpEDkXYzRuRhH
Reads ClassicAPI's script profiler (scriptProfile CVar) and prints CPU
time per addon, per Bagshui window and per Bagshui function since the
last reset, to find what causes the window-drag freezes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019W3rwt5PZSpEDkXYzRuRhH
BAG_UPDATE now marks the inventory as changed and BAG_UPDATE_DELAYED
queues the redraw for the next frame, instead of every BAG_UPDATE
restarting a 0.07s debounce. While a bag is being swapped between slots
the old debounce is kept so the redraw waits for the swap to settle.
A 0.5s safety-net update covers a missing BAG_UPDATE_DELAYED.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019W3rwt5PZSpEDkXYzRuRhH
- Changelog: release the Right/Top anchor UI-scale fix as 1.6.5
- Defer inventory redraws while a window is being dragged
- Cache class-callback event ids in QueueClassCallback (less garbage per BAG_UPDATE)