"Show Timestamps In Chat Copy" (chat text settings, on by default) is read
each time chat copy opens. With it off, chat copy takes each line through
pfUI.chat.StripTimestamp, which removes the exact timestamp AddMessage
prepends: the configured color and brackets, so other bracketed text
stays.
Whispers are now recolored before the timestamp goes on, not after. The
recolor turned the stamp's closing "|r " into "|r" plus the whisper color,
so whisper lines did not match. The shown text and the saved history come
out the same.
The set list, the unused-items grid and the trigger list each drew a
fixed number of slots and moved them with a mouse-wheel offset. All three
are pfUIScrollBoxListTemplate lists now, with a scroll bar.
The set list's rows are the sets and then the "New Set" entry, set up by
one initializer. Refresh rebuilds them only when the sets change and
otherwise reinitializes the shown rows, so a row keeps its frame between
the two clicks of the native OnDoubleClick that now equips a set, in
place of the hand-timed double click. PickupEquipmentSet is called
without a presence check.
The row's gear passes mouse motion on to the row, so moving onto it no
longer leaves the row and the MouseIsOverHitRect workaround is gone. The
gear rests at half alpha and lights up on hover with an additive copy of
itself, instead of the blue square highlight.
The unused items are a grid view that keeps its scroll position on
refresh. The trigger list scrolls to a new trigger with ScrollToEnd.
pfUIScrollFrameTemplate (api/ui-widgets.xml) is a ScrollFrame with
pfUIScrollBarTemplate inside its right edge and a Content scroll child,
driven by ScrollUtil.InitScrollFrameWithScrollBar. The panels keep a
ScrollFrame because the engine measures its range from the shown frames
inside the content, which the hand-placed config rows rely on. The bar
follows OnScrollRangeChanged instead of an OnUpdate poll per panel.
A panel measures its range once its rows are built, and the search
results measure theirs with UpdateScrollChildRect instead of hiding,
re-attaching and scrolling a frame later. Clearing the search measures
again too.
CreateScrollFrame and CreateScrollChild have no users left, and nothing
called CreateTabFrame or CreateTabChild; all four are gone. pfQuest's
compat layer brings its own copies of the scroll helpers.
pfUIScrollBoxListTemplate (api/ui-widgets.xml) is a WowScrollBoxList with
pfUIScrollBarTemplate beside it, 5px inside the frame, so a list's
backdrop goes on the frame itself. The addon list moves onto it and drops
the sibling backdrop frame.
Loot history builds a flat list of item rows and, under an expanded item,
player rows; the view sizes and indents them. The item frame array, the
player pool, the hand-placed rows and the scroll child re-attach are gone,
and the scroll position holds across roll updates.
The icon picker's FauxScrollFrame and 80 fixed buttons become a grid view
over the provider's icon indices. Picking an icon reinitializes the shown
buttons instead of redrawing the grid, and closing the popup drops the
grid's entries along with the provider.
pfUIScrollingEditBoxTemplate (api/ui-widgets.xml) is ScrollingEditBoxTemplate
with pfUIScrollBarTemplate beside the text. Its mixin's SetFont gives the
box a font object of its own, since the edit box sets its font by object on
every SetText and pfUI fonts are paths. ui-widgets.lua now loads before the
XML, which needs the mixin.
The share box no longer recomputes its scroll child on every text change.
Chat copy reads each chat frame's messages with ClassicAPI's
GetMessageInfo when it opens, so the AddMessage hook, its 100-line copy of
the history and the skip of combat frames are gone. It shows every line
the frame keeps, lines from before login included. It puts the caret at
the end to scroll to the newest line instead of three OnUpdate passes, and
Escape now leaves copy mode on every chat frame.
The list built one row per addon in a ScrollFrame, hid the rows out of
view by hand and drove pfUI's own slider. A WowScrollBoxList keeps rows
only for the addons in view and recycles them while scrolling.
pfUIScrollBarTemplate (api/ui-widgets.xml) is a ScrollBarMixin bar with
the old slider's look: a thin track and a flat teal thumb that hides when
nothing scrolls. Its steppers exist for the mixin but stay hidden.
Rows read the addon's enabled state, so profiles enable and disable
addons directly instead of clicking every row's checkbox. A checkbox
now shows whether an addon is enabled; it showed whether it was loaded.
/afk toggles. The overlay sent it on every click and key press, so when
the client or the server had already cleared AFK it set it again. Check
ClassicAPI's IsChatAFK first. It follows the client's /afk state at
once, where UnitIsAFK waits for the server's flag update.
62e0d4eb stopped the camera only while the start delay was shown, but the
delay hides itself once the camera starts. AFK cleared during the spin
left the overlay up, and the next key press sent /afk and set AFK again.
Stop when the camera spins instead, which also keeps stop() and its
SetView(4) from running when AFK clears before the camera started.
The tooltip was built once on enter, so its memory, network and addon
figures stayed at the values from that moment. The widget's one-second
ticker now rebuilds it while the panel still owns GameTooltip. The
tooltip takes its owner as self, not this, so the ticker can call it.
With HealComm-1.0 present (HealComm, LunaUnitFrames, NotGrid), the
compat hook unregistered every event on libpredict.sender to stop pfUI
broadcasting a duplicate of the player's casts. Since cast detection
moved onto that frame's UNIT_SPELLCAST_* handlers, that also blinded
libpredict to every cast, so the player's own resurrections never put
the rez icon on the target's frame: ParseChatMessage drops the player's
own Resurrection echo, expecting the cast events to have tracked it.
The compat hook now only mutes the outgoing HealComm and CTRA messages.
The HealComm.SendAddonMessage hook that parsed the player's own messages
while solo goes too, since libpredict tracks its own casts directly.
pfGridmath listed every exact cols x rows grid per bar size; the only
live use was seeding the layout dropdown, which a divisor loop now does.
Everything else that read it was unreachable: every layout option is a
"cols x rows" string, so ResolveBarLayout's BarLayoutFormfactor lookup
never matched, and the actionbar module resets a stored layout that
isn't one before BarLayoutSize/BarButtonAnchor run, so their fallbacks
never fired. BarLayoutFormfactor and env/tables.lua go with it.
CreateUnitFrame and CreateCastbar could take a character name instead of
a unit token, but every caller passes a token, so that mode and the
empty-label guards around it were dead. The OnClick TargetByName branch
could never run anyway: label was always a string, and "" is truthy.
With that gone, the aggro scan was the only reader of pfValidUnits, so
its unit list now lives in unitframes.lua and is built once at load.
/focusname resolves the name with UnitTokenFromName (exact first, then
prefix) instead of swapping the target and muting UIErrorsFrame.
C_Container.SetItemSearch drives the search box; slots dim from isFiltered on INVENTORY_SEARCH_UPDATE and on each slot update. Matches name, subclass, equip slot and equipment set names. Drops the tooltip-scanning full-text option.
Use UpdateAddOnMemoryUsage/GetAddOnMemoryUsage like Blizzard's MainMenuBar performance tooltip: total addon memory plus the top 3 consumers, formatted with the TOTAL_MEM/ADDON_MEM global strings. Guarded so the tooltip falls back gracefully on clients without these APIs.
* Add equipment manager auto-switching and "Unused" items panel
Equipment manager (modules/equipmentmanager.lua):
- Add automatic set switching: ordered triggers (mounted, swimming,
eating/drinking, shapeshift form/stance, zone, instance type, time
of day, resting, stealthed, targeting a boss) equip a set; topmost
matching trigger wins, with a 0.5s debounce
- Never swap gear in combat, while dead or casting; optionally restore
the previous gear via a hidden "pfUI Auto-Restore" set
- Add an "Unused" side panel listing equippable items in bags, bank
and paperdoll that no set uses, with an ignore list (tools and quest
disguises pre-ignored), bank snapshot and bag highlighting
- Persist triggers, ignore list and bank snapshot in new per-character
SavedVariable pfUI_eqmgr (all three .toc files)
- Add Character > Equipment Manager options (autoswitch, announce,
minimum item quality, include bank) in gui.lua and config.lua
- Hide ignored-slot overlays when the manager frame is closed
Add frFR translations for the new equipment manager strings.
* equipmentmanager: lean on ClassicAPI for unused scan and autoswitch
- Unused panel: list items via GetInventoryItemsForSlot instead of
hand-packing locations and walking the bags.
- Bank snapshot: record set membership while the bank is open.
GetItemLocations reports bank items as missing once it closes, so set
items in the bank were listed as unused.
- Autoswitch: check CanUseEquipmentSets and the UseEquipmentSet result
before marking a trigger applied, and retry when the swap is blocked.
- Drive the engine from events (aura, form, zone, resting, target,
regen) instead of a 4 Hz ticker; poll only swimming, time and eating.
- Detect eating/drinking by the localized names of the Food (433) and
Drink (430) auras instead of hardcoded locale strings and icon paths.
- Drop presence guards on APIs that always exist; use strsplittable and
strtrim for trigger values.
* equipmentmanager: wake the dining trigger on player health/mana events
Drop dining from the poll: listen to UNIT_HEALTH/UNIT_MANA for the player
while a dining trigger is enabled, so taking the set off once full is
event-driven. Register UNIT_AURA for the player only.
* equipmentmanager: split trigger values with strsplit
strsplittable needs ClassicAPI 1.17.11; strsplit has been there since
1.7.3, so this keeps the minimum where it is.
* equipmentmanager: let the trigger hint wrap
---------
Co-authored-by: Duciel <336374+Duciel@users.noreply.github.com>
Co-authored-by: Brues <5278969+brues-code@users.noreply.github.com>
CacheConfig clamped notargalpha to 0.99, so a 100% setting never reached full opacity. Clamp to 1.0 instead and detect the target plate by GUID comparison only, removing the alpha-based fallback that required the headroom.
Unit frame aura icons only get their size from the layout pass, but
RefreshUnit started their timers before it ran. A cooldown text created
on a never-laid-out icon saw a height of 0 and fell back to a 16pt font,
so some buff and debuff timers overflowed their icons. (Closes#64)
- RefreshUnit stores each aura's timer and starts them after
LayoutAuras, once every icon has its final size.
- With dynamic size on, the cooldown text re-sizes its font whenever
its frame's height changed since the last SetTimer, so icons that
switch between the normal and own aura size keep a matching font.
Leaving the world destroys the units before PLAYER_LOGOUT fires, so some
plates in the registry are already dead: their overlay buttons dropped
their events and lost their methods, and UnregisterAllEvents errored as a
nil method. Only silence the plates that are still alive.
Read casts from UNIT_SPELLCAST_* and heal amounts from
COMBAT_LOG_EVENT_UNFILTERED in libpredict, swingtimer and the prowl
page switch. Drop libdebuff's AURA_CAST/DEBUFF_* bookkeeping and hook
tables, which nothing read: its aura readers already use C_UnitAuras.
Drop the unitframe BUFF_ADDED_OTHER start-time tracker, since
C_UnitAuras stamps an expiration for auras seen being applied.
Read Innervate casts from COMBAT_LOG_EVENT_UNFILTERED instead of
Nampower's AURA_CAST events, taking the target name from the event.
Schedule the ready callout once Innervate's own cooldown appears on
SPELL_UPDATE_COOLDOWN; at cast time GetSpellCooldown reports only the GCD.
Unitframes: only set the unit attribute when it changes, poll group frame indicators every 3s since events already cover them, and limit full refreshes on eventless frames to unit changes or once a second.
Actionbar: handle UNIT_INVENTORY_CHANGED with a light count/cooldown/usable pass instead of a full update of every button, and skip hidden buttons in the cached passes, catching them up once they become visible.
Pull the CHAT_MSG payload once per line instead of decoding it from the
rendered text. The sender match uses arg2 rather than the name resolved
from the GUID, and channel shortening only runs on CHAT_MSG_CHANNEL with
a single anchored replacement in place of the backtracking pattern.
The engine name-queries a chat sender before the CHAT_MSG event fires,
so GetPlayerInfoByGUID(GetCurrentChatGUID()) resolves every player
sender, including strangers in world channels. Other names in the text
still fall back to C_PlayerCache.GetPlayerInfoByName and libunitscan.
This makes the silent /who lookup for unknown classes obsolete; remove
it along with its FriendsFrame_OnEvent wrapper, config default, GUI
entry and translations.
The ranged bar faked its fills with three textures resized and re-texcoorded every frame. A StatusBar with ClassicAPI's SetFillStyle covers all of it: CENTER for hunters (reload drains to the middle, the deadzone grows back out in the warn color), STANDARD otherwise.
Unit frame aura icons are placed by a layout pass after each aura
refresh instead of a fixed grid set at setup. Rows are as tall as
their largest icon, and the debuff block no longer uses the debuff
size to step past buff rows. (Closes#25)
- When buffs and debuffs share a corner, debuffs come first on
neutral and hostile units.
- New Own Buff Size / Own Debuff Size (-1 = normal size) enlarge the
player's auras, which C_UnitAuras already lists first.
- New Buff/Debuff X-Spacing and Y-Spacing set the gaps between icons
and rows; the default of 1 keeps the old look.
- The selfdebuff tooltip remap is gone from unit frames and buffwatch:
own auras lead the list, so the HARMFUL|PLAYER index is the HARMFUL
index.
ClassicAPI 1.17.1 draws the Cooldown sweep natively, as 4.3.4's
CGCooldown, so pfUI's cooldowns no longer need the indicator Model.
- Action buttons, bank slots, totems, unit frame auras and icons, and
nameplate debuffs are Cooldown frames with CooldownFrameTemplate.
- The plain-Frame fallbacks for disabled animations are gone; the hook
already hides the sweep with alpha 0.
- The 36px scale-and-inset realign only runs on stock indicator Models.
CreateBackdrop widens a frame's hit rect by the border, so mouse focus
and OnEnter/OnLeave cover a band that plain MouseIsOver reports as
outside. Add MouseIsOverHitRect, which passes the frame's hit rect
insets as MouseIsOver offsets, and use it at the unpadded call sites.
The XP bar's hover text follows the same OnEnter/OnLeave flag as its
fade.
Replace hand-rolled OnUpdate alpha loops with engine animation groups:
unit frame aggro/combat glow, tracking icon pulse, new-mail blink,
castbar fade-out, autohide, XP/rep bar fade, info box timeout and the
unlock-mode scale label. Timing no longer depends on framerate, and the
always-running glow driver and tracking OnUpdate are gone.
The XP bar tracks hover through OnEnter/OnLeave instead of MouseIsOver,
so a fade can't restart under the cursor.
The old pagemaster wipe block checked a setting that was migrated away and
never ran, so saved MOD-key bindings beat the paged action. Override every
key bound to ACTIONBUTTON1-12 for each enabled page modifier instead; the
saved binding set stays untouched.
Hoverbind now reports when a bind takes a key from another action, and when
an override masks the new bind.
* Only move the center panel when it overlaps the left panel
The panel aligner cached the left panel's rightmost child once and then
re-anchored the center panel to that edge on every change. Children that
were hidden later (such as Spellbook skill-line tabs) kept pushing the
center panel right, and panels that already cleared the left panel were
pulled back to the left.
Recalculate the rightmost visible child while both panels are shown and
only shift the center panel when its backdrop really overlaps.
* Align Quest Log, Friends and Spellbook panel heights
Most skinned panels draw their backdrop 430px tall, 10px below the frame
top (insets 10/-10 and -30/72). Three panels did not match:
- Quest Log: frame was 440px and anchored at y -104, so it stood 10px
taller than a panel opened beside it. It is now 430px at y -114, with
the list/detail panes and visible rows (22) reduced to fit.
- Friends: bottom inset was 74 instead of 72.
- Spellbook: top-left inset was 12/-12 instead of 10/-10.
The Quest Log is a doublewide UI panel. Opening another panel next to
it made UpdateUIPanelPositions re-anchor it to the default (0, -104),
causing a visible jump. Its UIPanelWindows entry now carries the same
x/y offsets as the OnShow anchor.
* Let the panel manager place UI panels
Remove the OnUpdate panel aligner. UpdateUIPanelPositions already lays
out left/center/right panels, and with the overlap-only rule the
aligner no longer changed the spacing in normal cases.
The Quest Log's UIPanelWindows offsets put it at 10, -114 on every
layout pass, so the QuestLog_OnShow re-anchor is redundant.
---------
Co-authored-by: Brues <5278969+brues-code@users.noreply.github.com>