4 Commits
Author SHA1 Message Date
Brues d02fcaa8ee We no longer use these features from SuperWoW/Nampower 2026-07-31 21:47:00 -05:00
Brues 5dd42a8d86 Drive nameplate castbars off UNIT_SPELLCAST_*
ClassicAPI now fires UNIT_SPELLCAST_* for nameplate tokens, so populate the
per-GUID castState cache from UNIT_SPELLCAST_{START,CHANNEL_START} (poll
PollCastInfo for the timing the payload omits) and clear it on
{STOP,CHANNEL_STOP} -- the remote poll fires STOP for natural end, interrupt,
and cancel alike. Replaces the nampower SPELL_{START,FAILED}_OTHER path; the
^nameplate arg1 gate ignores the target/focus/party fires of the same events,
and the NAME_PLATE_UNIT_ADDED seed still catches a plate spawning mid-cast.
Nameplate cast detection is now nampower-free.
2026-07-31 18:11:18 -05:00
Brues 1a342adfca Route target/focus castbars through remote UNIT_SPELLCAST_*
ClassicAPI now fires UNIT_SPELLCAST_* for remote tokens (target/focus/...)
via PollRemote, so drop the nampower SPELL_*_OTHER path and drive all three
bars off one event model. The gate is now token-based (arg1 == this.unitstr,
plus the arg1=="player" + UnitIsUnit case for target=self); the RunNextFrame
defer is gone since the remote poll fires after UnitCastingInfo is readable.
Cast detection is now nampower-free across every bar.

Use the event's rank payload (arg5): thread it through RefreshBar into
StampBar, which now only calls C_Spell.GetSpellSubtext as a fallback on the
retarget re-poll (PLAYER_TARGET/FOCUS_CHANGED) where no event is in hand.
2026-07-31 18:04:50 -05:00
Brues 892b48e60f Migrate player castbar to ClassicAPI UNIT_SPELLCAST_* events
Drive the player cast path off ClassicAPI's synthesized, player-only
UNIT_SPELLCAST_* events instead of the vanilla SPELLCAST_* plus nampower
SPELL_{START,GO,DELAYED}_SELF mix. START/CHANNEL_START poll UnitCastingInfo/
UnitChannelInfo and stamp; STOP/CHANNEL_STOP/FAILED/INTERRUPTED clear;
SUCCEEDED drives tradeskill craft counting; DELAYED/CHANNEL_UPDATE re-poll.
Since UNIT_SPELLCAST_START fires for chained same-spell recasts, the nampower
SELF deps and their RunNextFrame co-hook-ordering workarounds are gone.
Remote target/focus bars keep SPELL_*_OTHER (the new events are player-only).

Fix the cast-start flash: StampBar now primes the fill on the stamp frame,
and ClearBar no longer snaps the bar to full (that snap lingered in the fade
tail and flashed when the next cast stamped).

Add a red flash on a cancelled cast: new appearance.castbar.failcolor,
flashed by ClearBar only when a cast was actually in progress.

Handle pushback Quartz-style: DELAYED/CHANNEL_UPDATE re-poll just the times
and accumulate the endMs shift into this.delay for the +/- indicator (cast
+X, channel -X), rather than a full restamp.
2026-07-31 13:22:36 -05:00
26 changed files with 697 additions and 804 deletions
+11 -16
View File
@@ -2,11 +2,11 @@
[![Octo WoW](https://img.shields.io/badge/Octo%20WoW-1.18.1-brightgreen.svg)](https://octowow.st/) [![Octo WoW](https://img.shields.io/badge/Octo%20WoW-1.18.1-brightgreen.svg)](https://octowow.st/)
[![ClassicAPI](https://img.shields.io/badge/ClassicAPI-Required-purple.svg)](https://github.com/brues-code/ClassicAPI) [![ClassicAPI](https://img.shields.io/badge/ClassicAPI-Required-purple.svg)](https://github.com/brues-code/ClassicAPI)
[![SuperWoW](https://img.shields.io/badge/SuperWoW-Required-purple.svg)](https://github.com/balakethelock/SuperWoW)
[![Nampower](https://img.shields.io/badge/Nampower-Required-purple.svg)](https://github.com/brues-code/nampower) [![Nampower](https://img.shields.io/badge/Nampower-Required-purple.svg)](https://github.com/brues-code/nampower)
[![SuperWoW](https://img.shields.io/badge/SuperWoW-Optional-yellow.svg)](https://github.com/balakethelock/SuperWoW) [![UnitXP](https://img.shields.io/badge/UnitXP__SP3-Optional-yellow.svg)](https://codeberg.org/konaka/UnitXP_SP3)
[![UnitXP](https://img.shields.io/badge/UnitXP__SP3-Optional-yellow.svg)](https://github.com/brues-code/UnitXP_SP3)
**A pfUI fork specifically optimized for ClassicAPI on [Octo WoW](https://octowow.st/)** **A pfUI fork specifically optimized for ClassicAPI on [Octo WoW](https://octowow.st/) which requires Nampower and SuperWoW with optional UnitXP_SP3 DLL integration.**
This version includes significant performance improvements and DLL-enhanced features. This version includes significant performance improvements and DLL-enhanced features.
@@ -16,7 +16,7 @@ This version includes significant performance improvements and DLL-enhanced feat
4. Copy "pfUI" into Wow-Directory\Interface\AddOns 4. Copy "pfUI" into Wow-Directory\Interface\AddOns
5. Restart Wow 5. Restart Wow
## DLL Enhancements ## Optional DLL Enhancements
Since pfUI 6.0.0 includes integrations with client-side DLLs for enhanced functionality. These DLLs are permitted on Octo WoW: Since pfUI 6.0.0 includes integrations with client-side DLLs for enhanced functionality. These DLLs are permitted on Octo WoW:
@@ -36,24 +36,20 @@ Provides:
- Faster, safer profile sharing - Engine-side serialize/compress/base64 via C_EncodingUtil - Faster, safer profile sharing - Engine-side serialize/compress/base64 via C_EncodingUtil
- C_Timer - After / NewTicker replacing hand-rolled OnUpdate throttles - C_Timer - After / NewTicker replacing hand-rolled OnUpdate throttles
- Feign death, shapeshift and quest-item detection via real API calls - Feign death, shapeshift and quest-item detection via real API calls
- Mouseover Unit Frames
- Click-casting
- Loot Roll History (/loothistory)
- New item highlighting
- Plenty other functions - Plenty other functions
### [SuperWoW](https://github.com/balakethelock/SuperWoW)
Provides:
- SetMouseoverUnit for improved targeting
### [Nampower](https://github.com/brues-code/nampower) ### [Nampower](https://github.com/brues-code/nampower)
Provides: Provides:
- Spell queue indicator - Spell queue indicator
- GCD indicator - GCD indicator
### [SuperWoW](https://github.com/balakethelock/SuperWoW) ### [UnitXP_SP3](https://codeberg.org/konaka/UnitXP_SP3)
Provides:
- Tracks party/raid units on the minimap
### [UnitXP_SP3](https://github.com/brues-code/UnitXP_SP3)
Provides: Provides:
- Line of Sight detection - Line of Sight detection
@@ -80,7 +76,6 @@ Use `/pfdll` in-game to check which DLLs are detected.
/swapfocus Toggle Focus and Target-Frame /swapfocus Toggle Focus and Target-Frame
/pftest Toggle pfUI Unitframe Test Mode /pftest Toggle pfUI Unitframe Test Mode
/abp Addon Button Panel /abp Addon Button Panel
/loothistory Show Loot Roll History
## Languages ## Languages
pfUI supports and contains language specific code for the following gameclients. pfUI supports and contains language specific code for the following gameclients.
@@ -93,7 +88,7 @@ pfUI supports and contains language specific code for the following gameclients.
* Russian (ruRU) * Russian (ruRU)
## Recommended Addons ## Recommended Addons
* [pfQuest](https://github.com/brues-code/pfQuest) A simple database and quest helper * [pfQuest](https://shagu.org/pfQuest) A simple database and quest helper
* [SuperCleveRoidMacros](https://github.com/brues-code/SuperCleveRoidMacros) Supports modern macro formats * [SuperCleveRoidMacros](https://github.com/brues-code/SuperCleveRoidMacros) Supports modern macro formats
## Plugins ## Plugins
-1
View File
@@ -785,7 +785,6 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("tooltip", nil, "extguild", "1") pfUI:UpdateConfig("tooltip", nil, "extguild", "1")
pfUI:UpdateConfig("tooltip", nil, "itemid", "0") pfUI:UpdateConfig("tooltip", nil, "itemid", "0")
pfUI:UpdateConfig("tooltip", nil, "movespeed", "0") pfUI:UpdateConfig("tooltip", nil, "movespeed", "0")
pfUI:UpdateConfig("tooltip", nil, "aurasource", "0")
pfUI:UpdateConfig("tooltip", nil, "alpha", "0.8") pfUI:UpdateConfig("tooltip", nil, "alpha", "0.8")
pfUI:UpdateConfig("tooltip", nil, "alwaysperc", "0") pfUI:UpdateConfig("tooltip", nil, "alwaysperc", "0")
pfUI:UpdateConfig("tooltip", "compare", "basestats", "1") pfUI:UpdateConfig("tooltip", "compare", "basestats", "1")
-246
View File
@@ -1246,249 +1246,3 @@ function pfUI.api.SkinMoneyInputFrame(frame)
copperIcon:ClearAllPoints() copperIcon:ClearAllPoints()
copperIcon:SetPoint("LEFT", copper_editbox, "RIGHT", 2, 0) copperIcon:SetPoint("LEFT", copper_editbox, "RIGHT", 2, 0)
end end
-- Shared icon picker widget. Builds a name field, a "currently selected"
-- preview, and a 10x8 icon grid backed by IconDataProviderMixin with an
-- All/Spells/Items filter and a name search. Used by the macro icon picker
-- and the equipment manager's name/icon popup. The widgets attach to
-- `parent`; the caller owns the surrounding frame, its OK/Cancel buttons,
-- and the save flow. Selection is tracked by texture PATH (not index) so it
-- survives filter changes -- a spell icon you picked still saves after you
-- switch the filter to "Items" and it drops out of the visible grid.
--
-- name global-name prefix for the scroll frame and editboxes
-- parent the popup frame to attach the widgets to
-- extraType IconDataProviderExtraType.* seed (Spellbook / Equipment)
-- nameLabelText header shown above the name field
--
-- Returns a handle:
-- .editbox name EditBox (caller wires enter/escape)
-- .search search EditBox
-- .GetIcon() current selected texture path
-- .SetIcon(path) set selection (nil -> question mark)
-- .Refresh() ensure provider, redraw grid + preview
-- .SetIconAreaShown(shown) show/hide the grid, filter, search, and labels
function pfUI.api.CreateIconPicker(name, parent, extraType, nameLabelText)
local QUESTION_MARK = "INTERFACE\\ICONS\\INV_MISC_QUESTIONMARK"
local ICON_GRID_COLS = 10
local ICON_GRID_ROWS = 8
local ICON_BTN_SIZE = 36
local ICON_BTN_PAD = 6
local provider = nil
local selectedIconPath = QUESTION_MARK
local currentFilter = "all"
local searchText = ""
local filtered = nil -- provider indices matching the search, or nil when empty
local RefreshIconGrid, RebuildFilter
local function EnsureProvider()
if not provider then
provider = CreateAndInitFromMixin(IconDataProviderMixin, extraType)
end
end
-- Normalize a texture to an uppercase basename so matching works across
-- sources: GetMacroInfo / stored set icons return "Interface\Icons\<name>"
-- while provider paths are uppercase-prefixed for base icons and
-- mixed-case for spellbook extras.
local function IconKey(path)
if type(path) ~= "string" then return path end
return string.gsub(string.upper(path), "^.*[\\/]", "")
end
parent.nameLabel = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
parent.nameLabel:SetPoint("TOPLEFT", parent, "TOPLEFT", 14, -20)
parent.nameLabel:SetText(nameLabelText)
parent.editbox = CreateFrame("EditBox", name.."Name", parent, "InputBoxTemplate")
parent.editbox:SetSize(280, 20)
parent.editbox:SetPoint("TOPLEFT", parent, "TOPLEFT", 14, -38)
parent.editbox:SetAutoFocus(false)
parent.editbox:SetMaxLetters(16)
CreateBackdrop(parent.editbox)
parent.selectedLabel = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
parent.selectedLabel:SetPoint("TOPRIGHT", parent, "TOPRIGHT", -14, -14)
parent.selectedLabel:SetText(ICON_SELECTION_TITLE_CURRENT)
parent.selectedLabel:SetTextColor(1, 0.82, 0)
parent.selectedPreview = CreateFrame("Frame", nil, parent)
parent.selectedPreview:SetSize(42, 42)
parent.selectedPreview:SetPoint("TOPRIGHT", parent, "TOPRIGHT", -14, -30)
CreateBackdrop(parent.selectedPreview)
parent.selectedPreview.tex = parent.selectedPreview:CreateTexture(nil, "ARTWORK")
parent.selectedPreview.tex:SetAllPoints(parent.selectedPreview)
parent.selectedPreview.tex:SetTexCoord(.08, .92, .08, .92)
parent.iconLabel = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
parent.iconLabel:SetPoint("TOPLEFT", parent, "TOPLEFT", 14, -86)
parent.iconLabel:SetText(MACRO_POPUP_CHOOSE_ICON)
-- Icon grid + scroll
local iconScroll = CreateFrame("ScrollFrame", name.."Scroll", parent, "FauxScrollFrameTemplate")
iconScroll:SetPoint("TOPLEFT", parent, "TOPLEFT", 14, -116)
iconScroll:SetWidth(ICON_GRID_COLS * (ICON_BTN_SIZE + ICON_BTN_PAD) - ICON_BTN_PAD)
iconScroll:SetHeight(ICON_GRID_ROWS * (ICON_BTN_SIZE + ICON_BTN_PAD) - ICON_BTN_PAD)
local scrollbar = _G[name.."ScrollScrollBar"]
scrollbar:ClearAllPoints()
scrollbar:SetPoint("TOPLEFT", iconScroll, "TOPRIGHT", 8, -16)
scrollbar:SetPoint("BOTTOMLEFT", iconScroll, "BOTTOMRIGHT", 8, 16)
SkinScrollbar(scrollbar)
-- Filter dropdown: All / Spells / Items
local filterDropdown = CreateFrame("Frame", name.."Filter", parent, "UIDropDownMenuTemplate")
filterDropdown:SetPoint("TOPRIGHT", parent, "TOPRIGHT", 0, -80)
local function ApplyFilter(value)
currentFilter = value
UIDropDownMenu_SetSelectedValue(filterDropdown, value)
if provider then
if value == "spells" then provider:SetIconTypes({ IconDataProviderIconType.Spell })
elseif value == "items" then provider:SetIconTypes({ IconDataProviderIconType.Item })
else provider:SetIconTypes(nil) end
RebuildFilter()
RefreshIconGrid()
end
end
UIDropDownMenu_Initialize(filterDropdown, function()
local info
info = {}; info.text = ICON_FILTER_ALL; info.value = "all"
info.func = function() ApplyFilter("all") end
info.checked = currentFilter == "all"
UIDropDownMenu_AddButton(info)
info = {}; info.text = ICON_FILTER_SPELL; info.value = "spells"
info.func = function() ApplyFilter("spells") end
info.checked = currentFilter == "spells"
UIDropDownMenu_AddButton(info)
info = {}; info.text = ICON_FILTER_ITEM; info.value = "items"
info.func = function() ApplyFilter("items") end
info.checked = currentFilter == "items"
UIDropDownMenu_AddButton(info)
end)
UIDropDownMenu_SetWidth(120, filterDropdown)
UIDropDownMenu_SetSelectedValue(filterDropdown, "all")
SkinDropDown(filterDropdown)
local iconButtons = {}
for r = 1, ICON_GRID_ROWS do
for c = 1, ICON_GRID_COLS do
local i = (r - 1) * ICON_GRID_COLS + c
local btn = CreateFrame("Button", nil, parent)
btn:SetSize(ICON_BTN_SIZE, ICON_BTN_SIZE)
btn:SetPoint("TOPLEFT", iconScroll, "TOPLEFT", (c-1) * (ICON_BTN_SIZE + ICON_BTN_PAD), -(r-1) * (ICON_BTN_SIZE + ICON_BTN_PAD))
CreateBackdrop(btn)
btn.texture = btn:CreateTexture(nil, "ARTWORK")
btn.texture:SetAllPoints(btn)
btn.texture:SetTexCoord(.08, .92, .08, .92)
btn:SetScript("OnClick", function()
if this.iconIndex and provider then
local path = provider:GetIconByIndex(this.iconIndex)
if path then selectedIconPath = path end
RefreshIconGrid()
end
end)
btn:SetScript("OnEnter", function()
if not this.iconIndex or not provider then return end
local path = provider:GetIconByIndex(this.iconIndex)
if type(path) == "string" then
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetText(IconKey(path), 1, 1, 1)
GameTooltip:Show()
end
end)
btn:SetScript("OnLeave", GameTooltip_Hide)
iconButtons[i] = btn
end
end
-- Rebuild the search-filtered index list (provider indices whose icon
-- basename contains the search text); nil when the search box is empty.
function RebuildFilter()
EnsureProvider()
if searchText == "" then
filtered = nil
return
end
filtered = {}
for i = 1, provider:GetNumIcons() do
local path = provider:GetIconByIndex(i)
if type(path) == "string" and string.find(IconKey(path), searchText, 1, true) then
table.insert(filtered, i)
end
end
end
function RefreshIconGrid()
EnsureProvider()
local numIcons = filtered and table.getn(filtered) or provider:GetNumIcons()
local numRows = math.ceil(numIcons / ICON_GRID_COLS)
FauxScrollFrame_Update(iconScroll, numRows, ICON_GRID_ROWS, ICON_BTN_SIZE + ICON_BTN_PAD)
local offset = FauxScrollFrame_GetOffset(iconScroll)
for i = 1, ICON_GRID_ROWS * ICON_GRID_COLS do
local listIdx = i + offset * ICON_GRID_COLS
local btn = iconButtons[i]
if listIdx <= numIcons then
btn:Show()
local providerIdx = filtered and filtered[listIdx] or listIdx
btn.iconIndex = providerIdx
local path = provider:GetIconByIndex(providerIdx)
btn.texture:SetTexture(path)
if IconKey(path) == IconKey(selectedIconPath) then
btn.backdrop:SetBackdropBorderColor(1, 0.82, 0, 1)
else
btn.backdrop:SetBackdropBorderColor(pfUI.cache.er, pfUI.cache.eg, pfUI.cache.eb, pfUI.cache.ea)
end
else
btn:Hide()
btn.iconIndex = nil
end
end
parent.selectedPreview.tex:SetTexture(selectedIconPath)
end
iconScroll:SetScript("OnVerticalScroll", function()
FauxScrollFrame_OnVerticalScroll(ICON_BTN_SIZE + ICON_BTN_PAD, function() RefreshIconGrid() end)
end)
-- Search box (bottom-left) filters the grid by icon name.
parent.searchLabel = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
parent.searchLabel:SetPoint("BOTTOMLEFT", parent, "BOTTOMLEFT", 16, 18)
parent.searchLabel:SetText(SEARCH)
parent.search = CreateFrame("EditBox", name.."Search", parent, "InputBoxTemplate")
parent.search:SetSize(180, 20)
parent.search:SetPoint("LEFT", parent.searchLabel, "RIGHT", 10, 0)
parent.search:SetAutoFocus(false)
CreateBackdrop(parent.search)
parent.search:SetScript("OnEscapePressed", function() this:ClearFocus() end)
parent.search:SetScript("OnTextChanged", function()
searchText = strupper(strtrim(this:GetText()))
RebuildFilter()
scrollbar:SetValue(0)
RefreshIconGrid()
end)
-- Release the provider when the popup closes so its icon cache GCs.
parent:HookScript("OnHide", function()
if provider then provider:Release(); provider = nil end
end)
local handle = { editbox = parent.editbox, search = parent.search }
function handle.GetIcon() return selectedIconPath end
function handle.SetIcon(path) selectedIconPath = path or QUESTION_MARK end
function handle.Refresh() RefreshIconGrid() end
function handle.SetIconAreaShown(shown)
local method = shown and "Show" or "Hide"
iconScroll[method](iconScroll)
for _, b in ipairs(iconButtons) do b[method](b) end
parent.iconLabel[method](parent.iconLabel)
parent.selectedLabel[method](parent.selectedLabel)
parent.selectedPreview[method](parent.selectedPreview)
filterDropdown[method](filterDropdown)
parent.searchLabel[method](parent.searchLabel)
parent.search[method](parent.search)
end
return handle
end
+160 -90
View File
@@ -238,7 +238,6 @@ function pfUI.uf:UpdateVisibility()
end end
local unitstr = string.format("%s%s", self.label or "", self.id or "") local unitstr = string.format("%s%s", self.label or "", self.id or "")
self:SetAttribute("unit", unitstr ~= "" and unitstr or nil)
local visibility = string.format("[target=%s,exists] show; hide", unitstr) local visibility = string.format("[target=%s,exists] show; hide", unitstr)
-- Group frames are redundant when the group is already shown as a raid grid: -- Group frames are redundant when the group is already shown as a raid grid:
@@ -402,7 +401,7 @@ function pfUI.uf:UpdateConfig()
if tonumber(f.config.pheight) < 0 then f.power:Hide() end if tonumber(f.config.pheight) < 0 then f.power:Hide() end
pfUI.api.CreateBackdrop(f.power, default_border) pfUI.api.CreateBackdrop(f.power, default_border)
f.power.bar:SetFrameLevel(f.power.backdrop:GetFrameLevel() + 1) f.power.bar:SetFrameLevel(f.power:GetFrameLevel() + 1)
f.power.bar:SetStatusBarTexture(pfUI.media[f.config.pbartexture]) f.power.bar:SetStatusBarTexture(pfUI.media[f.config.pbartexture])
f.power.bar:SetAllPoints(f.power) f.power.bar:SetAllPoints(f.power)
@@ -1111,7 +1110,11 @@ function pfUI.uf.OnUpdate()
-- update ressurections -- update ressurections
local ress = libpredict:UnitHasIncomingResurrection(unit) local ress = libpredict:UnitHasIncomingResurrection(unit)
this.ressIcon:SetShown(ress and UnitIsDeadOrGhost(unit)) if ress and UnitIsDeadOrGhost(unit) then
this.ressIcon:Show()
else
this.ressIcon:Hide()
end
end end
end end
end end
@@ -1174,6 +1177,52 @@ function pfUI.uf.OnUpdate()
end end
end end
function pfUI.uf.OnEnter()
if not this.label then return end
local unitstr = this.label .. this.id
if UnitExists(unitstr) then
SetMouseoverUnit(unitstr)
end
if this.config.showtooltip == "0" then return end
GameTooltip_SetDefaultAnchor(GameTooltip, this)
GameTooltip:SetUnit(this.label .. this.id)
GameTooltip:Show()
end
function pfUI.uf.OnLeave()
SetMouseoverUnit("")
GameTooltip:FadeOut()
end
function pfUI.uf.OnClick()
if not this.label and this.unitname then
TargetByName(this.unitname, true)
else
pfUI.uf:ClickAction(arg1)
end
end
function pfUI.uf:RightClickAction(unit)
if unit == "player" then
ToggleDropDownMenu(1, nil, PlayerFrameDropDown, "cursor")
elseif unit == "target" then
ToggleDropDownMenu(1, nil, TargetFrameDropDown, "cursor")
elseif unit == "pet" then
ToggleDropDownMenu(1, nil, PetFrameDropDown, "cursor")
elseif unit == "party" or strfind(unit, "party%d") then
ToggleDropDownMenu(1, nil, getglobal("PartyMemberFrame" .. this.id .. "DropDown"), "cursor")
elseif unit == "raid" or strfind(unit, "raid%d") then
local name = this.lastUnit
local unitstr = this.label .. this.id
FriendsDropDown.displayMode = "MENU"
FriendsDropDown.initialize = function() UnitPopup_ShowMenu(_G[UIDROPDOWNMENU_OPEN_MENU], "PARTY", unitstr, name, id) end
ToggleDropDownMenu(1, nil, FriendsDropDown, "cursor")
end
end
function pfUI.uf:EnableEvents() function pfUI.uf:EnableEvents()
local f = self local f = self
@@ -1209,72 +1258,17 @@ function pfUI.uf:EnableEvents()
'MiddleButtonUp', 'Button4Up', 'Button5Up') 'MiddleButtonUp', 'Button4Up', 'Button5Up')
end end
-- ============================================================
-- Clique compatibility
-- Clique's pfUI plugin replaces pfUI.uf.ClickAction and expects an
-- OnClick script to call it (with `this` = frame, `arg1` = button). The
-- secure attribute path replaced that dispatch, so when Clique is loaded
-- EnableScripts routes clicks through this legacy Lua path instead. The
-- secure path is skipped there because type1="target" switches the target
-- before Clique can cast.
-- ============================================================
function pfUI.uf.OnClick()
if not this.label and this.unitname then
TargetByName(this.unitname, true)
else
pfUI.uf:ClickAction(arg1)
end
end
function pfUI.uf:ClickAction(button)
local label = this.label or ""
local id = this.id or ""
local unitstr = label .. id
if SpellIsTargeting() and button == "RightButton" then
SpellStopTargeting()
return
end
if SpellIsTargeting() and button == "LeftButton" then
SpellTargetUnit(unitstr)
elseif CursorHasItem() then
DropItemOnUnit(unitstr)
end
-- right-click opens the standard unit menu (ClassicAPI resolves the type)
if button == "RightButton" then
ClassicAPI_ToggleUnitMenu(unitstr)
return
end
-- drop food on petframe
if label == "pet" and CursorHasItem() then
if UnitClassBase("player") == "HUNTER" then
DropItemOnUnit("pet")
return
end
end
-- default click
TargetUnit(unitstr)
end
function pfUI.uf:EnableScripts() function pfUI.uf:EnableScripts()
local f = self local f = self
if IsAddOnLoaded("Clique") then f:SetScript("OnClick", pfUI.uf.OnClick)
f:SetScript("OnClick", pfUI.uf.OnClick)
else
f:SetAttribute("type1", "target")
f:SetAttribute("type2", "menu")
f:EnableClickCast()
end
f:SetScript("OnShow", pfUI.uf.OnShow) f:SetScript("OnShow", pfUI.uf.OnShow)
f:SetScript("OnEvent", pfUI.uf.OnEvent) f:SetScript("OnEvent", pfUI.uf.OnEvent)
f:SetScript("OnUpdate", pfUI.uf.OnUpdate) f:SetScript("OnUpdate", pfUI.uf.OnUpdate)
f:SetScript("OnEnter", pfUI.uf.OnEnter)
f:SetScript("OnLeave", pfUI.uf.OnLeave)
f:EnableClickCast()
-- add frame to visibility refresh handler -- add frame to visibility refresh handler
visibilityscan.frames[f] = true visibilityscan.frames[f] = true
@@ -1302,7 +1296,7 @@ function pfUI.uf:CreateUnitFrame(unit, id, config, tick)
unit, id = "target", "" unit, id = "target", ""
end end
local f = CreateFrame("Button", "pf" .. fname, UIParent) local f = CreateFrame("Button", "pf" .. fname, UIParent, UNITFRAME_SECURE_TEMPLATE)
-- add unitframe functions -- add unitframe functions
f.UpdateFrameSize = pfUI.uf.UpdateFrameSize f.UpdateFrameSize = pfUI.uf.UpdateFrameSize
@@ -1429,10 +1423,6 @@ function pfUI.uf:CreateUnitFrame(unit, id, config, tick)
f:Hide() f:Hide()
end end
if f.label ~= "" then
f:SetAttribute("unit", f.label .. f.id)
end
-- register frame for clique -- register frame for clique
_G.ClickCastFrames = ClickCastFrames or {} _G.ClickCastFrames = ClickCastFrames or {}
ClickCastFrames[f] = true ClickCastFrames[f] = true
@@ -1487,7 +1477,11 @@ function pfUI.uf:RefreshIndicators(unit)
local unitstr = unit.label .. unit.id local unitstr = unit.label .. unit.id
if unit.leaderIcon then -- Leader Icon if unit.leaderIcon then -- Leader Icon
unit.leaderIcon:SetShown(unit.config.leadericon == "1" and UnitIsPartyLeader(unitstr) and IsInGroup()) if unit.config.leadericon == "1" and UnitIsPartyLeader(unitstr) and IsInGroup() then
unit.leaderIcon:Show()
else
unit.leaderIcon:Hide()
end
end end
if unit.lootIcon then -- Loot Icon if unit.lootIcon then -- Loot Icon
@@ -1497,16 +1491,29 @@ function pfUI.uf:RefreshIndicators(unit)
-- no third return value here.. but leaving this as a hint -- no third return value here.. but leaving this as a hint
local method, group, raid = GetLootMethod() local method, group, raid = GetLootMethod()
local name = group and UnitName(group == 0 and "player" or "party"..group) or raid and UnitName("raid"..raid) or nil local name = group and UnitName(group == 0 and "player" or "party"..group) or raid and UnitName("raid"..raid) or nil
unit.lootIcon:SetShown(name and name == UnitName(unitstr))
if name and name == UnitName(unitstr) then
unit.lootIcon:Show()
else
unit.lootIcon:Hide()
end
end end
end end
if unit.pvpIcon then -- PvP Icon if unit.pvpIcon then -- PvP Icon
unit.pvpIcon:SetShown(unit.config.showPVP == "1" and UnitIsPVP(unitstr)) if unit.config.showPVP == "1" and UnitIsPVP(unitstr) then
unit.pvpIcon:Show()
else
unit.pvpIcon:Hide()
end
end end
if unit.restIcon and unit:GetName() == "pfPlayer" then -- Rest Icon if unit.restIcon and unit:GetName() == "pfPlayer" then -- Rest Icon
unit.restIcon:SetShown(C.unitframes.player.showRest == "1" and UnitIsUnit(unitstr, "player") and IsResting()) if C.unitframes.player.showRest == "1" and UnitIsUnit(unitstr, "player") and IsResting() then
unit.restIcon:Show()
else
unit.restIcon:Hide()
end
end end
if unit.happinessIcon and unit:GetName() == "pfPet" then -- Happiness Icon if unit.happinessIcon and unit:GetName() == "pfPet" then -- Happiness Icon
@@ -1576,7 +1583,7 @@ function pfUI.uf:RefreshUnit(unit, component)
if not unit.hp then return end if not unit.hp then return end
if not unit.power then return end if not unit.power then return end
if not unit.id then unit.id = "" end if not unit.id then unit.id = "" end
component = component or "" local component = component or ""
-- don't update scanner activity -- don't update scanner activity
if unit.label == "target" or unit.label == "targettarget" or unit.label == "targettargettarget" then if unit.label == "target" or unit.label == "targettarget" or unit.label == "targettargettarget" then
@@ -2119,6 +2126,14 @@ function pfUI.uf:RefreshUnit(unit, component)
end end
end end
local buttons = {
[1] = "LeftButton",
[2] = "RightButton",
[3] = "MiddleButton",
[4] = "Button4",
[5] = "Button5",
}
local modifiers = { local modifiers = {
[""] = "", [""] = "",
["alt"] = "_alt", ["alt"] = "_alt",
@@ -2128,31 +2143,86 @@ local modifiers = {
function pfUI.uf:EnableClickCast() function pfUI.uf:EnableClickCast()
if self.config.clickcast ~= "1" then return end if self.config.clickcast ~= "1" then return end
for bid = 1, 5 do -- LeftButton, RightButton, MiddleButton, Button4, Button5 for bid, button in pairs(buttons) do
for modifier, mconf in pairs(modifiers) do for modifier, mconf in pairs(modifiers) do
local bconf = bid == 1 and "" or bid local bconf = bid == 1 and "" or bid
local action = pfUI_config.unitframes["clickcast"..bconf..mconf] if pfUI_config.unitframes["clickcast"..bconf..mconf] ~= "" then
if action and action ~= "" then -- fill clickaction table
local prefix = modifier ~= "" and (modifier .. "-") or "" self.clickactions = self.clickactions or {}
local low = string.lower(action) self.clickactions[modifier..button] = pfUI_config.unitframes["clickcast"..bconf..mconf]
if low == "menu" then
self:SetAttribute(prefix .. "type" .. bid, "menu")
elseif low == "target" then
self:SetAttribute(prefix .. "type" .. bid, "target")
elseif low == "focus" then
self:SetAttribute(prefix .. "type" .. bid, "focus")
elseif string.find(action, "^/") then
self:SetAttribute(prefix .. "type" .. bid, "macro")
self:SetAttribute(prefix .. "macrotext" .. bid, action)
else
self:SetAttribute(prefix .. "type" .. bid, "spell")
self:SetAttribute(prefix .. "spell" .. bid, action)
end
end end
end end
end end
end end
function pfUI.uf:ClickAction(button)
local label = this.label or ""
local id = this.id or ""
local unitstr = label .. id
local showmenu = button == "RightButton" and true or nil
if SpellIsTargeting() and button == "RightButton" then
SpellStopTargeting()
return
end
if SpellIsTargeting() and button == "LeftButton" then
SpellTargetUnit(unitstr)
elseif CursorHasItem() then
DropItemOnUnit(unitstr)
end
-- run click casting if enabled
local modstring = ""
modstring = IsAltKeyDown() and modstring.."alt" or modstring
modstring = IsControlKeyDown() and modstring.."ctrl" or modstring
modstring = IsShiftKeyDown() and modstring.."shift" or modstring
modstring = modstring..button
if this.clickactions and this.clickactions[modstring] then
local action_lower = string.lower(this.clickactions[modstring])
if string.find(action_lower, "^menu") then
-- show menu
showmenu = true
elseif string.find(action_lower, "^target") then
-- target unit
showmenu = nil
else
-- run click cast action
local is_macro = string.find(this.clickactions[modstring], "^%/(.+)")
local tswitch = UnitIsUnit(unitstr, "target")
TargetUnit(unitstr)
if is_macro then
RunMacroText(this.clickactions[modstring])
else
CastSpellByName(this.clickactions[modstring])
end
if not tswitch then TargetLastTarget() end
return
end
end
-- dropdown menus
if showmenu then
pfUI.uf:RightClickAction(label)
return
end
-- drop food on petframe
if label == "pet" and CursorHasItem() then
local playerClass = UnitClassBase("player")
if playerClass == "HUNTER" then
DropItemOnUnit("pet")
return
end
end
-- default click
TargetUnit(unitstr)
end
function pfUI.uf:AddIcon(frame, pos, icon, timeleft, stacks, start, duration) function pfUI.uf:AddIcon(frame, pos, icon, timeleft, stacks, start, duration)
local showtime = frame.config.indicator_time == "1" and true or nil local showtime = frame.config.indicator_time == "1" and true or nil
local showstacks = frame.config.indicator_stacks == "1" and true or nil local showstacks = frame.config.indicator_stacks == "1" and true or nil
+1
View File
@@ -25,6 +25,7 @@ PLAYER_BUFF_START_ID = -1
ACTIONBAR_SECURE_TEMPLATE_BAR = nil ACTIONBAR_SECURE_TEMPLATE_BAR = nil
ACTIONBAR_SECURE_TEMPLATE_BUTTON = nil ACTIONBAR_SECURE_TEMPLATE_BUTTON = nil
UNITFRAME_SECURE_TEMPLATE = nil
--[[ Vanilla API Extensions ]]-- --[[ Vanilla API Extensions ]]--
-1
View File
@@ -71,7 +71,6 @@
<Include file="..\modules\energytick.lua"/> <Include file="..\modules\energytick.lua"/>
<Include file="..\modules\totems.lua"/> <Include file="..\modules\totems.lua"/>
<Include file="..\modules\macrotweak.lua"/> <Include file="..\modules\macrotweak.lua"/>
<Include file="..\modules\macroicons.lua"/>
<Include file="..\modules\turtle-wow.lua"/> <Include file="..\modules\turtle-wow.lua"/>
<Include file="..\modules\superwow.lua"/> <Include file="..\modules\superwow.lua"/>
<Include file="..\modules\innervatecall.lua"/> <Include file="..\modules\innervatecall.lua"/>
+51 -35
View File
@@ -600,17 +600,17 @@ pfUI:RegisterModule("actionbar", function ()
-- update usable [out-of-range = 1, oom = 2, not-usable = 3, default = 0] -- update usable [out-of-range = 1, oom = 2, not-usable = 3, default = 0]
if self.outofrange and C.bars.glowrange == "1" then if self.outofrange and C.bars.glowrange == "1" then
if self.vertexstate ~= 1 then if self.vertexstate ~= 1 then
self.icon:SetVertexColor(self.rangeColor:GetRGBA()) self.icon:SetVertexColor(self.rangeColor[1], self.rangeColor[2], self.rangeColor[3], self.rangeColor[4])
self.vertexstate = 1 self.vertexstate = 1
end end
elseif oom and C.bars.showoom == "1" then elseif oom and C.bars.showoom == "1" then
if self.vertexstate ~= 2 then if self.vertexstate ~= 2 then
self.icon:SetVertexColor(self.oomColor:GetRGBA()) self.icon:SetVertexColor(self.oomColor[1], self.oomColor[2], self.oomColor[3], self.oomColor[4])
self.vertexstate = 2 self.vertexstate = 2
end end
elseif not usable and C.bars.showna == "1" then elseif not usable and C.bars.showna == "1" then
if self.vertexstate ~= 3 then if self.vertexstate ~= 3 then
self.icon:SetVertexColor(self.naColor:GetRGBA()) self.icon:SetVertexColor(self.naColor[1], self.naColor[2], self.naColor[3], self.naColor[4])
self.vertexstate = 3 self.vertexstate = 3
end end
else else
@@ -992,13 +992,13 @@ pfUI:RegisterModule("actionbar", function ()
local font_offset = tonumber(C.bars.font_offset) local font_offset = tonumber(C.bars.font_offset)
local macro_size = tonumber(C.bars.macro_size) local macro_size = tonumber(C.bars.macro_size)
local macro_color = { GetStringColor(C.bars.macro_color) } local macro_color = { strsplit(",", C.bars.macro_color) }
local count_size = tonumber(C.bars.count_size) local count_size = tonumber(C.bars.count_size)
local count_color = { GetStringColor(C.bars.count_color) } local count_color = { strsplit(",", C.bars.count_color) }
local bind_size = tonumber(C.bars.bind_size) local bind_size = tonumber(C.bars.bind_size)
local bind_color = { GetStringColor(C.bars.bind_color) } local bind_color = { strsplit(",", C.bars.bind_color) }
local cd_size = tonumber(C.bars.cd_size) local cd_size = tonumber(C.bars.cd_size)
@@ -1157,17 +1157,17 @@ pfUI:RegisterModule("actionbar", function ()
end end
-- range glow color -- range glow color
f.rangeColor = GetStringColorObject(C.bars.rangecolor) f.rangeColor = { strsplit(",", C.bars.rangecolor) }
-- out of mana color -- out of mana color
f.oomColor = GetStringColorObject(C.bars.oomcolor) f.oomColor = { strsplit(",", C.bars.oomcolor) }
-- not usable color -- not usable color
f.naColor = GetStringColorObject(C.bars.nacolor) f.naColor = { strsplit(",", C.bars.nacolor) }
-- equipped color -- equipped color
if f.equipped then if f.equipped then
f.equipped:SetTexture(GetStringColor(C.bars.eqcolor)) f.equipped:SetTexture(strsplit(",", C.bars.eqcolor))
end end
-- general appearance -- general appearance
@@ -1546,7 +1546,7 @@ pfUI:RegisterModule("actionbar", function ()
-- via GetActionInfo + C_Spell.GetSpellReagents. Macro actions and -- via GetActionInfo + C_Spell.GetSpellReagents. Macro actions and
-- bag-item actions are skipped (their reagent resolution would need a -- bag-item actions are skipped (their reagent resolution would need a
-- macro-body parse / item-effect lookup that we don't bother with). -- macro-body parse / item-effect lookup that we don't bother with).
local function UpdateSlot(slot) local UpdateSlot = function(slot)
local newID = nil local newID = nil
if HasAction(slot) then if HasAction(slot) then
local kind, spellID = GetActionInfo(slot) local kind, spellID = GetActionInfo(slot)
@@ -1561,44 +1561,60 @@ pfUI:RegisterModule("actionbar", function ()
if reagent_slots[slot] ~= newID then if reagent_slots[slot] ~= newID then
reagent_slots[slot] = newID reagent_slots[slot] = newID
if newID then if newID then
reagent_counts[newID] = reagent_counts[newID] or C_Item.GetItemCount(newID) reagent_counts[newID] = reagent_counts[newID] or 0
end end
updatecache[slot] = true updatecache[slot] = true
end end
end end
-- Recount every tracked reagent and flag its buttons for a refresh.
local RecountReagents = function()
for itemID in pairs(reagent_counts) do
reagent_counts[itemID] = C_Item.GetItemCount(itemID)
end
for slot in pairs(reagent_slots) do
updatecache[slot] = true
end
end
local reagentcounter = CreateFrame("Frame", "pfReagentCounter", UIParent) local reagentcounter = CreateFrame("Frame", "pfReagentCounter", UIParent)
reagentcounter:RegisterEvent("PLAYER_ENTERING_WORLD") reagentcounter:RegisterEvent("PLAYER_ENTERING_WORLD")
reagentcounter:RegisterEvent("ACTIONBAR_SLOT_CHANGED") reagentcounter:RegisterEvent("ACTIONBAR_SLOT_CHANGED")
reagentcounter:RegisterEvent("BAG_UPDATE_DELAYED") reagentcounter:RegisterEvent("BAG_UPDATE_DELAYED")
reagentcounter:SetScript("OnEvent", function() reagentcounter:SetScript("OnEvent", function()
if event == "ACTIONBAR_SLOT_CHANGED" then if event == "BAG_UPDATE_DELAYED" then
-- arg1 is the changed slot; 0 (or nil) means "all slots" this.event = true
if arg1 and arg1 > 0 then
UpdateSlot(arg1)
else
for slot = 1, 120 do UpdateSlot(slot) end
end
elseif event == "BAG_UPDATE_DELAYED" then
-- inventory changed: refresh the counts we already track
RecountReagents()
else else
-- PLAYER_ENTERING_WORLD: seed the full reagent map (UpdateSlot seeds this.scan = 1
-- each new reagent's count; a BAG_UPDATE_DELAYED follows during login)
for slot = 1, 120 do UpdateSlot(slot) end
end end
end) end)
-- Reagent counter update with throttle for performance optimization
reagentcounter:SetScript("OnUpdate", function()
-- Throttle entire function to 10 FPS for smooth scanning
if (this.tick_update or 0) > GetTime() then return end
this.tick_update = GetTime() + 0.1
-- scan one action slot per update
if this.scan and this.scan <= 120 then
UpdateSlot(this.scan)
this.scan = this.scan + 1
end
-- trigger reagent count updates after action scans
if this.scan and this.scan >= 120 then
this.event = true
this.scan = nil
end
-- queue events to fire only once per second
if not this.event then return end
if ( this.tick or 1) > GetTime() then return else this.tick = GetTime() + 1 end
-- scan for all reagent item counts
for itemID in pairs(reagent_counts) do
reagent_counts[itemID] = C_Item.GetItemCount(itemID)
end
-- update all actionbar buttons
for slot in pairs(reagent_slots) do
updatecache[slot] = true
end
-- remove event trigger
this.event = nil
end)
function IsReagentAction(slot) function IsReagentAction(slot)
return reagent_slots[slot] and true or nil return reagent_slots[slot] and true or nil
end end
+13 -16
View File
@@ -397,25 +397,22 @@ pfUI:RegisterModule("addonbuttons", function ()
pfUI.addonbuttons:ProcessButtons() pfUI.addonbuttons:ProcessButtons()
end) end)
-- Initial setup on the next frame, once other addons' minimap buttons exist pfUI.addonbuttons:SetScript("OnUpdate", function()
RunNextFrame(function()
-- check if the panel should be shown by default -- check if the panel should be shown by default
if C.abuttons.showdefault == "1" and GetNumButtons() > 0 then if not this.initialized then
pfUI.addonbuttons:Show() if C.abuttons.showdefault == "1" and GetNumButtons() > 0 then
else pfUI.addonbuttons:Show()
pfUI.addonbuttons:Hide() else
pfUI.addonbuttons:Hide()
end
-- update all buttons
pfUI.addonbuttons:ProcessButtons()
this.initialized = true
end end
-- update all buttons and apply workarounds -- throttle updates to once per 5 seconds
pfUI.addonbuttons:ProcessButtons() if ( this.tick or 1) > GetTime() then return else this.tick = GetTime() + 5 end
for k, v in pairs(pfUI.addonbuttons.overrides) do
_G[k] = v
end
end)
-- Rescan minimap buttons every 5 seconds while the panel is shown
C_Timer.NewTicker(5, function()
if not pfUI.addonbuttons:IsShown() then return end
-- reload/rescan minimap buttons -- reload/rescan minimap buttons
pfUI.addonbuttons:ProcessButtons() pfUI.addonbuttons:ProcessButtons()
+8 -2
View File
@@ -138,10 +138,16 @@ pfUI:RegisterModule("buff", function ()
end end
end) end)
buff:SetScript("OnLeave", GameTooltip_Hide) buff:SetScript("OnLeave", function()
GameTooltip:Hide()
end)
buff:SetScript("OnClick", function() buff:SetScript("OnClick", function()
if this.spellId then if CancelItemTempEnchantment and this.mode and this.mode == "MAINHAND" then
CancelItemTempEnchantment(1)
elseif CancelItemTempEnchantment and this.mode and this.mode == "OFFHAND" then
CancelItemTempEnchantment(2)
elseif this.spellId then
C_Spell.CancelSpellByID(this.spellId) C_Spell.CancelSpellByID(this.spellId)
end end
end) end)
+7 -7
View File
@@ -82,10 +82,10 @@ pfUI:RegisterModule("chat", function ()
end end
if C.chat.global.custombg == "1" then if C.chat.global.custombg == "1" then
local r, g, b, a = GetStringColor(C.chat.global.background) local r, g, b, a = strsplit(",", C.chat.global.background)
pfUI.chat.left.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) pfUI.chat.left.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
local r, g, b, a = GetStringColor(C.chat.global.border) local r, g, b, a = strsplit(",", C.chat.global.border)
pfUI.chat.left.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) pfUI.chat.left.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
end end
@@ -257,10 +257,10 @@ pfUI:RegisterModule("chat", function ()
end end
if C.chat.global.custombg == "1" then if C.chat.global.custombg == "1" then
local r, g, b, a = GetStringColor(C.chat.global.background) local r, g, b, a = strsplit(",", C.chat.global.background)
pfUI.chat.right.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) pfUI.chat.right.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
local r, g, b, a = GetStringColor(C.chat.global.border) local r, g, b, a = strsplit(",", C.chat.global.border)
pfUI.chat.right.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) pfUI.chat.right.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
end end
@@ -675,7 +675,7 @@ pfUI:RegisterModule("chat", function ()
end end
-- read and parse whisper color settings -- read and parse whisper color settings
local cr, cg, cb, ca = GetStringColor(C.chat.global.whisper) local cr, cg, cb, ca = strsplit(",", C.chat.global.whisper)
cr, cg, cb = tonumber(cr), tonumber(cg), tonumber(cb) cr, cg, cb = tonumber(cr), tonumber(cg), tonumber(cb)
local wcol = rgbhex(cr, cg, cb) local wcol = rgbhex(cr, cg, cb)
@@ -706,10 +706,10 @@ pfUI:RegisterModule("chat", function ()
_G.CHAT_WHISPER_INFORM_GET = '[W]' .. default _G.CHAT_WHISPER_INFORM_GET = '[W]' .. default
end end
local r,g,b,a = GetStringColor(C.chat.text.timecolor) local r,g,b,a = strsplit(",", C.chat.text.timecolor)
local timecolorhex = rgbhex(r,g,b,a) local timecolorhex = rgbhex(r,g,b,a)
local r,g,b = GetStringColor(C.chat.text.unknowncolor) local r,g,b = strsplit(",", C.chat.text.unknowncolor)
local unknowncolorhex = rgbhex(r,g,b) local unknowncolorhex = rgbhex(r,g,b)
-- Suppress FriendsFrame's WHO_LIST_UPDATE handling for our DLL-issued -- Suppress FriendsFrame's WHO_LIST_UPDATE handling for our DLL-issued
+5 -5
View File
@@ -1,10 +1,10 @@
pfUI:RegisterModule("cooldown", function () pfUI:RegisterModule("cooldown", function ()
-- cache values -- cache values
-- local lowcolor = {strsplit(",", C.appearance.cd.lowcolor)} local lowcolor = {strsplit(",", C.appearance.cd.lowcolor)}
-- local normalcolor = {strsplit(",", C.appearance.cd.normalcolor)} local normalcolor = {strsplit(",", C.appearance.cd.normalcolor)}
-- local minutecolor = {strsplit(",", C.appearance.cd.minutecolor)} local minutecolor = {strsplit(",", C.appearance.cd.minutecolor)}
-- local hourcolor = {strsplit(",", C.appearance.cd.hourcolor)} local hourcolor = {strsplit(",", C.appearance.cd.hourcolor)}
-- local daycolor = {strsplit(",", C.appearance.cd.daycolor)} local daycolor = {strsplit(",", C.appearance.cd.daycolor)}
local parent, parent_name local parent, parent_name
local function pfCooldownOnUpdate() local function pfCooldownOnUpdate()
+268 -70
View File
@@ -1,10 +1,11 @@
-- Equipment Manager module -- Equipment Manager module
-- Backport of the 4.3.4 GearManagerDialog UI on top of ClassicAPI's C_EquipmentSet.* API. -- Backport of the 4.3.4 GearManagerDialog UI on top of ClassicAPI's
-- C_EquipmentSet.* API. Adds a 6th tab to CharacterFrame.
pfUI:RegisterModule("equipmentmanager", function() pfUI:RegisterModule("equipmentmanager", function()
if not C_EquipmentSet or not C_EquipmentSet.CanUseEquipmentSets() then return end if not C_EquipmentSet or not C_EquipmentSet.CanUseEquipmentSets() then return end
pfUI.equipmentmanager = {} pfUI.equipmentmanager = pfUI.equipmentmanager or {}
local SET_ROW_HEIGHT = 36 local SET_ROW_HEIGHT = 36
@@ -54,7 +55,7 @@ pfUI:RegisterModule("equipmentmanager", function()
local function EquipSet(setID) local function EquipSet(setID)
if not setID then return end if not setID then return end
if C_EquipmentSet.EquipmentSetContainsLockedItems(setID) then if C_EquipmentSet.EquipmentSetContainsLockedItems(setID) then
UIErrorsFrame:AddMessage(ERR_CLIENT_LOCKED_OUT, 1, .1, .1, 1) UIErrorsFrame:AddMessage(ERR_CLIENT_LOCKED_OUT or "Locked items in set", 1, .1, .1, 1)
return return
end end
ClearCursor() ClearCursor()
@@ -67,7 +68,8 @@ pfUI:RegisterModule("equipmentmanager", function()
-- ============================================================ -- ============================================================
local frame = CreateFrame("Frame", "pfEquipmentManagerFrame", CharacterFrame) local frame = CreateFrame("Frame", "pfEquipmentManagerFrame", CharacterFrame)
frame:SetSize(220, 350) frame:SetWidth(220)
frame:SetHeight(350)
frame:SetFrameStrata("HIGH") frame:SetFrameStrata("HIGH")
frame:SetScript("OnShow", function() frame:SetScript("OnShow", function()
this:ClearAllPoints() this:ClearAllPoints()
@@ -84,7 +86,7 @@ pfUI:RegisterModule("equipmentmanager", function()
frame.title = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal") frame.title = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
frame.title:SetPoint("TOP", frame, "TOP", 0, -10) frame.title:SetPoint("TOP", frame, "TOP", 0, -10)
frame.title:SetText(EQUIPMENT_MANAGER) frame.title:SetText(T["Equipment Manager"] or "Equipment Manager")
local closeBtn = CreateFrame("Button", nil, frame, "UIPanelCloseButton") local closeBtn = CreateFrame("Button", nil, frame, "UIPanelCloseButton")
closeBtn:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -4, -4) closeBtn:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -4, -4)
@@ -96,14 +98,15 @@ pfUI:RegisterModule("equipmentmanager", function()
-- ============================================================ -- ============================================================
local toggleBtn = CreateFrame("Button", "pfEqMgrToggleButton", PaperDollFrame) local toggleBtn = CreateFrame("Button", "pfEqMgrToggleButton", PaperDollFrame)
toggleBtn:SetSize(28, 28) toggleBtn:SetWidth(28)
toggleBtn:SetHeight(28)
toggleBtn:SetPoint("BOTTOM", CharacterHandsSlot, "TOP", 0, 4) toggleBtn:SetPoint("BOTTOM", CharacterHandsSlot, "TOP", 0, 4)
toggleBtn:SetNormalTexture(pfUI.path.."\\img\\UI-GearManager-Button") toggleBtn:SetNormalTexture(pfUI.path.."\\img\\UI-GearManager-Button")
toggleBtn:SetPushedTexture(pfUI.path.."\\img\\UI-GearManager-Button-Pushed") toggleBtn:SetPushedTexture(pfUI.path.."\\img\\UI-GearManager-Button-Pushed")
toggleBtn:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square", "ADD") toggleBtn:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square", "ADD")
toggleBtn:SetScript("OnEnter", function() toggleBtn:SetScript("OnEnter", function()
GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetText(PAPERDOLL_EQUIPMENTMANAGER) GameTooltip:SetText(T["Equipment Manager"] or "Equipment Manager")
GameTooltip:Show() GameTooltip:Show()
end) end)
toggleBtn:SetScript("OnLeave", function() GameTooltip:Hide() end) toggleBtn:SetScript("OnLeave", function() GameTooltip:Hide() end)
@@ -123,13 +126,13 @@ pfUI:RegisterModule("equipmentmanager", function()
-- ============================================================ -- ============================================================
local btnEquip = CreateFrame("Button", "pfEqMgrEquip", frame, "UIPanelButtonTemplate") local btnEquip = CreateFrame("Button", "pfEqMgrEquip", frame, "UIPanelButtonTemplate")
btnEquip:SetSize(86, 22); btnEquip:SetText(EQUIPSET_EQUIP) btnEquip:SetWidth(86); btnEquip:SetHeight(22); btnEquip:SetText(T["Equip"] or "Equip")
btnEquip:SetPoint("TOPLEFT", frame, "TOPLEFT", 16, -30) btnEquip:SetPoint("TOPLEFT", frame, "TOPLEFT", 16, -30)
SkinButton(btnEquip) SkinButton(btnEquip)
btnEquip:SetScript("OnClick", function() EquipSet(selectedSetID) end) btnEquip:SetScript("OnClick", function() EquipSet(selectedSetID) end)
local btnSave = CreateFrame("Button", "pfEqMgrSave", frame, "UIPanelButtonTemplate") local btnSave = CreateFrame("Button", "pfEqMgrSave", frame, "UIPanelButtonTemplate")
btnSave:SetSize(86, 22); btnSave:SetText(SAVE) btnSave:SetWidth(86); btnSave:SetHeight(22); btnSave:SetText(T["Save"] or "Save")
btnSave:SetPoint("LEFT", btnEquip, "RIGHT", 6, 0) btnSave:SetPoint("LEFT", btnEquip, "RIGHT", 6, 0)
SkinButton(btnSave) SkinButton(btnSave)
btnSave:SetScript("OnClick", function() btnSave:SetScript("OnClick", function()
@@ -138,7 +141,7 @@ pfUI:RegisterModule("equipmentmanager", function()
if not name then return end if not name then return end
local targetID = selectedSetID local targetID = selectedSetID
StaticPopupDialogs["PFUI_EQMGR_SAVE_CONFIRM"] = { StaticPopupDialogs["PFUI_EQMGR_SAVE_CONFIRM"] = {
text = string.format(CONFIRM_SAVE_EQUIPMENT_SET, name), text = string.format(T["Would you like to save the equipment set '%s'?"] or "Would you like to save the equipment set '%s'?", name),
button1 = YES, button2 = NO, button1 = YES, button2 = NO,
OnAccept = function() OnAccept = function()
C_EquipmentSet.ClearIgnoredSlotsForSave() C_EquipmentSet.ClearIgnoredSlotsForSave()
@@ -163,7 +166,7 @@ pfUI:RegisterModule("equipmentmanager", function()
local rowMenu = CreateFrame("Frame", "pfEqMgrRowMenu", UIParent) local rowMenu = CreateFrame("Frame", "pfEqMgrRowMenu", UIParent)
rowMenu:SetFrameStrata("DIALOG") rowMenu:SetFrameStrata("DIALOG")
rowMenu:SetSize(140, 50); rowMenu:SetWidth(140); rowMenu:SetHeight(50)
rowMenu:Hide() rowMenu:Hide()
CreateBackdrop(rowMenu, nil, nil, .95) CreateBackdrop(rowMenu, nil, nil, .95)
CreateBackdropShadow(rowMenu) CreateBackdropShadow(rowMenu)
@@ -182,9 +185,9 @@ pfUI:RegisterModule("equipmentmanager", function()
tinsert(UISpecialFrames, "pfEqMgrRowMenu") -- Escape closes it tinsert(UISpecialFrames, "pfEqMgrRowMenu") -- Escape closes it
rowMenu.changeBtn = CreateFrame("Button", nil, rowMenu, "UIPanelButtonTemplate") rowMenu.changeBtn = CreateFrame("Button", nil, rowMenu, "UIPanelButtonTemplate")
rowMenu.changeBtn:SetSize(130, 20); rowMenu.changeBtn:SetWidth(130); rowMenu.changeBtn:SetHeight(20)
rowMenu.changeBtn:SetPoint("TOPLEFT", rowMenu, "TOPLEFT", 5, -3) rowMenu.changeBtn:SetPoint("TOPLEFT", rowMenu, "TOPLEFT", 5, -3)
rowMenu.changeBtn:SetText(EQUIPMENT_SET_EDIT) rowMenu.changeBtn:SetText(T["Change Name/Icon"] or "Change Name/Icon")
SkinButton(rowMenu.changeBtn) SkinButton(rowMenu.changeBtn)
rowMenu.changeBtn:SetScript("OnClick", function() rowMenu.changeBtn:SetScript("OnClick", function()
rowMenu:Hide() rowMenu:Hide()
@@ -195,9 +198,9 @@ pfUI:RegisterModule("equipmentmanager", function()
end) end)
rowMenu.deleteBtn = CreateFrame("Button", nil, rowMenu, "UIPanelButtonTemplate") rowMenu.deleteBtn = CreateFrame("Button", nil, rowMenu, "UIPanelButtonTemplate")
rowMenu.deleteBtn:SetSize(130, 20); rowMenu.deleteBtn:SetWidth(130); rowMenu.deleteBtn:SetHeight(20)
rowMenu.deleteBtn:SetPoint("TOP", rowMenu.changeBtn, "BOTTOM", 0, -2) rowMenu.deleteBtn:SetPoint("TOP", rowMenu.changeBtn, "BOTTOM", 0, -2)
rowMenu.deleteBtn:SetText(DELETE) rowMenu.deleteBtn:SetText(T["Delete"] or "Delete")
SkinButton(rowMenu.deleteBtn) SkinButton(rowMenu.deleteBtn)
rowMenu.deleteBtn:SetScript("OnClick", function() rowMenu.deleteBtn:SetScript("OnClick", function()
rowMenu:Hide() rowMenu:Hide()
@@ -205,7 +208,7 @@ pfUI:RegisterModule("equipmentmanager", function()
local targetID = rowMenu.targetSetID local targetID = rowMenu.targetSetID
local name = C_EquipmentSet.GetEquipmentSetInfo(targetID) local name = C_EquipmentSet.GetEquipmentSetInfo(targetID)
StaticPopupDialogs["PFUI_EQMGR_DELETE"] = { StaticPopupDialogs["PFUI_EQMGR_DELETE"] = {
text = string.format(CONFIRM_DELETE_EQUIPMENT_SET, name or "?"), text = string.format(T["Delete equipment set '%s'?"] or "Delete equipment set '%s'?", name or "?"),
button1 = YES, button2 = NO, button1 = YES, button2 = NO,
OnAccept = function() OnAccept = function()
pendingIgnoredToggles[targetID] = nil pendingIgnoredToggles[targetID] = nil
@@ -226,8 +229,9 @@ pfUI:RegisterModule("equipmentmanager", function()
local LIST_ROW_STRIDE = SET_ROW_HEIGHT + 2 local LIST_ROW_STRIDE = SET_ROW_HEIGHT + 2
local listFrame = CreateFrame("Frame", nil, frame) local listFrame = CreateFrame("Frame", nil, frame)
listFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 16, -58) listFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 16, -58)
listFrame:SetWidth(180)
-- Height fits N rows + (N-1) inter-row gaps + 3px top/bottom padding. -- Height fits N rows + (N-1) inter-row gaps + 3px top/bottom padding.
listFrame:SetSize(180, LIST_VISIBLE_ROWS * LIST_ROW_STRIDE + 4) listFrame:SetHeight(LIST_VISIBLE_ROWS * LIST_ROW_STRIDE + 4)
CreateBackdrop(listFrame, nil, nil, .75) CreateBackdrop(listFrame, nil, nil, .75)
-- Mouse-wheel scroll: list of [sets..., newSetRow] is virtualized -- Mouse-wheel scroll: list of [sets..., newSetRow] is virtualized
@@ -243,13 +247,15 @@ pfUI:RegisterModule("equipmentmanager", function()
local setRows = {} local setRows = {}
local function CreateSetRow() local function CreateSetRow()
local row = CreateFrame("Button", nil, listFrame) local row = CreateFrame("Button", nil, listFrame)
row:SetSize(170, SET_ROW_HEIGHT) row:SetWidth(170)
row:SetHeight(SET_ROW_HEIGHT)
-- Position is set per-Refresh based on the row's visible slot; -- Position is set per-Refresh based on the row's visible slot;
-- start anchored to avoid uninitialized geometry before first Refresh. -- start anchored to avoid uninitialized geometry before first Refresh.
row:SetPoint("TOPLEFT", listFrame, "TOPLEFT", 5, -3) row:SetPoint("TOPLEFT", listFrame, "TOPLEFT", 5, -3)
row.icon = row:CreateTexture(nil, "ARTWORK") row.icon = row:CreateTexture(nil, "ARTWORK")
row.icon:SetSize(30, 30) row.icon:SetWidth(30)
row.icon:SetHeight(30)
row.icon:SetPoint("LEFT", row, "LEFT", 2, 0) row.icon:SetPoint("LEFT", row, "LEFT", 2, 0)
row.icon:SetTexCoord(.08, .92, .08, .92) row.icon:SetTexCoord(.08, .92, .08, .92)
@@ -264,7 +270,7 @@ pfUI:RegisterModule("equipmentmanager", function()
row.highlight:Hide() row.highlight:Hide()
row.gear = CreateFrame("Button", nil, row) row.gear = CreateFrame("Button", nil, row)
row.gear:SetSize(16, 16); row.gear:SetWidth(16); row.gear:SetHeight(16)
row.gear:SetPoint("RIGHT", row, "RIGHT", -4, 0) row.gear:SetPoint("RIGHT", row, "RIGHT", -4, 0)
row.gear.tex = row.gear:CreateTexture(nil, "ARTWORK") row.gear.tex = row.gear:CreateTexture(nil, "ARTWORK")
row.gear.tex:SetAllPoints(row.gear) row.gear.tex:SetAllPoints(row.gear)
@@ -300,27 +306,27 @@ pfUI:RegisterModule("equipmentmanager", function()
pfUI.equipmentmanager.Refresh() pfUI.equipmentmanager.Refresh()
end) end)
-- Show the gear and tooltip while the cursor is over the row or its -- Hover handling: OnLeave fires when the cursor moves onto a child
-- gear child. The gear sits inside the row's rectangle, so a single -- (the gear button becomes the topmost mouse target). Use an
-- MouseIsOver(row) check covers both. OnLeave on the row and the gear -- OnUpdate poll so the gear stays shown while the cursor is over
-- catches every exit path, so no OnUpdate poll is needed. -- the row OR the gear itself.
local function HideRowHover()
if MouseIsOver(row) then return end
GameTooltip:Hide()
row.gear:Hide()
end
row:SetScript("OnEnter", function() row:SetScript("OnEnter", function()
if not row.setID then return end if not this.setID then return end
local name = C_EquipmentSet.GetEquipmentSetInfo(row.setID) local name = C_EquipmentSet.GetEquipmentSetInfo(this.setID)
if name then if name then
GameTooltip:SetOwner(row, "ANCHOR_RIGHT") GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetEquipmentSet(name) GameTooltip:SetEquipmentSet(name)
GameTooltip:Show() GameTooltip:Show()
end end
row.gear:Show() row.gear:Show()
this:SetScript("OnUpdate", function()
if not MouseIsOver(this) and not MouseIsOver(row.gear) then
this:SetScript("OnUpdate", nil)
GameTooltip:Hide()
row.gear:Hide()
end
end)
end) end)
row:SetScript("OnLeave", HideRowHover)
row.gear:SetScript("OnLeave", HideRowHover)
return row return row
end end
@@ -332,10 +338,10 @@ pfUI:RegisterModule("equipmentmanager", function()
-- specific set index (row[i] always shows ids[i]). -- specific set index (row[i] always shows ids[i]).
local newSetRow = CreateFrame("Button", nil, listFrame) local newSetRow = CreateFrame("Button", nil, listFrame)
newSetRow:SetSize(170, SET_ROW_HEIGHT); newSetRow:SetWidth(170); newSetRow:SetHeight(SET_ROW_HEIGHT)
newSetRow.icon = newSetRow:CreateTexture(nil, "ARTWORK") newSetRow.icon = newSetRow:CreateTexture(nil, "ARTWORK")
newSetRow.icon:SetSize(24, 24); newSetRow.icon:SetWidth(24); newSetRow.icon:SetHeight(24)
newSetRow.icon:SetPoint("LEFT", newSetRow, "LEFT", 5, 0) newSetRow.icon:SetPoint("LEFT", newSetRow, "LEFT", 5, 0)
newSetRow.icon:SetTexture(pfUI.path.."\\img\\Character-Plus") newSetRow.icon:SetTexture(pfUI.path.."\\img\\Character-Plus")
@@ -343,7 +349,7 @@ pfUI:RegisterModule("equipmentmanager", function()
newSetRow.text:SetPoint("LEFT", newSetRow.icon, "RIGHT", 8, 0) newSetRow.text:SetPoint("LEFT", newSetRow.icon, "RIGHT", 8, 0)
newSetRow.text:SetPoint("RIGHT", newSetRow, "RIGHT", -4, 0) newSetRow.text:SetPoint("RIGHT", newSetRow, "RIGHT", -4, 0)
newSetRow.text:SetJustifyH("LEFT") newSetRow.text:SetJustifyH("LEFT")
newSetRow.text:SetText(PAPERDOLL_NEWEQUIPMENTSET) newSetRow.text:SetText(T["New Set"] or "New Set")
newSetRow.text:SetTextColor(0.2, 1, 0.2) newSetRow.text:SetTextColor(0.2, 1, 0.2)
newSetRow.highlight = newSetRow:CreateTexture(nil, "BACKGROUND") newSetRow.highlight = newSetRow:CreateTexture(nil, "BACKGROUND")
@@ -356,7 +362,8 @@ pfUI:RegisterModule("equipmentmanager", function()
local function MakeButton(name, label, parent, anchor, ax, ay, width) local function MakeButton(name, label, parent, anchor, ax, ay, width)
local b = CreateFrame("Button", name, parent, "UIPanelButtonTemplate") local b = CreateFrame("Button", name, parent, "UIPanelButtonTemplate")
b:SetSize(width or 70, 22) b:SetWidth(width or 70)
b:SetHeight(22)
b:SetText(label) b:SetText(label)
b:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", ax, ay) b:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", ax, ay)
SkinButton(b) SkinButton(b)
@@ -369,7 +376,8 @@ pfUI:RegisterModule("equipmentmanager", function()
local namePopup = CreateFrame("Frame", "pfEqMgrNamePopup", UIParent) local namePopup = CreateFrame("Frame", "pfEqMgrNamePopup", UIParent)
namePopup:SetFrameStrata("DIALOG") namePopup:SetFrameStrata("DIALOG")
namePopup:SetSize(472, 484) namePopup:SetWidth(472)
namePopup:SetHeight(498)
namePopup:SetPoint("CENTER", UIParent, "CENTER") namePopup:SetPoint("CENTER", UIParent, "CENTER")
namePopup:Hide() namePopup:Hide()
CreateBackdrop(namePopup, nil, nil, .9) CreateBackdrop(namePopup, nil, nil, .9)
@@ -380,28 +388,200 @@ pfUI:RegisterModule("equipmentmanager", function()
namePopup:SetScript("OnDragStart", function() this:StartMoving() end) namePopup:SetScript("OnDragStart", function() this:StartMoving() end)
namePopup:SetScript("OnDragStop", function() this:StopMovingOrSizing() end) namePopup:SetScript("OnDragStop", function() this:StopMovingOrSizing() end)
-- Equipment seed leads the grid with gear-relevant item icons. The widget namePopup.title = namePopup:CreateFontString(nil, "OVERLAY", "GameFontNormal")
-- owns the name field, preview, grid, filter, and search; this module keeps namePopup.title:SetPoint("TOP", namePopup, "TOP", 0, -10)
-- the OK/Cancel buttons and the create/save/rename flow below. namePopup.title:SetText(T["Save Set"] or "Save Set")
local iconPicker = CreateIconPicker("pfEqMgrIcon", namePopup,
IconDataProviderExtraType.Equipment, GEARSETS_POPUP_TEXT)
local btnPopupOK = MakeButton("pfEqMgrPopupOK", OKAY, namePopup, namePopup, 14, -340, 80) namePopup.nameLabel = namePopup:CreateFontString(nil, "OVERLAY", "GameFontNormal")
namePopup.nameLabel:SetPoint("TOPLEFT", namePopup, "TOPLEFT", 14, -34)
namePopup.nameLabel:SetText(T["Enter Set Name (Max 16 Characters):"] or "Enter Set Name (Max 16 Characters):")
local btnPopupCancel = MakeButton("pfEqMgrPopupCancel", CANCEL, namePopup, namePopup, 0, 0, 80) namePopup.editbox = CreateFrame("EditBox", "pfEqMgrNameEdit", namePopup, "InputBoxTemplate")
namePopup.editbox:SetWidth(280)
namePopup.editbox:SetHeight(20)
namePopup.editbox:SetPoint("TOPLEFT", namePopup, "TOPLEFT", 14, -52)
namePopup.editbox:SetAutoFocus(false)
namePopup.editbox:SetMaxLetters(16)
CreateBackdrop(namePopup.editbox)
namePopup.selectedLabel = namePopup:CreateFontString(nil, "OVERLAY", "GameFontNormal")
namePopup.selectedLabel:SetPoint("TOPRIGHT", namePopup, "TOPRIGHT", -14, -28)
namePopup.selectedLabel:SetText(T["Currently Selected"] or "Currently Selected")
namePopup.selectedLabel:SetTextColor(1, 0.82, 0)
namePopup.selectedPreview = CreateFrame("Frame", nil, namePopup)
namePopup.selectedPreview:SetWidth(42)
namePopup.selectedPreview:SetHeight(42)
namePopup.selectedPreview:SetPoint("TOPRIGHT", namePopup, "TOPRIGHT", -14, -44)
CreateBackdrop(namePopup.selectedPreview)
namePopup.selectedPreview.tex = namePopup.selectedPreview:CreateTexture(nil, "ARTWORK")
namePopup.selectedPreview.tex:SetAllPoints(namePopup.selectedPreview)
namePopup.selectedPreview.tex:SetTexCoord(.08, .92, .08, .92)
namePopup.iconLabel = namePopup:CreateFontString(nil, "OVERLAY", "GameFontNormal")
namePopup.iconLabel:SetPoint("TOPLEFT", namePopup, "TOPLEFT", 14, -100)
namePopup.iconLabel:SetText(T["Choose an Icon:"] or "Choose an Icon:")
-- Icon picker: 10×8 grid of buttons + scroll
local ICON_GRID_COLS = 10
local ICON_GRID_ROWS = 8
local ICON_BTN_SIZE = 36
local ICON_BTN_PAD = 6
local iconScroll = CreateFrame("ScrollFrame", "pfEqMgrIconScroll", namePopup, "FauxScrollFrameTemplate")
iconScroll:SetPoint("TOPLEFT", namePopup, "TOPLEFT", 14, -130)
iconScroll:SetWidth(ICON_GRID_COLS * (ICON_BTN_SIZE + ICON_BTN_PAD) - ICON_BTN_PAD)
iconScroll:SetHeight(ICON_GRID_ROWS * (ICON_BTN_SIZE + ICON_BTN_PAD) - ICON_BTN_PAD)
-- IconDataProviderMixin owns the icon DB, dedup, and lazy load.
-- Init on first picker open; release on hide so the cache GCs.
local provider = nil
-- Selection is tracked by PATH (not index) so it survives filter
-- changes: a spell icon you picked still saves correctly even after
-- you switch the filter to "Items" and it's no longer in the visible list.
local QUESTION_MARK = "INTERFACE\\ICONS\\INV_MISC_QUESTIONMARK"
local selectedIconPath = QUESTION_MARK
local function EnsureProvider()
if not provider then
provider = CreateAndInitFromMixin(IconDataProviderMixin,
IconDataProviderExtraType.Equipment)
end
end
-- Anchor scrollbar to iconScroll's right edge so its position tracks
-- the icon grid rather than the popup. -16/+16 vertical insets are the
-- standard up/down arrow spacing for UIPanelScrollBarTemplate.
local scrollbar = _G["pfEqMgrIconScrollScrollBar"]
if scrollbar then
scrollbar:ClearAllPoints()
scrollbar:SetPoint("TOPLEFT", iconScroll, "TOPRIGHT", 8, -16)
scrollbar:SetPoint("BOTTOMLEFT", iconScroll, "BOTTOMRIGHT", 8, 16)
SkinScrollbar(scrollbar)
end
-- Filter dropdown: "All Icons" / "Spells" / "Items" (top right of icon area).
local filterDropdown = CreateFrame("Frame", "pfEqMgrIconFilter", namePopup, "UIDropDownMenuTemplate")
filterDropdown:SetPoint("TOPRIGHT", namePopup, "TOPRIGHT", 0, -94)
local currentFilter = "all"
local function ApplyFilter(value)
currentFilter = value
UIDropDownMenu_SetSelectedValue(filterDropdown, value)
if provider then
if value == "spells" then provider:SetIconTypes({ IconDataProviderIconType.Spell })
elseif value == "items" then provider:SetIconTypes({ IconDataProviderIconType.Item })
else provider:SetIconTypes(nil) end
-- Don't reset selection — selectedIconPath persists. If the
-- selected icon isn't in the new filter, no grid entry will be
-- highlighted but Save will still write the chosen icon.
pfUI.equipmentmanager.RefreshIconGrid()
end
end
UIDropDownMenu_Initialize(filterDropdown, function()
local info
info = {}; info.text = T["All Icons"] or "All Icons"; info.value = "all"
info.func = function() ApplyFilter("all") end
info.checked = currentFilter == "all"
UIDropDownMenu_AddButton(info)
info = {}; info.text = T["Spells"] or "Spells"; info.value = "spells"
info.func = function() ApplyFilter("spells") end
info.checked = currentFilter == "spells"
UIDropDownMenu_AddButton(info)
info = {}; info.text = T["Items"] or "Items"; info.value = "items"
info.func = function() ApplyFilter("items") end
info.checked = currentFilter == "items"
UIDropDownMenu_AddButton(info)
end)
UIDropDownMenu_SetWidth(120, filterDropdown)
UIDropDownMenu_SetSelectedValue(filterDropdown, "all")
SkinDropDown(filterDropdown)
local iconButtons = {}
for r = 1, ICON_GRID_ROWS do
for c = 1, ICON_GRID_COLS do
local i = (r - 1) * ICON_GRID_COLS + c
local btn = CreateFrame("Button", nil, namePopup)
btn:SetWidth(ICON_BTN_SIZE)
btn:SetHeight(ICON_BTN_SIZE)
btn:SetPoint("TOPLEFT", iconScroll, "TOPLEFT", (c-1) * (ICON_BTN_SIZE + ICON_BTN_PAD), -(r-1) * (ICON_BTN_SIZE + ICON_BTN_PAD))
CreateBackdrop(btn)
btn.texture = btn:CreateTexture(nil, "ARTWORK")
btn.texture:SetAllPoints(btn)
btn.texture:SetTexCoord(.08, .92, .08, .92)
btn.gridIndex = i
btn:SetScript("OnClick", function()
if this.iconIndex and provider then
local path = provider:GetIconByIndex(this.iconIndex)
if path then selectedIconPath = path end
pfUI.equipmentmanager.RefreshIconGrid()
end
end)
btn:SetScript("OnEnter", function()
if not this.iconIndex or not provider then return end
local path = provider:GetIconByIndex(this.iconIndex)
if type(path) == "string" then
local name = string.gsub(path, "^.-INTERFACE\\\\ICONS\\\\", "")
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetText(name)
GameTooltip:Show()
end
end)
btn:SetScript("OnLeave", GameTooltip_Hide)
iconButtons[i] = btn
end
end
function pfUI.equipmentmanager.RefreshIconGrid()
EnsureProvider()
local numIcons = provider:GetNumIcons()
local numRows = math.ceil(numIcons / ICON_GRID_COLS)
FauxScrollFrame_Update(iconScroll, numRows, ICON_GRID_ROWS, ICON_BTN_SIZE + ICON_BTN_PAD)
local offset = FauxScrollFrame_GetOffset(iconScroll)
for i = 1, ICON_GRID_ROWS * ICON_GRID_COLS do
local listIdx = i + offset * ICON_GRID_COLS
local btn = iconButtons[i]
if listIdx <= numIcons then
btn:Show()
btn.iconIndex = listIdx
local path = provider:GetIconByIndex(listIdx)
btn.texture:SetTexture(path)
if path == selectedIconPath then
btn.backdrop:SetBackdropBorderColor(1, 0.82, 0, 1)
else
btn.backdrop:SetBackdropBorderColor(pfUI.cache.er, pfUI.cache.eg, pfUI.cache.eb, pfUI.cache.ea)
end
else
btn:Hide()
btn.iconIndex = nil
end
end
-- Sync the "Currently Selected" preview from the path directly so it
-- still shows the chosen icon when filtered out of the grid.
namePopup.selectedPreview.tex:SetTexture(selectedIconPath)
end
iconScroll:SetScript("OnVerticalScroll", function()
FauxScrollFrame_OnVerticalScroll(ICON_BTN_SIZE + ICON_BTN_PAD, function() pfUI.equipmentmanager.RefreshIconGrid() end)
end)
namePopup:SetScript("OnHide", function()
if provider then provider:Release(); provider = nil end
end)
local btnPopupOK = MakeButton("pfEqMgrPopupOK", T["OK"] or "OK", namePopup, namePopup, 14, -340, 80)
btnPopupOK:ClearAllPoints()
btnPopupOK:SetPoint("BOTTOMLEFT", namePopup, "BOTTOMLEFT", 14, 12)
local btnPopupCancel = MakeButton("pfEqMgrPopupCancel", T["Cancel"] or "Cancel", namePopup, namePopup, 0, 0, 80)
btnPopupCancel:ClearAllPoints() btnPopupCancel:ClearAllPoints()
btnPopupCancel:SetPoint("BOTTOMRIGHT", namePopup, "BOTTOMRIGHT", -14, 12) btnPopupCancel:SetPoint("BOTTOMRIGHT", namePopup, "BOTTOMRIGHT", -14, 12)
btnPopupCancel:SetScript("OnClick", function() namePopup:Hide() end) btnPopupCancel:SetScript("OnClick", function() namePopup:Hide() end)
-- Okay | Cancel, both anchored to the bottom-right corner.
btnPopupOK:ClearAllPoints()
btnPopupOK:SetPoint("BOTTOMRIGHT", btnPopupCancel, "BOTTOMLEFT", -6, 0)
btnPopupOK:SetScript("OnClick", function() btnPopupOK:SetScript("OnClick", function()
local name = namePopup.editbox:GetText() local name = namePopup.editbox:GetText()
if not name or name == "" then return end if not name or name == "" then return end
-- Strip the prefix to match ClassicAPI's persisted short-form basenames. -- Strip the prefix to match ClassicAPI's persisted short-form basenames.
local iconForSave = string.gsub(iconPicker.GetIcon(), "INTERFACE\\ICONS\\", "") local iconForSave = string.gsub(selectedIconPath, "INTERFACE\\ICONS\\", "")
if pendingAction == "new" then if pendingAction == "new" then
C_EquipmentSet.CreateEquipmentSet(name, iconForSave) C_EquipmentSet.CreateEquipmentSet(name, iconForSave)
C_EquipmentSet.ClearIgnoredSlotsForSave() C_EquipmentSet.ClearIgnoredSlotsForSave()
@@ -430,20 +610,31 @@ pfUI:RegisterModule("equipmentmanager", function()
function OpenNamePopup(action, prefillName, prefillIcon) function OpenNamePopup(action, prefillName, prefillIcon)
pendingAction = action pendingAction = action
namePopup.editbox:SetText(prefillName or "") namePopup.editbox:SetText(prefillName or "")
EnsureProvider()
if prefillIcon then if prefillIcon then
-- Stored icons come back either as a full path or a bare basename local short = string.gsub(prefillIcon, "INTERFACE\\ICONS\\", "")
-- (see the row rendering in Refresh). Only prepend the prefix when selectedIconPath = "INTERFACE\\ICONS\\" .. strupper(short)
-- there's no path separator, so a full path isn't double-prefixed.
iconPicker.SetIcon(string.find(prefillIcon, "\\") and prefillIcon
or ("INTERFACE\\ICONS\\" .. prefillIcon))
else else
iconPicker.SetIcon(nil) selectedIconPath = QUESTION_MARK
end
if action == "rename" then
namePopup.title:SetText(T["Rename Set"] or "Rename Set")
iconScroll:Hide()
for _, b in ipairs(iconButtons) do b:Hide() end
namePopup.iconLabel:Hide()
namePopup.selectedLabel:Hide()
namePopup.selectedPreview:Hide()
filterDropdown:Hide()
else
namePopup.title:SetText(action == "new" and (T["Name Set"] or "Name Set") or (T["Save Set"] or "Save Set"))
iconScroll:Show()
namePopup.iconLabel:Show()
namePopup.selectedLabel:Show()
namePopup.selectedPreview:Show()
filterDropdown:Show()
end end
namePopup.search:SetText("")
-- Rename only changes the name, so hide the whole icon-picking area.
iconPicker.SetIconAreaShown(action ~= "rename")
namePopup:Show() namePopup:Show()
if action ~= "rename" then iconPicker.Refresh() end if action ~= "rename" then pfUI.equipmentmanager.RefreshIconGrid() end
namePopup.editbox:SetFocus() namePopup.editbox:SetFocus()
end end
@@ -452,13 +643,9 @@ pfUI:RegisterModule("equipmentmanager", function()
-- ============================================================ -- ============================================================
local flyout = CreateFrame("Frame", "pfEqMgrFlyout", UIParent) local flyout = CreateFrame("Frame", "pfEqMgrFlyout", UIParent)
-- Everything tied to the EM sidecar closes with it: the popout arrows,
-- the per-slot flyout, and the name/icon popup. (OnShow re-shows the
-- popout arrows.)
frame:SetScript("OnHide", function() frame:SetScript("OnHide", function()
for _, b in ipairs(popoutButtons) do b:Hide() end for _, b in ipairs(popoutButtons) do b:Hide() end
flyout:Hide() flyout:Hide()
namePopup:Hide()
end) end)
flyout:SetFrameStrata("DIALOG") flyout:SetFrameStrata("DIALOG")
flyout:Hide() flyout:Hide()
@@ -489,7 +676,7 @@ pfUI:RegisterModule("equipmentmanager", function()
end end
end end
ClearCursor() ClearCursor()
UIErrorsFrame:AddMessage(ERR_EQUIPMENT_MANAGER_BAGS_FULL, 1, .1, .1, 1) UIErrorsFrame:AddMessage(EQUIPMENT_MANAGER_BAGS_FULL or "Your bags are full.", 1, .1, .1, 1)
end end
local function MakeFlyoutButton(i) local function MakeFlyoutButton(i)
@@ -505,11 +692,11 @@ pfUI:RegisterModule("equipmentmanager", function()
b:SetScript("OnEnter", function() b:SetScript("OnEnter", function()
GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
if this.specialAction == "placeInBags" then if this.specialAction == "placeInBags" then
GameTooltip:SetText(EQUIPMENT_MANAGER_PLACE_IN_BAGS, 1, 1, 1) GameTooltip:SetText(EQUIPMENT_MANAGER_PLACE_IN_BAGS or "Place in Bags", 1, 1, 1)
elseif this.specialAction == "ignore" then elseif this.specialAction == "ignore" then
GameTooltip:SetText(EQUIPMENT_MANAGER_IGNORE_SLOT, 1, 1, 1) GameTooltip:SetText(EQUIPMENT_MANAGER_IGNORE_SLOT or "Ignore this slot", 1, 1, 1)
elseif this.specialAction == "unignore" then elseif this.specialAction == "unignore" then
GameTooltip:SetText(EQUIPMENT_MANAGER_UNIGNORE_SLOT, 1, 1, 1) GameTooltip:SetText(EQUIPMENT_MANAGER_UNIGNORE_SLOT or "Stop ignoring this slot", 1, 1, 1)
elseif this.bag then elseif this.bag then
GameTooltip:SetBagItem(this.bag, this.slot) GameTooltip:SetBagItem(this.bag, this.slot)
elseif this.invSlot then elseif this.invSlot then
@@ -517,7 +704,7 @@ pfUI:RegisterModule("equipmentmanager", function()
end end
GameTooltip:Show() GameTooltip:Show()
end) end)
b:SetScript("OnLeave", GameTooltip_Hide) b:SetScript("OnLeave", function() GameTooltip:Hide() end)
b:SetScript("OnClick", function() b:SetScript("OnClick", function()
if this.specialAction == "placeInBags" then if this.specialAction == "placeInBags" then
UnequipToBags(flyout.targetInvSlot) UnequipToBags(flyout.targetInvSlot)
@@ -622,6 +809,7 @@ pfUI:RegisterModule("equipmentmanager", function()
if num == 0 then if num == 0 then
flyout:Hide() flyout:Hide()
UIErrorsFrame:AddMessage(T["No matching items in bags"] or "No matching items in bags", 1, 1, 0, 1)
return return
end end
@@ -750,6 +938,16 @@ pfUI:RegisterModule("equipmentmanager", function()
end end
end end
-- Tie popout visibility to the EM sidecar. They appear when the
-- sidecar opens, hide when it closes, and the flyout closes too.
frame:HookScript("OnShow", function()
for _, b in ipairs(popoutButtons) do b:Show() end
end)
frame:HookScript("OnHide", function()
for _, b in ipairs(popoutButtons) do b:Hide() end
if flyout then flyout:Hide() end
end)
-- ============================================================ -- ============================================================
-- Refresh -- Refresh
-- ============================================================ -- ============================================================
-1
View File
@@ -2772,7 +2772,6 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(nil, T["Always Show Health In Percent"], C.tooltip, "alwaysperc", "checkbox") CreateConfig(nil, T["Always Show Health In Percent"], C.tooltip, "alwaysperc", "checkbox")
CreateConfig(nil, T["Show Item IDs"], C.tooltip, "itemid", "checkbox") CreateConfig(nil, T["Show Item IDs"], C.tooltip, "itemid", "checkbox")
CreateConfig(nil, T["Show Movement Speed"], C.tooltip, "movespeed", "checkbox") CreateConfig(nil, T["Show Movement Speed"], C.tooltip, "movespeed", "checkbox")
CreateConfig(nil, T["Show Aura Caster"], C.tooltip, "aurasource", "checkbox")
CreateConfig(nil, T["Custom Transparency"], C.tooltip, "alpha") CreateConfig(nil, T["Custom Transparency"], C.tooltip, "alpha")
CreateConfig(nil, T["Status Bar Texture"], C.tooltip.statusbar, "texture", "dropdown", pfUI.gui.dropdowns.uf_bartexture) CreateConfig(nil, T["Status Bar Texture"], C.tooltip.statusbar, "texture", "dropdown", pfUI.gui.dropdowns.uf_bartexture)
CreateConfig(nil, T["Always Show Item Comparison"], C.tooltip.compare, "showalways", "checkbox") CreateConfig(nil, T["Always Show Item Comparison"], C.tooltip.compare, "showalways", "checkbox")
-128
View File
@@ -1,128 +0,0 @@
-- Macro icon picker
-- Replaces Blizzard's MacroPopupFrame (the "name + icon" dialog opened by the
-- New / Change-Icon buttons) with a pfUI-native picker driven by
-- IconDataProviderMixin, so the full spell + item + loose icon set is
-- available instead of the stock spell-only list. Saving goes through
-- C_Macro.CreateMacro / C_Macro.EditMacro, which take the icon as a texture
-- string -- so arbitrary icons (including index-less INV_* item icons) persist
-- on both the modern (Turtle/Octo) and stock-vanilla macro UIs. The surrounding
-- MacroFrame (list + body editor) is Blizzard's, already skinned elsewhere.
pfUI:RegisterModule("macroicons", function ()
HookAddonOrVariable("Blizzard_MacroUI", function()
-- ============================================================
-- Popup frame
-- ============================================================
local picker = CreateFrame("Frame", "pfMacroIconPicker", UIParent)
picker:SetFrameStrata("DIALOG")
picker:SetSize(472, 484)
-- Starts anchored to the right of the macro panel (re-anchored at open
-- once the skin's backdrop exists); dragging pins it in place after.
picker:SetPoint("BOTTOMLEFT", MacroFrame, "BOTTOMRIGHT", 8, 0)
picker:Hide()
CreateBackdrop(picker, nil, nil, .9)
CreateBackdropShadow(picker)
picker:EnableMouse(true)
picker:SetMovable(true)
picker:RegisterForDrag("LeftButton")
picker:SetScript("OnDragStart", function() this:StartMoving() end)
picker:SetScript("OnDragStop", function()
this:StopMovingOrSizing()
this.userMoved = true
end)
-- Spellbook seed leads the grid with class-relevant spell/talent icons.
local iconPicker = CreateIconPicker("pfMacroIcon", picker,
IconDataProviderExtraType.Spellbook, MACRO_POPUP_TEXT)
-- ============================================================
-- Open / save
-- ============================================================
-- Blizzard's popup disables these while it is open; mirror that so the
-- underlying frame can't be double-driven, then let MacroFrame_Update
-- restore the correct states on close.
local function SetMacroButtons(enabled)
local m = enabled and "Enable" or "Disable"
MacroNewButton[m](MacroNewButton)
MacroEditButton[m](MacroEditButton)
MacroDeleteButton[m](MacroDeleteButton)
end
local function OpenMacroPopup(mode)
if mode == "edit" and MacroFrame.selectedMacro then
picker.mode = "edit"
local name, texture = GetMacroInfo(MacroFrame.selectedMacro)
picker.editbox:SetText(name or "")
iconPicker.SetIcon(texture)
else
picker.mode = "new"
picker.editbox:SetText("")
iconPicker.SetIcon(nil)
end
picker.search:SetText("")
if not picker.userMoved then
picker:ClearAllPoints()
picker:SetPoint("BOTTOMLEFT", MacroFrame.backdrop or MacroFrame, "BOTTOMRIGHT", 8, 0)
end
SetMacroButtons(false)
picker:Show()
picker.editbox:SetFocus()
iconPicker.Refresh()
end
local function SaveMacroPopup()
local text = strtrim(picker.editbox:GetText())
if text == "" then return end
local icon = iconPicker.GetIcon()
if picker.mode == "edit" and MacroFrame.selectedMacro then
C_Macro.EditMacro(MacroFrame.selectedMacro, text, icon, nil)
MacroFrame_SelectMacro(MacroFrame.selectedMacro)
else
local idx = C_Macro.CreateMacro(text, icon, nil, (MacroFrame.macroBase or 0) > 0)
if idx then MacroFrame_SelectMacro(idx) end
end
picker:Hide()
end
picker:SetScript("OnHide", function() MacroFrame_Update() end)
picker.editbox:SetScript("OnEnterPressed", SaveMacroPopup)
picker.editbox:SetScript("OnEscapePressed", function() picker:Hide() end)
-- OK / Cancel
local okay = CreateFrame("Button", "pfMacroIconPickerOkay", picker, "UIPanelButtonTemplate")
okay:SetSize(80, 22)
okay:SetText(OKAY)
okay:SetScript("OnClick", SaveMacroPopup)
SkinButton(okay)
local cancel = CreateFrame("Button", "pfMacroIconPickerCancel", picker, "UIPanelButtonTemplate")
cancel:SetSize(80, 22)
cancel:SetText(CANCEL)
cancel:SetPoint("BOTTOMRIGHT", picker, "BOTTOMRIGHT", -14, 12)
cancel:SetScript("OnClick", function() picker:Hide() end)
SkinButton(cancel)
-- Okay | Cancel, both anchored to the bottom-right corner.
okay:SetPoint("BOTTOMRIGHT", cancel, "BOTTOMLEFT", -6, 0)
-- ============================================================
-- Take over the New / Change-Icon buttons; retire Blizzard's popup
-- ============================================================
MacroNewButton:SetScript("OnClick", function()
MacroFrame_SaveMacro()
OpenMacroPopup("new")
end)
MacroEditButton:SetScript("OnClick", function()
MacroFrame_SaveMacro()
OpenMacroPopup("edit")
end)
-- Closing the macro window takes the picker with it.
MacroFrame:HookScript("OnHide", function() picker:Hide() end)
end)
end)
+59 -54
View File
@@ -1,32 +1,57 @@
pfUI:RegisterModule("marktracking", function () pfUI:RegisterModule("marktracking", function ()
-- Requires mark1-mark8 unit tokens (Turtle WoW / Nampower)
if not UnitExists("mark1") and not UnitExists("mark8") then if not UnitExists("mark1") and not UnitExists("mark8") then
if not pcall(function() UnitExists("mark1") end) then return end if not pcall(function() UnitExists("mark1") end) then return end
end end
local rawborder, border = GetBorderSize() local rawborder, border = GetBorderSize()
-- Parse color strings "r,g,b,a" into components
local function ParseColor(str, dr, dg, db, da)
if not str or str == "" then return dr, dg, db, da end
local _, _, r, g, b, a = string.find(str, "([%d%.]+),([%d%.]+),([%d%.]+),([%d%.]+)")
if r then
return tonumber(r) or dr, tonumber(g) or dg, tonumber(b) or db, tonumber(a) or da
end
return dr, dg, db, da
end
local markerOrder = { 8, 7, 6, 5, 4, 3, 2, 1 } -- skull, cross, square, moon, triangle, diamond, circle, star local markerOrder = { 8, 7, 6, 5, 4, 3, 2, 1 } -- skull, cross, square, moon, triangle, diamond, circle, star
local markerTokens = {} local markerTokens = {}
for i = 1, 8 do markerTokens[i] = "mark" .. i end
-- Default colors per marker
local defaultColors = {
[1] = { 1.0, 0.9, 0.0, 1 }, -- star: yellow
[2] = { 1.0, 0.5, 0.0, 1 }, -- circle: orange
[3] = { 0.8, 0.0, 0.8, 1 }, -- diamond: purple
[4] = { 0.0, 0.8, 0.0, 1 }, -- triangle: green
[5] = { 0.7, 0.7, 0.7, 1 }, -- moon: silver
[6] = { 0.0, 0.4, 0.9, 1 }, -- square: blue
[7] = { 0.9, 0.0, 0.0, 1 }, -- cross: red
[8] = { 1.0, 1.0, 1.0, 1 }, -- skull: white
}
local markerConfigKeys = { local markerConfigKeys = {
"raidmarkercolor_star", [1] = "raidmarkercolor_star",
"raidmarkercolor_circle", [2] = "raidmarkercolor_circle",
"raidmarkercolor_diamond", [3] = "raidmarkercolor_diamond",
"raidmarkercolor_triangle", [4] = "raidmarkercolor_triangle",
"raidmarkercolor_moon", [5] = "raidmarkercolor_moon",
"raidmarkercolor_square", [6] = "raidmarkercolor_square",
"raidmarkercolor_cross", [7] = "raidmarkercolor_cross",
"raidmarkercolor_skull", [8] = "raidmarkercolor_skull",
} }
local markerColors = {} local markerColors = {}
for i, markKey in ipairs(markerConfigKeys) do for i = 1, 8 do
markerTokens[i] = "mark" .. i local d = defaultColors[i]
local r, g, b, a = GetStringColor(C.unitframes[markKey]) local r, g, b, a = ParseColor(C.unitframes[markerConfigKeys[i]], d[1], d[2], d[3], d[4])
markerColors[i] = { tonumber(r), tonumber(g), tonumber(b), tonumber(a) } markerColors[i] = { r, g, b, a }
end end
local FALLBACK_INTERVAL = 1.0 -- safety net for units that come into range after marker was set local FALLBACK_INTERVAL = 1.0 -- safety net for units that come into range after marker was set
local elapsed = 0
local isUnlocked = false local isUnlocked = false
local ROW_HEIGHT = tonumber(C.unitframes.raidmarkerheight) or 14 local ROW_HEIGHT = tonumber(C.unitframes.raidmarkerheight) or 14
local BAR_WIDTH = tonumber(C.unitframes.raidmarkerwidth) or 80 local BAR_WIDTH = tonumber(C.unitframes.raidmarkerwidth) or 80
@@ -100,16 +125,19 @@ pfUI.marktracking = CreateFrame("Frame", "pfMarkTracking", UIParent)
local i = markerOrder[idx] local i = markerOrder[idx]
local row = CreateFrame("Button", nil, pfUI.marktracking) local row = CreateFrame("Button", nil, pfUI.marktracking)
row:SetSize(TOTAL_ROW_WIDTH, ROW_HEIGHT) row:SetWidth(TOTAL_ROW_WIDTH)
row:SetHeight(ROW_HEIGHT)
row:Hide() row:Hide()
row:RegisterForClicks("LeftButtonUp", "RightButtonUp") row:RegisterForClicks("LeftButtonUp")
row:SetAttribute("type1", "target") row:SetScript("OnClick", function()
row:SetAttribute("type2", "menu") TargetUnit(markerTokens[this.markerIndex])
end)
-- raid icon -- raid icon
row.icon = row:CreateTexture(nil, "ARTWORK") row.icon = row:CreateTexture(nil, "ARTWORK")
row.icon:SetSize(ROW_HEIGHT, ROW_HEIGHT) row.icon:SetWidth(ROW_HEIGHT)
row.icon:SetHeight(ROW_HEIGHT)
row.icon:SetPoint("LEFT", row, "LEFT", 1, 0) row.icon:SetPoint("LEFT", row, "LEFT", 1, 0)
local markTex = C.unitframes.blizzard_raidicons == "1" and "Interface\\TargetingFrame\\UI-RaidTargetingIcons" or pfUI.media["img:raidicons"] local markTex = C.unitframes.blizzard_raidicons == "1" and "Interface\\TargetingFrame\\UI-RaidTargetingIcons" or pfUI.media["img:raidicons"]
row.icon:SetTexture(markTex) row.icon:SetTexture(markTex)
@@ -117,7 +145,8 @@ pfUI.marktracking = CreateFrame("Frame", "pfMarkTracking", UIParent)
-- portrait (right side) -- portrait (right side)
row.portrait = row:CreateTexture(nil, "ARTWORK") row.portrait = row:CreateTexture(nil, "ARTWORK")
row.portrait:SetSize(PORTRAIT_SIZE, PORTRAIT_SIZE) row.portrait:SetWidth(PORTRAIT_SIZE)
row.portrait:SetHeight(PORTRAIT_SIZE)
row.portrait:SetPoint("RIGHT", row, "RIGHT", -1, 0) row.portrait:SetPoint("RIGHT", row, "RIGHT", -1, 0)
row.portrait:SetTexCoord(.1, .9, .1, .9) row.portrait:SetTexCoord(.1, .9, .1, .9)
if not rm_showportrait then row.portrait:Hide() end if not rm_showportrait then row.portrait:Hide() end
@@ -175,8 +204,8 @@ pfUI.marktracking = CreateFrame("Frame", "pfMarkTracking", UIParent)
local token = markerTokens[i] local token = markerTokens[i]
if UnitExists(token) and not UnitIsDead(token) then if UnitExists(token) and not UnitIsDead(token) then
local hp, maxhp = UnitHealth(token), UnitHealthMax(token) local hp = UnitHealth(token)
row:SetAttribute('unit', token) local maxhp = UnitHealthMax(token)
if hp and maxhp and maxhp > 0 and hp > 0 then if hp and maxhp and maxhp > 0 and hp > 0 then
local pct = hp / maxhp local pct = hp / maxhp
@@ -238,27 +267,6 @@ pfUI.marktracking = CreateFrame("Frame", "pfMarkTracking", UIParent)
end end
end end
-- Fast per-row refresh for a single mark's UNIT_HEALTH/UNIT_MAXHEALTH: moves
-- just the bar + hp text. If the mark's visibility flips (comes into range,
-- dies, hp crosses 0) the visible rows re-pack, so hand off to UpdateDisplay.
local function UpdateRow(i)
if isUnlocked then return end
local row = pfUI.marktracking.rows[i]
if not row then return end
local token = markerTokens[i]
local hp, maxhp = UnitHealth(token), UnitHealthMax(token)
local shouldShow = UnitExists(token) and not UnitIsDead(token)
and hp and maxhp and maxhp > 0 and hp > 0 and true or false
if shouldShow ~= (row:IsShown() and true or false) then
UpdateDisplay()
return
end
if not shouldShow then return end
local pct = hp / maxhp
row.health:SetValue(pct)
if rm_showpct then row.hptext:SetText(math.ceil(pct * 100) .. "%") end
end
-- Unlock mode: show fixed 1-row placeholder so positioning works correctly -- Unlock mode: show fixed 1-row placeholder so positioning works correctly
if pfUI.unlock then if pfUI.unlock then
local origShow = pfUI.unlock:GetScript("OnShow") local origShow = pfUI.unlock:GetScript("OnShow")
@@ -284,27 +292,24 @@ pfUI.marktracking = CreateFrame("Frame", "pfMarkTracking", UIParent)
-- Event-driven scanner frame -- Event-driven scanner frame
local scanner = CreateFrame("Frame") local scanner = CreateFrame("Frame")
-- RAID_TARGET_UPDATE: a raid marker was set/cleared -> full refresh -- RAID_TARGET_UPDATE: fires when a raid marker is set/cleared
-- PLAYER_ENTERING_WORLD: login/reload/zone -> full refresh -- PLAYER_ENTERING_WORLD: fires on login, reload, and zone transitions
-- UNIT_HEALTH/UNIT_MAXHEALTH: ClassicAPI fires these per token; with the mark -- UNIT_HEALTH/UNIT_MAXHEALTH: fires on HP changes for real-time bar updates
-- tokens observed they arrive as arg1 == "markN", so we refresh just that
-- one row (UpdateRow) instead of rescanning all eight.
scanner:RegisterEvent("RAID_TARGET_UPDATE") scanner:RegisterEvent("RAID_TARGET_UPDATE")
scanner:RegisterEvent("PLAYER_ENTERING_WORLD") scanner:RegisterEvent("PLAYER_ENTERING_WORLD")
scanner:RegisterEvent("UNIT_HEALTH") scanner:RegisterEvent("UNIT_HEALTH")
scanner:RegisterEvent("UNIT_MAXHEALTH") scanner:RegisterEvent("UNIT_MAXHEALTH")
scanner:SetScript("OnEvent", function() scanner:SetScript("OnEvent", function()
if event == "UNIT_HEALTH" or event == "UNIT_MAXHEALTH" then
-- arg1 is the token; "markN" -> N, nil for any non-mark token.
local i = arg1 and tonumber(string.match(arg1, "^mark(%d)"))
if i then UpdateRow(i) end
return
end
UpdateDisplay() UpdateDisplay()
end) end)
-- Fallback poll: catches units that come into range AFTER a marker was set -- Fallback poll at 1s: catches units that come into range AFTER a marker was set
-- (no event fires for that case, so we need this safety net) -- (no event fires for that case, so we need this safety net)
C_Timer.NewTicker(FALLBACK_INTERVAL, UpdateDisplay) scanner:SetScript("OnUpdate", function()
elapsed = elapsed + arg1
if elapsed < FALLBACK_INTERVAL then return end
elapsed = 0
UpdateDisplay()
end)
end) end)
+9 -7
View File
@@ -131,16 +131,18 @@ pfUI:RegisterModule("minimap", function ()
-- Create coordinates text frame with location configurable -- Create coordinates text frame with location configurable
pfUI.minimapCoordinates = CreateFrame("Frame", "pfMinimapCoord", pfUI.minimap) pfUI.minimapCoordinates = CreateFrame("Frame", "pfMinimapCoord", pfUI.minimap)
-- Update coords every 0.1 seconds pfUI.minimapCoordinates:SetScript("OnUpdate", function()
C_Timer.NewTicker(0.1, function() -- Throttle to update coords every 0.1 seconds
if ( this.tick or 0) > GetTime() then return end
this.tick = GetTime() + .1
if C.appearance.minimap.coordstext == "off" then return end if C.appearance.minimap.coordstext == "off" then return end
local coord = pfUI.minimapCoordinates this.posX, this.posY = GetPlayerMapPosition("player")
coord.posX, coord.posY = GetPlayerMapPosition("player") if this.posX ~= 0 and this.posY ~= 0 then
if coord.posX ~= 0 and coord.posY ~= 0 then this.text:SetText(string.format("%.1f, %.1f", round(this.posX * 100, 1), round(this.posY * 100, 1)))
coord.text:SetText(string.format("%.1f, %.1f", round(coord.posX * 100, 1), round(coord.posY * 100, 1)))
else else
coord.text:SetText("|cffffaaaaN/A") this.text:SetText("|cffffaaaaN/A")
end end
end) end)
+3 -9
View File
@@ -55,7 +55,6 @@ pfUI:RegisterModule("nameplates", function ()
local savedHostileState = nil local savedHostileState = nil
local savedFriendlyState = nil local savedFriendlyState = nil
local inFriendlyZone = false local inFriendlyZone = false
local myGuild = nil
local platecount = 0 local platecount = 0
local registry = {} local registry = {}
-- Subset of registry that currently has a unit assigned (between -- Subset of registry that currently has a unit assigned (between
@@ -483,7 +482,6 @@ nameplates:RegisterEvent("UNIT_SPELLCAST_START")
nameplates:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START") nameplates:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START")
nameplates:RegisterEvent("UNIT_SPELLCAST_STOP") nameplates:RegisterEvent("UNIT_SPELLCAST_STOP")
nameplates:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP") nameplates:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP")
nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
nameplates:SetScript("OnEvent", function() nameplates:SetScript("OnEvent", function()
-- Stop event handling during logout to prevent crash 132 -- Stop event handling during logout to prevent crash 132
@@ -495,17 +493,13 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
nameplates.mouselook:SetScript("OnUpdate", nil) nameplates.mouselook:SetScript("OnUpdate", nil)
end end
return return
elseif event == "PLAYER_GUILD_UPDATE" and arg1 == 'player' then
myGuild = GetGuildInfo("player")
elseif event == "PLAYER_ENTERING_WORLD" or event == "ZONE_CHANGED_NEW_AREA" then elseif event == "PLAYER_ENTERING_WORLD" or event == "ZONE_CHANGED_NEW_AREA" then
if event == "PLAYER_ENTERING_WORLD" then if event == "PLAYER_ENTERING_WORLD" then
CacheConfig() CacheConfig()
this:SetGameVariables() this:SetGameVariables()
RebuildRaidGuidCache() RebuildRaidGuidCache()
frameState.targetGuid = UnitGUID("target") frameState.targetGuid = UnitGUID("target")
myGuild = GetGuildInfo("player")
end end
-- Handle friendly zone nameplate disable feature -- Handle friendly zone nameplate disable feature
@@ -954,7 +948,7 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
-- Use the same castbar texture and color as the unit frame castbar (castbar.lua) -- Use the same castbar texture and color as the unit frame castbar (castbar.lua)
local cbtexture = pfUI.media[C.appearance.castbar.texture] local cbtexture = pfUI.media[C.appearance.castbar.texture]
nameplate.castbar:SetStatusBarTexture(cbtexture or hptexture) nameplate.castbar:SetStatusBarTexture(cbtexture or hptexture)
local cbr, cbg, cbb, cba = GetStringColor(C.appearance.castbar.castbarcolor) local cbr, cbg, cbb, cba = strsplit(",", C.appearance.castbar.castbarcolor)
nameplate.castbar:SetStatusBarColor(cbr, cbg, cbb, cba) nameplate.castbar:SetStatusBarColor(cbr, cbg, cbb, cba)
-- reset endTime cache so color/texture refresh takes effect on next cast -- reset endTime cache so color/texture refresh takes effect on next cast
nameplate.castbar.lastEndTime = nil nameplate.castbar.lastEndTime = nil
@@ -1127,7 +1121,7 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
if guild and C.nameplates.showguildname == "1" then if guild and C.nameplates.showguildname == "1" then
plate.guild:SetText(guild) plate.guild:SetText(guild)
if guild == myGuild then if UnitIsInMyGuild(plate.unit) then
plate.guild:SetTextColor(0, 0.9, 0, 1) plate.guild:SetTextColor(0, 0.9, 0, 1)
else else
plate.guild:SetTextColor(0.8, 0.8, 0.8, 1) plate.guild:SetTextColor(0.8, 0.8, 0.8, 1)
+36 -17
View File
@@ -37,12 +37,18 @@ pfUI:RegisterModule("panel", function()
return return
end end
if arg1 == "LeftButton" then if arg1 == "LeftButton" then
widget.timerFrame:SetShown(not widget.timerFrame:IsShown()) if widget.timerFrame:IsShown() then
widget.timerFrame:Hide()
else
widget.timerFrame:Show()
end
elseif arg1 == "RightButton" then elseif arg1 == "RightButton" then
widget.timerFrame.Snapshot = GetTime() widget.timerFrame.Snapshot = GetTime()
end end
end end
C_Timer.NewTicker(1, function() widget:SetScript("OnUpdate",function()
if ( this.tick or 1) > GetTime() then return else this.tick = GetTime() + 1 end
local secondsenabled = C.panel.seconds == "1" local secondsenabled = C.panel.seconds == "1"
local fmt local fmt
if C.global.twentyfour == "0" then if C.global.twentyfour == "0" then
@@ -56,7 +62,8 @@ pfUI:RegisterModule("panel", function()
widget.timerFrame = CreateFrame("Frame", "pfUITimer", UIParent) widget.timerFrame = CreateFrame("Frame", "pfUITimer", UIParent)
widget.timerFrame:Hide() widget.timerFrame:Hide()
widget.timerFrame:SetSize(120, 35) widget.timerFrame:SetWidth(120)
widget.timerFrame:SetHeight(35)
widget.timerFrame:SetPoint("TOP", 0, -100) widget.timerFrame:SetPoint("TOP", 0, -100)
UpdateMovable(widget.timerFrame) UpdateMovable(widget.timerFrame)
@@ -96,9 +103,11 @@ pfUI:RegisterModule("panel", function()
pfUI.panel:OutputPanel("combat", T["Combat"] .. ": " .. NOT_APPLICABLE) pfUI.panel:OutputPanel("combat", T["Combat"] .. ": " .. NOT_APPLICABLE)
end end
end) end)
C_Timer.NewTicker(1, function() widget.combat:SetScript("OnUpdate", function()
if widget.combat.combat then if not this.tick then this.tick = GetTime() end
pfUI.panel:OutputPanel("combat", "|cffffaaaa" .. SecondsToTime(ceil(GetTime() - widget.combat.combat))) if GetTime() <= this.tick + 1 then return else this.tick = GetTime() end
if this.combat then
pfUI.panel:OutputPanel("combat", "|cffffaaaa" .. SecondsToTime(ceil(GetTime() - this.combat)))
end end
end) end)
end end
@@ -144,7 +153,9 @@ pfUI:RegisterModule("panel", function()
pfUI.addons:Show() pfUI.addons:Show()
end end
end end
C_Timer.NewTicker(1, function() widget:SetScript("OnUpdate",function()
if ( this.tick or 1) > GetTime() then return else this.tick = GetTime() + 1 end
fps = floor(GetFramerate()) fps = floor(GetFramerate())
_, _, lag = GetNetStats() _, _, lag = GetNetStats()
@@ -335,7 +346,7 @@ pfUI:RegisterModule("panel", function()
widget:RegisterEvent("PLAYER_GUILD_UPDATE") widget:RegisterEvent("PLAYER_GUILD_UPDATE")
widget.Tooltip = function() widget.Tooltip = function()
-- skip without guild -- skip without guild
if not IsInGuild() then return end if not GetGuildInfo("player") then return end
local raidparty = {} local raidparty = {}
for i=1,4 do -- detect people in group for i=1,4 do -- detect people in group
@@ -387,7 +398,7 @@ pfUI:RegisterModule("panel", function()
end end
widget.Click = function() ToggleFriendsFrame(3) end widget.Click = function() ToggleFriendsFrame(3) end
widget:SetScript("OnEvent", function() widget:SetScript("OnEvent", function()
if IsInGuild() then if GetGuildInfo("player") then
local count = 0 local count = 0
for i = 1, GetNumGuildMembers() do for i = 1, GetNumGuildMembers() do
local _, _, _, _, _, _, _, _, online = GetGuildRosterInfo(i) local _, _, _, _, _, _, _, _, online = GetGuildRosterInfo(i)
@@ -400,8 +411,9 @@ pfUI:RegisterModule("panel", function()
end end
end) end)
C_Timer.NewTicker(60, function() widget:SetScript("OnUpdate",function()
if IsInGuild() then GuildRoster() end if ( this.tick or 60) > GetTime() then return else this.tick = GetTime() + 60 end
if GetGuildInfo("player") then GuildRoster() end
end) end)
end end
@@ -480,7 +492,11 @@ pfUI:RegisterModule("panel", function()
GameTooltip:Show() GameTooltip:Show()
end end
widget.Click = function() widget.Click = function()
WorldMapFrame:SetShown(not WorldMapFrame:IsShown()) if WorldMapFrame:IsShown() then
WorldMapFrame:Hide()
else
WorldMapFrame:Show()
end
end end
widget:SetScript("OnEvent", function() widget:SetScript("OnEvent", function()
pfUI.panel:OutputPanel("zone", GetMinimapZoneText(), widget.Tooltip, widget.Click) pfUI.panel:OutputPanel("zone", GetMinimapZoneText(), widget.Tooltip, widget.Click)
@@ -629,7 +645,8 @@ pfUI:RegisterModule("panel", function()
local frame = CreateFrame("Button", nil, parent) local frame = CreateFrame("Button", nil, parent)
frame:SetFrameLevel(0) frame:SetFrameLevel(0)
frame:ClearAllPoints() frame:ClearAllPoints()
frame:SetSize(width, parent:GetHeight()) frame:SetWidth(width)
frame:SetHeight(parent:GetHeight())
frame:SetPoint(location, 0, 0) frame:SetPoint(location, 0, 0)
frame.text = frame:CreateFontString("Status", "LOW", "GameFontNormal") frame.text = frame:CreateFontString("Status", "LOW", "GameFontNormal")
frame.text:ClearAllPoints() frame.text:ClearAllPoints()
@@ -670,7 +687,8 @@ pfUI:RegisterModule("panel", function()
local imgstring = "img:" .. leftright local imgstring = "img:" .. leftright
parent.texture:SetTexture(pfUI.media[imgstring]) parent.texture:SetTexture(pfUI.media[imgstring])
parent.texture:SetPoint("CENTER", 0, 0) parent.texture:SetPoint("CENTER", 0, 0)
parent.texture:SetSize(8, 8) parent.texture:SetWidth(8)
parent.texture:SetHeight(8)
parent.texture:SetVertexColor(.25,.25,.25,1) parent.texture:SetVertexColor(.25,.25,.25,1)
return parent.texture return parent.texture
end end
@@ -692,7 +710,7 @@ pfUI:RegisterModule("panel", function()
UpdateMovable(pfUI.panel.left) UpdateMovable(pfUI.panel.left)
pfUI.panel.left.hide:SetScript("OnClick", function() pfUI.panel.left.hide:SetScript("OnClick", function()
pfUI.chat.left:SetShown(not pfUI.chat.left:IsShown()) if pfUI.chat.left:IsShown() then pfUI.chat.left:Hide() else pfUI.chat.left:Show() end
end) end)
if not pfUI.chat then pfUI.panel.left.hide:Hide() end if not pfUI.chat then pfUI.panel.left.hide:Hide() end
@@ -729,7 +747,7 @@ pfUI:RegisterModule("panel", function()
UpdateMovable(pfUI.panel.right) UpdateMovable(pfUI.panel.right)
pfUI.panel.right.hide:SetScript("OnClick", function() pfUI.panel.right.hide:SetScript("OnClick", function()
pfUI.chat.right:SetShown(not pfUI.chat.right:IsShown()) if pfUI.chat.right:IsShown() then pfUI.chat.right:Hide() else pfUI.chat.right:Show() end
end) end)
if not pfUI.chat then pfUI.panel.right.hide:Hide() end if not pfUI.chat then pfUI.panel.right.hide:Hide() end
@@ -778,7 +796,8 @@ pfUI:RegisterModule("panel", function()
pfUI.panel.microbutton = CreateFrame("Frame", "pfPanelMicroButton", UIParent) pfUI.panel.microbutton = CreateFrame("Frame", "pfPanelMicroButton", UIParent)
pfUI.panel.microbutton:SetPoint("TOP", pfUI.panel.minimap, "BOTTOM", 0, -2*default_border) pfUI.panel.microbutton:SetPoint("TOP", pfUI.panel.minimap, "BOTTOM", 0, -2*default_border)
UpdateMovable(pfUI.panel.microbutton) UpdateMovable(pfUI.panel.microbutton)
pfUI.panel.microbutton:SetSize(145, 23) pfUI.panel.microbutton:SetHeight(23)
pfUI.panel.microbutton:SetWidth(145)
pfUI.panel.microbutton:SetFrameStrata("MEDIUM") pfUI.panel.microbutton:SetFrameStrata("MEDIUM")
for i=1,table.getn(MICRO_BUTTONS) do for i=1,table.getn(MICRO_BUTTONS) do
+30 -28
View File
@@ -39,20 +39,17 @@ pfUI:RegisterModule("player", function ()
playerFrame.isSpellCaster = myclass ~= "WARRIOR" and myclass ~= "ROGUE" and myclass ~= "HUNTER" playerFrame.isSpellCaster = myclass ~= "WARRIOR" and myclass ~= "ROGUE" and myclass ~= "HUNTER"
-- Convert "r,g,b,a" config color string to a 6-char hex string, or nil if unset -- Convert "r,g,b,a" config color string to a 6-char hex string, or nil if unset
local cfgColorToHexTable = setmetatable({}, { local function cfgColorToHex(colorStr)
__index = function (t, colorStr) if not colorStr or colorStr == "" then return nil end
if not colorStr or colorStr == "" then return nil end local r, g, b = strsplit(",", colorStr)
local r, g, b = GetStringColor(colorStr) r, g, b = tonumber(r), tonumber(g), tonumber(b)
if not r or not g or not b then return nil end if not r or not g or not b then return nil end
local hex = C_ColorUtil.GenerateTextColorCode({ r=r, g = g, b=b}) return string.format("%02X%02X%02X", r * 255, g * 255, b * 255)
rawset(t, colorStr, hex) end
return hex
end
})
-- SP school colors indexed by GetSpellBonusDamage's 1-based school order -- SP school colors indexed by GetSpellBonusDamage's 1-based school order
-- (1=phys, 2=holy, 3=fire, 4=nature, 5=frost, 6=shadow, 7=arcane) -- (1=phys, 2=holy, 3=fire, 4=nature, 5=frost, 6=shadow, 7=arcane)
local spColors = { "FFFFFFFF", "FFFFFF80", "FFFF8000", "FF4DFF4D", "FF80FFFF", "FF9482C9", "FFFFFFFF" } local spColors = { "FFFFFF", "FFFF80", "FF8000", "4DFF4D", "80FFFF", "9482C9", "FFFFFF" }
-- Default SP school per class used as tiebreaker when multiple schools are equal -- Default SP school per class used as tiebreaker when multiple schools are equal
local spDefaultSchool = { local spDefaultSchool = {
@@ -71,37 +68,42 @@ pfUI:RegisterModule("player", function ()
-- from UNIT_MOD_CAST_SPEED). Talent/spell-specific cast-time reductions -- from UNIT_MOD_CAST_SPEED). Talent/spell-specific cast-time reductions
-- show up in the actual cast bar via C_Spell.UnitCastingInfo; folding them -- show up in the actual cast bar via C_Spell.UnitCastingInfo; folding them
-- in here too was mixing two different concepts into one number. -- in here too was mixing two different concepts into one number.
local isSpellCaster = playerFrame.isSpellCaster local showHaste = cfg.display_haste == "1"
local showHaste = isSpellCaster and cfg.display_haste == "1" local showSP = cfg.display_spellpower == "1"
local showSP = isSpellCaster and cfg.display_spellpower == "1"
if not showHaste and not showSP then local isSpellCaster = playerFrame.isSpellCaster
if (not showHaste or not isSpellCaster) and not showSP then
playerFrame.infoTopCenterText:SetText("") playerFrame.infoTopCenterText:SetText("")
return return
end end
local parts = {} local haste = UnitSpellHaste("player")
local text = ""
if showHaste then if showHaste and isSpellCaster and haste then
local hex = cfgColorToHexTable[cfg.display_haste_color] or "FFFFFFFF" local hasteHex = cfgColorToHex(cfg.display_haste_color) or "FFFFFF"
table.insert(parts, string.format("|c%s%.1f%%|r", hex, UnitSpellHaste("player"))) text = string.format("|cff%s%.1f%%|r", hasteHex, haste)
end end
if showSP then if showSP and isSpellCaster then
local school = spDefaultSchool[myclass] or 2 local defSchool = spDefaultSchool[myclass] or 2
local maxSP = GetSpellBonusDamage(school) or 0 local maxSP = GetSpellBonusDamage(defSchool) or 0
for i = 2, 7 do -- skip physical (1) local maxColor = spColors[defSchool]
for i = 2, 7 do -- skip physical (1); default school seeds the tiebreak
local v = GetSpellBonusDamage(i) or 0 local v = GetSpellBonusDamage(i) or 0
if v > maxSP then maxSP, school = v, i end if v > maxSP then
maxSP = v
maxColor = spColors[i]
end
end end
if maxSP > 0 then if maxSP > 0 then
local hex = (cfg.display_sp_color_override == "1" and cfgColorToHexTable[cfg.display_sp_color]) or spColors[school] local spHex = (cfg.display_sp_color_override == "1" and cfgColorToHex(cfg.display_sp_color)) or maxColor
table.insert(parts, string.format("|c%s+%d SP|r", hex, maxSP)) if text ~= "" then text = text .. " " end
text = text .. string.format("|cff%s+%d SP|r", spHex, maxSP)
end end
end end
playerFrame.infoTopCenterText:SetText(table.concat(parts, " ")) playerFrame.infoTopCenterText:SetText(text)
end end
-- Keep a reference to the generic UF UpdateConfig so we can chain it -- Keep a reference to the generic UF UpdateConfig so we can chain it
+1 -1
View File
@@ -234,7 +234,7 @@ pfUI:RegisterModule("roll", function ()
f.time.bar:SetAllPoints(f.time) f.time.bar:SetAllPoints(f.time)
f.time.bar:SetStatusBarTexture(pfUI.media["img:bar"]) f.time.bar:SetStatusBarTexture(pfUI.media["img:bar"])
f.time.bar:SetMinMaxValues(0, 100) f.time.bar:SetMinMaxValues(0, 100)
local r, g, b, a = GetStringColor(C.appearance.border.color) local r, g, b, a = strsplit(",", C.appearance.border.color)
f.time.bar:SetStatusBarColor(r, g, b) f.time.bar:SetStatusBarColor(r, g, b)
f.time.bar:SetValue(20) f.time.bar:SetValue(20)
f.time.bar:SetScript("OnUpdate", function() f.time.bar:SetScript("OnUpdate", function()
+6 -6
View File
@@ -100,10 +100,10 @@ pfUI:RegisterModule("thirdparty-vanilla", function()
CreateBackdropShadow(KLHTM_Frame) CreateBackdropShadow(KLHTM_Frame)
if C.thirdparty.chatbg == "1" and C.chat.global.custombg == "1" then if C.thirdparty.chatbg == "1" and C.chat.global.custombg == "1" then
local r, g, b, a = GetStringColor(C.chat.global.background) local r, g, b, a = strsplit(",", C.chat.global.background)
KLHTM_Frame.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) KLHTM_Frame.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
local r, g, b, a = GetStringColor(C.chat.global.border) local r, g, b, a = strsplit(",", C.chat.global.border)
KLHTM_Frame.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) KLHTM_Frame.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
end end
@@ -199,10 +199,10 @@ pfUI:RegisterModule("thirdparty-vanilla", function()
CreateBackdropShadow(TWTMain) CreateBackdropShadow(TWTMain)
if C.thirdparty.chatbg == "1" and C.chat.global.custombg == "1" then if C.thirdparty.chatbg == "1" and C.chat.global.custombg == "1" then
local r, g, b, a = GetStringColor(C.chat.global.background) local r, g, b, a = strsplit(",", C.chat.global.background)
TWTMain.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) TWTMain.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
local r, g, b, a = GetStringColor(C.chat.global.border) local r, g, b, a = strsplit(",", C.chat.global.border)
TWTMain.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) TWTMain.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
end end
@@ -328,10 +328,10 @@ pfUI:RegisterModule("thirdparty-vanilla", function()
CreateBackdropShadow(SW_BarFrame1) CreateBackdropShadow(SW_BarFrame1)
if C.thirdparty.chatbg == "1" and C.chat.global.custombg == "1" then if C.thirdparty.chatbg == "1" and C.chat.global.custombg == "1" then
local r, g, b, a = GetStringColor(C.chat.global.background) local r, g, b, a = strsplit(",", C.chat.global.background)
SW_BarFrame1.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) SW_BarFrame1.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
local r, g, b, a = GetStringColor(C.chat.global.border) local r, g, b, a = strsplit(",", C.chat.global.border)
SW_BarFrame1.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) SW_BarFrame1.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
end end
+4 -4
View File
@@ -244,10 +244,10 @@ pfUI:RegisterModule("thirdparty", function()
end end
if C.thirdparty.chatbg == "1" and C.chat.global.custombg == "1" then if C.thirdparty.chatbg == "1" and C.chat.global.custombg == "1" then
local r, g, b, a = GetStringColor(C.chat.global.background) local r, g, b, a = strsplit(",", C.chat.global.background)
window.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) window.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
local r, g, b, a = GetStringColor(C.chat.global.border) local r, g, b, a = strsplit(",", C.chat.global.border)
window.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) window.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
end end
@@ -350,10 +350,10 @@ pfUI:RegisterModule("thirdparty", function()
CreateBackdropShadow(frame) CreateBackdropShadow(frame)
if C.thirdparty.chatbg == "1" and C.chat.global.custombg == "1" then if C.thirdparty.chatbg == "1" and C.chat.global.custombg == "1" then
local r, g, b, a = GetStringColor(C.chat.global.background) local r, g, b, a = strsplit(",", C.chat.global.background)
frame.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) frame.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
local r, g, b, a = GetStringColor(C.chat.global.border) local r, g, b, a = strsplit(",", C.chat.global.border)
frame.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a)) frame.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
end end
end end
-14
View File
@@ -266,18 +266,4 @@ pfUI:RegisterModule("tooltip", function ()
end end
GameTooltip:Show() GameTooltip:Show()
end end
if C.tooltip.aurasource == "1" then
hooksecurefunc(GameTooltip, "SetUnitAura", function(self, ...)
local aura = C_UnitAuras.GetAuraDataByIndex(unpack(arg))
if not aura then return end
local caster = aura.sourceUnit and UnitName(aura.sourceUnit)
if not caster and aura.sourceGUID then
caster = UnitNameFromGUID(aura.sourceGUID)
end
if not caster or caster == "" then return end
self:AddLine(T["Cast by"] .. ": " .. caster, .7, .7, 1)
self:Show()
end)
end
end) end)
-19
View File
@@ -355,25 +355,6 @@ pfUI:RegisterModule("turtle-wow", function ()
end end
end) end)
if C.disabled["macroicons"] == "1" then
HookAddonOrVariable("Blizzard_MacroUI", function()
if type(UpdateMacroIconFilenames) ~= "function" then return end
function _G.UpdateMacroIconFilenames()
wipe(MACRO_ICON_FILENAMES)
local provider = CreateAndInitFromMixin(IconDataProviderMixin, IconDataProviderExtraType.Spellbook)
local seen = {}
for i = 1, provider:GetNumIcons() do
-- uppercase, prefix-stripped basename, matching Blizzard's original
local icon = string.gsub(string.upper(provider:GetIconByIndex(i)), "INTERFACE\\ICONS\\", "")
if not seen[icon] then
seen[icon] = true
table.insert(MACRO_ICON_FILENAMES, icon)
end
end
provider:Release()
end
end)
end
-- add turtle-wow sell values -- add turtle-wow sell values
pfSellData = { pfSellData = {
+1 -1
View File
@@ -23,7 +23,7 @@ do
-- ClassicAPI dependency check. -- ClassicAPI dependency check.
-- pfUI relies pervasively on the modern C_* / SuperWoW / nameplate / focus -- pfUI relies pervasively on the modern C_* / SuperWoW / nameplate / focus
-- API surface that ClassicAPI polyfills, so presence is required. -- API surface that ClassicAPI polyfills, so presence is required.
local PFUI_CLASSIC_API_MIN = 10903 -- (X*10000 + Y*100 + Z) local PFUI_CLASSIC_API_MIN = 10802 -- (X*10000 + Y*100 + Z)
local PFUI_CLASSIC_API_LATEST = PFUI_CLASSIC_API_MIN local PFUI_CLASSIC_API_LATEST = PFUI_CLASSIC_API_MIN
local PFUI_CLASSIC_API_WEBSITE = "https://github.com/brues-code/ClassicAPI" local PFUI_CLASSIC_API_WEBSITE = "https://github.com/brues-code/ClassicAPI"
local PFUI_CLASSIC_API_LATEST_URL = PFUI_CLASSIC_API_WEBSITE .. "/releases/latest" local PFUI_CLASSIC_API_LATEST_URL = PFUI_CLASSIC_API_WEBSITE .. "/releases/latest"
+24 -26
View File
@@ -60,35 +60,33 @@ pfUI:RegisterSkin("Macro", function ()
MacroFrameScrollFrame:ClearAllPoints() MacroFrameScrollFrame:ClearAllPoints()
MacroFrameScrollFrame:SetPoint("TOPLEFT", MacroFrameSelectedMacroBackground, "BOTTOMLEFT", 11, -13) MacroFrameScrollFrame:SetPoint("TOPLEFT", MacroFrameSelectedMacroBackground, "BOTTOMLEFT", 11, -13)
-- The macroicons module replaces MacroPopupFrame with its own picker.
-- Only skin the stock popup when that module is disabled.
if pfUI_config["disabled"] and pfUI_config["disabled"]["macroicons"] == "1" then
StripTextures(MacroPopupFrame)
CreateBackdrop(MacroPopupFrame, nil, nil, .75)
MacroPopupFrame:SetFrameStrata("DIALOG")
MacroPopupFrame:ClearAllPoints()
MacroPopupFrame:SetPoint("TOPLEFT", MacroFrame.backdrop, "TOPRIGHT", 2*border, 0)
StripTextures(MacroPopupScrollFrame)
SkinScrollbar(MacroPopupScrollFrameScrollBar)
MacroPopupEditBox:DisableDrawLayer("BACKGROUND") StripTextures(MacroPopupFrame)
CreateBackdrop(MacroPopupEditBox, nil, true) CreateBackdrop(MacroPopupFrame, nil, nil, .75)
MacroPopupEditBox:SetScript("OnEscapePressed", function() MacroPopupFrame:SetFrameStrata("DIALOG")
MacroPopupFrame:Hide() MacroPopupFrame:ClearAllPoints()
MacroFrame_Update() MacroPopupFrame:SetPoint("TOPLEFT", MacroFrame.backdrop, "TOPRIGHT", 2*border, 0)
end)
for i=1, NUM_MACRO_ICONS_SHOWN do StripTextures(MacroPopupScrollFrame)
local button = _G["MacroPopupButton"..i] SkinScrollbar(MacroPopupScrollFrameScrollBar)
local icon = _G["MacroPopupButton"..i..'Icon']
StripTextures(button) MacroPopupEditBox:DisableDrawLayer("BACKGROUND")
SkinButton(button, nil, nil, nil, icon) CreateBackdrop(MacroPopupEditBox, nil, true)
end MacroPopupEditBox:SetScript("OnEscapePressed", function()
SkinButton(MacroPopupCancelButton) MacroPopupFrame:Hide()
SkinButton(MacroPopupOkayButton) MacroFrame_Update()
MacroPopupOkayButton:ClearAllPoints() end)
MacroPopupOkayButton:SetPoint("RIGHT", MacroPopupCancelButton, "LEFT", -2*bpad, 0)
for i=1, NUM_MACRO_ICONS_SHOWN do
local button = _G["MacroPopupButton"..i]
local icon = _G["MacroPopupButton"..i..'Icon']
StripTextures(button)
SkinButton(button, nil, nil, nil, icon)
end end
SkinButton(MacroPopupCancelButton)
SkinButton(MacroPopupOkayButton)
MacroPopupOkayButton:ClearAllPoints()
MacroPopupOkayButton:SetPoint("RIGHT", MacroPopupCancelButton, "LEFT", -2*bpad, 0)
end) end)
end) end)