initial commit
This commit is contained in:
25
Libraries/oUF/LICENSE
Normal file
25
Libraries/oUF/LICENSE
Normal file
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2006-2020 Trond A Ekseth <troeks@gmail.com>
|
||||
Copyright (c) 2016-2020 Val Voronov <i.lightspark@gmail.com>
|
||||
Copyright (c) 2016-2020 Adrian L Lange <contact@p3lim.net>
|
||||
Copyright (c) 2016-2020 Rainrider <rainrider.wow@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
132
Libraries/oUF/blizzard.lua
Normal file
132
Libraries/oUF/blizzard.lua
Normal file
@@ -0,0 +1,132 @@
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
-- sourced from Blizzard_ArenaUI/Blizzard_ArenaUI.lua
|
||||
local MAX_ARENA_ENEMIES = MAX_ARENA_ENEMIES or 5
|
||||
|
||||
-- sourced from FrameXML/TargetFrame.lua
|
||||
local MAX_BOSS_FRAMES = MAX_BOSS_FRAMES or 5
|
||||
|
||||
-- sourced from FrameXML/PartyMemberFrame.lua
|
||||
local MAX_PARTY_MEMBERS = MAX_PARTY_MEMBERS or 4
|
||||
|
||||
local hiddenParent = CreateFrame('Frame', nil, UIParent)
|
||||
hiddenParent:SetAllPoints()
|
||||
hiddenParent:Hide()
|
||||
|
||||
local function insecureOnShow(self)
|
||||
self:Hide()
|
||||
end
|
||||
|
||||
local function handleFrame(baseName, doNotReparent)
|
||||
local frame
|
||||
if(type(baseName) == 'string') then
|
||||
frame = _G[baseName]
|
||||
else
|
||||
frame = baseName
|
||||
end
|
||||
|
||||
if(frame) then
|
||||
frame:UnregisterAllEvents()
|
||||
frame:Hide()
|
||||
|
||||
if(not doNotReparent) then
|
||||
frame:SetParent(hiddenParent)
|
||||
end
|
||||
|
||||
local health = frame.healthBar or frame.healthbar
|
||||
if(health) then
|
||||
health:UnregisterAllEvents()
|
||||
end
|
||||
|
||||
local power = frame.manabar
|
||||
if(power) then
|
||||
power:UnregisterAllEvents()
|
||||
end
|
||||
|
||||
local spell = frame.castBar or frame.spellbar
|
||||
if(spell) then
|
||||
spell:UnregisterAllEvents()
|
||||
end
|
||||
|
||||
local altpowerbar = frame.powerBarAlt
|
||||
if(altpowerbar) then
|
||||
altpowerbar:UnregisterAllEvents()
|
||||
end
|
||||
|
||||
local buffFrame = frame.BuffFrame
|
||||
if(buffFrame) then
|
||||
buffFrame:UnregisterAllEvents()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function oUF:DisableBlizzard(unit)
|
||||
if(not unit) then return end
|
||||
|
||||
if(unit == 'player') then
|
||||
handleFrame(PlayerFrame)
|
||||
|
||||
-- For the damn vehicle support:
|
||||
PlayerFrame:RegisterEvent('PLAYER_ENTERING_WORLD')
|
||||
PlayerFrame:RegisterEvent('UNIT_ENTERING_VEHICLE')
|
||||
PlayerFrame:RegisterEvent('UNIT_ENTERED_VEHICLE')
|
||||
PlayerFrame:RegisterEvent('UNIT_EXITING_VEHICLE')
|
||||
PlayerFrame:RegisterEvent('UNIT_EXITED_VEHICLE')
|
||||
|
||||
-- User placed frames don't animate
|
||||
PlayerFrame:SetUserPlaced(true)
|
||||
PlayerFrame:SetDontSavePosition(true)
|
||||
elseif(unit == 'pet') then
|
||||
handleFrame(PetFrame)
|
||||
elseif(unit == 'target') then
|
||||
handleFrame(TargetFrame)
|
||||
handleFrame(ComboFrame)
|
||||
elseif(unit == 'focus') then
|
||||
handleFrame(FocusFrame)
|
||||
handleFrame(TargetofFocusFrame)
|
||||
elseif(unit == 'targettarget') then
|
||||
handleFrame(TargetFrameToT)
|
||||
elseif(unit:match('boss%d?$')) then
|
||||
local id = unit:match('boss(%d)')
|
||||
if(id) then
|
||||
handleFrame('Boss' .. id .. 'TargetFrame')
|
||||
else
|
||||
for i = 1, MAX_BOSS_FRAMES do
|
||||
handleFrame(string.format('Boss%dTargetFrame', i))
|
||||
end
|
||||
end
|
||||
elseif(unit:match('party%d?$')) then
|
||||
local id = unit:match('party(%d)')
|
||||
if(id) then
|
||||
handleFrame('PartyMemberFrame' .. id)
|
||||
else
|
||||
for i = 1, MAX_PARTY_MEMBERS do
|
||||
handleFrame(string.format('PartyMemberFrame%d', i))
|
||||
end
|
||||
end
|
||||
elseif(unit:match('arena%d?$')) then
|
||||
local id = unit:match('arena(%d)')
|
||||
if(id) then
|
||||
handleFrame('ArenaEnemyFrame' .. id)
|
||||
else
|
||||
for i = 1, MAX_ARENA_ENEMIES do
|
||||
handleFrame(string.format('ArenaEnemyFrame%d', i))
|
||||
end
|
||||
end
|
||||
|
||||
-- Blizzard_ArenaUI should not be loaded
|
||||
Arena_LoadUI = function() end
|
||||
SetCVar('showArenaEnemyFrames', '0', 'SHOW_ARENA_ENEMY_FRAMES_TEXT')
|
||||
elseif(unit:match('nameplate%d+$')) then
|
||||
local frame = C_NamePlate.GetNamePlateForUnit(unit)
|
||||
if(frame and frame.UnitFrame) then
|
||||
if(not frame.UnitFrame.isHooked) then
|
||||
frame.UnitFrame:HookScript('OnShow', insecureOnShow)
|
||||
frame.UnitFrame.isHooked = true
|
||||
end
|
||||
|
||||
handleFrame(frame.UnitFrame, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
272
Libraries/oUF/colors.lua
Normal file
272
Libraries/oUF/colors.lua
Normal file
@@ -0,0 +1,272 @@
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local frame_metatable = Private.frame_metatable
|
||||
|
||||
local colors = {
|
||||
smooth = {
|
||||
1, 0, 0,
|
||||
1, 1, 0,
|
||||
0, 1, 0
|
||||
},
|
||||
health = {49 / 255, 207 / 255, 37 / 255},
|
||||
disconnected = {0.6, 0.6, 0.6},
|
||||
tapped = {0.6, 0.6, 0.6},
|
||||
runes = {
|
||||
{247 / 255, 65 / 255, 57 / 255}, -- blood
|
||||
{148 / 255, 203 / 255, 247 / 255}, -- frost
|
||||
{173 / 255, 235 / 255, 66 / 255}, -- unholy
|
||||
},
|
||||
selection = {
|
||||
[ 0] = {255 / 255, 0 / 255, 0 / 255}, -- HOSTILE
|
||||
[ 1] = {255 / 255, 129 / 255, 0 / 255}, -- UNFRIENDLY
|
||||
[ 2] = {255 / 255, 255 / 255, 0 / 255}, -- NEUTRAL
|
||||
[ 3] = {0 / 255, 255 / 255, 0 / 255}, -- FRIENDLY
|
||||
[ 4] = {0 / 255, 0 / 255, 255 / 255}, -- PLAYER_SIMPLE
|
||||
[ 5] = {96 / 255, 96 / 255, 255 / 255}, -- PLAYER_EXTENDED
|
||||
[ 6] = {170 / 255, 170 / 255, 255 / 255}, -- PARTY
|
||||
[ 7] = {170 / 255, 255 / 255, 170 / 255}, -- PARTY_PVP
|
||||
[ 8] = {83 / 255, 201 / 255, 255 / 255}, -- FRIEND
|
||||
[ 9] = {128 / 255, 128 / 255, 128 / 255}, -- DEAD
|
||||
-- [10] = {}, -- COMMENTATOR_TEAM_1, unavailable to players
|
||||
-- [11] = {}, -- COMMENTATOR_TEAM_2, unavailable to players
|
||||
[12] = {255 / 255, 255 / 255, 139 / 255}, -- SELF, buggy
|
||||
[13] = {0 / 255, 153 / 255, 0 / 255}, -- BATTLEGROUND_FRIENDLY_PVP
|
||||
},
|
||||
class = {},
|
||||
debuff = {},
|
||||
reaction = {},
|
||||
power = {},
|
||||
threat = {},
|
||||
}
|
||||
|
||||
-- We do this because people edit the vars directly, and changing the default
|
||||
-- globals makes SPICE FLOW!
|
||||
local function customClassColors()
|
||||
if(CUSTOM_CLASS_COLORS) then
|
||||
local function updateColors()
|
||||
for classToken, color in next, CUSTOM_CLASS_COLORS do
|
||||
colors.class[classToken] = {color.r, color.g, color.b}
|
||||
end
|
||||
|
||||
for _, obj in next, oUF.objects do
|
||||
obj:UpdateAllElements('CUSTOM_CLASS_COLORS')
|
||||
end
|
||||
end
|
||||
|
||||
updateColors()
|
||||
CUSTOM_CLASS_COLORS:RegisterCallback(updateColors)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
if(not customClassColors()) then
|
||||
for classToken, color in next, RAID_CLASS_COLORS do
|
||||
colors.class[classToken] = {color.r, color.g, color.b}
|
||||
end
|
||||
|
||||
local eventHandler = CreateFrame('Frame')
|
||||
eventHandler:RegisterEvent('ADDON_LOADED')
|
||||
eventHandler:SetScript('OnEvent', function(self)
|
||||
if(customClassColors()) then
|
||||
self:UnregisterEvent('ADDON_LOADED')
|
||||
self:SetScript('OnEvent', nil)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
for debuffType, color in next, DebuffTypeColor do
|
||||
colors.debuff[debuffType] = {color.r, color.g, color.b}
|
||||
end
|
||||
|
||||
for eclass, color in next, FACTION_BAR_COLORS do
|
||||
colors.reaction[eclass] = {color.r, color.g, color.b}
|
||||
end
|
||||
|
||||
for power, color in next, PowerBarColor do
|
||||
if (type(power) == 'string') then
|
||||
if(type(select(2, next(color))) == 'table') then
|
||||
colors.power[power] = {}
|
||||
|
||||
for index, color in next, color do
|
||||
colors.power[power][index] = {color.r, color.g, color.b}
|
||||
end
|
||||
else
|
||||
colors.power[power] = {color.r, color.g, color.b, atlas = color.atlas}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- sourced from FrameXML/Constants.lua
|
||||
colors.power[0] = colors.power.MANA
|
||||
colors.power[1] = colors.power.RAGE
|
||||
colors.power[2] = colors.power.FOCUS
|
||||
colors.power[3] = colors.power.ENERGY
|
||||
colors.power[4] = colors.power.COMBO_POINTS
|
||||
colors.power[5] = colors.power.RUNES
|
||||
colors.power[6] = colors.power.RUNIC_POWER
|
||||
colors.power[7] = colors.power.SOUL_SHARDS
|
||||
colors.power[8] = colors.power.LUNAR_POWER
|
||||
colors.power[9] = colors.power.HOLY_POWER
|
||||
colors.power[11] = colors.power.MAELSTROM
|
||||
colors.power[12] = colors.power.CHI
|
||||
colors.power[13] = colors.power.INSANITY
|
||||
colors.power[16] = colors.power.ARCANE_CHARGES
|
||||
colors.power[17] = colors.power.FURY
|
||||
colors.power[18] = colors.power.PAIN
|
||||
|
||||
-- alternate power, sourced from FrameXML/CompactUnitFrame.lua
|
||||
colors.power.ALTERNATE = {0.7, 0.7, 0.6}
|
||||
colors.power[10] = colors.power.ALTERNATE
|
||||
|
||||
for i = 0, 3 do
|
||||
colors.threat[i] = {GetThreatStatusColor(i)}
|
||||
end
|
||||
|
||||
local function colorsAndPercent(a, b, ...)
|
||||
if(a <= 0 or b == 0) then
|
||||
return nil, ...
|
||||
elseif(a >= b) then
|
||||
return nil, select(-3, ...)
|
||||
end
|
||||
|
||||
local num = select('#', ...) / 3
|
||||
local segment, relperc = math.modf((a / b) * (num - 1))
|
||||
return relperc, select((segment * 3) + 1, ...)
|
||||
end
|
||||
|
||||
-- http://www.wowwiki.com/ColorGradient
|
||||
--[[ Colors: oUF:RGBColorGradient(a, b, ...)
|
||||
Used to convert a percent value (the quotient of `a` and `b`) into a gradient from 2 or more RGB colors. If more than 2
|
||||
colors are passed, the gradient will be between the two colors which perc lies in an evenly divided range. A RGB color
|
||||
is a sequence of 3 consecutive RGB percent values (in the range [0-1]). If `a` is negative or `b` is zero then the first
|
||||
RGB color (the first 3 RGB values passed to the function) is returned. If `a` is bigger than or equal to `b`, then the
|
||||
last 3 RGB values are returned.
|
||||
|
||||
* self - the global oUF object
|
||||
* a - value used as numerator to calculate the percentage (number)
|
||||
* b - value used as denominator to calculate the percentage (number)
|
||||
* ... - a list of RGB percent values. At least 6 values should be passed (number [0-1])
|
||||
--]]
|
||||
function oUF:RGBColorGradient(...)
|
||||
local relperc, r1, g1, b1, r2, g2, b2 = colorsAndPercent(...)
|
||||
if(relperc) then
|
||||
return r1 + (r2 - r1) * relperc, g1 + (g2 - g1) * relperc, b1 + (b2 - b1) * relperc
|
||||
else
|
||||
return r1, g1, b1
|
||||
end
|
||||
end
|
||||
|
||||
-- HCY functions are based on http://www.chilliant.com/rgb2hsv.html
|
||||
local function getY(r, g, b)
|
||||
return 0.299 * r + 0.587 * g + 0.114 * b
|
||||
end
|
||||
|
||||
local function rgbToHCY(r, g, b)
|
||||
local min, max = math.min(r, g, b), math.max(r, g, b)
|
||||
local chroma = max - min
|
||||
local hue
|
||||
if(chroma > 0) then
|
||||
if(r == max) then
|
||||
hue = ((g - b) / chroma) % 6
|
||||
elseif(g == max) then
|
||||
hue = (b - r) / chroma + 2
|
||||
elseif(b == max) then
|
||||
hue = (r - g) / chroma + 4
|
||||
end
|
||||
hue = hue / 6
|
||||
end
|
||||
return hue, chroma, getY(r, g, b)
|
||||
end
|
||||
|
||||
local function hcyToRGB(hue, chroma, luma)
|
||||
local r, g, b = 0, 0, 0
|
||||
if(hue and luma > 0) then
|
||||
local h2 = hue * 6
|
||||
local x = chroma * (1 - math.abs(h2 % 2 - 1))
|
||||
if(h2 < 1) then
|
||||
r, g, b = chroma, x, 0
|
||||
elseif(h2 < 2) then
|
||||
r, g, b = x, chroma, 0
|
||||
elseif(h2 < 3) then
|
||||
r, g, b = 0, chroma, x
|
||||
elseif(h2 < 4) then
|
||||
r, g, b = 0, x, chroma
|
||||
elseif(h2 < 5) then
|
||||
r, g, b = x, 0, chroma
|
||||
else
|
||||
r, g, b = chroma, 0, x
|
||||
end
|
||||
|
||||
local y = getY(r, g, b)
|
||||
if(luma < y) then
|
||||
chroma = chroma * (luma / y)
|
||||
elseif(y < 1) then
|
||||
chroma = chroma * (1 - luma) / (1 - y)
|
||||
end
|
||||
|
||||
r = (r - y) * chroma + luma
|
||||
g = (g - y) * chroma + luma
|
||||
b = (b - y) * chroma + luma
|
||||
end
|
||||
return r, g, b
|
||||
end
|
||||
|
||||
--[[ Colors: oUF:HCYColorGradient(a, b, ...)
|
||||
Used to convert a percent value (the quotient of `a` and `b`) into a gradient from 2 or more HCY colors. If more than 2
|
||||
colors are passed, the gradient will be between the two colors which perc lies in an evenly divided range. A HCY color
|
||||
is a sequence of 3 consecutive values in the range [0-1]. If `a` is negative or `b` is zero then the first
|
||||
HCY color (the first 3 HCY values passed to the function) is returned. If `a` is bigger than or equal to `b`, then the
|
||||
last 3 HCY values are returned.
|
||||
|
||||
* self - the global oUF object
|
||||
* a - value used as numerator to calculate the percentage (number)
|
||||
* b - value used as denominator to calculate the percentage (number)
|
||||
* ... - a list of HCY color values. At least 6 values should be passed (number [0-1])
|
||||
--]]
|
||||
function oUF:HCYColorGradient(...)
|
||||
local relperc, r1, g1, b1, r2, g2, b2 = colorsAndPercent(...)
|
||||
if(not relperc) then
|
||||
return r1, g1, b1
|
||||
end
|
||||
|
||||
local h1, c1, y1 = rgbToHCY(r1, g1, b1)
|
||||
local h2, c2, y2 = rgbToHCY(r2, g2, b2)
|
||||
local c = c1 + (c2 - c1) * relperc
|
||||
local y = y1 + (y2 - y1) * relperc
|
||||
|
||||
if(h1 and h2) then
|
||||
local dh = h2 - h1
|
||||
if(dh < -0.5) then
|
||||
dh = dh + 1
|
||||
elseif(dh > 0.5) then
|
||||
dh = dh - 1
|
||||
end
|
||||
|
||||
return hcyToRGB((h1 + dh * relperc) % 1, c, y)
|
||||
else
|
||||
return hcyToRGB(h1 or h2, c, y)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[ Colors: oUF:ColorGradient(a, b, ...) or frame:ColorGradient(a, b, ...)
|
||||
Used as a proxy to call the proper gradient function depending on the user's preference. If `oUF.useHCYColorGradient` is
|
||||
set to true, `:HCYColorGradient` will be called, else `:RGBColorGradient`.
|
||||
|
||||
* self - the global oUF object or a unit frame
|
||||
* a - value used as numerator to calculate the percentage (number)
|
||||
* b - value used as denominator to calculate the percentage (number)
|
||||
* ... - a list of color values. At least 6 values should be passed (number [0-1])
|
||||
--]]
|
||||
function oUF:ColorGradient(...)
|
||||
return (oUF.useHCYColorGradient and oUF.HCYColorGradient or oUF.RGBColorGradient)(self, ...)
|
||||
end
|
||||
|
||||
oUF.colors = colors
|
||||
oUF.useHCYColorGradient = false
|
||||
|
||||
frame_metatable.__index.colors = colors
|
||||
frame_metatable.__index.ColorGradient = oUF.ColorGradient
|
||||
315
Libraries/oUF/elements/additionalpower.lua
Normal file
315
Libraries/oUF/elements/additionalpower.lua
Normal file
@@ -0,0 +1,315 @@
|
||||
--[[
|
||||
# Element: Additional Power Bar
|
||||
|
||||
Handles the visibility and updating of a status bar that displays the player's additional power, such as Mana for
|
||||
Balance druids.
|
||||
|
||||
## Widget
|
||||
|
||||
AdditionalPower - A `StatusBar` that is used to display the player's additional power.
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
.bg - A `Texture` used as a background. Inherits the widget's color.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a StatusBar and doesn't have a texture set.
|
||||
|
||||
## Options
|
||||
|
||||
.frequentUpdates - Indicates whether to use UNIT_POWER_FREQUENT instead UNIT_POWER_UPDATE to update the bar (boolean)
|
||||
.displayPairs - Use to override display pairs. (table)
|
||||
.smoothGradient - 9 color values to be used with the .colorSmooth option (table)
|
||||
|
||||
The following options are listed by priority. The first check that returns true decides the color of the bar.
|
||||
|
||||
.colorPower - Use `self.colors.power[token]` to color the bar based on the player's additional power type
|
||||
(boolean)
|
||||
.colorClass - Use `self.colors.class[class]` to color the bar based on unit class. `class` is defined by the
|
||||
second return of [UnitClass](http://wowprogramming.com/docs/api/UnitClass.html) (boolean)
|
||||
.colorSmooth - Use `self.colors.smooth` to color the bar with a smooth gradient based on the player's current
|
||||
additional power percentage (boolean)
|
||||
|
||||
## Sub-Widget Options
|
||||
|
||||
.multiplier - Used to tint the background based on the widget's R, G and B values. Defaults to 1 (number)[0-1]
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local AdditionalPower = CreateFrame('StatusBar', nil, self)
|
||||
AdditionalPower:SetSize(20, 20)
|
||||
AdditionalPower:SetPoint('TOP')
|
||||
AdditionalPower:SetPoint('LEFT')
|
||||
AdditionalPower:SetPoint('RIGHT')
|
||||
|
||||
-- Add a background
|
||||
local Background = AdditionalPower:CreateTexture(nil, 'BACKGROUND')
|
||||
Background:SetAllPoints(AdditionalPower)
|
||||
Background:SetTexture(1, 1, 1, .5)
|
||||
|
||||
-- Register it with oUF
|
||||
AdditionalPower.bg = Background
|
||||
self.AdditionalPower = AdditionalPower
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local _, playerClass = UnitClass('player')
|
||||
|
||||
-- ElvUI block
|
||||
local unpack = unpack
|
||||
local CopyTable = CopyTable
|
||||
local UnitIsUnit = UnitIsUnit
|
||||
local UnitPlayerControlled = UnitPlayerControlled
|
||||
local UnitIsTapDenied = UnitIsTapDenied
|
||||
local UnitThreatSituation = UnitThreatSituation
|
||||
local UnitIsPlayer = UnitIsPlayer
|
||||
local UnitClass = UnitClass
|
||||
local UnitSelectionType = UnitSelectionType
|
||||
local UnitReaction = UnitReaction
|
||||
local UnitPower = UnitPower
|
||||
local UnitPowerMax = UnitPowerMax
|
||||
local UnitIsConnected = UnitIsConnected
|
||||
local UnitHasVehicleUI = UnitHasVehicleUI
|
||||
local UnitPowerType = UnitPowerType
|
||||
-- end block
|
||||
|
||||
-- sourced from FrameXML/AlternatePowerBar.lua
|
||||
local ADDITIONAL_POWER_BAR_NAME = ADDITIONAL_POWER_BAR_NAME or 'MANA'
|
||||
local ADDITIONAL_POWER_BAR_INDEX = ADDITIONAL_POWER_BAR_INDEX or 0
|
||||
local ALT_MANA_BAR_PAIR_DISPLAY_INFO = ALT_MANA_BAR_PAIR_DISPLAY_INFO
|
||||
|
||||
local function UpdateColor(self, event, unit, powerType)
|
||||
if(not (unit and UnitIsUnit(unit, 'player') and powerType == ADDITIONAL_POWER_BAR_NAME)) then return end
|
||||
local element = self.AdditionalPower
|
||||
|
||||
local r, g, b, t
|
||||
if(element.colorPower) then
|
||||
t = self.colors.power[ADDITIONAL_POWER_BAR_INDEX]
|
||||
elseif(element.colorClass) then
|
||||
t = self.colors.class[playerClass]
|
||||
elseif(element.colorSmooth) then
|
||||
r, g, b = self:ColorGradient(element.cur or 1, element.max or 1, unpack(element.smoothGradient or self.colors.smooth))
|
||||
end
|
||||
|
||||
if(t) then
|
||||
r, g, b = t[1], t[2], t[3]
|
||||
end
|
||||
|
||||
if(b) then
|
||||
element:SetStatusBarColor(r, g, b)
|
||||
|
||||
local bg = element.bg
|
||||
if(bg) then
|
||||
local mu = bg.multiplier or 1
|
||||
bg:SetVertexColor(r * mu, g * mu, b * mu)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Callback: AdditionalPower:PostUpdateColor(r, g, b)
|
||||
Called after the element color has been updated.
|
||||
|
||||
* self - the AdditionalPower element
|
||||
* r - the red component of the used color (number)[0-1]
|
||||
* g - the green component of the used color (number)[0-1]
|
||||
* b - the blue component of the used color (number)[0-1]
|
||||
--]]
|
||||
if(element.PostUpdateColor) then
|
||||
element:PostUpdateColor(r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
local function Update(self, event, unit, powerType)
|
||||
if(not (unit and UnitIsUnit(unit, 'player') and powerType == ADDITIONAL_POWER_BAR_NAME)) then return end
|
||||
local element = self.AdditionalPower
|
||||
|
||||
--[[ Callback: AdditionalPower:PreUpdate(unit)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the AdditionalPower element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate(unit)
|
||||
end
|
||||
|
||||
local cur, max = UnitPower('player', ADDITIONAL_POWER_BAR_INDEX), UnitPowerMax('player', ADDITIONAL_POWER_BAR_INDEX)
|
||||
element:SetMinMaxValues(0, max)
|
||||
|
||||
element:SetValue(cur)
|
||||
|
||||
element.cur = cur
|
||||
element.max = max
|
||||
|
||||
--[[ Callback: AdditionalPower:PostUpdate(cur, max)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the AdditionalPower element
|
||||
* cur - the current value of the player's additional power (number)
|
||||
* max - the maximum value of the player's additional power (number)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(cur, max, event) -- ElvUI adds event
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: AdditionalPower.Override(self, event, unit, ...)
|
||||
Used to completely override the element's update process.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
(self.AdditionalPower.Override or Update) (self, ...);
|
||||
|
||||
--[[ Override: AdditionalPower.UpdateColor(self, event, unit, ...)
|
||||
Used to completely override the internal function for updating the widgets' colors.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
(self.AdditionalPower.UpdateColor or UpdateColor) (self, ...)
|
||||
end
|
||||
|
||||
local function ElementEnable(self)
|
||||
local element = self.AdditionalPower
|
||||
|
||||
if(element.frequentUpdates) then
|
||||
self:RegisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
else
|
||||
self:RegisterEvent('UNIT_POWER_UPDATE', Path)
|
||||
end
|
||||
|
||||
self:RegisterEvent('UNIT_MAXPOWER', Path)
|
||||
|
||||
element:Show()
|
||||
|
||||
element.__isEnabled = true
|
||||
|
||||
Path(self, 'ElementEnable', 'player', ADDITIONAL_POWER_BAR_NAME)
|
||||
end
|
||||
|
||||
local function ElementDisable(self)
|
||||
local element = self.AdditionalPower
|
||||
|
||||
self:UnregisterEvent('UNIT_MAXPOWER', Path)
|
||||
self:UnregisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
self:UnregisterEvent('UNIT_POWER_UPDATE', Path)
|
||||
|
||||
element:Hide()
|
||||
|
||||
element.__isEnabled = false
|
||||
Path(self, 'ElementDisable', 'player', ADDITIONAL_POWER_BAR_NAME)
|
||||
end
|
||||
|
||||
local function Visibility(self, event, unit)
|
||||
local element = self.AdditionalPower
|
||||
local shouldEnable
|
||||
|
||||
if(not UnitHasVehicleUI('player')) then
|
||||
if(UnitPowerMax(unit, ADDITIONAL_POWER_BAR_INDEX) ~= 0) then
|
||||
if(element.displayPairs[playerClass]) then
|
||||
local powerType = UnitPowerType(unit)
|
||||
shouldEnable = element.displayPairs[playerClass][powerType]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local isEnabled = element.__isEnabled
|
||||
|
||||
if(shouldEnable and not isEnabled) then
|
||||
ElementEnable(self)
|
||||
|
||||
--[[ Callback: AdditionalPower:PostVisibility(isVisible)
|
||||
Called after the element's visibility has been changed.
|
||||
|
||||
* self - the AdditionalPower element
|
||||
* isVisible - the current visibility state of the element (boolean)
|
||||
--]]
|
||||
if(element.PostVisibility) then
|
||||
element:PostVisibility(true)
|
||||
end
|
||||
elseif(not shouldEnable and (isEnabled or isEnabled == nil)) then
|
||||
ElementDisable(self)
|
||||
|
||||
if(element.PostVisibility) then
|
||||
element:PostVisibility(false)
|
||||
end
|
||||
elseif(shouldEnable and isEnabled) then
|
||||
Path(self, event, unit, ADDITIONAL_POWER_BAR_NAME)
|
||||
end
|
||||
end
|
||||
|
||||
local function VisibilityPath(self, ...)
|
||||
--[[ Override: AdditionalPower.OverrideVisibility(self, event, unit)
|
||||
Used to completely override the element's visibility update process.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
--]]
|
||||
(self.AdditionalPower.OverrideVisibility or Visibility) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
VisibilityPath(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
--[[ Power:SetFrequentUpdates(state, isForced)
|
||||
Used to toggle frequent updates.
|
||||
|
||||
* self - the Power element
|
||||
* state - the desired state (boolean)
|
||||
* isForced - forces the event update even if the state wasn't changed (boolean)
|
||||
--]]
|
||||
local function SetFrequentUpdates(element, state, isForced)
|
||||
if(element.frequentUpdates ~= state or isForced) then
|
||||
element.frequentUpdates = state
|
||||
if(state) then
|
||||
element.__owner:UnregisterEvent('UNIT_POWER_UPDATE', Path)
|
||||
element.__owner:RegisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
else
|
||||
element.__owner:UnregisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
element.__owner:RegisterEvent('UNIT_POWER_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function Enable(self, unit)
|
||||
local element = self.AdditionalPower
|
||||
if(element and UnitIsUnit(unit, 'player')) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
element.SetFrequentUpdates = SetFrequentUpdates
|
||||
|
||||
self:RegisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
|
||||
if(not element.displayPairs) then
|
||||
element.displayPairs = CopyTable(ALT_MANA_BAR_PAIR_DISPLAY_INFO)
|
||||
end
|
||||
|
||||
if(element:IsObjectType('StatusBar') and not (element:GetStatusBarTexture() or element:GetStatusBarAtlas())) then
|
||||
element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.AdditionalPower
|
||||
if(element) then
|
||||
ElementDisable(self)
|
||||
|
||||
self:UnregisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('AdditionalPower', VisibilityPath, Enable, Disable)
|
||||
303
Libraries/oUF/elements/alternativepower.lua
Normal file
303
Libraries/oUF/elements/alternativepower.lua
Normal file
@@ -0,0 +1,303 @@
|
||||
--[[
|
||||
# Element: Alternative Power Bar
|
||||
|
||||
Handles the visibility and updating of a status bar that displays encounter- or quest-related power information, such as
|
||||
the number of hour glass charges during the Murozond encounter in the dungeon End Time.
|
||||
|
||||
## Widget
|
||||
|
||||
AlternativePower - A `StatusBar` used to represent the unit's alternative power.
|
||||
|
||||
## Notes
|
||||
|
||||
If mouse interactivity is enabled for the widget, `OnEnter` and/or `OnLeave` handlers will be set to display a tooltip.
|
||||
A default texture will be applied if the widget is a StatusBar and doesn't have a texture set.
|
||||
|
||||
## Options
|
||||
|
||||
.smoothGradient - 9 color values to be used with the .colorSmooth option (table)
|
||||
.considerSelectionInCombatHostile - Indicates whether selection should be considered hostile while the unit is in
|
||||
combat with the player (boolean)
|
||||
|
||||
The following options are listed by priority. The first check that returns true decides the color of the bar.
|
||||
|
||||
.colorThreat - Use `self.colors.threat[threat]` to color the bar based on the unit's threat status. `threat` is
|
||||
defined by the first return of [UnitThreatSituation](https://wow.gamepedia.com/API_UnitThreatSituation) (boolean)
|
||||
.colorPower - Use `self.colors.power[token]` to color the bar based on the unit's alternative power type
|
||||
(boolean)
|
||||
.colorClass - Use `self.colors.class[class]` to color the bar based on unit class. `class` is defined by the
|
||||
second return of [UnitClass](http://wowprogramming.com/docs/api/UnitClass.html) (boolean)
|
||||
.colorClassNPC - Use `self.colors.class[class]` to color the bar if the unit is a NPC (boolean)
|
||||
.colorSelection - Use `self.colors.selection[selection]` to color the bar based on the unit's selection color.
|
||||
`selection` is defined by the return value of Private.unitSelectionType, a wrapper function
|
||||
for [UnitSelectionType](https://wow.gamepedia.com/API_UnitSelectionType) (boolean)
|
||||
.colorReaction - Use `self.colors.reaction[reaction]` to color the bar based on the player's reaction towards the
|
||||
unit. `reaction` is defined by the return value of
|
||||
[UnitReaction](http://wowprogramming.com/docs/api/UnitReaction.html) (boolean)
|
||||
.colorSmooth - Use `self.colors.smooth` to color the bar with a smooth gradient based on the unit's current
|
||||
alternative power percentage (boolean)
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local AlternativePower = CreateFrame('StatusBar', nil, self)
|
||||
AlternativePower:SetHeight(20)
|
||||
AlternativePower:SetPoint('BOTTOM')
|
||||
AlternativePower:SetPoint('LEFT')
|
||||
AlternativePower:SetPoint('RIGHT')
|
||||
|
||||
-- Register with oUF
|
||||
self.AlternativePower = AlternativePower
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local unitSelectionType = Private.unitSelectionType
|
||||
|
||||
-- sourced from FrameXML/UnitPowerBarAlt.lua
|
||||
local ALTERNATE_POWER_INDEX = Enum.PowerType.Alternate or 10
|
||||
local ALTERNATE_POWER_NAME = 'ALTERNATE'
|
||||
local GameTooltip = GameTooltip
|
||||
|
||||
local function updateTooltip(self)
|
||||
if GameTooltip:IsForbidden() then return end
|
||||
|
||||
local name, tooltip = GetUnitPowerBarStringsByID(self.__barID)
|
||||
GameTooltip:SetText(name or '', 1, 1, 1)
|
||||
GameTooltip:AddLine(tooltip or '', nil, nil, nil, true)
|
||||
GameTooltip:Show()
|
||||
end
|
||||
|
||||
local function onEnter(self)
|
||||
if GameTooltip:IsForbidden() or not self:IsVisible() then return end
|
||||
|
||||
GameTooltip:ClearAllPoints()
|
||||
GameTooltip_SetDefaultAnchor(GameTooltip, self)
|
||||
self:UpdateTooltip()
|
||||
end
|
||||
|
||||
local function onLeave()
|
||||
if GameTooltip:IsForbidden() then return end
|
||||
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
local function UpdateColor(self, event, unit, powerType)
|
||||
if(self.unit ~= unit or powerType ~= ALTERNATE_POWER_NAME) then return end
|
||||
local element = self.AlternativePower
|
||||
|
||||
local r, g, b, t
|
||||
if(element.colorThreat and not UnitPlayerControlled(unit) and UnitThreatSituation('player', unit)) then
|
||||
t = self.colors.threat[UnitThreatSituation('player', unit)]
|
||||
elseif(element.colorPower) then
|
||||
t = self.colors.power[ALTERNATE_POWER_INDEX]
|
||||
elseif(element.colorClass and UnitIsPlayer(unit))
|
||||
or (element.colorClassNPC and not UnitIsPlayer(unit)) then
|
||||
local _, class = UnitClass(unit)
|
||||
t = self.colors.class[class]
|
||||
elseif(element.colorSelection and unitSelectionType(unit, element.considerSelectionInCombatHostile)) then
|
||||
t = self.colors.selection[unitSelectionType(unit, element.considerSelectionInCombatHostile)]
|
||||
elseif(element.colorReaction and UnitReaction(unit, 'player')) then
|
||||
t = self.colors.reaction[UnitReaction(unit, 'player')]
|
||||
elseif(element.colorSmooth) then
|
||||
local adjust = 0 - (element.min or 0)
|
||||
r, g, b = self:ColorGradient((element.cur or 1) + adjust, (element.max or 1) + adjust, unpack(element.smoothGradient or self.colors.smooth))
|
||||
end
|
||||
|
||||
if(t) then
|
||||
r, g, b = t[1], t[2], t[3]
|
||||
end
|
||||
|
||||
if(b) then
|
||||
element:SetStatusBarColor(r, g, b)
|
||||
|
||||
local bg = element.bg
|
||||
if(bg) then
|
||||
local mu = bg.multiplier or 1
|
||||
bg:SetVertexColor(r * mu, g * mu, b * mu)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Callback: AlternativePower:PostUpdateColor(unit, r, g, b)
|
||||
Called after the element color has been updated.
|
||||
|
||||
* self - the AlternativePower element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* r - the red component of the used color (number)[0-1]
|
||||
* g - the green component of the used color (number)[0-1]
|
||||
* b - the blue component of the used color (number)[0-1]
|
||||
--]]
|
||||
if(element.PostUpdateColor) then
|
||||
element:PostUpdateColor(unit, r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
local function Update(self, event, unit, powerType)
|
||||
if(self.unit ~= unit or powerType ~= ALTERNATE_POWER_NAME) then return end
|
||||
local element = self.AlternativePower
|
||||
|
||||
--[[ Callback: AlternativePower:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the AlternativePower element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local min, max, cur = 0
|
||||
local barInfo = element.__barInfo
|
||||
if(barInfo) then
|
||||
cur = UnitPower(unit, ALTERNATE_POWER_INDEX)
|
||||
max = UnitPowerMax(unit, ALTERNATE_POWER_INDEX)
|
||||
|
||||
if barInfo.minPower then
|
||||
min = barInfo.minPower
|
||||
end
|
||||
|
||||
element:SetMinMaxValues(min, max)
|
||||
element:SetValue(cur)
|
||||
end
|
||||
|
||||
element.cur = cur
|
||||
element.min = min
|
||||
element.max = max
|
||||
|
||||
--[[ Callback: AlternativePower:PostUpdate(unit, cur, min, max)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the AlternativePower element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* cur - the current value of the unit's alternative power (number?)
|
||||
* min - the minimum value of the unit's alternative power (number?)
|
||||
* max - the maximum value of the unit's alternative power (number?)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(unit, cur, min, max)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: AlternativePower.Override(self, event, unit, ...)
|
||||
Used to completely override the element's update process.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
(self.AlternativePower.Override or Update) (self, ...);
|
||||
|
||||
--[[ Override: AlternativePower.UpdateColor(self, event, unit, ...)
|
||||
Used to completely override the internal function for updating the widgets' colors.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
(self.AlternativePower.UpdateColor or UpdateColor) (self, ...)
|
||||
end
|
||||
|
||||
local function Visibility(self, event, unit)
|
||||
if(unit ~= self.unit) then return end
|
||||
local element = self.AlternativePower
|
||||
|
||||
local barID = UnitPowerBarID(unit)
|
||||
local barInfo = GetUnitPowerBarInfoByID(barID)
|
||||
element.__barID = barID
|
||||
element.__barInfo = barInfo
|
||||
if(barInfo and (barInfo.showOnRaid and (UnitInParty(unit) or UnitInRaid(unit))
|
||||
or not barInfo.hideFromOthers
|
||||
or UnitIsUnit(unit, 'player')))
|
||||
then
|
||||
self:RegisterEvent('UNIT_POWER_UPDATE', Path)
|
||||
self:RegisterEvent('UNIT_MAXPOWER', Path)
|
||||
|
||||
element:Show()
|
||||
Path(self, event, unit, ALTERNATE_POWER_NAME)
|
||||
else
|
||||
self:UnregisterEvent('UNIT_POWER_UPDATE', Path)
|
||||
self:UnregisterEvent('UNIT_MAXPOWER', Path)
|
||||
|
||||
element:Hide()
|
||||
Path(self, event, unit, ALTERNATE_POWER_NAME)
|
||||
end
|
||||
end
|
||||
|
||||
local function VisibilityPath(self, ...)
|
||||
--[[ Override: AlternativePower.OverrideVisibility(self, event, unit)
|
||||
Used to completely override the element's visibility update process.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
--]]
|
||||
return (self.AlternativePower.OverrideVisibility or Visibility) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return VisibilityPath(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self, unit)
|
||||
local element = self.AlternativePower
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_POWER_BAR_SHOW', VisibilityPath)
|
||||
self:RegisterEvent('UNIT_POWER_BAR_HIDE', VisibilityPath)
|
||||
|
||||
if(element:IsObjectType('StatusBar') and not (element:GetStatusBarTexture() or element:GetStatusBarAtlas())) then
|
||||
element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
|
||||
if(element:IsMouseEnabled()) then
|
||||
if(not element:GetScript('OnEnter')) then
|
||||
element:SetScript('OnEnter', onEnter)
|
||||
end
|
||||
|
||||
if(not element:GetScript('OnLeave')) then
|
||||
element:SetScript('OnLeave', onLeave)
|
||||
end
|
||||
|
||||
--[[ Override: AlternativePower:UpdateTooltip()
|
||||
Called when the mouse is over the widget. Used to populate its tooltip.
|
||||
|
||||
* self - the AlternativePower element
|
||||
--]]
|
||||
if(not element.UpdateTooltip) then
|
||||
element.UpdateTooltip = updateTooltip
|
||||
end
|
||||
end
|
||||
|
||||
if(unit == 'player') then
|
||||
PlayerPowerBarAlt:UnregisterEvent('UNIT_POWER_BAR_SHOW')
|
||||
PlayerPowerBarAlt:UnregisterEvent('UNIT_POWER_BAR_HIDE')
|
||||
PlayerPowerBarAlt:UnregisterEvent('PLAYER_ENTERING_WORLD')
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self, unit)
|
||||
local element = self.AlternativePower
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('UNIT_POWER_BAR_SHOW', VisibilityPath)
|
||||
self:UnregisterEvent('UNIT_POWER_BAR_HIDE', VisibilityPath)
|
||||
|
||||
if(unit == 'player') then
|
||||
PlayerPowerBarAlt:RegisterEvent('UNIT_POWER_BAR_SHOW')
|
||||
PlayerPowerBarAlt:RegisterEvent('UNIT_POWER_BAR_HIDE')
|
||||
PlayerPowerBarAlt:RegisterEvent('PLAYER_ENTERING_WORLD')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('AlternativePower', VisibilityPath, Enable, Disable)
|
||||
99
Libraries/oUF/elements/assistantindicator.lua
Normal file
99
Libraries/oUF/elements/assistantindicator.lua
Normal file
@@ -0,0 +1,99 @@
|
||||
--[[
|
||||
# Element: Assistant Indicator
|
||||
|
||||
Toggles the visibility of an indicator based on the unit's raid assistant status.
|
||||
|
||||
## Widget
|
||||
|
||||
AssistantIndicator - Any UI widget.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local AssistantIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
AssistantIndicator:SetSize(16, 16)
|
||||
AssistantIndicator:SetPoint('TOP', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.AssistantIndicator = AssistantIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event)
|
||||
local element = self.AssistantIndicator
|
||||
local unit = self.unit
|
||||
|
||||
--[[ Callback: AssistantIndicator:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the AssistantIndicator element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local isAssistant = UnitInRaid(unit) and UnitIsGroupAssistant(unit) and not UnitIsGroupLeader(unit)
|
||||
if(isAssistant) then
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
--[[ Callback: AssistantIndicator:PostUpdate(isAssistant)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the AssistantIndicator element
|
||||
* isAssistant - indicates whether the unit is a raid assistant (boolean)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(isAssistant)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: AssistantIndicator.Override(self, event, ...)
|
||||
Used to completely override the element's update process.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event (string)
|
||||
--]]
|
||||
return (self.AssistantIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.AssistantIndicator
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('GROUP_ROSTER_UPDATE', Path, true)
|
||||
|
||||
if(element:IsObjectType('Texture') and not element:GetTexture()) then
|
||||
element:SetTexture([[Interface\GroupFrame\UI-Group-AssistantIcon]])
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.AssistantIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('GROUP_ROSTER_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('AssistantIndicator', Path, Enable, Disable)
|
||||
655
Libraries/oUF/elements/auras.lua
Normal file
655
Libraries/oUF/elements/auras.lua
Normal file
@@ -0,0 +1,655 @@
|
||||
--[[
|
||||
# Element: Auras
|
||||
|
||||
Handles creation and updating of aura icons.
|
||||
|
||||
## Widget
|
||||
|
||||
Auras - A Frame to hold `Button`s representing both buffs and debuffs.
|
||||
Buffs - A Frame to hold `Button`s representing buffs.
|
||||
Debuffs - A Frame to hold `Button`s representing debuffs.
|
||||
|
||||
## Notes
|
||||
|
||||
At least one of the above widgets must be present for the element to work.
|
||||
|
||||
## Options
|
||||
|
||||
.disableMouse - Disables mouse events (boolean)
|
||||
.disableCooldown - Disables the cooldown spiral (boolean)
|
||||
.size - Aura icon size. Defaults to 16 (number)
|
||||
.onlyShowPlayer - Shows only auras created by player/vehicle (boolean)
|
||||
.showStealableBuffs - Displays the stealable texture on buffs that can be stolen (boolean)
|
||||
.spacing - Spacing between each icon. Defaults to 0 (number)
|
||||
.['spacing-x'] - Horizontal spacing between each icon. Takes priority over `spacing` (number)
|
||||
.['spacing-y'] - Vertical spacing between each icon. Takes priority over `spacing` (number)
|
||||
.['growth-x'] - Horizontal growth direction. Defaults to 'RIGHT' (string)
|
||||
.['growth-y'] - Vertical growth direction. Defaults to 'UP' (string)
|
||||
.initialAnchor - Anchor point for the icons. Defaults to 'BOTTOMLEFT' (string)
|
||||
.filter - Custom filter list for auras to display. Defaults to 'HELPFUL' for buffs and 'HARMFUL' for
|
||||
debuffs (string)
|
||||
.tooltipAnchor - Anchor point for the tooltip. Defaults to 'ANCHOR_BOTTOMRIGHT', however, if a frame has anchoring
|
||||
restrictions it will be set to 'ANCHOR_CURSOR' (string)
|
||||
|
||||
## Options Auras
|
||||
|
||||
.numBuffs - The maximum number of buffs to display. Defaults to 32 (number)
|
||||
.numDebuffs - The maximum number of debuffs to display. Defaults to 40 (number)
|
||||
.numTotal - The maximum number of auras to display. Prioritizes buffs over debuffs. Defaults to the sum of
|
||||
.numBuffs and .numDebuffs (number)
|
||||
.gap - Controls the creation of an invisible icon between buffs and debuffs. Defaults to false (boolean)
|
||||
.buffFilter - Custom filter list for buffs to display. Takes priority over `filter` (string)
|
||||
.debuffFilter - Custom filter list for debuffs to display. Takes priority over `filter` (string)
|
||||
|
||||
## Options Buffs
|
||||
|
||||
.num - Number of buffs to display. Defaults to 32 (number)
|
||||
|
||||
## Options Debuffs
|
||||
|
||||
.num - Number of debuffs to display. Defaults to 40 (number)
|
||||
|
||||
## Attributes
|
||||
|
||||
button.caster - the unit who cast the aura (string)
|
||||
button.filter - the filter list used to determine the visibility of the aura (string)
|
||||
button.isDebuff - indicates if the button holds a debuff (boolean)
|
||||
button.isPlayer - indicates if the aura caster is the player or their vehicle (boolean)
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local Buffs = CreateFrame('Frame', nil, self)
|
||||
Buffs:SetPoint('RIGHT', self, 'LEFT')
|
||||
Buffs:SetSize(16 * 2, 16 * 16)
|
||||
|
||||
-- Register with oUF
|
||||
self.Buffs = Buffs
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local VISIBLE = 1
|
||||
local HIDDEN = 0
|
||||
|
||||
-- ElvUI changed block
|
||||
local CREATED = 2
|
||||
|
||||
local pcall = pcall
|
||||
local tinsert = tinsert
|
||||
local CreateFrame = CreateFrame
|
||||
local GetSpellInfo = GetSpellInfo
|
||||
local UnitAura = UnitAura
|
||||
local UnitIsUnit = UnitIsUnit
|
||||
local GameTooltip = GameTooltip
|
||||
local floor, min = math.floor, math.min
|
||||
-- end block
|
||||
|
||||
-- ElvUI adds IsForbidden checks
|
||||
local function UpdateTooltip(self)
|
||||
if GameTooltip:IsForbidden() then return end
|
||||
|
||||
GameTooltip:SetUnitAura(self:GetParent().__owner.unit, self:GetID(), self.filter)
|
||||
end
|
||||
|
||||
local function onEnter(self)
|
||||
if GameTooltip:IsForbidden() or not self:IsVisible() then return end
|
||||
|
||||
GameTooltip:SetOwner(self, self:GetParent().tooltipAnchor)
|
||||
self:UpdateTooltip()
|
||||
end
|
||||
|
||||
local function onLeave()
|
||||
if GameTooltip:IsForbidden() then return end
|
||||
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
local function createAuraIcon(element, index)
|
||||
local button = CreateFrame('Button', element:GetName() .. 'Button' .. index, element, "BackdropTemplate")
|
||||
button:RegisterForClicks('RightButtonUp')
|
||||
|
||||
local cd = CreateFrame('Cooldown', '$parentCooldown', button, 'CooldownFrameTemplate')
|
||||
cd:SetAllPoints()
|
||||
|
||||
local icon = button:CreateTexture(nil, 'BORDER')
|
||||
icon:SetAllPoints()
|
||||
|
||||
local countFrame = CreateFrame('Frame', nil, button)
|
||||
countFrame:SetAllPoints(button)
|
||||
countFrame:SetFrameLevel(cd:GetFrameLevel() + 1)
|
||||
|
||||
local count = countFrame:CreateFontString(nil, 'OVERLAY', 'NumberFontNormal')
|
||||
count:SetPoint('BOTTOMRIGHT', countFrame, 'BOTTOMRIGHT', -1, 0)
|
||||
|
||||
local overlay = button:CreateTexture(nil, 'OVERLAY')
|
||||
overlay:SetTexture([[Interface\Buttons\UI-Debuff-Overlays]])
|
||||
overlay:SetAllPoints()
|
||||
overlay:SetTexCoord(.296875, .5703125, 0, .515625)
|
||||
button.overlay = overlay
|
||||
|
||||
local stealable = button:CreateTexture(nil, 'OVERLAY')
|
||||
stealable:SetTexture([[Interface\TargetingFrame\UI-TargetingFrame-Stealable]])
|
||||
stealable:SetPoint('TOPLEFT', -3, 3)
|
||||
stealable:SetPoint('BOTTOMRIGHT', 3, -3)
|
||||
stealable:SetBlendMode('ADD')
|
||||
button.stealable = stealable
|
||||
|
||||
button.UpdateTooltip = UpdateTooltip
|
||||
button:SetScript('OnEnter', onEnter)
|
||||
button:SetScript('OnLeave', onLeave)
|
||||
|
||||
button.icon = icon
|
||||
button.count = count
|
||||
button.cd = cd
|
||||
|
||||
--[[ Callback: Auras:PostCreateIcon(button)
|
||||
Called after a new aura button has been created.
|
||||
|
||||
* self - the widget holding the aura buttons
|
||||
* button - the newly created aura button (Button)
|
||||
--]]
|
||||
if(element.PostCreateIcon) then element:PostCreateIcon(button) end
|
||||
|
||||
return button
|
||||
end
|
||||
|
||||
local function customFilter(element, unit, button, name)
|
||||
if((element.onlyShowPlayer and button.isPlayer) or (not element.onlyShowPlayer and name)) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function updateIcon(element, unit, index, offset, filter, isDebuff, visible)
|
||||
local name, texture, count, debuffType, duration, expiration, caster, isStealable,
|
||||
nameplateShowSelf, spellID, canApply, isBossDebuff, casterIsPlayer, nameplateShowAll,
|
||||
timeMod, effect1, effect2, effect3 = UnitAura(unit, index, filter)
|
||||
|
||||
-- ElvUI changed block
|
||||
if element.forceShow or element.forceCreate then
|
||||
spellID = 47540
|
||||
name, _, texture = GetSpellInfo(spellID)
|
||||
if element.forceShow then
|
||||
count, debuffType, duration, expiration, caster, isStealable, nameplateShowSelf, isBossDebuff = 5, "Magic", 0, 60, "player", nil, nil, nil
|
||||
end
|
||||
end
|
||||
|
||||
if isStealable then
|
||||
element.hasStealable = true -- for Style Filters
|
||||
end
|
||||
-- end Block
|
||||
|
||||
if(name) then
|
||||
local position = visible + offset + 1
|
||||
local button = element[position]
|
||||
if(not button) then
|
||||
--[[ Override: Auras:CreateIcon(position)
|
||||
Used to create the aura button at a given position.
|
||||
|
||||
* self - the widget holding the aura buttons
|
||||
* position - the position at which the aura button is to be created (number)
|
||||
|
||||
## Returns
|
||||
|
||||
* button - the button used to represent the aura (Button)
|
||||
--]]
|
||||
button = (element.CreateIcon or createAuraIcon) (element, position)
|
||||
|
||||
tinsert(element, button)
|
||||
element.createdIcons = element.createdIcons + 1
|
||||
end
|
||||
|
||||
button.caster = caster
|
||||
button.filter = filter
|
||||
button.isDebuff = isDebuff
|
||||
button.isPlayer = caster == 'player' or caster == 'vehicle'
|
||||
|
||||
--[[ Override: Auras:CustomFilter(unit, button, ...)
|
||||
Defines a custom filter that controls if the aura button should be shown.
|
||||
|
||||
* self - the widget holding the aura buttons
|
||||
* unit - the unit on which the aura is cast (string)
|
||||
* button - the button displaying the aura (Button)
|
||||
* ... - the return values from [UnitAura](http://wowprogramming.com/docs/api/UnitAura.html)
|
||||
|
||||
## Returns
|
||||
|
||||
* show - indicates whether the aura button should be shown (boolean)
|
||||
--]]
|
||||
|
||||
-- ElvUI changed block
|
||||
local show = not element.forceCreate
|
||||
if not (element.forceShow or element.forceCreate) then
|
||||
show = (element.CustomFilter or customFilter) (element, unit, button, name, texture,
|
||||
count, debuffType, duration, expiration, caster, isStealable, nameplateShowSelf, spellID,
|
||||
canApply, isBossDebuff, casterIsPlayer, nameplateShowAll,timeMod, effect1, effect2, effect3)
|
||||
end
|
||||
-- end block
|
||||
|
||||
if(show) then
|
||||
-- We might want to consider delaying the creation of an actual cooldown
|
||||
-- object to this point, but I think that will just make things needlessly
|
||||
-- complicated.
|
||||
if(button.cd and not element.disableCooldown) then
|
||||
if(duration and duration > 0) then
|
||||
button.cd:SetCooldown(expiration - duration, duration)
|
||||
button.cd:Show()
|
||||
else
|
||||
button.cd:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
if(button.overlay) then
|
||||
if((isDebuff and element.showDebuffType) or (not isDebuff and element.showBuffType) or element.showType) then
|
||||
local color = element.__owner.colors.debuff[debuffType] or element.__owner.colors.debuff.none
|
||||
|
||||
button.overlay:SetVertexColor(color[1], color[2], color[3])
|
||||
button.overlay:Show()
|
||||
else
|
||||
button.overlay:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
if(button.stealable) then
|
||||
if(not isDebuff and isStealable and element.showStealableBuffs and not UnitIsUnit('player', unit)) then
|
||||
button.stealable:Show()
|
||||
else
|
||||
button.stealable:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
if(button.icon) then button.icon:SetTexture(texture) end
|
||||
if(button.count) then button.count:SetText(count > 1 and count) end
|
||||
|
||||
local size = element.size or 16
|
||||
button:SetSize(size, size)
|
||||
|
||||
button:EnableMouse(not element.disableMouse)
|
||||
button:SetID(index)
|
||||
button:Show()
|
||||
|
||||
--[[ Callback: Auras:PostUpdateIcon(unit, button, index, position)
|
||||
Called after the aura button has been updated.
|
||||
|
||||
* self - the widget holding the aura buttons
|
||||
* unit - the unit on which the aura is cast (string)
|
||||
* button - the updated aura button (Button)
|
||||
* index - the index of the aura (number)
|
||||
* position - the actual position of the aura button (number)
|
||||
* duration - the aura duration in seconds (number?)
|
||||
* expiration - the point in time when the aura will expire. Comparable to GetTime() (number)
|
||||
* debuffType - the debuff type of the aura (string?)['Curse', 'Disease', 'Magic', 'Poison']
|
||||
* isStealable - whether the aura can be stolen or purged (boolean)
|
||||
--]]
|
||||
if(element.PostUpdateIcon) then
|
||||
element:PostUpdateIcon(unit, button, index, position, duration, expiration, debuffType, isStealable)
|
||||
end
|
||||
|
||||
return VISIBLE
|
||||
-- ElvUI changed block
|
||||
elseif element.forceCreate then
|
||||
local size = element.size or 16
|
||||
button:SetSize(size, size)
|
||||
button:Hide()
|
||||
|
||||
if element.PostUpdateIcon then
|
||||
element:PostUpdateIcon(unit, button, index, position, duration, expiration, debuffType, isStealable)
|
||||
end
|
||||
|
||||
return CREATED
|
||||
-- end block
|
||||
else
|
||||
return HIDDEN
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function SetPosition(element, from, to)
|
||||
local sizex = (element.size or 16) + (element['spacing-x'] or element.spacing or 0)
|
||||
local sizey = (element.size or 16) + (element['spacing-y'] or element.spacing or 0)
|
||||
local anchor = element.initialAnchor or 'BOTTOMLEFT'
|
||||
local growthx = (element['growth-x'] == 'LEFT' and -1) or 1
|
||||
local growthy = (element['growth-y'] == 'DOWN' and -1) or 1
|
||||
local cols = floor(element:GetWidth() / sizex + 0.5)
|
||||
|
||||
for i = from, to do
|
||||
local button = element[i]
|
||||
|
||||
-- Bail out if the to range is out of scope.
|
||||
if(not button) then break end
|
||||
local col = (i - 1) % cols
|
||||
local row = floor((i - 1) / cols)
|
||||
|
||||
button:ClearAllPoints()
|
||||
button:SetPoint(anchor, element, anchor, col * sizex * growthx, row * sizey * growthy)
|
||||
end
|
||||
end
|
||||
|
||||
local function filterIcons(element, unit, filter, limit, isDebuff, offset, dontHide)
|
||||
if(not offset) then offset = 0 end
|
||||
local index = 1
|
||||
local visible = 0
|
||||
local hidden = 0
|
||||
local created = 0 -- ElvUI
|
||||
element.hasStealable = nil -- ElvUI
|
||||
|
||||
while(visible < limit) do
|
||||
local result = updateIcon(element, unit, index, offset, filter, isDebuff, visible)
|
||||
if(not result) then
|
||||
break
|
||||
elseif(result == VISIBLE) then
|
||||
visible = visible + 1
|
||||
elseif(result == HIDDEN) then
|
||||
hidden = hidden + 1
|
||||
-- ElvUI changed block
|
||||
elseif result == CREATED then
|
||||
visible = visible + 1
|
||||
created = created + 1
|
||||
-- end block
|
||||
end
|
||||
|
||||
index = index + 1
|
||||
end
|
||||
|
||||
visible = visible - created -- ElvUI changed
|
||||
|
||||
if(not dontHide) then
|
||||
for i = visible + offset + 1, #element do
|
||||
element[i]:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
return visible, hidden
|
||||
end
|
||||
|
||||
local function UpdateAuras(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local auras = self.Auras
|
||||
if(auras) then
|
||||
--[[ Callback: Auras:PreUpdate(unit)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the widget holding the aura buttons
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(auras.PreUpdate) then auras:PreUpdate(unit) end
|
||||
|
||||
local numBuffs = auras.numBuffs or 32
|
||||
local numDebuffs = auras.numDebuffs or 40
|
||||
local max = auras.numTotal or numBuffs + numDebuffs
|
||||
|
||||
local visibleBuffs = filterIcons(auras, unit, auras.buffFilter or auras.filter or 'HELPFUL', min(numBuffs, max), nil, 0, true)
|
||||
|
||||
local hasGap
|
||||
if(visibleBuffs ~= 0 and auras.gap) then
|
||||
hasGap = true
|
||||
visibleBuffs = visibleBuffs + 1
|
||||
|
||||
local button = auras[visibleBuffs]
|
||||
if(not button) then
|
||||
button = (auras.CreateIcon or createAuraIcon) (auras, visibleBuffs)
|
||||
tinsert(auras, button)
|
||||
auras.createdIcons = auras.createdIcons + 1
|
||||
end
|
||||
|
||||
-- Prevent the button from displaying anything.
|
||||
if(button.cd) then button.cd:Hide() end
|
||||
if(button.icon) then button.icon:SetTexture() end
|
||||
if(button.overlay) then button.overlay:Hide() end
|
||||
if(button.stealable) then button.stealable:Hide() end
|
||||
if(button.count) then button.count:SetText() end
|
||||
|
||||
button:EnableMouse(false)
|
||||
button:Show()
|
||||
|
||||
--[[ Callback: Auras:PostUpdateGapIcon(unit, gapButton, visibleBuffs)
|
||||
Called after an invisible aura button has been created. Only used by Auras when the `gap` option is enabled.
|
||||
|
||||
* self - the widget holding the aura buttons
|
||||
* unit - the unit that has the invisible aura button (string)
|
||||
* gapButton - the invisible aura button (Button)
|
||||
* visibleBuffs - the number of currently visible aura buttons (number)
|
||||
--]]
|
||||
if(auras.PostUpdateGapIcon) then
|
||||
auras:PostUpdateGapIcon(unit, button, visibleBuffs)
|
||||
end
|
||||
end
|
||||
|
||||
local visibleDebuffs = filterIcons(auras, unit, auras.debuffFilter or auras.filter or 'HARMFUL', min(numDebuffs, max - visibleBuffs), true, visibleBuffs)
|
||||
auras.visibleDebuffs = visibleDebuffs
|
||||
|
||||
if(hasGap and visibleDebuffs == 0) then
|
||||
auras[visibleBuffs]:Hide()
|
||||
visibleBuffs = visibleBuffs - 1
|
||||
end
|
||||
|
||||
auras.visibleBuffs = visibleBuffs
|
||||
auras.visibleAuras = auras.visibleBuffs + auras.visibleDebuffs
|
||||
|
||||
local fromRange, toRange
|
||||
--[[ Callback: Auras:PreSetPosition(max)
|
||||
Called before the aura buttons have been (re-)anchored.
|
||||
|
||||
* self - the widget holding the aura buttons
|
||||
* max - the maximum possible number of aura buttons (number)
|
||||
|
||||
## Returns
|
||||
|
||||
* from - the offset of the first aura button to be (re-)anchored (number)
|
||||
* to - the offset of the last aura button to be (re-)anchored (number)
|
||||
--]]
|
||||
if(auras.PreSetPosition) then
|
||||
fromRange, toRange = auras:PreSetPosition(max)
|
||||
end
|
||||
|
||||
if(fromRange or auras.createdIcons > auras.anchoredIcons) then
|
||||
--[[ Override: Auras:SetPosition(from, to)
|
||||
Used to (re-)anchor the aura buttons.
|
||||
Called when new aura buttons have been created or if :PreSetPosition is defined.
|
||||
|
||||
* self - the widget that holds the aura buttons
|
||||
* from - the offset of the first aura button to be (re-)anchored (number)
|
||||
* to - the offset of the last aura button to be (re-)anchored (number)
|
||||
--]]
|
||||
(auras.SetPosition or SetPosition) (auras, fromRange or auras.anchoredIcons + 1, toRange or auras.createdIcons)
|
||||
auras.anchoredIcons = auras.createdIcons
|
||||
end
|
||||
|
||||
--[[ Callback: Auras:PostUpdate(unit)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the widget holding the aura buttons
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(auras.PostUpdate) then auras:PostUpdate(unit) end
|
||||
end
|
||||
|
||||
local buffs = self.Buffs
|
||||
if(buffs) then
|
||||
if(buffs.PreUpdate) then buffs:PreUpdate(unit) end
|
||||
|
||||
local numBuffs = buffs.num or 32
|
||||
local visibleBuffs = filterIcons(buffs, unit, buffs.filter or 'HELPFUL', numBuffs)
|
||||
buffs.visibleBuffs = visibleBuffs
|
||||
|
||||
local fromRange, toRange
|
||||
if(buffs.PreSetPosition) then
|
||||
fromRange, toRange = buffs:PreSetPosition(numBuffs)
|
||||
end
|
||||
|
||||
if(fromRange or buffs.createdIcons > buffs.anchoredIcons) then
|
||||
(buffs.SetPosition or SetPosition) (buffs, fromRange or buffs.anchoredIcons + 1, toRange or buffs.createdIcons)
|
||||
buffs.anchoredIcons = buffs.createdIcons
|
||||
end
|
||||
|
||||
if(buffs.PostUpdate) then buffs:PostUpdate(unit) end
|
||||
end
|
||||
|
||||
local debuffs = self.Debuffs
|
||||
if(debuffs) then
|
||||
if(debuffs.PreUpdate) then debuffs:PreUpdate(unit) end
|
||||
|
||||
local numDebuffs = debuffs.num or 40
|
||||
local visibleDebuffs = filterIcons(debuffs, unit, debuffs.filter or 'HARMFUL', numDebuffs, true)
|
||||
debuffs.visibleDebuffs = visibleDebuffs
|
||||
|
||||
local fromRange, toRange
|
||||
if(debuffs.PreSetPosition) then
|
||||
fromRange, toRange = debuffs:PreSetPosition(numDebuffs)
|
||||
end
|
||||
|
||||
if(fromRange or debuffs.createdIcons > debuffs.anchoredIcons) then
|
||||
(debuffs.SetPosition or SetPosition) (debuffs, fromRange or debuffs.anchoredIcons + 1, toRange or debuffs.createdIcons)
|
||||
debuffs.anchoredIcons = debuffs.createdIcons
|
||||
end
|
||||
|
||||
if(debuffs.PostUpdate) then debuffs:PostUpdate(unit) end
|
||||
end
|
||||
end
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if (self.isForced and event ~= 'ElvUI_UpdateAllElements') or (self.unit ~= unit) then return end -- ElvUI changed
|
||||
|
||||
-- Assume no event means someone wants to re-anchor things. This is usually done by UpdateAllElements and :ForceUpdate.
|
||||
if not event or event == 'ForceUpdate' or event == 'ElvUI_UpdateAllElements' then -- ElvUI changed
|
||||
if self.Buffs then self.Buffs.anchoredIcons = 0 end
|
||||
if self.Debuffs then self.Debuffs.anchoredIcons = 0 end
|
||||
if self.Auras then self.Auras.anchoredIcons = 0 end
|
||||
end
|
||||
|
||||
UpdateAuras(self, event, unit)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Update(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
-- ElvUI changed block
|
||||
local onUpdateElapsed, onUpdateWait = 0, 0.25
|
||||
local function onUpdateAuras(self, elapsed)
|
||||
if onUpdateElapsed > onUpdateWait then
|
||||
Update(self.__owner, 'OnUpdate', self.__owner.unit)
|
||||
|
||||
onUpdateElapsed = 0
|
||||
else
|
||||
onUpdateElapsed = onUpdateElapsed + elapsed
|
||||
end
|
||||
end
|
||||
|
||||
local function SetAuraUpdateSpeed(self, state)
|
||||
onUpdateWait = state
|
||||
end
|
||||
|
||||
local function SetAuraUpdateMethod(self, state, force)
|
||||
if self.effectiveAura ~= state or force then
|
||||
self.effectiveAura = state
|
||||
|
||||
if state then
|
||||
self.updateAurasFrame:SetScript('OnUpdate', onUpdateAuras)
|
||||
self:UnregisterEvent('UNIT_AURA', UpdateAuras)
|
||||
else
|
||||
self.updateAurasFrame:SetScript('OnUpdate', nil)
|
||||
self:RegisterEvent('UNIT_AURA', UpdateAuras)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- end block
|
||||
|
||||
local function Enable(self)
|
||||
-- ElvUI changed block
|
||||
if not self.updateAurasFrame then
|
||||
self.updateAurasFrame = CreateFrame('Frame', nil, self)
|
||||
self.updateAurasFrame.__owner = self
|
||||
end
|
||||
-- end block
|
||||
|
||||
if(self.Buffs or self.Debuffs or self.Auras) then
|
||||
-- ElvUI changed block
|
||||
self.SetAuraUpdateSpeed = SetAuraUpdateSpeed
|
||||
self.SetAuraUpdateMethod = SetAuraUpdateMethod
|
||||
SetAuraUpdateMethod(self, self.effectiveAura, true)
|
||||
-- end block
|
||||
|
||||
local buffs = self.Buffs
|
||||
if(buffs) then
|
||||
buffs.__owner = self
|
||||
buffs.ForceUpdate = ForceUpdate
|
||||
|
||||
buffs.createdIcons = buffs.createdIcons or 0
|
||||
buffs.anchoredIcons = 0
|
||||
|
||||
-- Avoid parenting GameTooltip to frames with anchoring restrictions,
|
||||
-- otherwise it'll inherit said restrictions which will cause issues
|
||||
-- with its further positioning, clamping, etc
|
||||
if(not pcall(self.GetCenter, self)) then
|
||||
buffs.tooltipAnchor = 'ANCHOR_CURSOR'
|
||||
else
|
||||
buffs.tooltipAnchor = buffs.tooltipAnchor or 'ANCHOR_BOTTOMRIGHT'
|
||||
end
|
||||
|
||||
buffs:Show()
|
||||
end
|
||||
|
||||
local debuffs = self.Debuffs
|
||||
if(debuffs) then
|
||||
debuffs.__owner = self
|
||||
debuffs.ForceUpdate = ForceUpdate
|
||||
|
||||
debuffs.createdIcons = debuffs.createdIcons or 0
|
||||
debuffs.anchoredIcons = 0
|
||||
|
||||
-- Avoid parenting GameTooltip to frames with anchoring restrictions,
|
||||
-- otherwise it'll inherit said restrictions which will cause issues
|
||||
-- with its further positioning, clamping, etc
|
||||
if(not pcall(self.GetCenter, self)) then
|
||||
debuffs.tooltipAnchor = 'ANCHOR_CURSOR'
|
||||
else
|
||||
debuffs.tooltipAnchor = debuffs.tooltipAnchor or 'ANCHOR_BOTTOMRIGHT'
|
||||
end
|
||||
|
||||
debuffs:Show()
|
||||
end
|
||||
|
||||
local auras = self.Auras
|
||||
if(auras) then
|
||||
auras.__owner = self
|
||||
auras.ForceUpdate = ForceUpdate
|
||||
|
||||
auras.createdIcons = auras.createdIcons or 0
|
||||
auras.anchoredIcons = 0
|
||||
|
||||
-- Avoid parenting GameTooltip to frames with anchoring restrictions,
|
||||
-- otherwise it'll inherit said restrictions which will cause issues
|
||||
-- with its further positioning, clamping, etc
|
||||
if(not pcall(self.GetCenter, self)) then
|
||||
auras.tooltipAnchor = 'ANCHOR_CURSOR'
|
||||
else
|
||||
auras.tooltipAnchor = auras.tooltipAnchor or 'ANCHOR_BOTTOMRIGHT'
|
||||
end
|
||||
|
||||
auras:Show()
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
-- ElvUI changed block
|
||||
if self.updateAurasFrame then
|
||||
self.updateAurasFrame:SetScript('OnUpdate', nil)
|
||||
end
|
||||
-- end block
|
||||
|
||||
if(self.Buffs or self.Debuffs or self.Auras) then
|
||||
self:UnregisterEvent('UNIT_AURA', UpdateAuras)
|
||||
|
||||
if(self.Buffs) then self.Buffs:Hide() end
|
||||
if(self.Debuffs) then self.Debuffs:Hide() end
|
||||
if(self.Auras) then self.Auras:Hide() end
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Auras', Update, Enable, Disable)
|
||||
518
Libraries/oUF/elements/castbar.lua
Normal file
518
Libraries/oUF/elements/castbar.lua
Normal file
@@ -0,0 +1,518 @@
|
||||
--[[
|
||||
# Element: Castbar
|
||||
|
||||
Handles the visibility and updating of spell castbars.
|
||||
|
||||
## Widget
|
||||
|
||||
Castbar - A `StatusBar` to represent spell cast/channel progress.
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
.Icon - A `Texture` to represent spell icon.
|
||||
.SafeZone - A `Texture` to represent latency.
|
||||
.Shield - A `Texture` to represent if it's possible to interrupt or spell steal.
|
||||
.Spark - A `Texture` to represent the castbar's edge.
|
||||
.Text - A `FontString` to represent spell name.
|
||||
.Time - A `FontString` to represent spell duration.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied to the StatusBar and Texture widgets if they don't have a texture or a color set.
|
||||
|
||||
## Options
|
||||
|
||||
.timeToHold - Indicates for how many seconds the castbar should be visible after a _FAILED or _INTERRUPTED
|
||||
event. Defaults to 0 (number)
|
||||
.hideTradeSkills - Makes the element ignore casts related to crafting professions (boolean)
|
||||
|
||||
## Attributes
|
||||
|
||||
.castID - A globally unique identifier of the currently cast spell (string?)
|
||||
.casting - Indicates whether the current spell is an ordinary cast (boolean)
|
||||
.channeling - Indicates whether the current spell is a channeled cast (boolean)
|
||||
.notInterruptible - Indicates whether the current spell is interruptible (boolean)
|
||||
.spellID - The spell identifier of the currently cast/channeled spell (number)
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local Castbar = CreateFrame('StatusBar', nil, self)
|
||||
Castbar:SetSize(20, 20)
|
||||
Castbar:SetPoint('TOP')
|
||||
Castbar:SetPoint('LEFT')
|
||||
Castbar:SetPoint('RIGHT')
|
||||
|
||||
-- Add a background
|
||||
local Background = Castbar:CreateTexture(nil, 'BACKGROUND')
|
||||
Background:SetAllPoints(Castbar)
|
||||
Background:SetTexture(1, 1, 1, .5)
|
||||
|
||||
-- Add a spark
|
||||
local Spark = Castbar:CreateTexture(nil, 'OVERLAY')
|
||||
Spark:SetSize(20, 20)
|
||||
Spark:SetBlendMode('ADD')
|
||||
Spark:SetPoint('CENTER', Castbar:GetStatusBarTexture(), 'RIGHT', 0, 0)
|
||||
|
||||
-- Add a timer
|
||||
local Time = Castbar:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
|
||||
Time:SetPoint('RIGHT', Castbar)
|
||||
|
||||
-- Add spell text
|
||||
local Text = Castbar:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
|
||||
Text:SetPoint('LEFT', Castbar)
|
||||
|
||||
-- Add spell icon
|
||||
local Icon = Castbar:CreateTexture(nil, 'OVERLAY')
|
||||
Icon:SetSize(20, 20)
|
||||
Icon:SetPoint('TOPLEFT', Castbar, 'TOPLEFT')
|
||||
|
||||
-- Add Shield
|
||||
local Shield = Castbar:CreateTexture(nil, 'OVERLAY')
|
||||
Shield:SetSize(20, 20)
|
||||
Shield:SetPoint('CENTER', Castbar)
|
||||
|
||||
-- Add safezone
|
||||
local SafeZone = Castbar:CreateTexture(nil, 'OVERLAY')
|
||||
|
||||
-- Register it with oUF
|
||||
Castbar.bg = Background
|
||||
Castbar.Spark = Spark
|
||||
Castbar.Time = Time
|
||||
Castbar.Text = Text
|
||||
Castbar.Icon = Icon
|
||||
Castbar.Shield = Shield
|
||||
Castbar.SafeZone = SafeZone
|
||||
self.Castbar = Castbar
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local FALLBACK_ICON = 136243 -- Interface\ICONS\Trade_Engineering
|
||||
|
||||
-- ElvUI block
|
||||
local select = select
|
||||
local FAILED = FAILED
|
||||
local INTERRUPTED = INTERRUPTED
|
||||
local GetNetStats = GetNetStats
|
||||
local UnitCastingInfo = UnitCastingInfo
|
||||
local UnitChannelInfo = UnitChannelInfo
|
||||
local UnitIsUnit = UnitIsUnit
|
||||
local GetTime = GetTime
|
||||
|
||||
-- GLOBALS: PetCastingBarFrame, PetCastingBarFrame_OnLoad
|
||||
-- GLOBALS: CastingBarFrame, CastingBarFrame_OnLoad, CastingBarFrame_SetUnit
|
||||
|
||||
local tradeskillCurrent, tradeskillTotal, mergeTradeskill = 0, 0, false
|
||||
local UNIT_SPELLCAST_SENT = function (self, event, unit, target, castID, spellID)
|
||||
local castbar = self.Castbar
|
||||
castbar.curTarget = (target and target ~= "") and target or nil
|
||||
|
||||
if castbar.isTradeSkill then
|
||||
castbar.tradeSkillCastId = castID
|
||||
end
|
||||
end
|
||||
-- end block
|
||||
|
||||
local function resetAttributes(self)
|
||||
self.castID = nil
|
||||
self.casting = nil
|
||||
self.channeling = nil
|
||||
self.notInterruptible = nil
|
||||
self.spellID = nil
|
||||
self.spellName = nil -- ElvUI
|
||||
end
|
||||
|
||||
local function CastStart(self, real, unit, castGUID)
|
||||
if self.unit ~= unit then return end
|
||||
if real == 'UNIT_SPELLCAST_START' and not castGUID then return end
|
||||
|
||||
local element = self.Castbar
|
||||
local name, _, texture, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(unit)
|
||||
local event = 'UNIT_SPELLCAST_START'
|
||||
if(not name) then
|
||||
name, _, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo(unit)
|
||||
event = 'UNIT_SPELLCAST_CHANNEL_START'
|
||||
end
|
||||
|
||||
if(not name or (isTradeSkill and element.hideTradeSkills)) then
|
||||
resetAttributes(element)
|
||||
element:Hide()
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
endTime = endTime / 1000
|
||||
startTime = startTime / 1000
|
||||
|
||||
element.max = endTime - startTime
|
||||
element.startTime = startTime
|
||||
element.delay = 0
|
||||
element.casting = event == 'UNIT_SPELLCAST_START'
|
||||
element.channeling = event == 'UNIT_SPELLCAST_CHANNEL_START'
|
||||
element.notInterruptible = notInterruptible
|
||||
element.holdTime = 0
|
||||
element.castID = castID
|
||||
element.spellID = spellID
|
||||
element.spellName = name -- ElvUI
|
||||
|
||||
if(element.casting) then
|
||||
element.duration = GetTime() - startTime
|
||||
else
|
||||
element.duration = endTime - GetTime()
|
||||
end
|
||||
|
||||
-- ElvUI block
|
||||
if(mergeTradeskill and isTradeSkill and UnitIsUnit(unit, "player")) then
|
||||
element.duration = element.duration + (element.max * tradeskillCurrent);
|
||||
element.max = element.max * tradeskillTotal;
|
||||
element.holdTime = 1
|
||||
|
||||
if(unit == "player") then
|
||||
tradeskillCurrent = tradeskillCurrent + 1;
|
||||
end
|
||||
end
|
||||
-- end block
|
||||
|
||||
element:SetMinMaxValues(0, element.max)
|
||||
element:SetValue(element.duration)
|
||||
|
||||
if(element.Icon) then element.Icon:SetTexture(texture or FALLBACK_ICON) end
|
||||
if(element.Shield) then element.Shield:SetShown(notInterruptible) end
|
||||
if(element.Spark) then element.Spark:Show() end
|
||||
if(element.Text) then element.Text:SetText(name) end
|
||||
if(element.Time) then element.Time:SetText() end
|
||||
|
||||
local safeZone = element.SafeZone
|
||||
if(safeZone) then
|
||||
local isHoriz = element:GetOrientation() == 'HORIZONTAL'
|
||||
|
||||
safeZone:ClearAllPoints()
|
||||
safeZone:SetPoint(isHoriz and 'TOP' or 'LEFT')
|
||||
safeZone:SetPoint(isHoriz and 'BOTTOM' or 'RIGHT')
|
||||
|
||||
if(element.casting) then
|
||||
safeZone:SetPoint(element:GetReverseFill() and (isHoriz and 'LEFT' or 'BOTTOM') or (isHoriz and 'RIGHT' or 'TOP'))
|
||||
else
|
||||
safeZone:SetPoint(element:GetReverseFill() and (isHoriz and 'RIGHT' or 'TOP') or (isHoriz and 'LEFT' or 'BOTTOM'))
|
||||
end
|
||||
|
||||
local ratio = (select(4, GetNetStats()) / 1000) / element.max
|
||||
if(ratio > 1) then
|
||||
ratio = 1
|
||||
end
|
||||
|
||||
safeZone[isHoriz and 'SetWidth' or 'SetHeight'](safeZone, element[isHoriz and 'GetWidth' or 'GetHeight'](element) * ratio)
|
||||
end
|
||||
|
||||
--[[ Callback: Castbar:PostCastStart(unit)
|
||||
Called after the element has been updated upon a spell cast or channel start.
|
||||
|
||||
* self - the Castbar widget
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PostCastStart) then
|
||||
element:PostCastStart(unit)
|
||||
end
|
||||
|
||||
element:Show()
|
||||
end
|
||||
|
||||
local function CastUpdate(self, event, unit, castID, spellID)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local element = self.Castbar
|
||||
if(not element:IsShown() or element.castID ~= castID or element.spellID ~= spellID) then
|
||||
return
|
||||
end
|
||||
|
||||
local name, startTime, endTime, _
|
||||
if(event == 'UNIT_SPELLCAST_DELAYED') then
|
||||
name, _, _, startTime, endTime = UnitCastingInfo(unit)
|
||||
else
|
||||
name, _, _, startTime, endTime = UnitChannelInfo(unit)
|
||||
end
|
||||
|
||||
if(not name) then return end
|
||||
|
||||
endTime = endTime / 1000
|
||||
startTime = startTime / 1000
|
||||
|
||||
local delta
|
||||
if(element.casting) then
|
||||
delta = startTime - element.startTime
|
||||
|
||||
element.duration = GetTime() - startTime
|
||||
else
|
||||
delta = element.startTime - startTime
|
||||
|
||||
element.duration = endTime - GetTime()
|
||||
end
|
||||
|
||||
if(delta < 0) then
|
||||
delta = 0
|
||||
end
|
||||
|
||||
element.max = endTime - startTime
|
||||
element.startTime = startTime
|
||||
element.delay = element.delay + delta
|
||||
|
||||
element:SetMinMaxValues(0, element.max)
|
||||
element:SetValue(element.duration)
|
||||
|
||||
--[[ Callback: Castbar:PostCastUpdate(unit)
|
||||
Called after the element has been updated when a spell cast or channel has been updated.
|
||||
|
||||
* self - the Castbar widget
|
||||
* unit - the unit that the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PostCastUpdate) then
|
||||
return element:PostCastUpdate(unit)
|
||||
end
|
||||
end
|
||||
|
||||
local function CastStop(self, event, unit, castID, spellID)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local element = self.Castbar
|
||||
if(not element:IsShown() or element.castID ~= castID or element.spellID ~= spellID) then
|
||||
return
|
||||
end
|
||||
|
||||
-- ElvUI block
|
||||
if mergeTradeskill and UnitIsUnit(unit, "player") then
|
||||
if tradeskillCurrent == tradeskillTotal then
|
||||
mergeTradeskill = false
|
||||
end
|
||||
end
|
||||
-- end block
|
||||
|
||||
resetAttributes(element)
|
||||
|
||||
--[[ Callback: Castbar:PostCastStop(unit, spellID)
|
||||
Called after the element has been updated when a spell cast or channel has stopped.
|
||||
|
||||
* self - the Castbar widget
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* spellID - the ID of the spell (number)
|
||||
--]]
|
||||
if(element.PostCastStop) then
|
||||
return element:PostCastStop(unit, spellID)
|
||||
end
|
||||
end
|
||||
|
||||
local function CastFail(self, event, unit, castID, spellID)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local element = self.Castbar
|
||||
if(not element:IsShown() or element.castID ~= castID or element.spellID ~= spellID) then
|
||||
return
|
||||
end
|
||||
|
||||
if(element.Text) then
|
||||
element.Text:SetText(event == 'UNIT_SPELLCAST_FAILED' and FAILED or INTERRUPTED)
|
||||
end
|
||||
|
||||
if(element.Spark) then element.Spark:Hide() end
|
||||
|
||||
element.holdTime = element.timeToHold or 0
|
||||
|
||||
-- ElvUI block
|
||||
if mergeTradeskill and UnitIsUnit(unit, "player") then
|
||||
mergeTradeskill = false
|
||||
element.tradeSkillCastId = nil
|
||||
end
|
||||
-- end block
|
||||
|
||||
resetAttributes(element)
|
||||
element:SetValue(element.max)
|
||||
|
||||
--[[ Callback: Castbar:PostCastFail(unit, spellID)
|
||||
Called after the element has been updated upon a failed or interrupted spell cast.
|
||||
|
||||
* self - the Castbar widget
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* spellID - the ID of the spell (number)
|
||||
--]]
|
||||
if(element.PostCastFail) then
|
||||
return element:PostCastFail(unit, spellID)
|
||||
end
|
||||
end
|
||||
|
||||
local function CastInterruptible(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local element = self.Castbar
|
||||
if(not element:IsShown()) then return end
|
||||
|
||||
element.notInterruptible = event == 'UNIT_SPELLCAST_NOT_INTERRUPTIBLE'
|
||||
|
||||
if(element.Shield) then element.Shield:SetShown(element.notInterruptible) end
|
||||
|
||||
--[[ Callback: Castbar:PostCastInterruptible(unit)
|
||||
Called after the element has been updated when a spell cast has become interruptible or uninterruptible.
|
||||
|
||||
* self - the Castbar widget
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PostCastInterruptible) then
|
||||
return element:PostCastInterruptible(unit)
|
||||
end
|
||||
end
|
||||
|
||||
local function onUpdate(self, elapsed)
|
||||
if(self.casting or self.channeling) then
|
||||
local isCasting = self.casting
|
||||
if(isCasting) then
|
||||
self.duration = self.duration + elapsed
|
||||
if(self.duration >= self.max) then
|
||||
local spellID = self.spellID
|
||||
|
||||
resetAttributes(self)
|
||||
self:Hide()
|
||||
|
||||
if(self.PostCastStop) then
|
||||
self:PostCastStop(self.__owner.unit, spellID)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
else
|
||||
self.duration = self.duration - elapsed
|
||||
if(self.duration <= 0) then
|
||||
local spellID = self.spellID
|
||||
|
||||
resetAttributes(self)
|
||||
self:Hide()
|
||||
|
||||
if(self.PostCastStop) then
|
||||
self:PostCastStop(self.__owner.unit, spellID)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if(self.Time) then
|
||||
if(self.delay ~= 0) then
|
||||
if(self.CustomDelayText) then
|
||||
self:CustomDelayText(self.duration)
|
||||
else
|
||||
self.Time:SetFormattedText('%.1f|cffff0000%s%.2f|r', self.duration, isCasting and '+' or '-', self.delay)
|
||||
end
|
||||
else
|
||||
if(self.CustomTimeText) then
|
||||
self:CustomTimeText(self.duration)
|
||||
else
|
||||
self.Time:SetFormattedText('%.1f', self.duration)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:SetValue(self.duration)
|
||||
elseif(self.holdTime > 0) then
|
||||
self.holdTime = self.holdTime - elapsed
|
||||
else
|
||||
resetAttributes(self)
|
||||
self:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local function Update(...)
|
||||
CastStart(...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Update(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self, unit)
|
||||
local element = self.Castbar
|
||||
if(element and unit and not unit:match('%wtarget$')) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_SPELLCAST_START', CastStart)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_START', CastStart)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_STOP', CastStop)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_STOP', CastStop)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_DELAYED', CastUpdate)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_UPDATE', CastUpdate)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_FAILED', CastFail)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_INTERRUPTED', CastFail)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_INTERRUPTIBLE', CastInterruptible)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_NOT_INTERRUPTIBLE', CastInterruptible)
|
||||
|
||||
-- ElvUI block
|
||||
self:RegisterEvent('UNIT_SPELLCAST_SENT', UNIT_SPELLCAST_SENT, true)
|
||||
-- end block
|
||||
|
||||
element.holdTime = 0
|
||||
|
||||
element:SetScript('OnUpdate', element.OnUpdate or onUpdate)
|
||||
|
||||
if(self.unit == 'player' and not (self.hasChildren or self.isChild or self.isNamePlate)) then
|
||||
CastingBarFrame_SetUnit(CastingBarFrame, nil)
|
||||
CastingBarFrame_SetUnit(PetCastingBarFrame, nil)
|
||||
end
|
||||
|
||||
if(element:IsObjectType('StatusBar') and not element:GetStatusBarTexture()) then
|
||||
element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
|
||||
local spark = element.Spark
|
||||
if(spark and spark:IsObjectType('Texture') and not spark:GetTexture()) then
|
||||
spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
|
||||
end
|
||||
|
||||
local shield = element.Shield
|
||||
if(shield and shield:IsObjectType('Texture') and not shield:GetTexture()) then
|
||||
shield:SetTexture([[Interface\CastingBar\UI-CastingBar-Small-Shield]])
|
||||
end
|
||||
|
||||
local safeZone = element.SafeZone
|
||||
if(safeZone and safeZone:IsObjectType('Texture') and not safeZone:GetTexture()) then
|
||||
safeZone:SetColorTexture(1, 0, 0)
|
||||
end
|
||||
|
||||
element:Hide()
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.Castbar
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_START', CastStart)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_START', CastStart)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_DELAYED', CastUpdate)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_UPDATE', CastUpdate)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_STOP', CastStop)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_STOP', CastStop)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_FAILED', CastFail)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_INTERRUPTED', CastFail)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_INTERRUPTIBLE', CastInterruptible)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_NOT_INTERRUPTIBLE', CastInterruptible)
|
||||
|
||||
element:SetScript('OnUpdate', nil)
|
||||
|
||||
if(self.unit == 'player' and not (self.hasChildren or self.isChild or self.isNamePlate)) then
|
||||
CastingBarFrame_OnLoad(CastingBarFrame, 'player', true, false)
|
||||
PetCastingBarFrame_OnLoad(PetCastingBarFrame)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ElvUI block
|
||||
hooksecurefunc(C_TradeSkillUI, "CraftRecipe", function(_, num)
|
||||
tradeskillCurrent = 0
|
||||
tradeskillTotal = num or 1
|
||||
mergeTradeskill = true
|
||||
end)
|
||||
-- end block
|
||||
|
||||
oUF:AddElement('Castbar', Update, Enable, Disable)
|
||||
357
Libraries/oUF/elements/classpower.lua
Normal file
357
Libraries/oUF/elements/classpower.lua
Normal file
@@ -0,0 +1,357 @@
|
||||
--[[
|
||||
# Element: ClassPower
|
||||
|
||||
Handles the visibility and updating of the player's class resources (like Chi Orbs or Holy Power) and combo points.
|
||||
|
||||
## Widget
|
||||
|
||||
ClassPower - An `table` consisting of as many StatusBars as the theoretical maximum return of [UnitPowerMax](http://wowprogramming.com/docs/api/UnitPowerMax.html).
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
.bg - A `Texture` used as a background. It will inherit the color of the main StatusBar.
|
||||
|
||||
## Sub-Widget Options
|
||||
|
||||
.multiplier - Used to tint the background based on the widget's R, G and B values. Defaults to 1 (number)[0-1]
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the sub-widgets are StatusBars and don't have a texture set.
|
||||
If the sub-widgets are StatusBars, their minimum and maximum values will be set to 0 and 1 respectively.
|
||||
|
||||
Supported class powers:
|
||||
- All - Combo Points
|
||||
- Mage - Arcane Charges
|
||||
- Monk - Chi Orbs
|
||||
- Paladin - Holy Power
|
||||
- Warlock - Soul Shards
|
||||
|
||||
## Examples
|
||||
|
||||
local ClassPower = {}
|
||||
for index = 1, 10 do
|
||||
local Bar = CreateFrame('StatusBar', nil, self)
|
||||
|
||||
-- Position and size.
|
||||
Bar:SetSize(16, 16)
|
||||
Bar:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', (index - 1) * Bar:GetWidth(), 0)
|
||||
|
||||
ClassPower[index] = Bar
|
||||
end
|
||||
|
||||
-- Register with oUF
|
||||
self.ClassPower = ClassPower
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local _, PlayerClass = UnitClass('player')
|
||||
|
||||
-- sourced from FrameXML/Constants.lua
|
||||
local SPEC_MAGE_ARCANE = SPEC_MAGE_ARCANE or 1
|
||||
local SPEC_MONK_WINDWALKER = SPEC_MONK_WINDWALKER or 3
|
||||
local SPEC_PALADIN_RETRIBUTION = SPEC_PALADIN_RETRIBUTION or 3
|
||||
local SPEC_WARLOCK_DESTRUCTION = SPEC_WARLOCK_DESTRUCTION or 3
|
||||
local SPELL_POWER_ENERGY = Enum.PowerType.Energy or 3
|
||||
local SPELL_POWER_COMBO_POINTS = Enum.PowerType.ComboPoints or 4
|
||||
local SPELL_POWER_SOUL_SHARDS = Enum.PowerType.SoulShards or 7
|
||||
local SPELL_POWER_HOLY_POWER = Enum.PowerType.HolyPower or 9
|
||||
local SPELL_POWER_CHI = Enum.PowerType.Chi or 12
|
||||
local SPELL_POWER_ARCANE_CHARGES = Enum.PowerType.ArcaneCharges or 16
|
||||
|
||||
-- Holds the class specific stuff.
|
||||
local ClassPowerID, ClassPowerType
|
||||
local ClassPowerEnable, ClassPowerDisable
|
||||
local RequireSpec, RequirePower, RequireSpell
|
||||
|
||||
local function UpdateColor(element, powerType)
|
||||
local color = element.__owner.colors.power[powerType]
|
||||
local r, g, b = color[1], color[2], color[3]
|
||||
for i = 1, #element do
|
||||
local bar = element[i]
|
||||
bar:SetStatusBarColor(r, g, b)
|
||||
|
||||
local bg = bar.bg
|
||||
if(bg) then
|
||||
local mu = bg.multiplier or 1
|
||||
bg:SetVertexColor(r * mu, g * mu, b * mu)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Callback: ClassPower:PostUpdateColor(r, g, b)
|
||||
Called after the element color has been updated.
|
||||
|
||||
* self - the ClassPower element
|
||||
* r - the red component of the used color (number)[0-1]
|
||||
* g - the green component of the used color (number)[0-1]
|
||||
* b - the blue component of the used color (number)[0-1]
|
||||
--]]
|
||||
if(element.PostUpdateColor) then
|
||||
element:PostUpdateColor(r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
local function Update(self, event, unit, powerType)
|
||||
if(not (unit and (UnitIsUnit(unit, 'player') and (not powerType or powerType == ClassPowerType)
|
||||
or unit == 'vehicle' and powerType == 'COMBO_POINTS'))) then
|
||||
return
|
||||
end
|
||||
|
||||
local element = self.ClassPower
|
||||
|
||||
--[[ Callback: ClassPower:PreUpdate(event)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the ClassPower element
|
||||
]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local cur, max, mod, oldMax, chargedIndex
|
||||
if(event ~= 'ClassPowerDisable') then
|
||||
local powerID = unit == 'vehicle' and SPELL_POWER_COMBO_POINTS or ClassPowerID
|
||||
cur = UnitPower(unit, powerID, true)
|
||||
max = UnitPowerMax(unit, powerID)
|
||||
mod = UnitPowerDisplayMod(powerID)
|
||||
|
||||
-- mod should never be 0, but according to Blizz code it can actually happen
|
||||
cur = mod == 0 and 0 or cur / mod
|
||||
|
||||
-- BUG: Destruction is supposed to show partial soulshards, but Affliction and Demonology should only show full ones
|
||||
if(ClassPowerType == 'SOUL_SHARDS' and GetSpecialization() ~= SPEC_WARLOCK_DESTRUCTION) then
|
||||
cur = cur - cur % 1
|
||||
end
|
||||
|
||||
if(PlayerClass == 'ROGUE') then
|
||||
local chargedPoints = GetUnitChargedPowerPoints(unit)
|
||||
-- according to Blizzard there will only be one
|
||||
chargedIndex = chargedPoints and chargedPoints[1]
|
||||
end
|
||||
|
||||
local numActive = cur + 0.9
|
||||
for i = 1, max do
|
||||
if(i > numActive) then
|
||||
element[i]:Hide()
|
||||
element[i]:SetValue(0)
|
||||
else
|
||||
element[i]:Show()
|
||||
element[i]:SetValue(cur - i + 1)
|
||||
end
|
||||
end
|
||||
|
||||
oldMax = element.__max
|
||||
if(max ~= oldMax) then
|
||||
if(max < oldMax) then
|
||||
for i = max + 1, oldMax do
|
||||
element[i]:Hide()
|
||||
element[i]:SetValue(0)
|
||||
end
|
||||
end
|
||||
|
||||
element.__max = max
|
||||
end
|
||||
end
|
||||
--[[ Callback: ClassPower:PostUpdate(cur, max, hasMaxChanged, powerType)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the ClassPower element
|
||||
* cur - the current amount of power (number)
|
||||
* max - the maximum amount of power (number)
|
||||
* hasMaxChanged - indicates whether the maximum amount has changed since the last update (boolean)
|
||||
* powerType - the active power type (string)
|
||||
* chargedIndex - the index of the currently charged power point (number?)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(cur, max, oldMax ~= max, powerType, chargedIndex)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: ClassPower.Override(self, event, unit, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.ClassPower.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function Visibility(self, event, unit)
|
||||
local element = self.ClassPower
|
||||
local shouldEnable
|
||||
|
||||
if(UnitHasVehicleUI('player')) then
|
||||
shouldEnable = PlayerVehicleHasComboPoints()
|
||||
unit = 'vehicle'
|
||||
elseif(ClassPowerID) then
|
||||
if(not RequireSpec or RequireSpec == GetSpecialization()) then
|
||||
-- use 'player' instead of unit because 'SPELLS_CHANGED' is a unitless event
|
||||
if(not RequirePower or RequirePower == UnitPowerType('player')) then
|
||||
if(not RequireSpell or IsPlayerSpell(RequireSpell)) then
|
||||
self:UnregisterEvent('SPELLS_CHANGED', Visibility)
|
||||
shouldEnable = true
|
||||
unit = 'player'
|
||||
else
|
||||
self:RegisterEvent('SPELLS_CHANGED', Visibility, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local isEnabled = element.__isEnabled
|
||||
local powerType = unit == 'vehicle' and 'COMBO_POINTS' or ClassPowerType
|
||||
|
||||
if(shouldEnable) then
|
||||
--[[ Override: ClassPower:UpdateColor(powerType)
|
||||
Used to completely override the internal function for updating the widgets' colors.
|
||||
|
||||
* self - the ClassPower element
|
||||
* powerType - the active power type (string)
|
||||
--]]
|
||||
(element.UpdateColor or UpdateColor) (element, powerType)
|
||||
end
|
||||
|
||||
if(shouldEnable and not isEnabled) then
|
||||
ClassPowerEnable(self)
|
||||
|
||||
--[[ Callback: ClassPower:PostVisibility(isVisible)
|
||||
Called after the element's visibility has been changed.
|
||||
|
||||
* self - the ClassPower element
|
||||
* isVisible - the current visibility state of the element (boolean)
|
||||
--]]
|
||||
if(element.PostVisibility) then
|
||||
element:PostVisibility(true)
|
||||
end
|
||||
elseif(not shouldEnable and (isEnabled or isEnabled == nil)) then
|
||||
ClassPowerDisable(self)
|
||||
|
||||
if(element.PostVisibility) then
|
||||
element:PostVisibility(false)
|
||||
end
|
||||
elseif(shouldEnable and isEnabled) then
|
||||
Path(self, event, unit, powerType)
|
||||
end
|
||||
end
|
||||
|
||||
local function VisibilityPath(self, ...)
|
||||
--[[ Override: ClassPower.OverrideVisibility(self, event, unit)
|
||||
Used to completely override the internal visibility function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
--]]
|
||||
return (self.ClassPower.OverrideVisibility or Visibility) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return VisibilityPath(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
do
|
||||
function ClassPowerEnable(self)
|
||||
self:RegisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
self:RegisterEvent('UNIT_MAXPOWER', Path)
|
||||
|
||||
if(PlayerClass == 'ROGUE') then
|
||||
self:RegisterEvent('UNIT_POWER_POINT_CHARGE', Path)
|
||||
end
|
||||
|
||||
self.ClassPower.__isEnabled = true
|
||||
|
||||
if(UnitHasVehicleUI('player')) then
|
||||
Path(self, 'ClassPowerEnable', 'vehicle', 'COMBO_POINTS')
|
||||
else
|
||||
Path(self, 'ClassPowerEnable', 'player', ClassPowerType)
|
||||
end
|
||||
end
|
||||
|
||||
function ClassPowerDisable(self)
|
||||
self:UnregisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
self:UnregisterEvent('UNIT_MAXPOWER', Path)
|
||||
self:UnregisterEvent('UNIT_POWER_POINT_CHARGE', Path)
|
||||
|
||||
local element = self.ClassPower
|
||||
for i = 1, #element do
|
||||
element[i]:Hide()
|
||||
end
|
||||
|
||||
element.__isEnabled = false
|
||||
Path(self, 'ClassPowerDisable', 'player', ClassPowerType)
|
||||
end
|
||||
|
||||
if(PlayerClass == 'MONK') then
|
||||
ClassPowerID = SPELL_POWER_CHI
|
||||
ClassPowerType = 'CHI'
|
||||
RequireSpec = SPEC_MONK_WINDWALKER
|
||||
elseif(PlayerClass == 'PALADIN') then
|
||||
ClassPowerID = SPELL_POWER_HOLY_POWER
|
||||
ClassPowerType = 'HOLY_POWER'
|
||||
elseif(PlayerClass == 'WARLOCK') then
|
||||
ClassPowerID = SPELL_POWER_SOUL_SHARDS
|
||||
ClassPowerType = 'SOUL_SHARDS'
|
||||
elseif(PlayerClass == 'ROGUE' or PlayerClass == 'DRUID') then
|
||||
ClassPowerID = SPELL_POWER_COMBO_POINTS
|
||||
ClassPowerType = 'COMBO_POINTS'
|
||||
|
||||
if(PlayerClass == 'DRUID') then
|
||||
RequirePower = SPELL_POWER_ENERGY
|
||||
RequireSpell = 5221 -- Shred
|
||||
end
|
||||
elseif(PlayerClass == 'MAGE') then
|
||||
ClassPowerID = SPELL_POWER_ARCANE_CHARGES
|
||||
ClassPowerType = 'ARCANE_CHARGES'
|
||||
RequireSpec = SPEC_MAGE_ARCANE
|
||||
end
|
||||
end
|
||||
|
||||
local function Enable(self, unit)
|
||||
local element = self.ClassPower
|
||||
if(element and UnitIsUnit(unit, 'player')) then
|
||||
element.__owner = self
|
||||
element.__max = #element
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
if(RequireSpec or RequireSpell) then
|
||||
self:RegisterEvent('PLAYER_TALENT_UPDATE', VisibilityPath, true)
|
||||
end
|
||||
|
||||
if(RequirePower) then
|
||||
self:RegisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
end
|
||||
|
||||
element.ClassPowerEnable = ClassPowerEnable
|
||||
element.ClassPowerDisable = ClassPowerDisable
|
||||
|
||||
for i = 1, #element do
|
||||
local bar = element[i]
|
||||
if(bar:IsObjectType('StatusBar')) then
|
||||
if(not (bar:GetStatusBarTexture() or bar:GetStatusBarAtlas())) then
|
||||
bar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
|
||||
bar:SetMinMaxValues(0, 1)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
if(self.ClassPower) then
|
||||
ClassPowerDisable(self)
|
||||
|
||||
self:UnregisterEvent('PLAYER_TALENT_UPDATE', VisibilityPath)
|
||||
self:UnregisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
self:UnregisterEvent('SPELLS_CHANGED', Visibility)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('ClassPower', VisibilityPath, Enable, Disable)
|
||||
105
Libraries/oUF/elements/combatindicator.lua
Normal file
105
Libraries/oUF/elements/combatindicator.lua
Normal file
@@ -0,0 +1,105 @@
|
||||
--[[
|
||||
# Element: Combat Indicator
|
||||
|
||||
Toggles the visibility of an indicator based on the player's combat status.
|
||||
|
||||
## Widget
|
||||
|
||||
CombatIndicator - Any UI widget.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local CombatIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
CombatIndicator:SetSize(16, 16)
|
||||
CombatIndicator:SetPoint('TOP', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.CombatIndicator = CombatIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if not unit or self.unit ~= unit then return end
|
||||
local element = self.CombatIndicator
|
||||
|
||||
--[[ Callback: CombatIndicator:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the CombatIndicator element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local inCombat = UnitAffectingCombat(unit)
|
||||
if(inCombat) then
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
--[[ Callback: CombatIndicator:PostUpdate(inCombat)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the CombatIndicator element
|
||||
* inCombat - indicates if the player is affecting combat (boolean)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(inCombat)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: CombatIndicator.Override(self, event)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
--]]
|
||||
return (self.CombatIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local function Enable(self, unit)
|
||||
local element = self.CombatIndicator
|
||||
if element then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_COMBAT', Path)
|
||||
self:RegisterEvent('UNIT_FLAGS', Path)
|
||||
self:RegisterEvent('PLAYER_REGEN_DISABLED', Path, true)
|
||||
self:RegisterEvent('PLAYER_REGEN_ENABLED', Path, true)
|
||||
|
||||
if(element:IsObjectType('Texture') and not element:GetTexture()) then
|
||||
element:SetTexture([[Interface\CharacterFrame\UI-StateIcon]])
|
||||
element:SetTexCoord(.5, 1, 0, .49)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.CombatIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('UNIT_COMBAT', Path)
|
||||
self:UnregisterEvent('UNIT_FLAGS', Path)
|
||||
self:UnregisterEvent('PLAYER_REGEN_DISABLED', Path)
|
||||
self:UnregisterEvent('PLAYER_REGEN_ENABLED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('CombatIndicator', Path, Enable, Disable)
|
||||
104
Libraries/oUF/elements/grouproleindicator.lua
Normal file
104
Libraries/oUF/elements/grouproleindicator.lua
Normal file
@@ -0,0 +1,104 @@
|
||||
--[[
|
||||
# Element: Group Role Indicator
|
||||
|
||||
Toggles the visibility of an indicator based on the unit's current group role (tank, healer or damager).
|
||||
|
||||
## Widget
|
||||
|
||||
GroupRoleIndicator - A `Texture` used to display the group role icon.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local GroupRoleIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
GroupRoleIndicator:SetSize(16, 16)
|
||||
GroupRoleIndicator:SetPoint('LEFT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.GroupRoleIndicator = GroupRoleIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event)
|
||||
local element = self.GroupRoleIndicator
|
||||
|
||||
--[[ Callback: GroupRoleIndicator:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the GroupRoleIndicator element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local role = UnitGroupRolesAssigned(self.unit)
|
||||
if(role == 'TANK' or role == 'HEALER' or role == 'DAMAGER') then
|
||||
element:SetTexCoord(GetTexCoordsForRoleSmallCircle(role))
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
--[[ Callback: GroupRoleIndicator:PostUpdate(role)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the GroupRoleIndicator element
|
||||
* role - the role as returned by [UnitGroupRolesAssigned](http://wowprogramming.com/docs/api/UnitGroupRolesAssigned.html)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(role)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: GroupRoleIndicator.Override(self, event, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.GroupRoleIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.GroupRoleIndicator
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
if(self.unit == 'player') then
|
||||
self:RegisterEvent('PLAYER_ROLES_ASSIGNED', Path, true)
|
||||
else
|
||||
self:RegisterEvent('GROUP_ROSTER_UPDATE', Path, true)
|
||||
end
|
||||
|
||||
if(element:IsObjectType('Texture') and not element:GetTexture()) then
|
||||
element:SetTexture([[Interface\LFGFrame\UI-LFG-ICON-PORTRAITROLES]])
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.GroupRoleIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('PLAYER_ROLES_ASSIGNED', Path)
|
||||
self:UnregisterEvent('GROUP_ROSTER_UPDATE', Path, true)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('GroupRoleIndicator', Path, Enable, Disable)
|
||||
379
Libraries/oUF/elements/health.lua
Normal file
379
Libraries/oUF/elements/health.lua
Normal file
@@ -0,0 +1,379 @@
|
||||
--[[
|
||||
# Element: Health Bar
|
||||
|
||||
Handles the updating of a status bar that displays the unit's health.
|
||||
|
||||
## Widget
|
||||
|
||||
Health - A `StatusBar` used to represent the unit's health.
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
.bg - A `Texture` used as a background. It will inherit the color of the main StatusBar.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a StatusBar and doesn't have a texture set.
|
||||
|
||||
## Options
|
||||
|
||||
.smoothGradient - 9 color values to be used with the .colorSmooth option (table)
|
||||
.considerSelectionInCombatHostile - Indicates whether selection should be considered hostile while the unit is in
|
||||
combat with the player (boolean)
|
||||
|
||||
The following options are listed by priority. The first check that returns true decides the color of the bar.
|
||||
|
||||
.colorDisconnected - Use `self.colors.disconnected` to color the bar if the unit is offline (boolean)
|
||||
.colorTapping - Use `self.colors.tapping` to color the bar if the unit isn't tapped by the player (boolean)
|
||||
.colorThreat - Use `self.colors.threat[threat]` to color the bar based on the unit's threat status. `threat` is
|
||||
defined by the first return of [UnitThreatSituation](https://wow.gamepedia.com/API_UnitThreatSituation) (boolean)
|
||||
.colorClass - Use `self.colors.class[class]` to color the bar based on unit class. `class` is defined by the
|
||||
second return of [UnitClass](http://wowprogramming.com/docs/api/UnitClass.html) (boolean)
|
||||
.colorClassNPC - Use `self.colors.class[class]` to color the bar if the unit is a NPC (boolean)
|
||||
.colorClassPet - Use `self.colors.class[class]` to color the bar if the unit is player controlled, but not a player
|
||||
(boolean)
|
||||
.colorSelection - Use `self.colors.selection[selection]` to color the bar based on the unit's selection color.
|
||||
`selection` is defined by the return value of Private.unitSelectionType, a wrapper function
|
||||
for [UnitSelectionType](https://wow.gamepedia.com/API_UnitSelectionType) (boolean)
|
||||
.colorReaction - Use `self.colors.reaction[reaction]` to color the bar based on the player's reaction towards the
|
||||
unit. `reaction` is defined by the return value of
|
||||
[UnitReaction](http://wowprogramming.com/docs/api/UnitReaction.html) (boolean)
|
||||
.colorSmooth - Use `smoothGradient` if present or `self.colors.smooth` to color the bar with a smooth gradient
|
||||
based on the player's current health percentage (boolean)
|
||||
.colorHealth - Use `self.colors.health` to color the bar. This flag is used to reset the bar color back to default
|
||||
if none of the above conditions are met (boolean)
|
||||
|
||||
## Sub-Widgets Options
|
||||
|
||||
.multiplier - Used to tint the background based on the main widgets R, G and B values. Defaults to 1 (number)[0-1]
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local Health = CreateFrame('StatusBar', nil, self)
|
||||
Health:SetHeight(20)
|
||||
Health:SetPoint('TOP')
|
||||
Health:SetPoint('LEFT')
|
||||
Health:SetPoint('RIGHT')
|
||||
|
||||
-- Add a background
|
||||
local Background = Health:CreateTexture(nil, 'BACKGROUND')
|
||||
Background:SetAllPoints(Health)
|
||||
Background:SetTexture(1, 1, 1, .5)
|
||||
|
||||
-- Options
|
||||
Health.colorTapping = true
|
||||
Health.colorDisconnected = true
|
||||
Health.colorClass = true
|
||||
Health.colorReaction = true
|
||||
Health.colorHealth = true
|
||||
|
||||
-- Make the background darker.
|
||||
Background.multiplier = .5
|
||||
|
||||
-- Register it with oUF
|
||||
Health.bg = Background
|
||||
self.Health = Health
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local unitSelectionType = Private.unitSelectionType
|
||||
|
||||
local function UpdateColor(self, event, unit)
|
||||
if(not unit or self.unit ~= unit) then return end
|
||||
local element = self.Health
|
||||
|
||||
local r, g, b, t
|
||||
if(element.colorDisconnected and not UnitIsConnected(unit)) then
|
||||
t = self.colors.disconnected
|
||||
elseif(element.colorTapping and not UnitPlayerControlled(unit) and UnitIsTapDenied(unit)) then
|
||||
t = self.colors.tapped
|
||||
elseif(element.colorThreat and not UnitPlayerControlled(unit) and UnitThreatSituation('player', unit)) then
|
||||
t = self.colors.threat[UnitThreatSituation('player', unit)]
|
||||
elseif(element.colorClass and UnitIsPlayer(unit))
|
||||
or (element.colorClassNPC and not UnitIsPlayer(unit))
|
||||
or ((element.colorClassPet or element.colorPetByUnitClass) and UnitPlayerControlled(unit) and not UnitIsPlayer(unit)) then
|
||||
if element.colorPetByUnitClass then unit = unit == 'pet' and 'player' or gsub(unit, 'pet', '') end
|
||||
local _, class = UnitClass(unit)
|
||||
t = self.colors.class[class]
|
||||
elseif(element.colorSelection and unitSelectionType(unit, element.considerSelectionInCombatHostile)) then
|
||||
t = self.colors.selection[unitSelectionType(unit, element.considerSelectionInCombatHostile)]
|
||||
elseif(element.colorReaction and UnitReaction(unit, 'player')) then
|
||||
t = self.colors.reaction[UnitReaction(unit, 'player')]
|
||||
elseif(element.colorSmooth) then
|
||||
r, g, b = self:ColorGradient(element.cur or 1, element.max or 1, unpack(element.smoothGradient or self.colors.smooth))
|
||||
elseif(element.colorHealth) then
|
||||
t = self.colors.health
|
||||
end
|
||||
|
||||
if(t) then
|
||||
r, g, b = t[1], t[2], t[3]
|
||||
end
|
||||
|
||||
if(b) then
|
||||
element:SetStatusBarColor(r, g, b)
|
||||
|
||||
local bg = element.bg
|
||||
if(bg) then
|
||||
local mu = bg.multiplier or 1
|
||||
bg:SetVertexColor(r * mu, g * mu, b * mu)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Callback: Health:PostUpdateColor(unit, r, g, b)
|
||||
Called after the element color has been updated.
|
||||
|
||||
* self - the Health element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* r - the red component of the used color (number)[0-1]
|
||||
* g - the green component of the used color (number)[0-1]
|
||||
* b - the blue component of the used color (number)[0-1]
|
||||
--]]
|
||||
if(element.PostUpdateColor) then
|
||||
element:PostUpdateColor(unit, r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
local function ColorPath(self, ...)
|
||||
--[[ Override: Health.UpdateColor(self, event, unit)
|
||||
Used to completely override the internal function for updating the widgets' colors.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
--]]
|
||||
(self.Health.UpdateColor or UpdateColor) (self, ...)
|
||||
end
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(not unit or self.unit ~= unit) then return end
|
||||
local element = self.Health
|
||||
|
||||
--[[ Callback: Health:PreUpdate(unit)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the Health element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate(unit)
|
||||
end
|
||||
|
||||
local cur, max = UnitHealth(unit), UnitHealthMax(unit)
|
||||
element:SetMinMaxValues(0, max)
|
||||
|
||||
if(UnitIsConnected(unit)) then
|
||||
element:SetValue(cur)
|
||||
else
|
||||
element:SetValue(max)
|
||||
end
|
||||
|
||||
element.cur = cur
|
||||
element.max = max
|
||||
|
||||
--[[ Callback: Health:PostUpdate(unit, cur, max)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the Health element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* cur - the unit's current health value (number)
|
||||
* max - the unit's maximum possible health value (number)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
element:PostUpdate(unit, cur, max)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, event, ...)
|
||||
if (self.isForced and event ~= 'ElvUI_UpdateAllElements') then return end -- ElvUI changed
|
||||
|
||||
--[[ Override: Health.Override(self, event, unit)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
--]]
|
||||
(self.Health.Override or Update) (self, event, ...);
|
||||
|
||||
ColorPath(self, event, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
--[[ Health:SetColorDisconnected(state, isForced)
|
||||
Used to toggle coloring if the unit is offline.
|
||||
|
||||
* self - the Health element
|
||||
* state - the desired state (boolean)
|
||||
* isForced - forces the event update even if the state wasn't changed (boolean)
|
||||
--]]
|
||||
local function SetColorDisconnected(element, state, isForced)
|
||||
if(element.colorDisconnected ~= state or isForced) then
|
||||
element.colorDisconnected = state
|
||||
if(state) then
|
||||
element.__owner:RegisterEvent('UNIT_CONNECTION', ColorPath)
|
||||
element.__owner:RegisterEvent('PARTY_MEMBER_ENABLE', ColorPath)
|
||||
element.__owner:RegisterEvent('PARTY_MEMBER_DISABLE', ColorPath)
|
||||
else
|
||||
element.__owner:UnregisterEvent('UNIT_CONNECTION', ColorPath)
|
||||
element.__owner:UnregisterEvent('PARTY_MEMBER_ENABLE', ColorPath)
|
||||
element.__owner:UnregisterEvent('PARTY_MEMBER_DISABLE', ColorPath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Health:SetColorSelection(state, isForced)
|
||||
Used to toggle coloring by the unit's selection.
|
||||
|
||||
* self - the Health element
|
||||
* state - the desired state (boolean)
|
||||
* isForced - forces the event update even if the state wasn't changed (boolean)
|
||||
--]]
|
||||
local function SetColorSelection(element, state, isForced)
|
||||
if(element.colorSelection ~= state or isForced) then
|
||||
element.colorSelection = state
|
||||
if(state) then
|
||||
element.__owner:RegisterEvent('UNIT_FLAGS', ColorPath)
|
||||
else
|
||||
element.__owner:UnregisterEvent('UNIT_FLAGS', ColorPath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Health:SetColorTapping(state, isForced)
|
||||
Used to toggle coloring if the unit isn't tapped by the player.
|
||||
|
||||
* self - the Health element
|
||||
* state - the desired state (boolean)
|
||||
* isForced - forces the event update even if the state wasn't changed (boolean)
|
||||
--]]
|
||||
local function SetColorTapping(element, state, isForced)
|
||||
if(element.colorTapping ~= state or isForced) then
|
||||
element.colorTapping = state
|
||||
if(state) then
|
||||
element.__owner:RegisterEvent('UNIT_FACTION', ColorPath)
|
||||
else
|
||||
element.__owner:UnregisterEvent('UNIT_FACTION', ColorPath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Health:SetColorThreat(state, isForced)
|
||||
Used to toggle coloring by the unit's threat status.
|
||||
|
||||
* self - the Health element
|
||||
* state - the desired state (boolean)
|
||||
* isForced - forces the event update even if the state wasn't changed (boolean)
|
||||
--]]
|
||||
local function SetColorThreat(element, state, isForced)
|
||||
if(element.colorThreat ~= state or isForced) then
|
||||
element.colorThreat = state
|
||||
if(state) then
|
||||
element.__owner:RegisterEvent('UNIT_THREAT_LIST_UPDATE', ColorPath)
|
||||
else
|
||||
element.__owner:UnregisterEvent('UNIT_THREAT_LIST_UPDATE', ColorPath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ElvUI changed block
|
||||
local onUpdateElapsed, onUpdateWait = 0, 0.25
|
||||
local function onUpdateHealth(self, elapsed)
|
||||
if onUpdateElapsed > onUpdateWait then
|
||||
Path(self.__owner, 'OnUpdate', self.__owner.unit)
|
||||
|
||||
onUpdateElapsed = 0
|
||||
else
|
||||
onUpdateElapsed = onUpdateElapsed + elapsed
|
||||
end
|
||||
end
|
||||
|
||||
local function SetHealthUpdateSpeed(self, state)
|
||||
onUpdateWait = state
|
||||
end
|
||||
|
||||
local function SetHealthUpdateMethod(self, state, force)
|
||||
if self.effectiveHealth ~= state or force then
|
||||
self.effectiveHealth = state
|
||||
|
||||
if state then
|
||||
self.Health:SetScript('OnUpdate', onUpdateHealth)
|
||||
self:UnregisterEvent('UNIT_HEALTH', Path)
|
||||
self:UnregisterEvent('UNIT_MAXHEALTH', Path)
|
||||
else
|
||||
self.Health:SetScript('OnUpdate', nil)
|
||||
self:RegisterEvent('UNIT_HEALTH', Path)
|
||||
self:RegisterEvent('UNIT_MAXHEALTH', Path)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- end block
|
||||
|
||||
local function Enable(self, unit)
|
||||
local element = self.Health
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
element.SetColorDisconnected = SetColorDisconnected
|
||||
element.SetColorSelection = SetColorSelection
|
||||
element.SetColorTapping = SetColorTapping
|
||||
element.SetColorThreat = SetColorThreat
|
||||
|
||||
-- ElvUI changed block
|
||||
self.SetHealthUpdateSpeed = SetHealthUpdateSpeed
|
||||
self.SetHealthUpdateMethod = SetHealthUpdateMethod
|
||||
SetHealthUpdateMethod(self, self.effectiveHealth, true)
|
||||
-- end block
|
||||
|
||||
if(element.colorDisconnected) then
|
||||
self:RegisterEvent('UNIT_CONNECTION', ColorPath)
|
||||
self:RegisterEvent('PARTY_MEMBER_ENABLE', ColorPath)
|
||||
self:RegisterEvent('PARTY_MEMBER_DISABLE', ColorPath)
|
||||
end
|
||||
|
||||
if(element.colorSelection) then
|
||||
self:RegisterEvent('UNIT_FLAGS', ColorPath)
|
||||
end
|
||||
|
||||
if(element.colorTapping) then
|
||||
self:RegisterEvent('UNIT_FACTION', ColorPath)
|
||||
end
|
||||
|
||||
if(element.colorThreat) then
|
||||
self:RegisterEvent('UNIT_THREAT_LIST_UPDATE', ColorPath)
|
||||
end
|
||||
|
||||
if(element:IsObjectType('StatusBar') and not (element:GetStatusBarTexture() or element:GetStatusBarAtlas())) then
|
||||
element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
|
||||
element:Show()
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.Health
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
element:SetScript('OnUpdate', nil) -- ElvUI changed
|
||||
self:UnregisterEvent('UNIT_HEALTH', Path)
|
||||
self:UnregisterEvent('UNIT_MAXHEALTH', Path)
|
||||
self:UnregisterEvent('UNIT_CONNECTION', ColorPath)
|
||||
self:UnregisterEvent('UNIT_FACTION', ColorPath)
|
||||
self:UnregisterEvent('UNIT_FLAGS', ColorPath)
|
||||
self:UnregisterEvent('PARTY_MEMBER_ENABLE', ColorPath)
|
||||
self:UnregisterEvent('PARTY_MEMBER_DISABLE', ColorPath)
|
||||
self:UnregisterEvent('UNIT_THREAT_LIST_UPDATE', ColorPath)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Health', Path, Enable, Disable)
|
||||
300
Libraries/oUF/elements/healthprediction.lua
Normal file
300
Libraries/oUF/elements/healthprediction.lua
Normal file
@@ -0,0 +1,300 @@
|
||||
--[[
|
||||
# Element: Health Prediction Bars
|
||||
|
||||
Handles the visibility and updating of incoming heals and heal/damage absorbs.
|
||||
|
||||
## Widget
|
||||
|
||||
HealthPrediction - A `table` containing references to sub-widgets and options.
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
myBar - A `StatusBar` used to represent incoming heals from the player.
|
||||
otherBar - A `StatusBar` used to represent incoming heals from others.
|
||||
absorbBar - A `StatusBar` used to represent damage absorbs.
|
||||
healAbsorbBar - A `StatusBar` used to represent heal absorbs.
|
||||
overAbsorb - A `Texture` used to signify that the amount of damage absorb is greater than the unit's missing health.
|
||||
overHealAbsorb - A `Texture` used to signify that the amount of heal absorb is greater than the unit's current health.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied to the StatusBar widgets if they don't have a texture set.
|
||||
A default texture will be applied to the Texture widgets if they don't have a texture or a color set.
|
||||
|
||||
## Options
|
||||
|
||||
.maxOverflow - The maximum amount of overflow past the end of the health bar. Set this to 1 to disable the overflow.
|
||||
Defaults to 1.05 (number)
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local myBar = CreateFrame('StatusBar', nil, self.Health)
|
||||
myBar:SetPoint('TOP')
|
||||
myBar:SetPoint('BOTTOM')
|
||||
myBar:SetPoint('LEFT', self.Health:GetStatusBarTexture(), 'RIGHT')
|
||||
myBar:SetWidth(200)
|
||||
|
||||
local otherBar = CreateFrame('StatusBar', nil, self.Health)
|
||||
otherBar:SetPoint('TOP')
|
||||
otherBar:SetPoint('BOTTOM')
|
||||
otherBar:SetPoint('LEFT', myBar:GetStatusBarTexture(), 'RIGHT')
|
||||
otherBar:SetWidth(200)
|
||||
|
||||
local absorbBar = CreateFrame('StatusBar', nil, self.Health)
|
||||
absorbBar:SetPoint('TOP')
|
||||
absorbBar:SetPoint('BOTTOM')
|
||||
absorbBar:SetPoint('LEFT', otherBar:GetStatusBarTexture(), 'RIGHT')
|
||||
absorbBar:SetWidth(200)
|
||||
|
||||
local healAbsorbBar = CreateFrame('StatusBar', nil, self.Health)
|
||||
healAbsorbBar:SetPoint('TOP')
|
||||
healAbsorbBar:SetPoint('BOTTOM')
|
||||
healAbsorbBar:SetPoint('RIGHT', self.Health:GetStatusBarTexture())
|
||||
healAbsorbBar:SetWidth(200)
|
||||
healAbsorbBar:SetReverseFill(true)
|
||||
|
||||
local overAbsorb = self.Health:CreateTexture(nil, "OVERLAY")
|
||||
overAbsorb:SetPoint('TOP')
|
||||
overAbsorb:SetPoint('BOTTOM')
|
||||
overAbsorb:SetPoint('LEFT', self.Health, 'RIGHT')
|
||||
overAbsorb:SetWidth(10)
|
||||
|
||||
local overHealAbsorb = self.Health:CreateTexture(nil, "OVERLAY")
|
||||
overHealAbsorb:SetPoint('TOP')
|
||||
overHealAbsorb:SetPoint('BOTTOM')
|
||||
overHealAbsorb:SetPoint('RIGHT', self.Health, 'LEFT')
|
||||
overHealAbsorb:SetWidth(10)
|
||||
|
||||
-- Register with oUF
|
||||
self.HealthPrediction = {
|
||||
myBar = myBar,
|
||||
otherBar = otherBar,
|
||||
absorbBar = absorbBar,
|
||||
healAbsorbBar = healAbsorbBar,
|
||||
overAbsorb = overAbsorb,
|
||||
overHealAbsorb = overHealAbsorb,
|
||||
maxOverflow = 1.05,
|
||||
}
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local element = self.HealthPrediction
|
||||
|
||||
--[[ Callback: HealthPrediction:PreUpdate(unit)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the HealthPrediction element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate(unit)
|
||||
end
|
||||
|
||||
local myIncomingHeal = UnitGetIncomingHeals(unit, 'player') or 0
|
||||
local allIncomingHeal = UnitGetIncomingHeals(unit) or 0
|
||||
local absorb = UnitGetTotalAbsorbs(unit) or 0
|
||||
local healAbsorb = UnitGetTotalHealAbsorbs(unit) or 0
|
||||
local health, maxHealth = UnitHealth(unit), UnitHealthMax(unit)
|
||||
local otherIncomingHeal = 0
|
||||
local hasOverHealAbsorb = false
|
||||
|
||||
if(healAbsorb > allIncomingHeal) then
|
||||
healAbsorb = healAbsorb - allIncomingHeal
|
||||
allIncomingHeal = 0
|
||||
myIncomingHeal = 0
|
||||
|
||||
if(health < healAbsorb) then
|
||||
hasOverHealAbsorb = true
|
||||
end
|
||||
else
|
||||
allIncomingHeal = allIncomingHeal - healAbsorb
|
||||
healAbsorb = 0
|
||||
|
||||
if(health + allIncomingHeal > maxHealth * element.maxOverflow) then
|
||||
allIncomingHeal = maxHealth * element.maxOverflow - health
|
||||
end
|
||||
|
||||
if(allIncomingHeal < myIncomingHeal) then
|
||||
myIncomingHeal = allIncomingHeal
|
||||
else
|
||||
otherIncomingHeal = allIncomingHeal - myIncomingHeal
|
||||
end
|
||||
end
|
||||
|
||||
local hasOverAbsorb = false
|
||||
if(health + allIncomingHeal + absorb >= maxHealth) and (absorb > 0) then
|
||||
hasOverAbsorb = true
|
||||
end
|
||||
|
||||
if(element.myBar) then
|
||||
element.myBar:SetMinMaxValues(0, maxHealth)
|
||||
element.myBar:SetValue(myIncomingHeal)
|
||||
element.myBar:Show()
|
||||
end
|
||||
|
||||
if(element.otherBar) then
|
||||
element.otherBar:SetMinMaxValues(0, maxHealth)
|
||||
element.otherBar:SetValue(otherIncomingHeal)
|
||||
element.otherBar:Show()
|
||||
end
|
||||
|
||||
if(element.absorbBar) then
|
||||
element.absorbBar:SetMinMaxValues(0, maxHealth)
|
||||
element.absorbBar:SetValue(absorb)
|
||||
element.absorbBar:Show()
|
||||
end
|
||||
|
||||
if(element.healAbsorbBar) then
|
||||
element.healAbsorbBar:SetMinMaxValues(0, maxHealth)
|
||||
element.healAbsorbBar:SetValue(healAbsorb)
|
||||
element.healAbsorbBar:Show()
|
||||
end
|
||||
|
||||
if(element.overAbsorb) then
|
||||
if(hasOverAbsorb) then
|
||||
element.overAbsorb:Show()
|
||||
else
|
||||
element.overAbsorb:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
if(element.overHealAbsorb) then
|
||||
if(hasOverHealAbsorb) then
|
||||
element.overHealAbsorb:Show()
|
||||
else
|
||||
element.overHealAbsorb:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Callback: HealthPrediction:PostUpdate(unit, myIncomingHeal, otherIncomingHeal, absorb, healAbsorb, hasOverAbsorb, hasOverHealAbsorb)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the HealthPrediction element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* myIncomingHeal - the amount of incoming healing done by the player (number)
|
||||
* otherIncomingHeal - the amount of incoming healing done by others (number)
|
||||
* absorb - the amount of damage the unit can absorb without losing health (number)
|
||||
* healAbsorb - the amount of healing the unit can absorb without gaining health (number)
|
||||
* hasOverAbsorb - indicates if the amount of damage absorb is higher than the unit's missing health (boolean)
|
||||
* hasOverHealAbsorb - indicates if the amount of heal absorb is higher than the unit's current health (boolean)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(unit, myIncomingHeal, otherIncomingHeal, absorb, healAbsorb, hasOverAbsorb, hasOverHealAbsorb, health, maxHealth)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: HealthPrediction.Override(self, event, unit)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event
|
||||
--]]
|
||||
return (self.HealthPrediction.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.HealthPrediction
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_HEALTH', Path)
|
||||
self:RegisterEvent('UNIT_MAXHEALTH', Path)
|
||||
self:RegisterEvent('UNIT_HEAL_PREDICTION', Path)
|
||||
self:RegisterEvent('UNIT_ABSORB_AMOUNT_CHANGED', Path)
|
||||
self:RegisterEvent('UNIT_HEAL_ABSORB_AMOUNT_CHANGED', Path)
|
||||
|
||||
if(not element.maxOverflow) then
|
||||
element.maxOverflow = 1.05
|
||||
end
|
||||
|
||||
if(element.myBar) then
|
||||
if(element.myBar:IsObjectType('StatusBar') and not element.myBar:GetStatusBarTexture()) then
|
||||
element.myBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
if(element.otherBar) then
|
||||
if(element.otherBar:IsObjectType('StatusBar') and not element.otherBar:GetStatusBarTexture()) then
|
||||
element.otherBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
if(element.absorbBar) then
|
||||
if(element.absorbBar:IsObjectType('StatusBar') and not element.absorbBar:GetStatusBarTexture()) then
|
||||
element.absorbBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
if(element.healAbsorbBar) then
|
||||
if(element.healAbsorbBar:IsObjectType('StatusBar') and not element.healAbsorbBar:GetStatusBarTexture()) then
|
||||
element.healAbsorbBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
if(element.overAbsorb) then
|
||||
if(element.overAbsorb:IsObjectType('Texture') and not element.overAbsorb:GetTexture()) then
|
||||
element.overAbsorb:SetTexture([[Interface\RaidFrame\Shield-Overshield]])
|
||||
element.overAbsorb:SetBlendMode('ADD')
|
||||
end
|
||||
end
|
||||
|
||||
if(element.overHealAbsorb) then
|
||||
if(element.overHealAbsorb:IsObjectType('Texture') and not element.overHealAbsorb:GetTexture()) then
|
||||
element.overHealAbsorb:SetTexture([[Interface\RaidFrame\Absorb-Overabsorb]])
|
||||
element.overHealAbsorb:SetBlendMode('ADD')
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.HealthPrediction
|
||||
if(element) then
|
||||
if(element.myBar) then
|
||||
element.myBar:Hide()
|
||||
end
|
||||
|
||||
if(element.otherBar) then
|
||||
element.otherBar:Hide()
|
||||
end
|
||||
|
||||
if(element.absorbBar) then
|
||||
element.absorbBar:Hide()
|
||||
end
|
||||
|
||||
if(element.healAbsorbBar) then
|
||||
element.healAbsorbBar:Hide()
|
||||
end
|
||||
|
||||
if(element.overAbsorb) then
|
||||
element.overAbsorb:Hide()
|
||||
end
|
||||
|
||||
if(element.overHealAbsorb) then
|
||||
element.overHealAbsorb:Hide()
|
||||
end
|
||||
|
||||
self:UnregisterEvent('UNIT_HEALTH', Path)
|
||||
self:UnregisterEvent('UNIT_MAXHEALTH', Path)
|
||||
self:UnregisterEvent('UNIT_HEAL_PREDICTION', Path)
|
||||
self:UnregisterEvent('UNIT_ABSORB_AMOUNT_CHANGED', Path)
|
||||
self:UnregisterEvent('UNIT_HEAL_ABSORB_AMOUNT_CHANGED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('HealthPrediction', Path, Enable, Disable)
|
||||
109
Libraries/oUF/elements/leaderindicator.lua
Normal file
109
Libraries/oUF/elements/leaderindicator.lua
Normal file
@@ -0,0 +1,109 @@
|
||||
--[[
|
||||
# Element: Leader Indicator
|
||||
|
||||
Toggles the visibility of an indicator based on the unit's leader status.
|
||||
|
||||
## Widget
|
||||
|
||||
LeaderIndicator - Any UI widget.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local LeaderIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
LeaderIndicator:SetSize(16, 16)
|
||||
LeaderIndicator:SetPoint('BOTTOM', self, 'TOP')
|
||||
|
||||
-- Register it with oUF
|
||||
self.LeaderIndicator = LeaderIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event)
|
||||
local element = self.LeaderIndicator
|
||||
local unit = self.unit
|
||||
|
||||
--[[ Callback: LeaderIndicator:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the LeaderIndicator element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
-- ElvUI changed block
|
||||
local isLeader
|
||||
if IsInInstance() then
|
||||
isLeader = UnitIsGroupLeader(unit)
|
||||
else
|
||||
isLeader = UnitLeadsAnyGroup(unit)
|
||||
end
|
||||
-- end block
|
||||
|
||||
if(isLeader) then
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
--[[ Callback: LeaderIndicator:PostUpdate(isLeader)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the LeaderIndicator element
|
||||
* isLeader - indicates whether the element is shown (boolean)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(isLeader)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: LeaderIndicator.Override(self, event, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.LeaderIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.LeaderIndicator
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('PARTY_LEADER_CHANGED', Path, true)
|
||||
self:RegisterEvent('GROUP_ROSTER_UPDATE', Path, true)
|
||||
|
||||
if(element:IsObjectType('Texture') and not element:GetTexture()) then
|
||||
element:SetTexture([[Interface\GroupFrame\UI-Group-LeaderIcon]])
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.LeaderIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('PARTY_LEADER_CHANGED', Path)
|
||||
self:UnregisterEvent('GROUP_ROSTER_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('LeaderIndicator', Path, Enable, Disable)
|
||||
90
Libraries/oUF/elements/partyindicator.lua
Normal file
90
Libraries/oUF/elements/partyindicator.lua
Normal file
@@ -0,0 +1,90 @@
|
||||
--[[
|
||||
# Element: Party Indicator
|
||||
Toggles the visibility of an indicator based on if the player was in a group before joining the instance.
|
||||
|
||||
## Widget
|
||||
PartyIndicator - Player only widget.
|
||||
]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event)
|
||||
local element = self.PartyIndicator
|
||||
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local forced = not event or event == 'ElvUI_UpdateAllElements'
|
||||
if forced or event == 'GROUP_ROSTER_UPDATE' then
|
||||
if IsInGroup(LE_PARTY_CATEGORY_HOME) and IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
if forced or event == 'UPDATE_CHAT_COLOR' then
|
||||
local private = ChatTypeInfo.PARTY
|
||||
if private and element.HomeIcon then
|
||||
element.HomeIcon:SetVertexColor(private.r, private.g, private.b, 1)
|
||||
end
|
||||
|
||||
local public = ChatTypeInfo.INSTANCE_CHAT
|
||||
if public and element.InstanceIcon then
|
||||
element.InstanceIcon:SetVertexColor(public.r, public.g, public.b, 1)
|
||||
end
|
||||
end
|
||||
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate()
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: PartyIndicator.Override(self, event)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
--]]
|
||||
return (self.PartyIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.PartyIndicator
|
||||
if element then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UPDATE_CHAT_COLOR', Path, true)
|
||||
self:RegisterEvent('GROUP_ROSTER_UPDATE', Path, true)
|
||||
|
||||
if(element.HomeIcon and element.HomeIcon:IsObjectType('Texture') and not element.HomeIcon:GetTexture()) then
|
||||
element.HomeIcon:SetTexture([[Interface\FriendsFrame\UI-Toast-FriendOnlineIcon]])
|
||||
end
|
||||
|
||||
if(element.InstanceIcon and element.InstanceIcon:IsObjectType('Texture') and not element.InstanceIcon:GetTexture()) then
|
||||
element.InstanceIcon:SetTexture([[Interface\FriendsFrame\UI-Toast-FriendOnlineIcon]])
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.PartyIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('UPDATE_CHAT_COLOR', Path)
|
||||
self:UnregisterEvent('GROUP_ROSTER_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('PartyIndicator', Path, Enable, Disable)
|
||||
159
Libraries/oUF/elements/phaseindicator.lua
Normal file
159
Libraries/oUF/elements/phaseindicator.lua
Normal file
@@ -0,0 +1,159 @@
|
||||
--[[
|
||||
# Element: Phasing Indicator
|
||||
|
||||
Toggles the visibility of an indicator based on the unit's phasing relative to the player.
|
||||
|
||||
## Widget
|
||||
|
||||
PhaseIndicator - Any UI widget.
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
Icon - A `Texture` to represent the phased status.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
|
||||
OnEnter and OnLeave script handlers will be set to display a Tooltip if the widget is mouse enabled and does not have
|
||||
OnEnter and/or OnLeave handlers.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local PhaseIndicator = CreateFrame('Frame', nil, self)
|
||||
PhaseIndicator:SetSize(16, 16)
|
||||
PhaseIndicator:SetPoint('TOPLEFT', self)
|
||||
PhaseIndicator:EnableMouse(true)
|
||||
|
||||
local Icon = PhaseIndicator:CreateTexture(nil, 'OVERLAY')
|
||||
Icon:SetAllPoints()
|
||||
PhaseIndicator.Icon = Icon
|
||||
|
||||
-- Register it with oUF
|
||||
self.PhaseIndicator = PhaseIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local GameTooltip = GameTooltip
|
||||
|
||||
--[[ Override: PhaseIndicator:UpdateTooltip()
|
||||
Used to populate the tooltip when the widget is hovered.
|
||||
|
||||
* self - the PhaseIndicator widget
|
||||
--]]
|
||||
local function UpdateTooltip(element)
|
||||
if GameTooltip:IsForbidden() then return end
|
||||
|
||||
local text = PartyUtil.GetPhasedReasonString(element.reason, element.__owner.unit)
|
||||
if(text) then
|
||||
GameTooltip:SetText(text, nil, nil, nil, nil, true)
|
||||
GameTooltip:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local function onEnter(element)
|
||||
if GameTooltip:IsForbidden() or not element:IsVisible() then return end
|
||||
|
||||
if(element.reason) then
|
||||
GameTooltip:SetOwner(element, 'ANCHOR_BOTTOMRIGHT')
|
||||
element:UpdateTooltip()
|
||||
end
|
||||
end
|
||||
|
||||
local function onLeave()
|
||||
if GameTooltip:IsForbidden() then return end
|
||||
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local element = self.PhaseIndicator
|
||||
|
||||
--[[ Callback: PhaseIndicator:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the PhaseIndicator element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local phaseReason = UnitIsPlayer(unit) and UnitIsConnected(unit) and UnitPhaseReason(unit) or nil
|
||||
if(phaseReason) then
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
element.reason = phaseReason
|
||||
|
||||
--[[ Callback: PhaseIndicator:PostUpdate(isInSamePhase, phaseReason)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the PhaseIndicator element
|
||||
* isInSamePhase - indicates whether the unit is in the same phase as the player (boolean)
|
||||
* phaseReason - the reason why the unit is in a different phase (number?)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(not phaseReason, phaseReason)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: PhaseIndicator.Override(self, event, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.PhaseIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.PhaseIndicator
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_PHASE', Path)
|
||||
|
||||
local icon = (element.Icon or element)
|
||||
if(icon:IsObjectType('Texture') and not icon:GetTexture()) then
|
||||
icon:SetTexture([[Interface\TargetingFrame\UI-PhasingIcon]])
|
||||
end
|
||||
|
||||
if(element.IsMouseEnabled and element:IsMouseEnabled()) then
|
||||
if(not element:GetScript('OnEnter')) then
|
||||
element:SetScript('OnEnter', onEnter)
|
||||
end
|
||||
|
||||
if(not element:GetScript('OnLeave')) then
|
||||
element:SetScript('OnLeave', onLeave)
|
||||
end
|
||||
|
||||
element.UpdateTooltip = element.UpdateTooltip or UpdateTooltip
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.PhaseIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('UNIT_PHASE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('PhaseIndicator', Path, Enable, Disable)
|
||||
152
Libraries/oUF/elements/portrait.lua
Normal file
152
Libraries/oUF/elements/portrait.lua
Normal file
@@ -0,0 +1,152 @@
|
||||
--[[
|
||||
# Element: Portraits
|
||||
|
||||
Handles the updating of the unit's portrait.
|
||||
|
||||
## Widget
|
||||
|
||||
Portrait - A `PlayerModel` or a `Texture` used to represent the unit's portrait.
|
||||
|
||||
## Notes
|
||||
|
||||
A question mark model will be used if the widget is a PlayerModel and the client doesn't have the model information for
|
||||
the unit.
|
||||
|
||||
## Examples
|
||||
|
||||
-- 3D Portrait
|
||||
-- Position and size
|
||||
local Portrait = CreateFrame('PlayerModel', nil, self)
|
||||
Portrait:SetSize(32, 32)
|
||||
Portrait:SetPoint('RIGHT', self, 'LEFT')
|
||||
|
||||
-- Register it with oUF
|
||||
self.Portrait = Portrait
|
||||
|
||||
-- 2D Portrait
|
||||
local Portrait = self:CreateTexture(nil, 'OVERLAY')
|
||||
Portrait:SetSize(32, 32)
|
||||
Portrait:SetPoint('RIGHT', self, 'LEFT')
|
||||
|
||||
-- Register it with oUF
|
||||
self.Portrait = Portrait
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
-- ElvUI block
|
||||
local UnitIsUnit = UnitIsUnit
|
||||
local UnitGUID = UnitGUID
|
||||
local UnitIsConnected = UnitIsConnected
|
||||
local UnitIsVisible = UnitIsVisible
|
||||
local SetPortraitTexture = SetPortraitTexture
|
||||
-- end block
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(not unit or not UnitIsUnit(self.unit, unit)) then return end
|
||||
|
||||
--[[ Callback: Portrait:PreUpdate(unit)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the Portrait element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
|
||||
local element = self.Portrait
|
||||
if(element.PreUpdate) then element:PreUpdate(unit) end
|
||||
|
||||
local guid = UnitGUID(unit)
|
||||
local isAvailable = UnitIsConnected(unit) and UnitIsVisible(unit)
|
||||
element.stateChanged = event ~= 'OnUpdate' or element.guid ~= guid or element.state ~= isAvailable
|
||||
if element.stateChanged then -- ElvUI changed
|
||||
element.playerModel = element:IsObjectType('PlayerModel')
|
||||
element.state = isAvailable
|
||||
element.guid = guid
|
||||
|
||||
if element.playerModel then
|
||||
if not isAvailable then
|
||||
element:SetCamDistanceScale(0.25)
|
||||
element:SetPortraitZoom(0)
|
||||
element:SetPosition(0, 0, 0.25)
|
||||
element:ClearModel()
|
||||
element:SetModel([[Interface\Buttons\TalkToMeQuestionMark.m2]])
|
||||
else
|
||||
element:SetCamDistanceScale(1)
|
||||
element:SetPortraitZoom(1)
|
||||
element:SetPosition(0, 0, 0)
|
||||
element:ClearModel()
|
||||
element:SetUnit(unit)
|
||||
end
|
||||
elseif not element.customTexture then -- ElvUI changed
|
||||
SetPortraitTexture(element, unit)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Callback: Portrait:PostUpdate(unit)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the Portrait element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(unit, event)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: Portrait.Override(self, event, unit)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
--]]
|
||||
return (self.Portrait.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self, unit)
|
||||
local element = self.Portrait
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_MODEL_CHANGED', Path)
|
||||
self:RegisterEvent('UNIT_PORTRAIT_UPDATE', Path)
|
||||
self:RegisterEvent('PORTRAITS_UPDATED', Path, true)
|
||||
self:RegisterEvent('UNIT_CONNECTION', Path)
|
||||
|
||||
-- The quest log uses PARTY_MEMBER_{ENABLE,DISABLE} to handle updating of
|
||||
-- party members overlapping quests. This will probably be enough to handle
|
||||
-- model updating.
|
||||
--
|
||||
-- DISABLE isn't used as it fires when we most likely don't have the
|
||||
-- information we want.
|
||||
if(unit == 'party') then
|
||||
self:RegisterEvent('PARTY_MEMBER_ENABLE', Path)
|
||||
end
|
||||
|
||||
element:Show()
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.Portrait
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('UNIT_MODEL_CHANGED', Path)
|
||||
self:UnregisterEvent('UNIT_PORTRAIT_UPDATE', Path)
|
||||
self:UnregisterEvent('PORTRAITS_UPDATED', Path)
|
||||
self:UnregisterEvent('PARTY_MEMBER_ENABLE', Path)
|
||||
self:UnregisterEvent('UNIT_CONNECTION', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Portrait', Path, Enable, Disable)
|
||||
481
Libraries/oUF/elements/power.lua
Normal file
481
Libraries/oUF/elements/power.lua
Normal file
@@ -0,0 +1,481 @@
|
||||
--[[
|
||||
# Element: Power Bar
|
||||
|
||||
Handles the updating of a status bar that displays the unit's power.
|
||||
|
||||
## Widget
|
||||
|
||||
Power - A `StatusBar` used to represent the unit's power.
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
.bg - A `Texture` used as a background. It will inherit the color of the main StatusBar.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a StatusBar and doesn't have a texture or a color set.
|
||||
|
||||
## Options
|
||||
|
||||
.frequentUpdates - Indicates whether to use UNIT_POWER_FREQUENT instead UNIT_POWER_UPDATE to update the
|
||||
bar (boolean)
|
||||
.displayAltPower - Use this to let the widget display alternative power, if the unit has one.
|
||||
By default, it does so only for raid and party units. If none, the display will fall
|
||||
back to the primary power (boolean)
|
||||
.useAtlas - Use this to let the widget use an atlas for its texture if an atlas is present in
|
||||
`self.colors.power` for the appropriate power type (boolean)
|
||||
.smoothGradient - 9 color values to be used with the .colorSmooth option (table)
|
||||
.considerSelectionInCombatHostile - Indicates whether selection should be considered hostile while the unit is in
|
||||
combat with the player (boolean)
|
||||
|
||||
The following options are listed by priority. The first check that returns true decides the color of the bar.
|
||||
|
||||
.colorDisconnected - Use `self.colors.disconnected` to color the bar if the unit is offline (boolean)
|
||||
.colorTapping - Use `self.colors.tapping` to color the bar if the unit isn't tapped by the player (boolean)
|
||||
.colorThreat - Use `self.colors.threat[threat]` to color the bar based on the unit's threat status. `threat` is
|
||||
defined by the first return of [UnitThreatSituation](https://wow.gamepedia.com/API_UnitThreatSituation) (boolean)
|
||||
.colorPower - Use `self.colors.power[token]` to color the bar based on the unit's power type. This method will
|
||||
fall-back to `:GetAlternativeColor()` if it can't find a color matching the token. If this function
|
||||
isn't defined, then it will attempt to color based upon the alternative power colors returned by
|
||||
[UnitPowerType](http://wowprogramming.com/docs/api/UnitPowerType.html). If these aren't
|
||||
defined, then it will attempt to color the bar based upon `self.colors.power[type]`. In case of
|
||||
failure it'll default to `self.colors.power.MANA` (boolean)
|
||||
.colorClass - Use `self.colors.class[class]` to color the bar based on unit class. `class` is defined by the
|
||||
second return of [UnitClass](http://wowprogramming.com/docs/api/UnitClass.html) (boolean)
|
||||
.colorClassNPC - Use `self.colors.class[class]` to color the bar if the unit is a NPC (boolean)
|
||||
.colorClassPet - Use `self.colors.class[class]` to color the bar if the unit is player controlled, but not a player
|
||||
(boolean)
|
||||
.colorSelection - Use `self.colors.selection[selection]` to color the bar based on the unit's selection color.
|
||||
`selection` is defined by the return value of Private.unitSelectionType, a wrapper function
|
||||
for [UnitSelectionType](https://wow.gamepedia.com/API_UnitSelectionType) (boolean)
|
||||
.colorReaction - Use `self.colors.reaction[reaction]` to color the bar based on the player's reaction towards the
|
||||
unit. `reaction` is defined by the return value of
|
||||
[UnitReaction](http://wowprogramming.com/docs/api/UnitReaction.html) (boolean)
|
||||
.colorSmooth - Use `smoothGradient` if present or `self.colors.smooth` to color the bar with a smooth gradient
|
||||
based on the player's current power percentage (boolean)
|
||||
|
||||
## Sub-Widget Options
|
||||
|
||||
.multiplier - A multiplier used to tint the background based on the main widgets R, G and B values. Defaults to 1
|
||||
(number)[0-1]
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local Power = CreateFrame('StatusBar', nil, self)
|
||||
Power:SetHeight(20)
|
||||
Power:SetPoint('BOTTOM')
|
||||
Power:SetPoint('LEFT')
|
||||
Power:SetPoint('RIGHT')
|
||||
|
||||
-- Add a background
|
||||
local Background = Power:CreateTexture(nil, 'BACKGROUND')
|
||||
Background:SetAllPoints(Power)
|
||||
Background:SetTexture(1, 1, 1, .5)
|
||||
|
||||
-- Options
|
||||
Power.frequentUpdates = true
|
||||
Power.colorTapping = true
|
||||
Power.colorDisconnected = true
|
||||
Power.colorPower = true
|
||||
Power.colorClass = true
|
||||
Power.colorReaction = true
|
||||
|
||||
-- Make the background darker.
|
||||
Background.multiplier = .5
|
||||
|
||||
-- Register it with oUF
|
||||
Power.bg = Background
|
||||
self.Power = Power
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local unitSelectionType = Private.unitSelectionType
|
||||
|
||||
-- sourced from FrameXML/UnitPowerBarAlt.lua
|
||||
local ALTERNATE_POWER_INDEX = Enum.PowerType.Alternate or 10
|
||||
|
||||
--[[ Override: Power:GetDisplayPower()
|
||||
Used to get info on the unit's alternative power, if any.
|
||||
Should return the power type index (see [Enum.PowerType.Alternate](https://wow.gamepedia.com/Enum_Unit.PowerType))
|
||||
and the minimum value for the given power type (see [info.minPower](https://wow.gamepedia.com/API_GetUnitPowerBarInfo))
|
||||
or nil if the unit has no alternative (alternate) power or it should not be
|
||||
displayed. In case of a nil return, the element defaults to the primary power
|
||||
type and zero for the minimum value.
|
||||
|
||||
* self - the Power element
|
||||
--]]
|
||||
local function GetDisplayPower(element)
|
||||
local unit = element.__owner.unit
|
||||
local barInfo = GetUnitPowerBarInfo(unit)
|
||||
if(barInfo and barInfo.showOnRaid and (UnitInParty(unit) or UnitInRaid(unit))) then
|
||||
return ALTERNATE_POWER_INDEX, barInfo.minPower
|
||||
end
|
||||
end
|
||||
|
||||
local function UpdateColor(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
local element = self.Power
|
||||
|
||||
local pType, pToken, altR, altG, altB = UnitPowerType(unit)
|
||||
|
||||
local r, g, b, t, atlas
|
||||
if(element.colorDisconnected and not UnitIsConnected(unit)) then
|
||||
t = self.colors.disconnected
|
||||
elseif(element.colorTapping and not UnitPlayerControlled(unit) and UnitIsTapDenied(unit)) then
|
||||
t = self.colors.tapped
|
||||
elseif(element.colorThreat and not UnitPlayerControlled(unit) and UnitThreatSituation('player', unit)) then
|
||||
t = self.colors.threat[UnitThreatSituation('player', unit)]
|
||||
elseif(element.colorPower) then
|
||||
if(element.displayType ~= ALTERNATE_POWER_INDEX) then
|
||||
t = self.colors.power[pToken]
|
||||
if(not t) then
|
||||
if(element.GetAlternativeColor) then
|
||||
r, g, b = element:GetAlternativeColor(unit, pType, pToken, altR, altG, altB)
|
||||
elseif(altR) then
|
||||
r, g, b = altR, altG, altB
|
||||
if(r > 1 or g > 1 or b > 1) then
|
||||
-- BUG: As of 7.0.3, altR, altG, altB may be in 0-1 or 0-255 range.
|
||||
r, g, b = r / 255, g / 255, b / 255
|
||||
end
|
||||
else
|
||||
t = self.colors.power[pType] or self.colors.power.MANA
|
||||
end
|
||||
end
|
||||
else
|
||||
t = self.colors.power[ALTERNATE_POWER_INDEX]
|
||||
end
|
||||
|
||||
if(element.useAtlas and t and t.atlas) then
|
||||
atlas = t.atlas
|
||||
end
|
||||
elseif(element.colorClass and UnitIsPlayer(unit))
|
||||
or (element.colorClassNPC and not UnitIsPlayer(unit))
|
||||
or (element.colorClassPet and UnitPlayerControlled(unit) and not UnitIsPlayer(unit)) then
|
||||
local _, class = UnitClass(unit)
|
||||
t = self.colors.class[class]
|
||||
elseif(element.colorSelection and unitSelectionType(unit, element.considerSelectionInCombatHostile)) then
|
||||
t = self.colors.selection[unitSelectionType(unit, element.considerSelectionInCombatHostile)]
|
||||
elseif(element.colorReaction and UnitReaction(unit, 'player')) then
|
||||
t = self.colors.reaction[UnitReaction(unit, 'player')]
|
||||
elseif(element.colorSmooth) then
|
||||
local adjust = 0 - (element.min or 0)
|
||||
r, g, b = self:ColorGradient((element.cur or 1) + adjust, (element.max or 1) + adjust, unpack(element.smoothGradient or self.colors.smooth))
|
||||
end
|
||||
|
||||
if(t) then
|
||||
r, g, b = t[1], t[2], t[3]
|
||||
end
|
||||
|
||||
if(atlas) then
|
||||
element:SetStatusBarAtlas(atlas)
|
||||
element:SetStatusBarColor(1, 1, 1)
|
||||
elseif(b) then
|
||||
element:SetStatusBarColor(r, g, b)
|
||||
|
||||
local bg = element.bg
|
||||
if(bg) then
|
||||
local mu = bg.multiplier or 1
|
||||
bg:SetVertexColor(r * mu, g * mu, b * mu)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Callback: Power:PostUpdateColor(unit, r, g, b)
|
||||
Called after the element color has been updated.
|
||||
|
||||
local bg = element.bg
|
||||
if(bg and b) then
|
||||
local mu = bg.multiplier or 1
|
||||
bg:SetVertexColor(r * mu, g * mu, b * mu)
|
||||
end
|
||||
--]]
|
||||
|
||||
if(element.PostUpdateColor) then
|
||||
element:PostUpdateColor(unit, r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
local function ColorPath(self, ...)
|
||||
--[[ Override: Power.UpdateColor(self, event, unit)
|
||||
Used to completely override the internal function for updating the widgets' colors.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
--]]
|
||||
(self.Power.UpdateColor or UpdateColor) (self, ...)
|
||||
end
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
local element = self.Power
|
||||
|
||||
--[[ Callback: Power:PreUpdate(unit)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the Power element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate(unit)
|
||||
end
|
||||
|
||||
local displayType, min
|
||||
if(element.displayAltPower) then
|
||||
displayType, min = element:GetDisplayPower()
|
||||
end
|
||||
|
||||
local cur, max = UnitPower(unit, displayType), UnitPowerMax(unit, displayType)
|
||||
if not min then min = 0 end
|
||||
|
||||
element:SetMinMaxValues(min, max)
|
||||
|
||||
if(UnitIsConnected(unit)) then
|
||||
element:SetValue(cur)
|
||||
else
|
||||
element:SetValue(max)
|
||||
end
|
||||
|
||||
element.cur = cur
|
||||
element.min = min
|
||||
element.max = max
|
||||
element.displayType = displayType
|
||||
|
||||
--[[ Callback: Power:PostUpdate(unit, cur, min, max)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the Power element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* cur - the unit's current power value (number)
|
||||
* min - the unit's minimum possible power value (number)
|
||||
* max - the unit's maximum possible power value (number)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
element:PostUpdate(unit, cur, min, max)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, event, ...)
|
||||
if (self.isForced and event ~= 'ElvUI_UpdateAllElements') then return end -- ElvUI changed
|
||||
|
||||
--[[ Override: Power.Override(self, event, unit, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
(self.Power.Override or Update) (self, event, ...);
|
||||
|
||||
ColorPath(self, event, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
--[[ Power:SetColorDisconnected(state, isForced)
|
||||
Used to toggle coloring if the unit is offline.
|
||||
|
||||
* self - the Power element
|
||||
* state - the desired state (boolean)
|
||||
* isForced - forces the event update even if the state wasn't changed (boolean)
|
||||
--]]
|
||||
local function SetColorDisconnected(element, state, isForced)
|
||||
if(element.colorDisconnected ~= state or isForced) then
|
||||
element.colorDisconnected = state
|
||||
if(state) then
|
||||
element.__owner:RegisterEvent('UNIT_CONNECTION', ColorPath)
|
||||
else
|
||||
element.__owner:UnregisterEvent('UNIT_CONNECTION', ColorPath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Power:SetColorSelection(state, isForced)
|
||||
Used to toggle coloring by the unit's selection.
|
||||
|
||||
* self - the Power element
|
||||
* state - the desired state (boolean)
|
||||
* isForced - forces the event update even if the state wasn't changed (boolean)
|
||||
--]]
|
||||
local function SetColorSelection(element, state, isForced)
|
||||
if(element.colorSelection ~= state or isForced) then
|
||||
element.colorSelection = state
|
||||
if(state) then
|
||||
element.__owner:RegisterEvent('UNIT_FLAGS', ColorPath)
|
||||
else
|
||||
element.__owner:UnregisterEvent('UNIT_FLAGS', ColorPath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Power:SetColorTapping(state, isForced)
|
||||
Used to toggle coloring if the unit isn't tapped by the player.
|
||||
|
||||
* self - the Power element
|
||||
* state - the desired state (boolean)
|
||||
* isForced - forces the event update even if the state wasn't changed (boolean)
|
||||
--]]
|
||||
local function SetColorTapping(element, state, isForced)
|
||||
if(element.colorTapping ~= state or isForced) then
|
||||
element.colorTapping = state
|
||||
if(state) then
|
||||
element.__owner:RegisterEvent('UNIT_FACTION', ColorPath)
|
||||
else
|
||||
element.__owner:UnregisterEvent('UNIT_FACTION', ColorPath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Power:SetColorThreat(state, isForced)
|
||||
Used to toggle coloring by the unit's threat status.
|
||||
|
||||
* self - the Power element
|
||||
* state - the desired state (boolean)
|
||||
* isForced - forces the event update even if the state wasn't changed (boolean)
|
||||
--]]
|
||||
local function SetColorThreat(element, state, isForced)
|
||||
if(element.colorThreat ~= state or isForced) then
|
||||
element.colorThreat = state
|
||||
if(state) then
|
||||
element.__owner:RegisterEvent('UNIT_THREAT_LIST_UPDATE', ColorPath)
|
||||
else
|
||||
element.__owner:UnregisterEvent('UNIT_THREAT_LIST_UPDATE', ColorPath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Power:SetFrequentUpdates(state, isForced)
|
||||
Used to toggle frequent updates.
|
||||
|
||||
* self - the Power element
|
||||
* state - the desired state (boolean)
|
||||
* isForced - forces the event update even if the state wasn't changed (boolean)
|
||||
--]]
|
||||
local function SetFrequentUpdates(element, state, isForced)
|
||||
if(element.frequentUpdates ~= state or isForced) then
|
||||
element.frequentUpdates = state
|
||||
if(state) then
|
||||
element.__owner:UnregisterEvent('UNIT_POWER_UPDATE', Path)
|
||||
element.__owner:RegisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
else
|
||||
element.__owner:UnregisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
element.__owner:RegisterEvent('UNIT_POWER_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ElvUI changed block
|
||||
local onUpdateElapsed, onUpdateWait = 0, 0.25
|
||||
local function onUpdatePower(self, elapsed)
|
||||
if onUpdateElapsed > onUpdateWait then
|
||||
Path(self.__owner, 'OnUpdate', self.__owner.unit)
|
||||
|
||||
onUpdateElapsed = 0
|
||||
else
|
||||
onUpdateElapsed = onUpdateElapsed + elapsed
|
||||
end
|
||||
end
|
||||
|
||||
local function SetPowerUpdateSpeed(self, state)
|
||||
onUpdateWait = state
|
||||
end
|
||||
|
||||
local function SetPowerUpdateMethod(self, state, force)
|
||||
if self.effectivePower ~= state or force then
|
||||
self.effectivePower = state
|
||||
|
||||
if state then
|
||||
self.Power:SetScript('OnUpdate', onUpdatePower)
|
||||
self:UnregisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
self:UnregisterEvent('UNIT_POWER_UPDATE', Path)
|
||||
self:UnregisterEvent('UNIT_MAXPOWER', Path)
|
||||
else
|
||||
self.Power:SetScript('OnUpdate', nil)
|
||||
self:RegisterEvent('UNIT_MAXPOWER', Path)
|
||||
if self.Power.frequentUpdates then
|
||||
self:RegisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
else
|
||||
self:RegisterEvent('UNIT_POWER_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- end block
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.Power
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
element.SetColorDisconnected = SetColorDisconnected
|
||||
element.SetColorSelection = SetColorSelection
|
||||
element.SetColorTapping = SetColorTapping
|
||||
element.SetColorThreat = SetColorThreat
|
||||
element.SetFrequentUpdates = SetFrequentUpdates
|
||||
|
||||
-- ElvUI changed block
|
||||
self.SetPowerUpdateSpeed = SetPowerUpdateSpeed
|
||||
self.SetPowerUpdateMethod = SetPowerUpdateMethod
|
||||
SetPowerUpdateMethod(self, self.effectivePower, true)
|
||||
-- end block
|
||||
|
||||
if(element.colorDisconnected) then
|
||||
self:RegisterEvent('UNIT_CONNECTION', ColorPath)
|
||||
end
|
||||
|
||||
if(element.colorSelection) then
|
||||
self:RegisterEvent('UNIT_FLAGS', ColorPath)
|
||||
end
|
||||
|
||||
if(element.colorTapping) then
|
||||
self:RegisterEvent('UNIT_FACTION', ColorPath)
|
||||
end
|
||||
|
||||
if(element.colorThreat) then
|
||||
self:RegisterEvent('UNIT_THREAT_LIST_UPDATE', ColorPath)
|
||||
end
|
||||
|
||||
self:RegisterEvent('UNIT_DISPLAYPOWER', Path)
|
||||
self:RegisterEvent('UNIT_POWER_BAR_HIDE', Path)
|
||||
self:RegisterEvent('UNIT_POWER_BAR_SHOW', Path)
|
||||
|
||||
if(element:IsObjectType('StatusBar') and not (element:GetStatusBarTexture() or element:GetStatusBarAtlas())) then
|
||||
element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
|
||||
if(not element.GetDisplayPower) then
|
||||
element.GetDisplayPower = GetDisplayPower
|
||||
end
|
||||
|
||||
element:Show()
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.Power
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
element:SetScript('OnUpdate', nil) -- ElvUI changed
|
||||
self:UnregisterEvent('UNIT_DISPLAYPOWER', Path)
|
||||
self:UnregisterEvent('UNIT_MAXPOWER', Path)
|
||||
self:UnregisterEvent('UNIT_POWER_BAR_HIDE', Path)
|
||||
self:UnregisterEvent('UNIT_POWER_BAR_SHOW', Path)
|
||||
self:UnregisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
self:UnregisterEvent('UNIT_POWER_UPDATE', Path)
|
||||
self:UnregisterEvent('UNIT_CONNECTION', ColorPath)
|
||||
self:UnregisterEvent('UNIT_FACTION', ColorPath)
|
||||
self:UnregisterEvent('UNIT_FLAGS', ColorPath)
|
||||
self:UnregisterEvent('UNIT_THREAT_LIST_UPDATE', ColorPath)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Power', Path, Enable, Disable)
|
||||
194
Libraries/oUF/elements/powerprediction.lua
Normal file
194
Libraries/oUF/elements/powerprediction.lua
Normal file
@@ -0,0 +1,194 @@
|
||||
--[[
|
||||
# Element: Power Prediction Bar
|
||||
|
||||
Handles the visibility and updating of power cost prediction.
|
||||
|
||||
## Widget
|
||||
|
||||
PowerPrediction - A `table` containing the sub-widgets.
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
mainBar - A `StatusBar` used to represent power cost of spells on top of the Power element.
|
||||
altBar - A `StatusBar` used to represent power cost of spells on top of the AdditionalPower element.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a StatusBar and doesn't have a texture set.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local mainBar = CreateFrame('StatusBar', nil, self.Power)
|
||||
mainBar:SetReverseFill(true)
|
||||
mainBar:SetPoint('TOP')
|
||||
mainBar:SetPoint('BOTTOM')
|
||||
mainBar:SetPoint('RIGHT', self.Power:GetStatusBarTexture(), 'RIGHT')
|
||||
mainBar:SetWidth(200)
|
||||
|
||||
local altBar = CreateFrame('StatusBar', nil, self.AdditionalPower)
|
||||
altBar:SetReverseFill(true)
|
||||
altBar:SetPoint('TOP')
|
||||
altBar:SetPoint('BOTTOM')
|
||||
altBar:SetPoint('RIGHT', self.AdditionalPower:GetStatusBarTexture(), 'RIGHT')
|
||||
altBar:SetWidth(200)
|
||||
|
||||
-- Register with oUF
|
||||
self.PowerPrediction = {
|
||||
mainBar = mainBar,
|
||||
altBar = altBar
|
||||
}
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
-- sourced from FrameXML/AlternatePowerBar.lua
|
||||
local ADDITIONAL_POWER_BAR_INDEX = ADDITIONAL_POWER_BAR_INDEX or 0
|
||||
local ALT_MANA_BAR_PAIR_DISPLAY_INFO = ALT_MANA_BAR_PAIR_DISPLAY_INFO
|
||||
|
||||
local _, playerClass = UnitClass('player')
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local element = self.PowerPrediction
|
||||
|
||||
--[[ Callback: PowerPrediction:PreUpdate(unit)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the PowerPrediction element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate(unit)
|
||||
end
|
||||
|
||||
local mainCost, altCost = 0, 0
|
||||
local mainType = UnitPowerType(unit)
|
||||
local mainMax = UnitPowerMax(unit, mainType)
|
||||
local isPlayer = UnitIsUnit('player', unit)
|
||||
local altManaInfo = isPlayer and ALT_MANA_BAR_PAIR_DISPLAY_INFO[playerClass]
|
||||
local hasAltManaBar = altManaInfo and altManaInfo[mainType]
|
||||
local _, _, _, startTime, endTime, _, _, _, spellID = UnitCastingInfo(unit)
|
||||
|
||||
if(event == 'UNIT_SPELLCAST_START' and startTime ~= endTime) then
|
||||
local costTable = GetSpellPowerCost(spellID)
|
||||
local checkRequiredAura = isPlayer and #costTable > 1
|
||||
for _, costInfo in next, costTable do
|
||||
local cost, ctype, cperc = costInfo.cost, costInfo.type, costInfo.costPercent
|
||||
local checkSpec = not checkRequiredAura or costInfo.hasRequiredAura
|
||||
if checkSpec and ctype == mainType then
|
||||
mainCost = ((isPlayer or cost < mainMax) and cost) or (mainMax * cperc) / 100
|
||||
element.mainCost = mainCost
|
||||
|
||||
break
|
||||
elseif hasAltManaBar and checkSpec and ctype == ADDITIONAL_POWER_BAR_INDEX then
|
||||
altCost = cost
|
||||
element.altCost = altCost
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif(spellID) then
|
||||
-- if we try to cast a spell while casting another one we need to avoid
|
||||
-- resetting the element
|
||||
mainCost = element.mainCost or 0
|
||||
altCost = element.altCost or 0
|
||||
else
|
||||
element.mainCost = mainCost
|
||||
element.altCost = altCost
|
||||
end
|
||||
|
||||
if(element.mainBar) then
|
||||
element.mainBar:SetMinMaxValues(0, mainMax)
|
||||
element.mainBar:SetValue(mainCost)
|
||||
element.mainBar:Show()
|
||||
end
|
||||
|
||||
if(element.altBar and hasAltManaBar) then
|
||||
element.altBar:SetMinMaxValues(0, UnitPowerMax(unit, ADDITIONAL_POWER_BAR_INDEX))
|
||||
element.altBar:SetValue(altCost)
|
||||
element.altBar:Show()
|
||||
end
|
||||
|
||||
--[[ Callback: PowerPrediction:PostUpdate(unit, mainCost, altCost, hasAltManaBar)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the PowerPrediction element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* mainCost - the main power type cost of the cast ability (number)
|
||||
* altCost - the secondary power type cost of the cast ability (number)
|
||||
* hasAltManaBar - indicates if the unit has a secondary power bar (boolean)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(unit, mainCost, altCost, hasAltManaBar)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: PowerPrediction.Override(self, event, unit, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.PowerPrediction.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.PowerPrediction
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_SPELLCAST_START', Path)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_STOP', Path)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_FAILED', Path)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_SUCCEEDED', Path)
|
||||
self:RegisterEvent('UNIT_DISPLAYPOWER', Path)
|
||||
|
||||
if(element.mainBar) then
|
||||
if(element.mainBar:IsObjectType('StatusBar')
|
||||
and not (element.mainBar:GetStatusBarTexture() or element.mainBar:GetStatusBarAtlas())) then
|
||||
element.mainBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
if(element.altBar) then
|
||||
if(element.altBar:IsObjectType('StatusBar')
|
||||
and not (element.altBar:GetStatusBarTexture() or element.altBar:GetStatusBarAtlas())) then
|
||||
element.altBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.PowerPrediction
|
||||
if(element) then
|
||||
if(element.mainBar) then
|
||||
element.mainBar:Hide()
|
||||
end
|
||||
|
||||
if(element.altBar) then
|
||||
element.altBar:Hide()
|
||||
end
|
||||
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_START', Path)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_STOP', Path)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_FAILED', Path)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_SUCCEEDED', Path)
|
||||
self:UnregisterEvent('UNIT_DISPLAYPOWER', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('PowerPrediction', Path, Enable, Disable)
|
||||
119
Libraries/oUF/elements/pvpclassificationindicator.lua
Normal file
119
Libraries/oUF/elements/pvpclassificationindicator.lua
Normal file
@@ -0,0 +1,119 @@
|
||||
--[[
|
||||
# Element: PvPClassificationIndicator
|
||||
|
||||
Handles the visibility and updating of an indicator based on the unit's PvP classification.
|
||||
|
||||
## Widget
|
||||
|
||||
PvPClassificationIndicator - A `Texture` used to display PvP classification.
|
||||
|
||||
## Notes
|
||||
|
||||
This element updates by changing the texture.
|
||||
|
||||
## Options
|
||||
|
||||
.useAtlasSize - Makes the element use preprogrammed atlas' size instead of its set dimensions (boolean)
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local PvPClassificationIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
PvPClassificationIndicator:SetSize(24, 24)
|
||||
PvPClassificationIndicator:SetPoint('CENTER')
|
||||
|
||||
-- Register it with oUF
|
||||
self.PvPClassificationIndicator = PvPClassificationIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
-- sourced from FrameXML/CompactUnitFrame.lua
|
||||
local ICONS = {
|
||||
[Enum.PvPUnitClassification.FlagCarrierHorde or 0] = "nameplates-icon-flag-horde",
|
||||
[Enum.PvPUnitClassification.FlagCarrierAlliance or 1] = "nameplates-icon-flag-alliance",
|
||||
[Enum.PvPUnitClassification.FlagCarrierNeutral or 2] = "nameplates-icon-flag-neutral",
|
||||
[Enum.PvPUnitClassification.CartRunnerHorde or 3] = "nameplates-icon-cart-horde",
|
||||
[Enum.PvPUnitClassification.CartRunnerAlliance or 4] = "nameplates-icon-cart-alliance",
|
||||
[Enum.PvPUnitClassification.AssassinHorde or 5] = "nameplates-icon-bounty-horde",
|
||||
[Enum.PvPUnitClassification.AssassinAlliance or 6] = "nameplates-icon-bounty-alliance",
|
||||
[Enum.PvPUnitClassification.OrbCarrierBlue or 7] = "nameplates-icon-orb-blue",
|
||||
[Enum.PvPUnitClassification.OrbCarrierGreen or 8] = "nameplates-icon-orb-green",
|
||||
[Enum.PvPUnitClassification.OrbCarrierOrange or 9] = "nameplates-icon-orb-orange",
|
||||
[Enum.PvPUnitClassification.OrbCarrierPurple or 10] = "nameplates-icon-orb-purple",
|
||||
}
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(unit ~= self.unit) then return end
|
||||
|
||||
local element = self.PvPClassificationIndicator
|
||||
|
||||
--[[ Callback: PvPClassificationIndicator:PreUpdate(unit)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the PvPClassificationIndicator element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate(unit)
|
||||
end
|
||||
|
||||
local class = UnitPvpClassification(unit)
|
||||
local icon = ICONS[class]
|
||||
if(icon) then
|
||||
element:SetAtlas(icon, element.useAtlasSize)
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
--[[ Callback: PvPClassificationIndicator:PostUpdate(unit, class)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the PvPClassificationIndicator element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* class - the pvp classification of the unit (number?)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(unit, class)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[Override: PvPClassificationIndicator.Override(self, event, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.PvPClassificationIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.PvPClassificationIndicator
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_CLASSIFICATION_CHANGED', Path)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.PvPClassificationIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('UNIT_CLASSIFICATION_CHANGED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('PvPClassificationIndicator', Path, Enable, Disable)
|
||||
151
Libraries/oUF/elements/pvpindicator.lua
Normal file
151
Libraries/oUF/elements/pvpindicator.lua
Normal file
@@ -0,0 +1,151 @@
|
||||
--[[
|
||||
# Element: PvP and Honor Level Icons
|
||||
|
||||
Handles the visibility and updating of an indicator based on the unit's PvP status and honor level.
|
||||
|
||||
## Widget
|
||||
|
||||
PvPIndicator - A `Texture` used to display faction, FFA PvP status or honor level icon.
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
Badge - A `Texture` used to display the honor badge background image.
|
||||
|
||||
## Notes
|
||||
|
||||
This element updates by changing the texture.
|
||||
The `Badge` sub-widget has to be on a lower sub-layer than the `PvP` texture.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local PvPIndicator = self:CreateTexture(nil, 'ARTWORK', nil, 1)
|
||||
PvPIndicator:SetSize(30, 30)
|
||||
PvPIndicator:SetPoint('RIGHT', self, 'LEFT')
|
||||
|
||||
local Badge = self:CreateTexture(nil, 'ARTWORK')
|
||||
Badge:SetSize(50, 52)
|
||||
Badge:SetPoint('CENTER', PvPIndicator, 'CENTER')
|
||||
|
||||
-- Register it with oUF
|
||||
PvPIndicator.Badge = Badge
|
||||
self.PvPIndicator = PvPIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(unit and unit ~= self.unit) then return end
|
||||
|
||||
local element = self.PvPIndicator
|
||||
unit = unit or self.unit
|
||||
|
||||
--[[ Callback: PvPIndicator:PreUpdate(unit)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the PvPIndicator element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate(unit)
|
||||
end
|
||||
|
||||
local status
|
||||
local factionGroup = UnitFactionGroup(unit) or 'Neutral'
|
||||
local honorRewardInfo = C_PvP.GetHonorRewardInfo(UnitHonorLevel(unit))
|
||||
|
||||
if(UnitIsPVPFreeForAll(unit)) then
|
||||
status = 'FFA'
|
||||
elseif(factionGroup ~= 'Neutral' and UnitIsPVP(unit)) then
|
||||
if(unit == 'player' and UnitIsMercenary(unit)) then
|
||||
if(factionGroup == 'Horde') then
|
||||
factionGroup = 'Alliance'
|
||||
elseif(factionGroup == 'Alliance') then
|
||||
factionGroup = 'Horde'
|
||||
end
|
||||
end
|
||||
|
||||
status = factionGroup
|
||||
end
|
||||
|
||||
if(status) then
|
||||
element:Show()
|
||||
|
||||
if(element.Badge and honorRewardInfo) then
|
||||
element:SetTexture(honorRewardInfo.badgeFileDataID)
|
||||
element:SetTexCoord(0, 1, 0, 1)
|
||||
element.Badge:SetAtlas('honorsystem-portrait-' .. factionGroup, false)
|
||||
element.Badge:Show()
|
||||
else
|
||||
element:SetTexture([[Interface\TargetingFrame\UI-PVP-]] .. status)
|
||||
element:SetTexCoord(0, 0.65625, 0, 0.65625)
|
||||
|
||||
if(element.Badge) then
|
||||
element.Badge:Hide()
|
||||
end
|
||||
end
|
||||
else
|
||||
element:Hide()
|
||||
|
||||
if(element.Badge) then
|
||||
element.Badge:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Callback: PvPIndicator:PostUpdate(unit, status)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the PvPIndicator element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* status - the unit's current PvP status or faction accounting for mercenary mode (string)['FFA', 'Alliance',
|
||||
'Horde']
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(unit, status)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[Override: PvPIndicator.Override(self, event, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.PvPIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.PvPIndicator
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_FACTION', Path)
|
||||
self:RegisterEvent('HONOR_LEVEL_UPDATE', Path, true)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.PvPIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
if(element.Badge) then
|
||||
element.Badge:Hide()
|
||||
end
|
||||
|
||||
self:UnregisterEvent('UNIT_FACTION', Path)
|
||||
self:UnregisterEvent('HONOR_LEVEL_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('PvPIndicator', Path, Enable, Disable)
|
||||
100
Libraries/oUF/elements/questindicator.lua
Normal file
100
Libraries/oUF/elements/questindicator.lua
Normal file
@@ -0,0 +1,100 @@
|
||||
--[[
|
||||
# Element: Quest Indicator
|
||||
|
||||
Handles the visibility and updating of an indicator based on the unit's involvement in a quest.
|
||||
|
||||
## Widget
|
||||
|
||||
QuestIndicator - Any UI widget.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local QuestIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
QuestIndicator:SetSize(16, 16)
|
||||
QuestIndicator:SetPoint('TOPRIGHT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.QuestIndicator = QuestIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(unit ~= self.unit) then return end
|
||||
|
||||
local element = self.QuestIndicator
|
||||
|
||||
--[[ Callback: QuestIndicator:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the QuestIndicator element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local isQuestBoss = UnitIsQuestBoss(unit)
|
||||
if(isQuestBoss) then
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
--[[ Callback: QuestIndicator:PostUpdate(isQuestBoss)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the QuestIndicator element
|
||||
* isQuestBoss - indicates if the element is shown (boolean)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(isQuestBoss)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: QuestIndicator.Override(self, event, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.QuestIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.QuestIndicator
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_CLASSIFICATION_CHANGED', Path)
|
||||
|
||||
if(element:IsObjectType('Texture') and not element:GetTexture()) then
|
||||
element:SetTexture([[Interface\TargetingFrame\PortraitQuestBadge]])
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.QuestIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('UNIT_CLASSIFICATION_CHANGED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('QuestIndicator', Path, Enable, Disable)
|
||||
106
Libraries/oUF/elements/raidroleindicator.lua
Normal file
106
Libraries/oUF/elements/raidroleindicator.lua
Normal file
@@ -0,0 +1,106 @@
|
||||
--[[
|
||||
# Element: Raid Role Indicator
|
||||
|
||||
Handles the visibility and updating of an indicator based on the unit's raid assignment (main tank or main assist).
|
||||
|
||||
## Widget
|
||||
|
||||
RaidRoleIndicator - A `Texture` representing the unit's raid assignment.
|
||||
|
||||
## Notes
|
||||
|
||||
This element updates by changing the texture.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local RaidRoleIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
RaidRoleIndicator:SetSize(16, 16)
|
||||
RaidRoleIndicator:SetPoint('TOPLEFT')
|
||||
|
||||
-- Register it with oUF
|
||||
self.RaidRoleIndicator = RaidRoleIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local MAINTANK_ICON = [[Interface\GROUPFRAME\UI-GROUP-MAINTANKICON]]
|
||||
local MAINASSIST_ICON = [[Interface\GROUPFRAME\UI-GROUP-MAINASSISTICON]]
|
||||
|
||||
local function Update(self, event)
|
||||
local element = self.RaidRoleIndicator
|
||||
local unit = self.unit
|
||||
|
||||
--[[ Callback: RaidRoleIndicator:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the RaidRoleIndicator element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local role, isShown
|
||||
if(UnitInRaid(unit) and not UnitHasVehicleUI(unit)) then
|
||||
if(GetPartyAssignment('MAINTANK', unit)) then
|
||||
isShown = true
|
||||
element:SetTexture(MAINTANK_ICON)
|
||||
role = 'MAINTANK'
|
||||
elseif(GetPartyAssignment('MAINASSIST', unit)) then
|
||||
isShown = true
|
||||
element:SetTexture(MAINASSIST_ICON)
|
||||
role = 'MAINASSIST'
|
||||
end
|
||||
end
|
||||
|
||||
element:SetShown(isShown)
|
||||
|
||||
--[[ Callback: RaidRoleIndicator:PostUpdate(role)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the RaidRoleIndicator element
|
||||
* role - the unit's raid assignment (string?)['MAINTANK', 'MAINASSIST']
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(role)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: RaidRoleIndicator.Override(self, event, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.RaidRoleIndicator.Override or Update)(self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.RaidRoleIndicator
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('GROUP_ROSTER_UPDATE', Path, true)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.RaidRoleIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('GROUP_ROSTER_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('RaidRoleIndicator', Path, Enable, Disable)
|
||||
102
Libraries/oUF/elements/raidtargetindicator.lua
Normal file
102
Libraries/oUF/elements/raidtargetindicator.lua
Normal file
@@ -0,0 +1,102 @@
|
||||
--[[
|
||||
# Element: Raid Target Indicator
|
||||
|
||||
Handles the visibility and updating of an indicator based on the unit's raid target assignment.
|
||||
|
||||
## Widget
|
||||
|
||||
RaidTargetIndicator - A `Texture` used to display the raid target icon.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a Texture and doesn't have a texture set.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local RaidTargetIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
RaidTargetIndicator:SetSize(16, 16)
|
||||
RaidTargetIndicator:SetPoint('TOPRIGHT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.RaidTargetIndicator = RaidTargetIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local GetRaidTargetIndex = GetRaidTargetIndex
|
||||
local SetRaidTargetIconTexture = SetRaidTargetIconTexture
|
||||
|
||||
local function Update(self, event)
|
||||
local element = self.RaidTargetIndicator
|
||||
|
||||
--[[ Callback: RaidTargetIndicator:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the RaidTargetIndicator element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local index = GetRaidTargetIndex(self.unit)
|
||||
if(index) then
|
||||
SetRaidTargetIconTexture(element, index)
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
--[[ Callback: RaidTargetIndicator:PostUpdate(index)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the RaidTargetIndicator element
|
||||
* index - the index of the raid target marker (number?)[1-8]
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(index)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: RaidTargetIndicator.Override(self, event)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
--]]
|
||||
return (self.RaidTargetIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
if(not element.__owner.unit) then return end
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.RaidTargetIndicator
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('RAID_TARGET_UPDATE', Path, true)
|
||||
|
||||
if(element:IsObjectType('Texture') and not element:GetTexture()) then
|
||||
element:SetTexture([[Interface\TargetingFrame\UI-RaidTargetingIcons]])
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.RaidTargetIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('RAID_TARGET_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('RaidTargetIndicator', Path, Enable, Disable)
|
||||
138
Libraries/oUF/elements/range.lua
Normal file
138
Libraries/oUF/elements/range.lua
Normal file
@@ -0,0 +1,138 @@
|
||||
--[[
|
||||
# Element: Range Fader
|
||||
|
||||
Changes the opacity of a unit frame based on whether the frame's unit is in the player's range.
|
||||
|
||||
## Widget
|
||||
|
||||
Range - A table containing opacity values.
|
||||
|
||||
## Notes
|
||||
|
||||
Offline units are handled as if they are in range.
|
||||
|
||||
## Options
|
||||
|
||||
.outsideAlpha - Opacity when the unit is out of range. Defaults to 0.55 (number)[0-1].
|
||||
.insideAlpha - Opacity when the unit is within range. Defaults to 1 (number)[0-1].
|
||||
|
||||
## Examples
|
||||
|
||||
-- Register with oUF
|
||||
self.Range = {
|
||||
insideAlpha = 1,
|
||||
outsideAlpha = 1/2,
|
||||
}
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local _FRAMES = {}
|
||||
local OnRangeFrame
|
||||
|
||||
local UnitInRange, UnitIsConnected = UnitInRange, UnitIsConnected
|
||||
|
||||
local function Update(self, event)
|
||||
local element = self.Range
|
||||
local unit = self.unit
|
||||
|
||||
--[[ Callback: Range:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the Range element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local inRange, checkedRange
|
||||
local connected = UnitIsConnected(unit)
|
||||
if(connected) then
|
||||
inRange, checkedRange = UnitInRange(unit)
|
||||
if(checkedRange and not inRange) then
|
||||
self:SetAlpha(element.outsideAlpha)
|
||||
else
|
||||
self:SetAlpha(element.insideAlpha)
|
||||
end
|
||||
else
|
||||
self:SetAlpha(element.insideAlpha)
|
||||
end
|
||||
|
||||
--[[ Callback: Range:PostUpdate(object, inRange, checkedRange, isConnected)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the Range element
|
||||
* object - the parent object
|
||||
* inRange - indicates if the unit was within 40 yards of the player (boolean)
|
||||
* checkedRange - indicates if the range check was actually performed (boolean)
|
||||
* isConnected - indicates if the unit is online (boolean)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(self, inRange, checkedRange, connected)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: Range.Override(self, event)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
--]]
|
||||
return (self.Range.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
-- Internal updating method
|
||||
local timer = 0
|
||||
local function OnRangeUpdate(_, elapsed)
|
||||
timer = timer + elapsed
|
||||
|
||||
if(timer >= .20) then
|
||||
for _, object in next, _FRAMES do
|
||||
if(object:IsShown()) then
|
||||
Path(object, 'OnUpdate')
|
||||
end
|
||||
end
|
||||
|
||||
timer = 0
|
||||
end
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.Range
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.insideAlpha = element.insideAlpha or 1
|
||||
element.outsideAlpha = element.outsideAlpha or 0.55
|
||||
|
||||
if(not OnRangeFrame) then
|
||||
OnRangeFrame = CreateFrame('Frame')
|
||||
OnRangeFrame:SetScript('OnUpdate', OnRangeUpdate)
|
||||
end
|
||||
|
||||
table.insert(_FRAMES, self)
|
||||
OnRangeFrame:Show()
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.Range
|
||||
if(element) then
|
||||
for index, frame in next, _FRAMES do
|
||||
if(frame == self) then
|
||||
table.remove(_FRAMES, index)
|
||||
break
|
||||
end
|
||||
end
|
||||
self:SetAlpha(element.insideAlpha)
|
||||
|
||||
if(#_FRAMES == 0) then
|
||||
OnRangeFrame:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Range', nil, Enable, Disable)
|
||||
163
Libraries/oUF/elements/readycheckindicator.lua
Normal file
163
Libraries/oUF/elements/readycheckindicator.lua
Normal file
@@ -0,0 +1,163 @@
|
||||
--[[
|
||||
# Element: Ready Check Indicator
|
||||
|
||||
Handles the visibility and updating of an indicator based on the unit's ready check status.
|
||||
|
||||
## Widget
|
||||
|
||||
ReadyCheckIndicator - A `Texture` representing ready check status.
|
||||
|
||||
## Notes
|
||||
|
||||
This element updates by changing the texture.
|
||||
Default textures will be applied if the layout does not provide custom ones. See Options.
|
||||
|
||||
## Options
|
||||
|
||||
.finishedTime - For how many seconds the icon should stick after a check has completed. Defaults to 10 (number).
|
||||
.fadeTime - For how many seconds the icon should fade away after the stick duration has completed. Defaults to
|
||||
1.5 (number).
|
||||
.readyTexture - Path to an alternate texture for the ready check 'ready' status.
|
||||
.notReadyTexture - Path to an alternate texture for the ready check 'notready' status.
|
||||
.waitingTexture - Path to an alternate texture for the ready check 'waiting' status.
|
||||
|
||||
## Attributes
|
||||
|
||||
.status - the unit's ready check status (string?)['ready', 'noready', 'waiting']
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local ReadyCheckIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
ReadyCheckIndicator:SetSize(16, 16)
|
||||
ReadyCheckIndicator:SetPoint('TOP')
|
||||
|
||||
-- Register with oUF
|
||||
self.ReadyCheckIndicator = ReadyCheckIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local unitExists = Private.unitExists
|
||||
|
||||
local function OnFinished(self)
|
||||
local element = self:GetParent()
|
||||
element:Hide()
|
||||
|
||||
--[[ Callback: ReadyCheckIndicator:PostUpdateFadeOut()
|
||||
Called after the element has been faded out.
|
||||
|
||||
* self - the ReadyCheckIndicator element
|
||||
--]]
|
||||
if(element.PostUpdateFadeOut) then
|
||||
element:PostUpdateFadeOut()
|
||||
end
|
||||
end
|
||||
|
||||
local function Update(self, event)
|
||||
local element = self.ReadyCheckIndicator
|
||||
local unit = self.unit
|
||||
|
||||
--[[ Callback: ReadyCheckIndicator:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the ReadyCheckIndicator element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local status = GetReadyCheckStatus(unit)
|
||||
if(unitExists(unit) and status) then
|
||||
if(status == 'ready') then
|
||||
element:SetTexture(element.readyTexture)
|
||||
elseif(status == 'notready') then
|
||||
element:SetTexture(element.notReadyTexture)
|
||||
else
|
||||
element:SetTexture(element.waitingTexture)
|
||||
end
|
||||
|
||||
element.status = status
|
||||
element:Show()
|
||||
elseif(event ~= 'READY_CHECK_FINISHED') then
|
||||
element.status = nil
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
if(event == 'READY_CHECK_FINISHED') then
|
||||
if(element.status == 'waiting') then
|
||||
element:SetTexture(element.notReadyTexture)
|
||||
end
|
||||
|
||||
element.Animation:Play()
|
||||
end
|
||||
|
||||
--[[ Callback: ReadyCheckIndicator:PostUpdate(status)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the ReadyCheckIndicator element
|
||||
* status - the unit's ready check status (string?)['ready', 'notready', 'waiting']
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(status)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: ReadyCheckIndicator.Override(self, event, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.ReadyCheckIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local function Enable(self, unit)
|
||||
local element = self.ReadyCheckIndicator
|
||||
unit = unit and unit:match('(%a+)%d*$')
|
||||
if(element and (unit == 'party' or unit == 'raid')) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
element.readyTexture = element.readyTexture or READY_CHECK_READY_TEXTURE
|
||||
element.notReadyTexture = element.notReadyTexture or READY_CHECK_NOT_READY_TEXTURE
|
||||
element.waitingTexture = element.waitingTexture or READY_CHECK_WAITING_TEXTURE
|
||||
|
||||
local AnimationGroup = element:CreateAnimationGroup()
|
||||
AnimationGroup:HookScript('OnFinished', OnFinished)
|
||||
element.Animation = AnimationGroup
|
||||
|
||||
local Animation = AnimationGroup:CreateAnimation('Alpha')
|
||||
Animation:SetFromAlpha(1)
|
||||
Animation:SetToAlpha(0)
|
||||
Animation:SetDuration(element.fadeTime or 1.5)
|
||||
Animation:SetStartDelay(element.finishedTime or 10)
|
||||
|
||||
self:RegisterEvent('READY_CHECK', Path, true)
|
||||
self:RegisterEvent('READY_CHECK_CONFIRM', Path, true)
|
||||
self:RegisterEvent('READY_CHECK_FINISHED', Path, true)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.ReadyCheckIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('READY_CHECK', Path)
|
||||
self:UnregisterEvent('READY_CHECK_CONFIRM', Path)
|
||||
self:UnregisterEvent('READY_CHECK_FINISHED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('ReadyCheckIndicator', Path, Enable, Disable)
|
||||
98
Libraries/oUF/elements/restingindicator.lua
Normal file
98
Libraries/oUF/elements/restingindicator.lua
Normal file
@@ -0,0 +1,98 @@
|
||||
--[[
|
||||
# Element: Resting Indicator
|
||||
|
||||
Toggles the visibility of an indicator based on the player's resting status.
|
||||
|
||||
## Widget
|
||||
|
||||
RestingIndicator - Any UI widget.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local RestingIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
RestingIndicator:SetSize(16, 16)
|
||||
RestingIndicator:SetPoint('TOPLEFT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.RestingIndicator = RestingIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event)
|
||||
local element = self.RestingIndicator
|
||||
|
||||
--[[ Callback: RestingIndicator:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the RestingIndicator element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local isResting = IsResting()
|
||||
if(isResting) then
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
--[[ Callback: RestingIndicator:PostUpdate(isResting)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the RestingIndicator element
|
||||
* isResting - indicates if the player is resting (boolean)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(isResting)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: RestingIndicator.Override(self, event)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
--]]
|
||||
return (self.RestingIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local function Enable(self, unit)
|
||||
local element = self.RestingIndicator
|
||||
if(element and UnitIsUnit(unit, 'player')) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('PLAYER_UPDATE_RESTING', Path, true)
|
||||
|
||||
if(element:IsObjectType('Texture') and not element:GetTexture()) then
|
||||
element:SetTexture([[Interface\CharacterFrame\UI-StateIcon]])
|
||||
element:SetTexCoord(0, 0.5, 0, 0.421875)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.RestingIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('PLAYER_UPDATE_RESTING', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('RestingIndicator', Path, Enable, Disable)
|
||||
100
Libraries/oUF/elements/resurrectindicator.lua
Normal file
100
Libraries/oUF/elements/resurrectindicator.lua
Normal file
@@ -0,0 +1,100 @@
|
||||
--[[
|
||||
# Element: Resurrect Indicator
|
||||
|
||||
Handles the visibility and updating of an indicator based on the unit's incoming resurrect status.
|
||||
|
||||
## Widget
|
||||
|
||||
ResurrectIndicator - A `Texture` used to display if the unit has an incoming resurrect.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local ResurrectIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
ResurrectIndicator:SetSize(16, 16)
|
||||
ResurrectIndicator:SetPoint('TOPRIGHT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.ResurrectIndicator = ResurrectIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local element = self.ResurrectIndicator
|
||||
|
||||
--[[ Callback: ResurrectIndicator:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the ResurrectIndicator element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local incomingResurrect = UnitHasIncomingResurrection(unit)
|
||||
if(incomingResurrect) then
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
--[[ Callback: ResurrectIndicator:PostUpdate(incomingResurrect)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the ResurrectIndicator element
|
||||
* incomingResurrect - indicates if the unit has an incoming resurrection (boolean)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(incomingResurrect)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: ResurrectIndicator.Override(self, event, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.ResurrectIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.ResurrectIndicator
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('INCOMING_RESURRECT_CHANGED', Path)
|
||||
|
||||
if(element:IsObjectType('Texture') and not element:GetTexture()) then
|
||||
element:SetTexture([[Interface\RaidFrame\Raid-Icon-Rez]])
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.ResurrectIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('INCOMING_RESURRECT_CHANGED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('ResurrectIndicator', Path, Enable, Disable)
|
||||
245
Libraries/oUF/elements/runes.lua
Normal file
245
Libraries/oUF/elements/runes.lua
Normal file
@@ -0,0 +1,245 @@
|
||||
--[[
|
||||
# Element: Runes
|
||||
|
||||
Handles the visibility and updating of Death Knight's runes.
|
||||
|
||||
## Widget
|
||||
|
||||
Runes - An `table` holding `StatusBar`s.
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
.bg - A `Texture` used as a background. It will inherit the color of the main StatusBar.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the sub-widgets are StatusBars and don't have a texture set.
|
||||
|
||||
## Options
|
||||
|
||||
.colorSpec - Use `self.colors.runes[specID]` to color the bar based on player's spec. `specID` is defined by the return
|
||||
value of [GetSpecialization](http://wowprogramming.com/docs/api/GetSpecialization.html) (boolean)
|
||||
.sortOrder - Sorting order. Sorts by the remaining cooldown time, 'asc' - from the least cooldown time remaining (fully
|
||||
charged) to the most (fully depleted), 'desc' - the opposite (string?)['asc', 'desc']
|
||||
|
||||
## Sub-Widgets Options
|
||||
|
||||
.multiplier - Used to tint the background based on the main widgets R, G and B values. Defaults to 1 (number)[0-1]
|
||||
|
||||
## Examples
|
||||
|
||||
local Runes = {}
|
||||
for index = 1, 6 do
|
||||
-- Position and size of the rune bar indicators
|
||||
local Rune = CreateFrame('StatusBar', nil, self)
|
||||
Rune:SetSize(120 / 6, 20)
|
||||
Rune:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', index * 120 / 6, 0)
|
||||
|
||||
Runes[index] = Rune
|
||||
end
|
||||
|
||||
-- Register with oUF
|
||||
self.Runes = Runes
|
||||
--]]
|
||||
|
||||
if(select(2, UnitClass('player')) ~= 'DEATHKNIGHT') then return end
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local runemap = {1, 2, 3, 4, 5, 6}
|
||||
local hasSortOrder = false
|
||||
|
||||
local function onUpdate(self, elapsed)
|
||||
local duration = self.duration + elapsed
|
||||
self.duration = duration
|
||||
self:SetValue(duration)
|
||||
end
|
||||
|
||||
local function ascSort(runeAID, runeBID)
|
||||
local runeAStart, _, runeARuneReady = GetRuneCooldown(runeAID)
|
||||
local runeBStart, _, runeBRuneReady = GetRuneCooldown(runeBID)
|
||||
if(runeARuneReady ~= runeBRuneReady) then
|
||||
return runeARuneReady
|
||||
elseif(runeAStart ~= runeBStart) then
|
||||
return runeAStart < runeBStart
|
||||
else
|
||||
return runeAID < runeBID
|
||||
end
|
||||
end
|
||||
|
||||
local function descSort(runeAID, runeBID)
|
||||
local runeAStart, _, runeARuneReady = GetRuneCooldown(runeAID)
|
||||
local runeBStart, _, runeBRuneReady = GetRuneCooldown(runeBID)
|
||||
if(runeARuneReady ~= runeBRuneReady) then
|
||||
return runeBRuneReady
|
||||
elseif(runeAStart ~= runeBStart) then
|
||||
return runeAStart > runeBStart
|
||||
else
|
||||
return runeAID > runeBID
|
||||
end
|
||||
end
|
||||
|
||||
local function UpdateColor(self, event)
|
||||
local element = self.Runes
|
||||
|
||||
local spec = GetSpecialization() or 0
|
||||
|
||||
local color
|
||||
if(spec > 0 and spec < 4 and element.colorSpec) then
|
||||
color = self.colors.runes[spec]
|
||||
else
|
||||
color = self.colors.power.RUNES
|
||||
end
|
||||
|
||||
local r, g, b = color[1], color[2], color[3]
|
||||
|
||||
for index = 1, #element do
|
||||
element[index]:SetStatusBarColor(r, g, b)
|
||||
|
||||
local bg = element[index].bg
|
||||
if(bg) then
|
||||
local mu = bg.multiplier or 1
|
||||
bg:SetVertexColor(r * mu, g * mu, b * mu)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Callback: Runes:PostUpdateColor(r, g, b)
|
||||
Called after the element color has been updated.
|
||||
|
||||
* self - the Runes element
|
||||
* r - the red component of the used color (number)[0-1]
|
||||
* g - the green component of the used color (number)[0-1]
|
||||
* b - the blue component of the used color (number)[0-1]
|
||||
--]]
|
||||
if(element.PostUpdateColor) then
|
||||
element:PostUpdateColor(r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
local function ColorPath(self, ...)
|
||||
--[[ Override: Runes.UpdateColor(self, event, ...)
|
||||
Used to completely override the internal function for updating the widgets' colors.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
(self.Runes.UpdateColor or UpdateColor) (self, ...)
|
||||
end
|
||||
|
||||
local function Update(self, event)
|
||||
local element = self.Runes
|
||||
|
||||
if(element.sortOrder == 'asc') then
|
||||
table.sort(runemap, ascSort)
|
||||
hasSortOrder = true
|
||||
elseif(element.sortOrder == 'desc') then
|
||||
table.sort(runemap, descSort)
|
||||
hasSortOrder = true
|
||||
elseif(hasSortOrder) then
|
||||
table.sort(runemap)
|
||||
hasSortOrder = false
|
||||
end
|
||||
|
||||
local rune, start, duration, runeReady
|
||||
for index, runeID in next, runemap do
|
||||
rune = element[index]
|
||||
if(not rune) then break end
|
||||
|
||||
if(UnitHasVehicleUI('player')) then
|
||||
rune:Hide()
|
||||
else
|
||||
start, duration, runeReady = GetRuneCooldown(runeID)
|
||||
if(runeReady) then
|
||||
rune:SetMinMaxValues(0, 1)
|
||||
rune:SetValue(1)
|
||||
rune:SetScript('OnUpdate', nil)
|
||||
elseif(start) then
|
||||
rune.duration = GetTime() - start
|
||||
rune:SetMinMaxValues(0, duration)
|
||||
rune:SetValue(0)
|
||||
rune:SetScript('OnUpdate', onUpdate)
|
||||
end
|
||||
|
||||
rune:Show()
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Callback: Runes:PostUpdate(runemap)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the Runes element
|
||||
* runemap - the ordered list of runes' indices (table)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(runemap)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: Runes.Override(self, event, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
(self.Runes.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function AllPath(...)
|
||||
Path(...)
|
||||
ColorPath(...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
Path(element.__owner, 'ForceUpdate')
|
||||
ColorPath(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local function Enable(self, unit)
|
||||
local element = self.Runes
|
||||
if(element and UnitIsUnit(unit, 'player')) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
for i = 1, #element do
|
||||
local rune = element[i]
|
||||
if(rune:IsObjectType('StatusBar') and not (rune:GetStatusBarTexture() or rune:GetStatusBarAtlas())) then
|
||||
rune:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
-- ElvUI block
|
||||
if element.IsObjectType and element:IsObjectType("Frame") then
|
||||
element:Show()
|
||||
end
|
||||
-- end block
|
||||
|
||||
self:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED', ColorPath)
|
||||
self:RegisterEvent('RUNE_POWER_UPDATE', Path, true)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.Runes
|
||||
if(element) then
|
||||
for i = 1, #element do
|
||||
element[i]:Hide()
|
||||
end
|
||||
|
||||
-- ElvUI block
|
||||
if element.IsObjectType and element:IsObjectType("Frame") then
|
||||
element:Hide()
|
||||
end
|
||||
-- end block
|
||||
|
||||
self:UnregisterEvent('PLAYER_SPECIALIZATION_CHANGED', ColorPath)
|
||||
self:UnregisterEvent('RUNE_POWER_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Runes', AllPath, Enable, Disable)
|
||||
245
Libraries/oUF/elements/stagger.lua
Normal file
245
Libraries/oUF/elements/stagger.lua
Normal file
@@ -0,0 +1,245 @@
|
||||
--[[
|
||||
# Element: Monk Stagger Bar
|
||||
|
||||
Handles the visibility and updating of the Monk's stagger bar.
|
||||
|
||||
## Widget
|
||||
|
||||
Stagger - A `StatusBar` used to represent the current stagger level.
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
.bg - A `Texture` used as a background. It will inherit the color of the main StatusBar.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a StatusBar and doesn't have a texture set.
|
||||
|
||||
## Sub-Widgets Options
|
||||
|
||||
.multiplier - Used to tint the background based on the main widgets R, G and B values. Defaults to 1 (number)[0-1]
|
||||
|
||||
## Examples
|
||||
|
||||
local Stagger = CreateFrame('StatusBar', nil, self)
|
||||
Stagger:SetSize(120, 20)
|
||||
Stagger:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', 0, 0)
|
||||
|
||||
-- Register with oUF
|
||||
self.Stagger = Stagger
|
||||
--]]
|
||||
|
||||
if(select(2, UnitClass('player')) ~= 'MONK') then return end
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
-- ElvUI block
|
||||
local GetSpecialization = GetSpecialization
|
||||
local UnitHasVehiclePlayerFrameUI = UnitHasVehiclePlayerFrameUI
|
||||
local UnitHealthMax = UnitHealthMax
|
||||
local UnitIsUnit = UnitIsUnit
|
||||
local UnitStagger = UnitStagger
|
||||
-- GLOBALS: MonkStaggerBar
|
||||
-- end block
|
||||
|
||||
-- sourced from FrameXML/Constants.lua
|
||||
local SPEC_MONK_BREWMASTER = SPEC_MONK_BREWMASTER or 1
|
||||
|
||||
-- sourced from FrameXML/MonkStaggerBar.lua
|
||||
local BREWMASTER_POWER_BAR_NAME = BREWMASTER_POWER_BAR_NAME or 'STAGGER'
|
||||
|
||||
-- percentages at which bar should change color
|
||||
local STAGGER_YELLOW_TRANSITION = STAGGER_YELLOW_TRANSITION or 0.3
|
||||
local STAGGER_RED_TRANSITION = STAGGER_RED_TRANSITION or 0.6
|
||||
|
||||
-- table indices of bar colors
|
||||
local STAGGER_GREEN_INDEX = STAGGER_GREEN_INDEX or 1
|
||||
local STAGGER_YELLOW_INDEX = STAGGER_YELLOW_INDEX or 2
|
||||
local STAGGER_RED_INDEX = STAGGER_RED_INDEX or 3
|
||||
|
||||
local function UpdateColor(self, event, unit)
|
||||
if(unit and unit ~= self.unit) then return end
|
||||
local element = self.Stagger
|
||||
|
||||
local colors = self.colors.power[BREWMASTER_POWER_BAR_NAME]
|
||||
local perc = (element.cur or 0) / (element.max or 1)
|
||||
|
||||
local t
|
||||
if(perc >= STAGGER_RED_TRANSITION) then
|
||||
t = colors and colors[STAGGER_RED_INDEX]
|
||||
elseif(perc > STAGGER_YELLOW_TRANSITION) then
|
||||
t = colors and colors[STAGGER_YELLOW_INDEX]
|
||||
else
|
||||
t = colors and colors[STAGGER_GREEN_INDEX]
|
||||
end
|
||||
|
||||
local r, g, b
|
||||
if(t) then
|
||||
r, g, b = t[1], t[2], t[3]
|
||||
if(b) then
|
||||
element:SetStatusBarColor(r, g, b)
|
||||
|
||||
local bg = element.bg
|
||||
if(bg and b) then
|
||||
local mu = bg.multiplier or 1
|
||||
bg:SetVertexColor(r * mu, g * mu, b * mu)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Callback: Stagger:PostUpdateColor(r, g, b)
|
||||
Called after the element color has been updated.
|
||||
|
||||
* self - the Stagger element
|
||||
* r - the red component of the used color (number)[0-1]
|
||||
* g - the green component of the used color (number)[0-1]
|
||||
* b - the blue component of the used color (number)[0-1]
|
||||
--]]
|
||||
if(element.PostUpdateColor) then
|
||||
element:PostUpdateColor(r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(unit and unit ~= self.unit) then return end
|
||||
|
||||
local element = self.Stagger
|
||||
|
||||
--[[ Callback: Stagger:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the Stagger element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
-- Blizzard code has nil checks for UnitStagger return
|
||||
local cur = UnitStagger('player') or 0
|
||||
local max = UnitHealthMax('player')
|
||||
|
||||
element:SetMinMaxValues(0, max)
|
||||
element:SetValue(cur)
|
||||
|
||||
element.cur = cur
|
||||
element.max = max
|
||||
|
||||
--[[ Callback: Stagger:PostUpdate(cur, max)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the Stagger element
|
||||
* cur - the amount of staggered damage (number)
|
||||
* max - the player's maximum possible health value (number)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
element:PostUpdate(cur, max)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: Stagger.Override(self, event, unit)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
--]]
|
||||
(self.Stagger.Override or Update)(self, ...);
|
||||
|
||||
--[[ Override: Stagger.UpdateColor(self, event, unit)
|
||||
Used to completely override the internal function for updating the widgets' colors.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
--]]
|
||||
(self.Stagger.UpdateColor or UpdateColor) (self, ...)
|
||||
end
|
||||
|
||||
-- ElvUI changed
|
||||
local function Visibility(self, event, unit)
|
||||
local element = self.Stagger
|
||||
local isShown = element:IsShown()
|
||||
local useClassbar = (SPEC_MONK_BREWMASTER ~= GetSpecialization()) or UnitHasVehiclePlayerFrameUI('player')
|
||||
local stateChanged = false
|
||||
|
||||
if useClassbar and isShown then
|
||||
element:Hide()
|
||||
self:UnregisterEvent('UNIT_AURA', Path)
|
||||
stateChanged = true
|
||||
elseif not useClassbar and not isShown then
|
||||
element:Show()
|
||||
self:RegisterEvent('UNIT_AURA', Path)
|
||||
stateChanged = true
|
||||
end
|
||||
|
||||
if element.PostVisibility then
|
||||
element.PostVisibility(self, event, unit, not useClassbar, stateChanged)
|
||||
end
|
||||
|
||||
if not useClassbar then
|
||||
Path(self, event, unit)
|
||||
end
|
||||
end
|
||||
-- end block
|
||||
|
||||
local function VisibilityPath(self, ...)
|
||||
--[[ Override: Stagger.OverrideVisibility(self, event, unit)
|
||||
Used to completely override the internal visibility toggling function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* unit - the unit accompanying the event (string)
|
||||
--]]
|
||||
(self.Stagger.OverrideVisibility or Visibility)(self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
VisibilityPath(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self, unit)
|
||||
local element = self.Stagger
|
||||
if(element and UnitIsUnit(unit, 'player')) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
self:RegisterEvent('PLAYER_TALENT_UPDATE', VisibilityPath, true)
|
||||
|
||||
if(element:IsObjectType('StatusBar') and not (element:GetStatusBarTexture() or element:GetStatusBarAtlas())) then
|
||||
element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
|
||||
MonkStaggerBar:UnregisterEvent('PLAYER_ENTERING_WORLD')
|
||||
MonkStaggerBar:UnregisterEvent('PLAYER_SPECIALIZATION_CHANGED')
|
||||
MonkStaggerBar:UnregisterEvent('UNIT_DISPLAYPOWER')
|
||||
MonkStaggerBar:UnregisterEvent('UNIT_EXITED_VEHICLE')
|
||||
MonkStaggerBar:UnregisterEvent('UPDATE_VEHICLE_ACTIONBAR')
|
||||
|
||||
-- do not change this without taking Visibility into account
|
||||
element:Hide()
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.Stagger
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('UNIT_AURA', Path)
|
||||
self:UnregisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
self:UnregisterEvent('PLAYER_TALENT_UPDATE', VisibilityPath)
|
||||
|
||||
MonkStaggerBar:RegisterEvent('PLAYER_ENTERING_WORLD')
|
||||
MonkStaggerBar:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED')
|
||||
MonkStaggerBar:RegisterEvent('UNIT_DISPLAYPOWER')
|
||||
MonkStaggerBar:RegisterEvent('UNIT_EXITED_VEHICLE')
|
||||
MonkStaggerBar:RegisterEvent('UPDATE_VEHICLE_ACTIONBAR')
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Stagger', VisibilityPath, Enable, Disable)
|
||||
110
Libraries/oUF/elements/summonindicator.lua
Normal file
110
Libraries/oUF/elements/summonindicator.lua
Normal file
@@ -0,0 +1,110 @@
|
||||
--[[
|
||||
# Element: SummonIndicator
|
||||
|
||||
Handles the visibility and updating of an indicator based on the unit's incoming summon status.
|
||||
|
||||
## Widget
|
||||
|
||||
SummonIndicator - A `Texture` used to display if the unit has an incoming summon.
|
||||
|
||||
## Notes
|
||||
|
||||
This element updates by changing the texture.
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local SummonIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
SummonIndicator:SetSize(32, 32)
|
||||
SummonIndicator:SetPoint('TOPRIGHT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.SummonIndicator = SummonIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
-- sourced from Blizzard_APIDocumentation/IncomingSummonDocumentation.lua
|
||||
local SUMMON_STATUS_NONE = Enum.SummonStatus.None or 0
|
||||
local SUMMON_STATUS_PENDING = Enum.SummonStatus.Pending or 1
|
||||
local SUMMON_STATUS_ACCEPTED = Enum.SummonStatus.Accepted or 2
|
||||
local SUMMON_STATUS_DECLINED = Enum.SummonStatus.Declined or 3
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local element = self.SummonIndicator
|
||||
|
||||
--[[ Callback: SummonIndicator:PreUpdate()
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the SummonIndicator element
|
||||
--]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local status = C_IncomingSummon.IncomingSummonStatus(unit)
|
||||
if(status ~= SUMMON_STATUS_NONE) then
|
||||
if(status == SUMMON_STATUS_PENDING) then
|
||||
element:SetAtlas('Raid-Icon-SummonPending')
|
||||
elseif(status == SUMMON_STATUS_ACCEPTED) then
|
||||
element:SetAtlas('Raid-Icon-SummonAccepted')
|
||||
elseif(status == SUMMON_STATUS_DECLINED) then
|
||||
element:SetAtlas('Raid-Icon-SummonDeclined')
|
||||
end
|
||||
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
--[[ Callback: SummonIndicator:PostUpdate(status)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the SummonIndicator element
|
||||
* status - the unit's incoming summon status (number)[0-3]
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(status)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: SummonIndicator.Override(self, event)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.SummonIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.SummonIndicator
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('INCOMING_SUMMON_CHANGED', Path)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.SummonIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('INCOMING_SUMMON_CHANGED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('SummonIndicator', Path, Enable, Disable)
|
||||
977
Libraries/oUF/elements/tags.lua
Normal file
977
Libraries/oUF/elements/tags.lua
Normal file
@@ -0,0 +1,977 @@
|
||||
-- Credits: Vika, Cladhaire, Tekkub
|
||||
--[[
|
||||
# Element: Tags
|
||||
|
||||
Provides a system for text-based display of information by binding a tag string to a font string widget which in turn is
|
||||
tied to a unit frame.
|
||||
|
||||
## Widget
|
||||
|
||||
A FontString to hold a tag string. Unlike other elements, this widget must not have a preset name.
|
||||
|
||||
## Notes
|
||||
|
||||
A `Tag` is a Lua string consisting of a function name surrounded by square brackets. The tag will be replaced by the
|
||||
output of the function and displayed as text on the font string widget with that the tag has been registered.
|
||||
Literals can be pre or appended by separating them with a `>` before or `<` after the function name. The literals will be only
|
||||
displayed when the function returns a non-nil value. I.e. `"[perhp<%]"` will display the current health as a percentage
|
||||
of the maximum health followed by the % sign.
|
||||
|
||||
A `Tag String` is a Lua string consisting of one or multiple tags with optional literals between them.
|
||||
Each tag will be updated individually and the output will follow the tags order. Literals will be displayed in the
|
||||
output string regardless of whether the surrounding tag functions return a value. I.e. `"[curhp]/[maxhp]"` will resolve
|
||||
to something like `2453/5000`.
|
||||
|
||||
A `Tag Function` is used to replace a single tag in a tag string by its output. A tag function receives only two
|
||||
arguments - the unit and the realUnit of the unit frame used to register the tag (see Options for further details). The
|
||||
tag function is called when the unit frame is shown or when a specified event has fired. It the tag is registered on an
|
||||
eventless frame (i.e. one holding the unit "targettarget"), then the tag function is called in a set time interval.
|
||||
|
||||
A number of built-in tag functions exist. The layout can also define its own tag functions by adding them to the
|
||||
`oUF.Tags.Methods` table. The events upon which the function will be called are specified in a white-space separated
|
||||
list added to the `oUF.Tags.Events` table. Should an event fire without unit information, then it should also be listed
|
||||
in the `oUF.Tags.SharedEvents` table as follows: `oUF.Tags.SharedEvents.EVENT_NAME = true`.
|
||||
|
||||
## Options
|
||||
|
||||
.overrideUnit - if specified on the font string widget, the frame's realUnit will be passed as the second argument to
|
||||
every tag function whose name is contained in the relevant tag string. Otherwise the second argument
|
||||
is always nil (boolean)
|
||||
.frequentUpdates - defines how often the corresponding tag function(s) should be called. This will override the events
|
||||
for the tag(s), if any. If the value is a number, it is taken as a time interval in seconds. If the
|
||||
value is a boolean, the time interval is set to 0.5 seconds (number or boolean)
|
||||
|
||||
## Attributes
|
||||
|
||||
.parent - the unit frame on which the tag has been registered
|
||||
|
||||
## Examples
|
||||
|
||||
-- define the tag function
|
||||
oUF.Tags.Methods['mylayout:threatname'] = function(unit, realUnit)
|
||||
local color = _TAGS['threatcolor'](unit)
|
||||
local name = _TAGS['name'](unit, realUnit)
|
||||
return string.format('%s%s|r', color, name)
|
||||
end
|
||||
|
||||
-- add the events
|
||||
oUF.Tags.Events['mylayout:threatname'] = 'UNIT_NAME_UPDATE UNIT_THREAT_SITUATION_UPDATE'
|
||||
|
||||
-- create the text widget
|
||||
local info = self.Health:CreateFontString(nil, 'OVERLAY', 'GameFontNormal')
|
||||
info:SetPoint('LEFT')
|
||||
|
||||
-- register the tag on the text widget with oUF
|
||||
self:Tag(info, '[mylayout:threatname]')
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local unitExists = Private.unitExists
|
||||
|
||||
-- ElvUI block
|
||||
local _G = _G
|
||||
local CreateFrame = CreateFrame
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
local setfenv, getfenv = setfenv, getfenv
|
||||
local rawget, rawset, select = rawget, rawset, select
|
||||
local format, tinsert, tremove = format, tinsert, tremove
|
||||
local next, type, pcall, unpack = next, type, pcall, unpack
|
||||
local error, assert, loadstring = error, assert, loadstring
|
||||
-- end block
|
||||
|
||||
local _PATTERN = '%[..-%]+'
|
||||
|
||||
local _ENV = {
|
||||
Hex = function(r, g, b)
|
||||
if(type(r) == 'table') then
|
||||
if(r.r) then
|
||||
r, g, b = r.r, r.g, r.b
|
||||
else
|
||||
r, g, b = unpack(r)
|
||||
end
|
||||
end
|
||||
|
||||
-- ElvUI block
|
||||
if not r or type(r) == 'string' then --wtf?
|
||||
return '|cffFFFFFF'
|
||||
end
|
||||
-- end block
|
||||
|
||||
return format('|cff%02x%02x%02x', r * 255, g * 255, b * 255)
|
||||
end,
|
||||
}
|
||||
_ENV.ColorGradient = function(...)
|
||||
return _ENV._FRAME:ColorGradient(...)
|
||||
end
|
||||
|
||||
local _PROXY = setmetatable(_ENV, {__index = _G})
|
||||
|
||||
local tagStrings = {
|
||||
['affix'] = [[function(u)
|
||||
local c = UnitClassification(u)
|
||||
if(c == 'minus') then
|
||||
return 'Affix'
|
||||
end
|
||||
end]],
|
||||
|
||||
['arcanecharges'] = [[function()
|
||||
if(GetSpecialization() == SPEC_MAGE_ARCANE) then
|
||||
local num = UnitPower('player', Enum.PowerType.ArcaneCharges)
|
||||
if(num > 0) then
|
||||
return num
|
||||
end
|
||||
end
|
||||
end]],
|
||||
|
||||
['arenaspec'] = [[function(u)
|
||||
local id = u:match('arena(%d)$')
|
||||
if(id) then
|
||||
local specID = GetArenaOpponentSpec(tonumber(id))
|
||||
if(specID and specID > 0) then
|
||||
local _, specName = GetSpecializationInfoByID(specID)
|
||||
return specName
|
||||
end
|
||||
end
|
||||
end]],
|
||||
|
||||
['chi'] = [[function()
|
||||
if(GetSpecialization() == SPEC_MONK_WINDWALKER) then
|
||||
local num = UnitPower('player', Enum.PowerType.Chi)
|
||||
if(num > 0) then
|
||||
return num
|
||||
end
|
||||
end
|
||||
end]],
|
||||
|
||||
['classification'] = [[function(u)
|
||||
local c = UnitClassification(u)
|
||||
if(c == 'rare') then
|
||||
return 'Rare'
|
||||
elseif(c == 'rareelite') then
|
||||
return 'Rare Elite'
|
||||
elseif(c == 'elite') then
|
||||
return 'Elite'
|
||||
elseif(c == 'worldboss') then
|
||||
return 'Boss'
|
||||
elseif(c == 'minus') then
|
||||
return 'Affix'
|
||||
end
|
||||
end]],
|
||||
|
||||
['cpoints'] = [[function(u)
|
||||
local cp = UnitPower(u, Enum.PowerType.ComboPoints)
|
||||
|
||||
if(cp > 0) then
|
||||
return cp
|
||||
end
|
||||
end]],
|
||||
|
||||
['creature'] = [[function(u)
|
||||
return UnitCreatureFamily(u) or UnitCreatureType(u)
|
||||
end]],
|
||||
|
||||
['curmana'] = [[function(unit)
|
||||
return UnitPower(unit, Enum.PowerType.Mana)
|
||||
end]],
|
||||
|
||||
['dead'] = [[function(u)
|
||||
if(UnitIsDead(u)) then
|
||||
return 'Dead'
|
||||
elseif(UnitIsGhost(u)) then
|
||||
return 'Ghost'
|
||||
end
|
||||
end]],
|
||||
|
||||
['deficit:name'] = [[function(u)
|
||||
local missinghp = _TAGS['missinghp'](u)
|
||||
if(missinghp) then
|
||||
return '-' .. missinghp
|
||||
else
|
||||
return _TAGS['name'](u)
|
||||
end
|
||||
end]],
|
||||
|
||||
['difficulty'] = [[function(u)
|
||||
if UnitCanAttack('player', u) then
|
||||
local l = UnitEffectiveLevel(u)
|
||||
return Hex(GetCreatureDifficultyColor((l > 0) and l or 999))
|
||||
end
|
||||
end]],
|
||||
|
||||
['group'] = [[function(unit)
|
||||
local name, server = UnitName(unit)
|
||||
if(server and server ~= '') then
|
||||
name = string.format('%s-%s', name, server)
|
||||
end
|
||||
|
||||
for i=1, GetNumGroupMembers() do
|
||||
local raidName, _, group = GetRaidRosterInfo(i)
|
||||
if( raidName == name ) then
|
||||
return group
|
||||
end
|
||||
end
|
||||
end]],
|
||||
|
||||
['holypower'] = [[function()
|
||||
if(GetSpecialization() == SPEC_PALADIN_RETRIBUTION) then
|
||||
local num = UnitPower('player', Enum.PowerType.HolyPower)
|
||||
if(num > 0) then
|
||||
return num
|
||||
end
|
||||
end
|
||||
end]],
|
||||
|
||||
['leader'] = [[function(u)
|
||||
if(UnitIsGroupLeader(u)) then
|
||||
return 'L'
|
||||
end
|
||||
end]],
|
||||
|
||||
['leaderlong'] = [[function(u)
|
||||
if(UnitIsGroupLeader(u)) then
|
||||
return 'Leader'
|
||||
end
|
||||
end]],
|
||||
|
||||
['level'] = [[function(u)
|
||||
local l = UnitEffectiveLevel(u)
|
||||
if(UnitIsWildBattlePet(u) or UnitIsBattlePetCompanion(u)) then
|
||||
l = UnitBattlePetLevel(u)
|
||||
end
|
||||
|
||||
if(l > 0) then
|
||||
return l
|
||||
else
|
||||
return '??'
|
||||
end
|
||||
end]],
|
||||
|
||||
['maxmana'] = [[function(unit)
|
||||
return UnitPowerMax(unit, Enum.PowerType.Mana)
|
||||
end]],
|
||||
|
||||
['missinghp'] = [[function(u)
|
||||
local current = UnitHealthMax(u) - UnitHealth(u)
|
||||
if(current > 0) then
|
||||
return current
|
||||
end
|
||||
end]],
|
||||
|
||||
['missingpp'] = [[function(u)
|
||||
local current = UnitPowerMax(u) - UnitPower(u)
|
||||
if(current > 0) then
|
||||
return current
|
||||
end
|
||||
end]],
|
||||
|
||||
['name'] = [[function(u, r)
|
||||
return UnitName(r or u)
|
||||
end]],
|
||||
|
||||
['offline'] = [[function(u)
|
||||
if(not UnitIsConnected(u)) then
|
||||
return 'Offline'
|
||||
end
|
||||
end]],
|
||||
|
||||
['perhp'] = [[function(u)
|
||||
local m = UnitHealthMax(u)
|
||||
if(m == 0) then
|
||||
return 0
|
||||
else
|
||||
return math.floor(UnitHealth(u) / m * 100 + .5)
|
||||
end
|
||||
end]],
|
||||
|
||||
['perpp'] = [[function(u)
|
||||
local m = UnitPowerMax(u)
|
||||
if(m == 0) then
|
||||
return 0
|
||||
else
|
||||
return math.floor(UnitPower(u) / m * 100 + .5)
|
||||
end
|
||||
end]],
|
||||
|
||||
['plus'] = [[function(u)
|
||||
local c = UnitClassification(u)
|
||||
if(c == 'elite' or c == 'rareelite') then
|
||||
return '+'
|
||||
end
|
||||
end]],
|
||||
|
||||
['powercolor'] = [[function(u)
|
||||
local pType, pToken, altR, altG, altB = UnitPowerType(u)
|
||||
local t = _COLORS.power[pToken]
|
||||
|
||||
if(not t) then
|
||||
if(altR) then
|
||||
if(altR > 1 or altG > 1 or altB > 1) then
|
||||
return Hex(altR / 255, altG / 255, altB / 255)
|
||||
else
|
||||
return Hex(altR, altG, altB)
|
||||
end
|
||||
else
|
||||
return Hex(_COLORS.power[pType] or _COLORS.power.MANA)
|
||||
end
|
||||
end
|
||||
|
||||
return Hex(t)
|
||||
end]],
|
||||
|
||||
['pvp'] = [[function(u)
|
||||
if(UnitIsPVP(u)) then
|
||||
return 'PvP'
|
||||
end
|
||||
end]],
|
||||
|
||||
['raidcolor'] = [[function(u)
|
||||
local _, class = UnitClass(u)
|
||||
if(class) then
|
||||
return Hex(_COLORS.class[class])
|
||||
else
|
||||
local id = u:match('arena(%d)$')
|
||||
if(id) then
|
||||
local specID = GetArenaOpponentSpec(tonumber(id))
|
||||
if(specID and specID > 0) then
|
||||
_, _, _, _, _, class = GetSpecializationInfoByID(specID)
|
||||
return Hex(_COLORS.class[class])
|
||||
end
|
||||
end
|
||||
end
|
||||
end]],
|
||||
|
||||
['rare'] = [[function(u)
|
||||
local c = UnitClassification(u)
|
||||
if(c == 'rare' or c == 'rareelite') then
|
||||
return 'Rare'
|
||||
end
|
||||
end]],
|
||||
|
||||
['resting'] = [[function(u)
|
||||
if(u == 'player' and IsResting()) then
|
||||
return 'zzz'
|
||||
end
|
||||
end]],
|
||||
|
||||
['runes'] = [[function()
|
||||
local amount = 0
|
||||
|
||||
for i = 1, 6 do
|
||||
local _, _, ready = GetRuneCooldown(i)
|
||||
if(ready) then
|
||||
amount = amount + 1
|
||||
end
|
||||
end
|
||||
|
||||
return amount
|
||||
end]],
|
||||
|
||||
['sex'] = [[function(u)
|
||||
local s = UnitSex(u)
|
||||
if(s == 2) then
|
||||
return 'Male'
|
||||
elseif(s == 3) then
|
||||
return 'Female'
|
||||
end
|
||||
end]],
|
||||
|
||||
['shortclassification'] = [[function(u)
|
||||
local c = UnitClassification(u)
|
||||
if(c == 'rare') then
|
||||
return 'R'
|
||||
elseif(c == 'rareelite') then
|
||||
return 'R+'
|
||||
elseif(c == 'elite') then
|
||||
return '+'
|
||||
elseif(c == 'worldboss') then
|
||||
return 'B'
|
||||
elseif(c == 'minus') then
|
||||
return '-'
|
||||
end
|
||||
end]],
|
||||
|
||||
['smartclass'] = [[function(u)
|
||||
if(UnitIsPlayer(u)) then
|
||||
return _TAGS['class'](u)
|
||||
end
|
||||
|
||||
return _TAGS['creature'](u)
|
||||
end]],
|
||||
|
||||
['smartlevel'] = [[function(u)
|
||||
local c = UnitClassification(u)
|
||||
if(c == 'worldboss') then
|
||||
return 'Boss'
|
||||
else
|
||||
local plus = _TAGS['plus'](u)
|
||||
local level = _TAGS['level'](u)
|
||||
if(plus) then
|
||||
return level .. plus
|
||||
else
|
||||
return level
|
||||
end
|
||||
end
|
||||
end]],
|
||||
|
||||
['soulshards'] = [[function()
|
||||
local num = UnitPower('player', Enum.PowerType.SoulShards)
|
||||
if(num > 0) then
|
||||
return num
|
||||
end
|
||||
end]],
|
||||
|
||||
['status'] = [[function(u)
|
||||
if(UnitIsDead(u)) then
|
||||
return 'Dead'
|
||||
elseif(UnitIsGhost(u)) then
|
||||
return 'Ghost'
|
||||
elseif(not UnitIsConnected(u)) then
|
||||
return 'Offline'
|
||||
else
|
||||
return _TAGS['resting'](u)
|
||||
end
|
||||
end]],
|
||||
|
||||
['threat'] = [[function(u)
|
||||
local s = UnitThreatSituation(u)
|
||||
if(s == 1) then
|
||||
return '++'
|
||||
elseif(s == 2) then
|
||||
return '--'
|
||||
elseif(s == 3) then
|
||||
return 'Aggro'
|
||||
end
|
||||
end]],
|
||||
|
||||
['threatcolor'] = [[function(u)
|
||||
return Hex(GetThreatStatusColor(UnitThreatSituation(u)))
|
||||
end]],
|
||||
}
|
||||
|
||||
local tags = setmetatable(
|
||||
{
|
||||
curhp = UnitHealth,
|
||||
curpp = UnitPower,
|
||||
maxhp = UnitHealthMax,
|
||||
maxpp = UnitPowerMax,
|
||||
class = UnitClass,
|
||||
faction = UnitFactionGroup,
|
||||
race = UnitRace,
|
||||
},
|
||||
{
|
||||
__index = function(self, key)
|
||||
local tagString = tagStrings[key]
|
||||
if(tagString) then
|
||||
self[key] = tagString
|
||||
tagStrings[key] = nil
|
||||
end
|
||||
|
||||
return rawget(self, key)
|
||||
end,
|
||||
__newindex = function(self, key, val)
|
||||
if(type(val) == 'string') then
|
||||
local func, err = loadstring('return ' .. val)
|
||||
if(func) then
|
||||
val = func()
|
||||
else
|
||||
error(err, 3)
|
||||
end
|
||||
end
|
||||
|
||||
assert(type(val) == 'function', 'Tag function must be a function or a string that evaluates to a function.')
|
||||
|
||||
-- We don't want to clash with any custom envs
|
||||
if(getfenv(val) == _G) then
|
||||
-- pcall is needed for cases when Blizz functions are passed as
|
||||
-- strings, for intance, 'UnitPowerMax', an attempt to set a
|
||||
-- custom env will result in an error
|
||||
pcall(setfenv, val, _PROXY)
|
||||
end
|
||||
|
||||
rawset(self, key, val)
|
||||
end,
|
||||
}
|
||||
)
|
||||
|
||||
_ENV._TAGS = tags
|
||||
|
||||
local vars = setmetatable({}, {
|
||||
__newindex = function(self, key, val)
|
||||
if(type(val) == 'string') then
|
||||
local func = loadstring('return ' .. val)
|
||||
if(func) then
|
||||
val = func() or val
|
||||
end
|
||||
end
|
||||
|
||||
rawset(self, key, val)
|
||||
end,
|
||||
})
|
||||
|
||||
_ENV._VARS = vars
|
||||
|
||||
-- ElvUI sets UNIT_POWER_UPDATE to UNIT_POWER_FREQUENT in tagEvents
|
||||
local tagEvents = {
|
||||
['affix'] = 'UNIT_CLASSIFICATION_CHANGED',
|
||||
['arcanecharges'] = 'UNIT_POWER_FREQUENT PLAYER_TALENT_UPDATE',
|
||||
['arenaspec'] = 'ARENA_PREP_OPPONENT_SPECIALIZATIONS',
|
||||
['chi'] = 'UNIT_POWER_FREQUENT PLAYER_TALENT_UPDATE',
|
||||
['classification'] = 'UNIT_CLASSIFICATION_CHANGED',
|
||||
['cpoints'] = 'UNIT_POWER_FREQUENT PLAYER_TARGET_CHANGED',
|
||||
['curhp'] = 'UNIT_HEALTH UNIT_MAXHEALTH',
|
||||
['curmana'] = 'UNIT_POWER_FREQUENT UNIT_MAXPOWER',
|
||||
['curpp'] = 'UNIT_POWER_FREQUENT UNIT_MAXPOWER',
|
||||
['dead'] = 'UNIT_HEALTH',
|
||||
['deficit:name'] = 'UNIT_HEALTH UNIT_MAXHEALTH UNIT_NAME_UPDATE',
|
||||
['difficulty'] = 'UNIT_FACTION',
|
||||
['faction'] = 'NEUTRAL_FACTION_SELECT_RESULT',
|
||||
['group'] = 'GROUP_ROSTER_UPDATE',
|
||||
['holypower'] = 'UNIT_POWER_FREQUENT PLAYER_TALENT_UPDATE',
|
||||
['leader'] = 'PARTY_LEADER_CHANGED',
|
||||
['leaderlong'] = 'PARTY_LEADER_CHANGED',
|
||||
['level'] = 'UNIT_LEVEL PLAYER_LEVEL_UP',
|
||||
['maxhp'] = 'UNIT_MAXHEALTH',
|
||||
['maxmana'] = 'UNIT_POWER_FREQUENT UNIT_MAXPOWER',
|
||||
['maxpp'] = 'UNIT_MAXPOWER',
|
||||
['missinghp'] = 'UNIT_HEALTH UNIT_MAXHEALTH',
|
||||
['missingpp'] = 'UNIT_MAXPOWER UNIT_POWER_FREQUENT',
|
||||
['name'] = 'UNIT_NAME_UPDATE',
|
||||
['offline'] = 'UNIT_HEALTH UNIT_CONNECTION',
|
||||
['perhp'] = 'UNIT_HEALTH UNIT_MAXHEALTH',
|
||||
['perpp'] = 'UNIT_MAXPOWER UNIT_POWER_FREQUENT',
|
||||
['plus'] = 'UNIT_CLASSIFICATION_CHANGED',
|
||||
['powercolor'] = 'UNIT_DISPLAYPOWER',
|
||||
['pvp'] = 'UNIT_FACTION',
|
||||
['rare'] = 'UNIT_CLASSIFICATION_CHANGED',
|
||||
['resting'] = 'PLAYER_UPDATE_RESTING',
|
||||
['runes'] = 'RUNE_POWER_UPDATE',
|
||||
['shortclassification'] = 'UNIT_CLASSIFICATION_CHANGED',
|
||||
['smartlevel'] = 'UNIT_LEVEL PLAYER_LEVEL_UP UNIT_CLASSIFICATION_CHANGED',
|
||||
['soulshards'] = 'UNIT_POWER_FREQUENT',
|
||||
['status'] = 'UNIT_HEALTH PLAYER_UPDATE_RESTING UNIT_CONNECTION',
|
||||
['threat'] = 'UNIT_THREAT_SITUATION_UPDATE',
|
||||
['threatcolor'] = 'UNIT_THREAT_SITUATION_UPDATE',
|
||||
}
|
||||
|
||||
local unitlessEvents = {
|
||||
ARENA_PREP_OPPONENT_SPECIALIZATIONS = true,
|
||||
GROUP_ROSTER_UPDATE = true,
|
||||
NEUTRAL_FACTION_SELECT_RESULT = true,
|
||||
PARTY_LEADER_CHANGED = true,
|
||||
PLAYER_LEVEL_UP = true,
|
||||
PLAYER_TARGET_CHANGED = true,
|
||||
PLAYER_UPDATE_RESTING = true,
|
||||
RUNE_POWER_UPDATE = true,
|
||||
}
|
||||
|
||||
local events = {}
|
||||
local eventFrame = CreateFrame('Frame')
|
||||
eventFrame:SetScript('OnEvent', function(self, event, unit)
|
||||
local strings = events[event]
|
||||
if(strings) then
|
||||
for _, fs in next, strings do
|
||||
if(fs:IsVisible() and (unitlessEvents[event] or fs.parent.unit == unit or (fs.extraUnits and fs.extraUnits[unit]))) then
|
||||
fs:UpdateTag()
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local onUpdates = {}
|
||||
local eventlessUnits = {}
|
||||
|
||||
local function createOnUpdate(timer)
|
||||
if(not onUpdates[timer]) then
|
||||
local total = timer
|
||||
local frame = CreateFrame('Frame')
|
||||
local strings = eventlessUnits[timer]
|
||||
|
||||
frame:SetScript('OnUpdate', function(self, elapsed)
|
||||
if(total >= timer) then
|
||||
for _, fs in next, strings do
|
||||
if(fs.parent:IsShown() and unitExists(fs.parent.unit)) then
|
||||
fs:UpdateTag()
|
||||
end
|
||||
end
|
||||
|
||||
total = 0
|
||||
end
|
||||
|
||||
total = total + elapsed
|
||||
end)
|
||||
|
||||
onUpdates[timer] = frame
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Tags: frame:UpdateTags()
|
||||
Used to update all tags on a frame.
|
||||
|
||||
* self - the unit frame from which to update the tags
|
||||
--]]
|
||||
local function Update(self)
|
||||
if(self.__tags) then
|
||||
for fs in next, self.__tags do
|
||||
fs:UpdateTag()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ElvUI block
|
||||
local onEnter = function(self) for fs in next, self.__mousetags do fs:SetAlpha(1) end end
|
||||
local onLeave = function(self) for fs in next, self.__mousetags do fs:SetAlpha(0) end end
|
||||
local onUpdateDelay = {}
|
||||
local escapeSequences = {
|
||||
["||c"] = "|c",
|
||||
["||r"] = "|r",
|
||||
["||T"] = "|T",
|
||||
["||t"] = "|t",
|
||||
}
|
||||
-- end block
|
||||
|
||||
local tagPool = {}
|
||||
local funcPool = {}
|
||||
local tmp = {}
|
||||
|
||||
local function getTagName(tag)
|
||||
local tagStart = tag:match('>+()') or 2
|
||||
local tagEnd = (tag:match('.-()<') or -1) - 1
|
||||
|
||||
return tag:sub(tagStart, tagEnd), tagStart, tagEnd
|
||||
end
|
||||
|
||||
local function getTagFunc(tagstr)
|
||||
local func = tagPool[tagstr]
|
||||
if(not func) then
|
||||
local frmt, numTags = tagstr:gsub('%%', '%%%%'):gsub(_PATTERN, '%%s')
|
||||
local args = {}
|
||||
|
||||
for bracket in tagstr:gmatch(_PATTERN) do
|
||||
local tagFunc = funcPool[bracket] or tags[bracket:sub(2, -2)]
|
||||
if(not tagFunc) then
|
||||
local tagName, tagStart, tagEnd = getTagName(bracket)
|
||||
|
||||
local tag = tags[tagName]
|
||||
if(tag) then
|
||||
tagStart = tagStart - 2
|
||||
tagEnd = tagEnd + 2
|
||||
|
||||
if(tagStart ~= 0 and tagEnd ~= 0) then
|
||||
local prefix = bracket:sub(2, tagStart)
|
||||
local suffix = bracket:sub(tagEnd, -2)
|
||||
|
||||
tagFunc = function(unit, realUnit)
|
||||
local str = tag(unit, realUnit)
|
||||
if(str) then
|
||||
return prefix .. str .. suffix
|
||||
end
|
||||
end
|
||||
elseif(tagStart ~= 0) then
|
||||
local prefix = bracket:sub(2, tagStart)
|
||||
|
||||
tagFunc = function(unit, realUnit)
|
||||
local str = tag(unit, realUnit)
|
||||
if(str) then
|
||||
return prefix .. str
|
||||
end
|
||||
end
|
||||
elseif(tagEnd ~= 0) then
|
||||
local suffix = bracket:sub(tagEnd, -2)
|
||||
|
||||
tagFunc = function(unit, realUnit)
|
||||
local str = tag(unit, realUnit)
|
||||
if(str) then
|
||||
return str .. suffix
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
funcPool[bracket] = tagFunc
|
||||
end
|
||||
end
|
||||
|
||||
-- ElvUI changed
|
||||
if(tagFunc) then
|
||||
tinsert(args, tagFunc)
|
||||
else
|
||||
numTags = -1
|
||||
func = function(self)
|
||||
self:SetText(bracket)
|
||||
end
|
||||
end
|
||||
-- end block
|
||||
end
|
||||
|
||||
-- ElvUI changed
|
||||
if numTags ~= -1 then
|
||||
func = function(self)
|
||||
local parent = self.parent
|
||||
local unit = parent.unit
|
||||
|
||||
local customArgs = parent.__customargs
|
||||
local realUnit = self.overrideUnit and parent.realUnit
|
||||
|
||||
_ENV._COLORS = parent.colors
|
||||
_ENV._FRAME = parent
|
||||
for i, fnc in next, args do
|
||||
tmp[i] = fnc(unit, realUnit, customArgs[self]) or ''
|
||||
end
|
||||
|
||||
-- We do 1, numTags because tmp can hold several unneeded variables.
|
||||
self:SetFormattedText(frmt, unpack(tmp, 1, numTags))
|
||||
end
|
||||
|
||||
tagPool[tagstr] = func
|
||||
end
|
||||
-- end block
|
||||
end
|
||||
|
||||
return func
|
||||
end
|
||||
|
||||
local function registerEvent(fontstr, event)
|
||||
if(not events[event]) then events[event] = {} end
|
||||
|
||||
eventFrame:RegisterEvent(event)
|
||||
tinsert(events[event], fontstr)
|
||||
end
|
||||
|
||||
local function registerEvents(fontstr, tagstr)
|
||||
for tag in tagstr:gmatch(_PATTERN) do
|
||||
tag = getTagName(tag)
|
||||
local tagevents = tagEvents[tag]
|
||||
if(tagevents) then
|
||||
for event in tagevents:gmatch('%S+') do
|
||||
registerEvent(fontstr, event)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function unregisterEvents(fontstr)
|
||||
for event, data in next, events do
|
||||
for i, tagfsstr in next, data do
|
||||
if(tagfsstr == fontstr) then
|
||||
if(#data == 1) then
|
||||
eventFrame:UnregisterEvent(event)
|
||||
end
|
||||
|
||||
tremove(data, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- this bullshit is to fix texture strings not adjusting to its inherited alpha
|
||||
-- it is a blizzard issue with how texture strings are rendered
|
||||
local alphaFix = CreateFrame('Frame')
|
||||
alphaFix.fontStrings = {}
|
||||
alphaFix:SetScript('OnUpdate', function()
|
||||
local strs = alphaFix.fontStrings
|
||||
if next(strs) then
|
||||
for fs in next, strs do
|
||||
strs[fs] = nil
|
||||
|
||||
local a = fs:GetAlpha()
|
||||
fs:SetAlpha(0)
|
||||
fs:SetAlpha(a)
|
||||
end
|
||||
else
|
||||
alphaFix:Hide()
|
||||
end
|
||||
end)
|
||||
|
||||
local function fixAlpha(self)
|
||||
alphaFix.fontStrings[self] = true
|
||||
alphaFix:Show()
|
||||
end
|
||||
|
||||
local taggedFS = {}
|
||||
|
||||
--[[ Tags: frame:Tag(fs, tagstr, ...)
|
||||
Used to register a tag on a unit frame.
|
||||
|
||||
* self - the unit frame on which to register the tag
|
||||
* fs - the font string to display the tag (FontString)
|
||||
* tagstr - the tag string (string)
|
||||
* ... - additional optional unitID(s) the tag should update for
|
||||
--]]
|
||||
local function Tag(self, fs, tagstr, ...)
|
||||
if(not fs or not tagstr) then return end
|
||||
|
||||
if(not self.__tags) then
|
||||
self.__tags = {}
|
||||
self.__mousetags = {} -- ElvUI
|
||||
self.__customargs = {} -- ElvUI
|
||||
|
||||
tinsert(self.__elements, Update)
|
||||
elseif(self.__tags[fs]) then
|
||||
-- We don't need to remove it from the __tags table as Untag handles
|
||||
-- that for us.
|
||||
self:Untag(fs)
|
||||
end
|
||||
|
||||
-- ElvUI
|
||||
if not fs.__HookedAlphaFix then
|
||||
hooksecurefunc(fs, 'SetText', fixAlpha)
|
||||
hooksecurefunc(fs, 'SetFormattedText', fixAlpha)
|
||||
fs.__HookedAlphaFix = true
|
||||
end
|
||||
|
||||
for escapeSequence, replacement in next, escapeSequences do
|
||||
while tagstr:find(escapeSequence) do
|
||||
tagstr = tagstr:gsub(escapeSequence, replacement)
|
||||
end
|
||||
end
|
||||
|
||||
local customArgs = tagstr:match('{(.-)}%]')
|
||||
if customArgs then
|
||||
self.__customargs[fs] = customArgs
|
||||
tagstr = tagstr:gsub('{.-}%]', ']')
|
||||
else
|
||||
self.__customargs[fs] = nil
|
||||
end
|
||||
|
||||
if tagstr:find('%[mouseover%]') then
|
||||
self.__mousetags[fs] = true
|
||||
fs:SetAlpha(0)
|
||||
if not self.__HookFunc then
|
||||
self:HookScript('OnEnter', onEnter)
|
||||
self:HookScript('OnLeave', onLeave)
|
||||
self.__HookFunc = true;
|
||||
end
|
||||
tagstr = tagstr:gsub('%[mouseover%]', '')
|
||||
else
|
||||
for fontString in next, self.__mousetags do
|
||||
if fontString == fs then
|
||||
self.__mousetags[fontString] = nil
|
||||
fs:SetAlpha(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local containsOnUpdate
|
||||
for tag in tagstr:gmatch(_PATTERN) do
|
||||
tag = getTagName(tag)
|
||||
if not tagEvents[tag] then
|
||||
containsOnUpdate = onUpdateDelay[tag] or 0.15;
|
||||
end
|
||||
end
|
||||
-- end block
|
||||
|
||||
fs.parent = self
|
||||
fs.UpdateTag = getTagFunc(tagstr)
|
||||
|
||||
if(self.__eventless or fs.frequentUpdates) or containsOnUpdate then -- ElvUI changed
|
||||
local timer
|
||||
if(type(fs.frequentUpdates) == 'number') then
|
||||
timer = fs.frequentUpdates
|
||||
-- ElvUI added check
|
||||
elseif containsOnUpdate then
|
||||
timer = containsOnUpdate
|
||||
-- end block
|
||||
else
|
||||
timer = .5
|
||||
end
|
||||
|
||||
if(not eventlessUnits[timer]) then eventlessUnits[timer] = {} end
|
||||
tinsert(eventlessUnits[timer], fs)
|
||||
|
||||
createOnUpdate(timer)
|
||||
else
|
||||
registerEvents(fs, tagstr)
|
||||
|
||||
if(...) then
|
||||
if(not fs.extraUnits) then
|
||||
fs.extraUnits = {}
|
||||
end
|
||||
|
||||
for index = 1, select('#', ...) do
|
||||
fs.extraUnits[select(index, ...)] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
taggedFS[fs] = tagstr
|
||||
self.__tags[fs] = true
|
||||
end
|
||||
|
||||
--[[ Tags: frame:Untag(fs)
|
||||
Used to unregister a tag from a unit frame.
|
||||
|
||||
* self - the unit frame from which to unregister the tag
|
||||
* fs - the font string holding the tag (FontString)
|
||||
--]]
|
||||
local function Untag(self, fs)
|
||||
if(not fs or not self.__tags) then return end
|
||||
|
||||
unregisterEvents(fs)
|
||||
for _, timers in next, eventlessUnits do
|
||||
for i, fontstr in next, timers do
|
||||
if(fs == fontstr) then
|
||||
tremove(timers, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
fs.UpdateTag = nil
|
||||
|
||||
taggedFS[fs] = nil
|
||||
self.__tags[fs] = nil
|
||||
end
|
||||
|
||||
oUF.Tags = {
|
||||
Methods = tags,
|
||||
Events = tagEvents,
|
||||
SharedEvents = unitlessEvents,
|
||||
OnUpdateThrottle = onUpdateDelay, -- ElvUI
|
||||
Vars = vars,
|
||||
RefreshMethods = function(self, tag)
|
||||
if(not tag) then return end
|
||||
|
||||
funcPool['[' .. tag .. ']'] = nil
|
||||
|
||||
-- If a tag's name contains magic chars, there's a chance that
|
||||
-- string.match will fail to find the match.
|
||||
tag = '%[' .. tag:gsub('[%^%$%(%)%%%.%*%+%-%?]', '%%%1') .. '%]'
|
||||
for tagstr, func in next, tagPool do
|
||||
if(tagstr:gsub("%[[^%[%]]*>", "["):gsub("<[^%[%]]*%]", "]"):match(tag)) then
|
||||
tagPool[tagstr] = nil
|
||||
|
||||
for fs in next, taggedFS do
|
||||
if(fs.UpdateTag == func) then
|
||||
fs.UpdateTag = getTagFunc(tagstr)
|
||||
|
||||
if(fs:IsVisible()) then
|
||||
fs:UpdateTag()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
RefreshEvents = function(self, tag)
|
||||
if(not tag) then return end
|
||||
|
||||
-- If a tag's name contains magic chars, there's a chance that
|
||||
-- string.match will fail to find the match.
|
||||
tag = '%[' .. tag:gsub('[%^%$%(%)%%%.%*%+%-%?]', '%%%1') .. '%]'
|
||||
for tagstr in next, tagPool do
|
||||
if(tagstr:gsub("%[[^%[%]]*>", "["):gsub("<[^%[%]]*%]", "]"):match(tag)) then
|
||||
for fs, ts in next, taggedFS do
|
||||
if(ts == tagstr) then
|
||||
unregisterEvents(fs)
|
||||
registerEvents(fs, tagstr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
oUF:RegisterMetaFunction('Tag', Tag)
|
||||
oUF:RegisterMetaFunction('Untag', Untag)
|
||||
oUF:RegisterMetaFunction('UpdateTags', Update)
|
||||
132
Libraries/oUF/elements/threatindicator.lua
Normal file
132
Libraries/oUF/elements/threatindicator.lua
Normal file
@@ -0,0 +1,132 @@
|
||||
--[[
|
||||
# Element: Threat Indicator
|
||||
|
||||
Handles the visibility and updating of an indicator based on the unit's current threat level.
|
||||
|
||||
## Widget
|
||||
|
||||
ThreatIndicator - A `Texture` used to display the current threat level.
|
||||
The element works by changing the texture's vertex color.
|
||||
|
||||
## Notes
|
||||
|
||||
A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
|
||||
|
||||
## Options
|
||||
|
||||
.feedbackUnit - The unit whose threat situation is being requested. If defined, it'll be passed as the first argument to
|
||||
[UnitThreatSituation](https://wow.gamepedia.com/API_UnitThreatSituation).
|
||||
|
||||
## Examples
|
||||
|
||||
-- Position and size
|
||||
local ThreatIndicator = self:CreateTexture(nil, 'OVERLAY')
|
||||
ThreatIndicator:SetSize(16, 16)
|
||||
ThreatIndicator:SetPoint('TOPRIGHT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.ThreatIndicator = ThreatIndicator
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local unitExists = Private.unitExists
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(unit ~= self.unit) then return end
|
||||
|
||||
local element = self.ThreatIndicator
|
||||
--[[ Callback: ThreatIndicator:PreUpdate(unit)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the ThreatIndicator element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
--]]
|
||||
if(element.PreUpdate) then element:PreUpdate(unit) end
|
||||
|
||||
local feedbackUnit = element.feedbackUnit
|
||||
unit = unit or self.unit
|
||||
|
||||
local status
|
||||
-- BUG: Non-existent '*target' or '*pet' units cause UnitThreatSituation() errors
|
||||
if(unitExists(unit)) then
|
||||
if(feedbackUnit and feedbackUnit ~= unit and unitExists(feedbackUnit)) then
|
||||
status = UnitThreatSituation(feedbackUnit, unit)
|
||||
else
|
||||
status = UnitThreatSituation(unit)
|
||||
end
|
||||
end
|
||||
|
||||
local r, g, b
|
||||
if(status and status > 0) then
|
||||
r, g, b = unpack(self.colors.threat[status])
|
||||
|
||||
if(element.SetVertexColor) then
|
||||
element:SetVertexColor(r, g, b)
|
||||
end
|
||||
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
--[[ Callback: ThreatIndicator:PostUpdate(unit, status, r, g, b)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the ThreatIndicator element
|
||||
* unit - the unit for which the update has been triggered (string)
|
||||
* status - the unit's threat status (see [UnitThreatSituation](http://wowprogramming.com/docs/api/UnitThreatSituation.html))
|
||||
* r - the red color component based on the unit's threat status (number?)[0-1]
|
||||
* g - the green color component based on the unit's threat status (number?)[0-1]
|
||||
* b - the blue color component based on the unit's threat status (number?)[0-1]
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(unit, status, r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: ThreatIndicator.Override(self, event, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.ThreatIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.ThreatIndicator
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_THREAT_SITUATION_UPDATE', Path)
|
||||
self:RegisterEvent('UNIT_THREAT_LIST_UPDATE', Path)
|
||||
|
||||
if(element:IsObjectType('Texture') and not element:GetTexture()) then
|
||||
element:SetTexture([[Interface\RAIDFRAME\UI-RaidFrame-Threat]])
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.ThreatIndicator
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('UNIT_THREAT_SITUATION_UPDATE', Path)
|
||||
self:UnregisterEvent('UNIT_THREAT_LIST_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('ThreatIndicator', Path, Enable, Disable)
|
||||
190
Libraries/oUF/elements/totems.lua
Normal file
190
Libraries/oUF/elements/totems.lua
Normal file
@@ -0,0 +1,190 @@
|
||||
--[[
|
||||
# Element: Totem Indicator
|
||||
|
||||
Handles the updating and visibility of totems.
|
||||
|
||||
## Widget
|
||||
|
||||
Totems - A `table` to hold sub-widgets.
|
||||
|
||||
## Sub-Widgets
|
||||
|
||||
Totem - Any UI widget.
|
||||
|
||||
## Sub-Widget Options
|
||||
|
||||
.Icon - A `Texture` representing the totem icon.
|
||||
.Cooldown - A `Cooldown` representing the duration of the totem.
|
||||
|
||||
## Notes
|
||||
|
||||
OnEnter and OnLeave script handlers will be set to display a Tooltip if the `Totem` widget is mouse enabled.
|
||||
|
||||
## Examples
|
||||
|
||||
local Totems = {}
|
||||
for index = 1, 5 do
|
||||
-- Position and size of the totem indicator
|
||||
local Totem = CreateFrame('Button', nil, self)
|
||||
Totem:SetSize(40, 40)
|
||||
Totem:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', index * Totem:GetWidth(), 0)
|
||||
|
||||
local Icon = Totem:CreateTexture(nil, 'OVERLAY')
|
||||
Icon:SetAllPoints()
|
||||
|
||||
local Cooldown = CreateFrame('Cooldown', nil, Totem, 'CooldownFrameTemplate')
|
||||
Cooldown:SetAllPoints()
|
||||
|
||||
Totem.Icon = Icon
|
||||
Totem.Cooldown = Cooldown
|
||||
|
||||
Totems[index] = Totem
|
||||
end
|
||||
|
||||
-- Register with oUF
|
||||
self.Totems = Totems
|
||||
--]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local GameTooltip = GameTooltip
|
||||
|
||||
local function UpdateTooltip(self)
|
||||
if GameTooltip:IsForbidden() then return end
|
||||
|
||||
GameTooltip:SetTotem(self:GetID())
|
||||
end
|
||||
|
||||
local function OnEnter(self)
|
||||
if GameTooltip:IsForbidden() or not self:IsVisible() then return end
|
||||
|
||||
GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT')
|
||||
self:UpdateTooltip()
|
||||
end
|
||||
|
||||
local function OnLeave()
|
||||
if GameTooltip:IsForbidden() then return end
|
||||
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
local function UpdateTotem(self, event, slot)
|
||||
local element = self.Totems
|
||||
if(slot > #element) then return end
|
||||
|
||||
--[[ Callback: Totems:PreUpdate(slot)
|
||||
Called before the element has been updated.
|
||||
|
||||
* self - the Totems element
|
||||
* slot - the slot of the totem to be updated (number)
|
||||
--]]
|
||||
if(element.PreUpdate) then element:PreUpdate(slot) end
|
||||
|
||||
local totem = element[slot]
|
||||
local haveTotem, name, start, duration, icon = GetTotemInfo(slot)
|
||||
if(haveTotem and duration > 0) then
|
||||
if(totem.Icon) then
|
||||
totem.Icon:SetTexture(icon)
|
||||
end
|
||||
|
||||
if(totem.Cooldown) then
|
||||
totem.Cooldown:SetCooldown(start, duration)
|
||||
end
|
||||
|
||||
totem:Show()
|
||||
else
|
||||
totem:Hide()
|
||||
end
|
||||
|
||||
--[[ Callback: Totems:PostUpdate(slot, haveTotem, name, start, duration, icon)
|
||||
Called after the element has been updated.
|
||||
|
||||
* self - the Totems element
|
||||
* slot - the slot of the updated totem (number)
|
||||
* haveTotem - indicates if a totem is present in the given slot (boolean)
|
||||
* name - the name of the totem (string)
|
||||
* start - the value of `GetTime()` when the totem was created (number)
|
||||
* duration - the total duration for which the totem should last (number)
|
||||
* icon - the totem's icon (Texture)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(slot, haveTotem, name, start, duration, icon)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
--[[ Override: Totem.Override(self, event, ...)
|
||||
Used to completely override the internal update function.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* ... - the arguments accompanying the event
|
||||
--]]
|
||||
return (self.Totems.Override or UpdateTotem) (self, ...)
|
||||
end
|
||||
|
||||
local function Update(self, event)
|
||||
for i = 1, #self.Totems do
|
||||
Path(self, event, i)
|
||||
end
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Update(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.Totems
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
for i = 1, #element do
|
||||
local totem = element[i]
|
||||
|
||||
totem:SetID(i)
|
||||
|
||||
if(totem:IsMouseEnabled()) then
|
||||
totem:SetScript('OnEnter', OnEnter)
|
||||
totem:SetScript('OnLeave', OnLeave)
|
||||
|
||||
--[[ Override: Totems[slot]:UpdateTooltip()
|
||||
Used to populate the tooltip when the totem is hovered.
|
||||
|
||||
* self - the widget at the given slot index
|
||||
--]]
|
||||
if(not totem.UpdateTooltip) then
|
||||
totem.UpdateTooltip = UpdateTooltip
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:RegisterEvent('PLAYER_TOTEM_UPDATE', Path, true)
|
||||
|
||||
TotemFrame:UnregisterEvent('PLAYER_TOTEM_UPDATE')
|
||||
TotemFrame:UnregisterEvent('PLAYER_ENTERING_WORLD')
|
||||
TotemFrame:UnregisterEvent('UPDATE_SHAPESHIFT_FORM')
|
||||
TotemFrame:UnregisterEvent('PLAYER_TALENT_UPDATE')
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.Totems
|
||||
if(element) then
|
||||
for i = 1, #element do
|
||||
element[i]:Hide()
|
||||
end
|
||||
|
||||
TotemFrame:RegisterEvent('PLAYER_TOTEM_UPDATE')
|
||||
TotemFrame:RegisterEvent('PLAYER_ENTERING_WORLD')
|
||||
TotemFrame:RegisterEvent('UPDATE_SHAPESHIFT_FORM')
|
||||
TotemFrame:RegisterEvent('PLAYER_TALENT_UPDATE')
|
||||
|
||||
self:UnregisterEvent('PLAYER_TOTEM_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Totems', Update, Enable, Disable)
|
||||
187
Libraries/oUF/events.lua
Normal file
187
Libraries/oUF/events.lua
Normal file
@@ -0,0 +1,187 @@
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local argcheck = Private.argcheck
|
||||
local error = Private.error
|
||||
local validateUnit = Private.validateUnit
|
||||
local frame_metatable = Private.frame_metatable
|
||||
|
||||
-- Original event methods
|
||||
local registerEvent = frame_metatable.__index.RegisterEvent
|
||||
local registerUnitEvent = frame_metatable.__index.RegisterUnitEvent
|
||||
local unregisterEvent = frame_metatable.__index.UnregisterEvent
|
||||
local isEventRegistered = frame_metatable.__index.IsEventRegistered
|
||||
|
||||
-- to update unit frames correctly, some events need to be registered for
|
||||
-- a specific combination of primary and secondary units
|
||||
local secondaryUnits = {
|
||||
UNIT_ENTERED_VEHICLE = {
|
||||
pet = 'player',
|
||||
},
|
||||
UNIT_EXITED_VEHICLE = {
|
||||
pet = 'player',
|
||||
},
|
||||
UNIT_PET = {
|
||||
pet = 'player',
|
||||
},
|
||||
}
|
||||
|
||||
function Private.UpdateUnits(frame, unit, realUnit)
|
||||
if(unit == realUnit) then
|
||||
realUnit = nil
|
||||
end
|
||||
|
||||
if(frame.unit ~= unit or frame.realUnit ~= realUnit) then
|
||||
-- don't let invalid units in, otherwise unit events will end up being
|
||||
-- registered as unitless
|
||||
if(frame.unitEvents and validateUnit(unit)) then
|
||||
local resetRealUnit = false
|
||||
|
||||
for event in next, frame.unitEvents do
|
||||
if(not realUnit and secondaryUnits[event]) then
|
||||
realUnit = secondaryUnits[event][unit]
|
||||
resetRealUnit = true
|
||||
end
|
||||
|
||||
local registered, unit1, unit2 = isEventRegistered(frame, event)
|
||||
-- we don't want to re-register unitless/shared events in case
|
||||
-- someone added them by hand to the unitEvents table
|
||||
if(not registered or unit1 and (unit1 ~= unit or unit2 ~= realUnit)) then
|
||||
-- BUG: passing explicit nil units to RegisterUnitEvent
|
||||
-- makes it silently fall back to RegisterEvent, using ''
|
||||
-- instead of explicit nils doesn't cause this behaviour
|
||||
registerUnitEvent(frame, event, unit, realUnit or '')
|
||||
end
|
||||
|
||||
if(resetRealUnit) then
|
||||
realUnit = nil
|
||||
resetRealUnit = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
frame.unit = unit
|
||||
frame.realUnit = realUnit
|
||||
frame.id = unit:match('^.-(%d+)')
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function onEvent(self, event, ...)
|
||||
if(self:IsVisible()) then
|
||||
return self[event](self, event, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local event_metatable = {
|
||||
__call = function(funcs, self, ...)
|
||||
for _, func in next, funcs do
|
||||
func(self, ...)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
--[[ Events: frame:RegisterEvent(event, func, unitless)
|
||||
Used to register a frame for a game event and add an event handler. OnUpdate polled frames are prevented from
|
||||
registering events.
|
||||
|
||||
* self - frame that will be registered for the given event.
|
||||
* event - name of the event to register (string)
|
||||
* func - a function that will be executed when the event fires. Multiple functions can be added for the same frame
|
||||
and event (function)
|
||||
* unitless - indicates that the event does not fire for a specific unit, so the event arguments won't be
|
||||
matched to the frame unit(s). Obligatory for unitless event (boolean)
|
||||
--]]
|
||||
function frame_metatable.__index:RegisterEvent(event, func, unitless)
|
||||
-- Block OnUpdate polled frames from registering events except for
|
||||
-- UNIT_PORTRAIT_UPDATE and UNIT_MODEL_CHANGED which are used for
|
||||
-- portrait updates.
|
||||
if(self.__eventless and event ~= 'UNIT_PORTRAIT_UPDATE' and event ~= 'UNIT_MODEL_CHANGED') then return end
|
||||
|
||||
argcheck(event, 2, 'string')
|
||||
argcheck(func, 3, 'function')
|
||||
|
||||
local curev = self[event]
|
||||
local kind = type(curev)
|
||||
if(curev) then
|
||||
if(kind == 'function' and curev ~= func) then
|
||||
self[event] = setmetatable({curev, func}, event_metatable)
|
||||
elseif(kind == 'table') then
|
||||
for _, infunc in next, curev do
|
||||
if(infunc == func) then return end
|
||||
end
|
||||
|
||||
table.insert(curev, func)
|
||||
end
|
||||
|
||||
if(unitless or self.__eventless) then
|
||||
-- re-register the event in case we have mixed registration
|
||||
registerEvent(self, event)
|
||||
if(self.unitEvents) then
|
||||
self.unitEvents[event] = nil
|
||||
end
|
||||
end
|
||||
else
|
||||
self[event] = func
|
||||
|
||||
if(not self:GetScript('OnEvent')) then
|
||||
self:SetScript('OnEvent', onEvent)
|
||||
end
|
||||
|
||||
if(unitless or self.__eventless) then
|
||||
registerEvent(self, event)
|
||||
else
|
||||
self.unitEvents = self.unitEvents or {}
|
||||
self.unitEvents[event] = true
|
||||
-- UpdateUnits will take care of unit event registration for header
|
||||
-- units in case we don't have a valid unit yet
|
||||
local unit1, unit2 = self.unit
|
||||
if(unit1 and validateUnit(unit1)) then
|
||||
if(secondaryUnits[event]) then
|
||||
unit2 = secondaryUnits[event][unit1]
|
||||
end
|
||||
|
||||
registerUnitEvent(self, event, unit1, unit2 or '')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Events: frame:UnregisterEvent(event, func)
|
||||
Used to remove a function from the event handler list for a game event.
|
||||
|
||||
* self - the frame registered for the event
|
||||
* event - name of the registered event (string)
|
||||
* func - function to be removed from the list of event handlers. If this is the only handler for the given event, then
|
||||
the frame will be unregistered for the event (function)
|
||||
--]]
|
||||
function frame_metatable.__index:UnregisterEvent(event, func)
|
||||
argcheck(event, 2, 'string')
|
||||
|
||||
local cleanUp = false
|
||||
local curev = self[event]
|
||||
if(type(curev) == 'table' and func) then
|
||||
for k, infunc in next, curev do
|
||||
if(infunc == func) then
|
||||
curev[k] = nil
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if(not next(curev)) then
|
||||
cleanUp = true
|
||||
end
|
||||
end
|
||||
|
||||
if(cleanUp or curev == func) then
|
||||
self[event] = nil
|
||||
if(self.unitEvents) then
|
||||
self.unitEvents[event] = nil
|
||||
end
|
||||
|
||||
unregisterEvent(self, event)
|
||||
end
|
||||
end
|
||||
71
Libraries/oUF/factory.lua
Normal file
71
Libraries/oUF/factory.lua
Normal file
@@ -0,0 +1,71 @@
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local argcheck = Private.argcheck
|
||||
|
||||
local queue = {}
|
||||
local factory = CreateFrame('Frame')
|
||||
factory:SetScript('OnEvent', function(self, event, ...)
|
||||
return self[event](self, event, ...)
|
||||
end)
|
||||
|
||||
factory:RegisterEvent('PLAYER_LOGIN')
|
||||
factory.active = true
|
||||
|
||||
function factory:PLAYER_LOGIN()
|
||||
if(not self.active) then return end
|
||||
|
||||
for _, func in next, queue do
|
||||
func(oUF)
|
||||
end
|
||||
|
||||
-- Avoid creating dupes.
|
||||
wipe(queue)
|
||||
end
|
||||
|
||||
--[[ Factory: oUF:Factory(func)
|
||||
Used to call a function directly if the current character is logged in and the factory is active. Else the function is
|
||||
queued up to be executed at a later time (upon PLAYER_LOGIN by default).
|
||||
|
||||
* self - the global oUF object
|
||||
* func - function to be executed or delayed (function)
|
||||
--]]
|
||||
function oUF:Factory(func)
|
||||
argcheck(func, 2, 'function')
|
||||
|
||||
-- Call the function directly if we're active and logged in.
|
||||
if(IsLoggedIn() and factory.active) then
|
||||
return func(self)
|
||||
else
|
||||
table.insert(queue, func)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Factory: oUF:EnableFactory()
|
||||
Used to enable the factory.
|
||||
|
||||
* self - the global oUF object
|
||||
--]]
|
||||
function oUF:EnableFactory()
|
||||
factory.active = true
|
||||
end
|
||||
|
||||
--[[ Factory: oUF:DisableFactory()
|
||||
Used to disable the factory.
|
||||
|
||||
* self - the global oUF object
|
||||
--]]
|
||||
function oUF:DisableFactory()
|
||||
factory.active = nil
|
||||
end
|
||||
|
||||
--[[ Factory: oUF:RunFactoryQueue()
|
||||
Used to try to execute queued up functions. The current player must be logged in and the factory must be active for
|
||||
this to succeed.
|
||||
|
||||
* self - the global oUF object
|
||||
--]]
|
||||
function oUF:RunFactoryQueue()
|
||||
factory:PLAYER_LOGIN()
|
||||
end
|
||||
4
Libraries/oUF/finalize.lua
Normal file
4
Libraries/oUF/finalize.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
local parent, ns = ...
|
||||
|
||||
-- It's named Private for a reason!
|
||||
ns.oUF.Private = nil
|
||||
6
Libraries/oUF/init.lua
Normal file
6
Libraries/oUF/init.lua
Normal file
@@ -0,0 +1,6 @@
|
||||
local parent, ns = ...
|
||||
ns.oUF = {}
|
||||
ns.oUF.Private = {}
|
||||
|
||||
ns.oUF.isClassic = select(4, GetBuildInfo()) < 20000
|
||||
ns.oUF.isRetail = not ns.oUF.isClassic
|
||||
12
Libraries/oUF/oUF.toc
Normal file
12
Libraries/oUF/oUF.toc
Normal file
@@ -0,0 +1,12 @@
|
||||
## Interface: 90001
|
||||
## Title: oUF
|
||||
## Author: Haste, lightspark, p3lim, Rainrider
|
||||
## Version: @project-version@
|
||||
## Notes: Unit frame framework. Does nothing by itself.
|
||||
## OptionalDeps: Clique
|
||||
## X-oUF: oUF
|
||||
|
||||
## X-Curse-Project-ID: 21187
|
||||
## X-WoWI-ID: 9994
|
||||
|
||||
oUF.xml
|
||||
87
Libraries/oUF/oUF.xml
Normal file
87
Libraries/oUF/oUF.xml
Normal file
@@ -0,0 +1,87 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<Script file="init.lua"/>
|
||||
<Script file="private.lua"/>
|
||||
<Script file="ouf.lua"/>
|
||||
<Script file="events.lua"/>
|
||||
<Script file="factory.lua"/>
|
||||
<Script file="blizzard.lua"/>
|
||||
<Script file="units.lua"/>
|
||||
<Script file="colors.lua"/>
|
||||
|
||||
<Script file="elements\additionalpower.lua"/>
|
||||
<Script file="elements\alternativepower.lua"/>
|
||||
<Script file="elements\assistantindicator.lua"/>
|
||||
<Script file="elements\auras.lua"/>
|
||||
<Script file="elements\castbar.lua"/>
|
||||
<Script file="elements\classpower.lua"/>
|
||||
<Script file="elements\combatindicator.lua"/>
|
||||
<Script file="elements\grouproleindicator.lua"/>
|
||||
<Script file="elements\health.lua"/>
|
||||
<Script file="elements\healthprediction.lua"/>
|
||||
<Script file="elements\leaderindicator.lua"/>
|
||||
<Script file="elements\partyindicator.lua"/>
|
||||
<Script file="elements\phaseindicator.lua"/>
|
||||
<Script file="elements\portrait.lua"/>
|
||||
<Script file="elements\power.lua"/>
|
||||
<Script file="elements\powerprediction.lua"/>
|
||||
<Script file="elements\pvpclassificationindicator.lua"/>
|
||||
<Script file="elements\pvpindicator.lua"/>
|
||||
<Script file="elements\questindicator.lua"/>
|
||||
<Script file="elements\raidroleindicator.lua"/>
|
||||
<Script file="elements\raidtargetindicator.lua"/>
|
||||
<Script file="elements\range.lua"/>
|
||||
<Script file="elements\readycheckindicator.lua"/>
|
||||
<Script file="elements\restingindicator.lua"/>
|
||||
<Script file="elements\resurrectindicator.lua"/>
|
||||
<Script file="elements\runes.lua"/>
|
||||
<Script file="elements\stagger.lua"/>
|
||||
<Script file="elements\summonindicator.lua"/>
|
||||
<Script file="elements\tags.lua"/>
|
||||
<Script file="elements\threatindicator.lua"/>
|
||||
<Script file="elements\totems.lua"/>
|
||||
|
||||
<Script file="finalize.lua"/>
|
||||
|
||||
<!--
|
||||
Sub-object as a child of the parent unit frame:
|
||||
<Button name="oUF_HeaderTargetTemplate" inherits="SecureUnitButtonTemplate" virtual="true">
|
||||
<Frames>
|
||||
<Button name="$parentTarget" inherits="SecureUnitButtonTemplate">
|
||||
<Attributes>
|
||||
<Attribute name="unitsuffix" type="string" value="target"/>
|
||||
<Attribute name="useparent-unit" type="boolean" value="true"/>
|
||||
</Attributes>
|
||||
</Button>
|
||||
</Frames>
|
||||
</Button>
|
||||
|
||||
Separate unit template example:
|
||||
<Button name="oUF_HeaderSeparateSubOjectsTemplate" inherits="SecureUnitButtonTemplate" virtual="true">
|
||||
<Attributes>
|
||||
<Attribute name="oUF-onlyProcessChildren" type="boolean" value="true"/>
|
||||
</Attributes>
|
||||
|
||||
<Frames>
|
||||
<Button name="$parentUnit" inherits="SecureUnitButtonTemplate">
|
||||
<Attributes>
|
||||
<Attribute name="useparent-unit" type="boolean" value="true"/>
|
||||
</Attributes>
|
||||
</Button>
|
||||
|
||||
<Button name="$parentPet" inherits="SecureUnitButtonTemplate">
|
||||
<Attributes>
|
||||
<Attribute name="unitsuffix" type="string" value="pet"/>
|
||||
<Attribute name="useparent-unit" type="boolean" value="true"/>
|
||||
</Attributes>
|
||||
</Button>
|
||||
|
||||
<Button name="$parentTarget" inherits="SecureUnitButtonTemplate">
|
||||
<Attributes>
|
||||
<Attribute name="unitsuffix" type="string" value="target"/>
|
||||
<Attribute name="useparent-unit" type="boolean" value="true"/>
|
||||
</Attributes>
|
||||
</Button>
|
||||
</Frames>
|
||||
</Button>
|
||||
-->
|
||||
</Ui>
|
||||
897
Libraries/oUF/ouf.lua
Normal file
897
Libraries/oUF/ouf.lua
Normal file
@@ -0,0 +1,897 @@
|
||||
local parent, ns = ...
|
||||
local global = GetAddOnMetadata(parent, 'X-oUF')
|
||||
local _VERSION = '@project-version@'
|
||||
if(_VERSION:find('project%-version')) then
|
||||
_VERSION = 'devel'
|
||||
end
|
||||
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local argcheck = Private.argcheck
|
||||
local error = Private.error
|
||||
local print = Private.print
|
||||
local unitExists = Private.unitExists
|
||||
|
||||
local styles, style = {}
|
||||
local callback, objects, headers = {}, {}, {}
|
||||
|
||||
local elements = {}
|
||||
local activeElements = {}
|
||||
|
||||
local PetBattleFrameHider = CreateFrame('Frame', (global or parent) .. '_PetBattleFrameHider', UIParent, 'SecureHandlerStateTemplate')
|
||||
PetBattleFrameHider:SetAllPoints()
|
||||
PetBattleFrameHider:SetFrameStrata('LOW')
|
||||
RegisterStateDriver(PetBattleFrameHider, 'visibility', '[petbattle] hide; show')
|
||||
|
||||
-- updating of "invalid" units, function edited by ElvUI
|
||||
local function enableTargetUpdate(object)
|
||||
object.onUpdateFrequency = object.onUpdateFrequency or 0.1
|
||||
object.__eventless = true
|
||||
|
||||
object:SetScript('OnUpdate', function(self, elapsed)
|
||||
if not self.unit then
|
||||
return
|
||||
elseif self.elapsed and self.elapsed > self.onUpdateFrequency then
|
||||
self:UpdateAllElements('OnUpdate')
|
||||
|
||||
self.elapsed = 0
|
||||
else
|
||||
self.elapsed = (self.elapsed or 0) + elapsed
|
||||
end
|
||||
end)
|
||||
end
|
||||
Private.enableTargetUpdate = enableTargetUpdate
|
||||
|
||||
local function updateActiveUnit(self, event, unit)
|
||||
-- Calculate units to work with
|
||||
local realUnit, modUnit = SecureButton_GetUnit(self), SecureButton_GetModifiedUnit(self)
|
||||
|
||||
-- _GetUnit() doesn't rewrite playerpet -> pet like _GetModifiedUnit does.
|
||||
if(realUnit == 'playerpet') then
|
||||
realUnit = 'pet'
|
||||
elseif(realUnit == 'playertarget') then
|
||||
realUnit = 'target'
|
||||
end
|
||||
|
||||
if(modUnit == 'pet' and realUnit ~= 'pet') then
|
||||
modUnit = 'vehicle'
|
||||
end
|
||||
|
||||
if(not unitExists(modUnit)) then return end
|
||||
|
||||
-- Change the active unit and run a full update.
|
||||
if(Private.UpdateUnits(self, modUnit, realUnit)) then
|
||||
self:UpdateAllElements('RefreshUnit')
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function iterateChildren(...)
|
||||
for i = 1, select('#', ...) do
|
||||
local obj = select(i, ...)
|
||||
|
||||
if(type(obj) == 'table' and obj.isChild) then
|
||||
updateActiveUnit(obj, 'iterateChildren')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function onAttributeChanged(self, name, value)
|
||||
if(name == 'unit' and value) then
|
||||
if(self.hasChildren) then
|
||||
iterateChildren(self:GetChildren())
|
||||
end
|
||||
|
||||
if(not self:GetAttribute('oUF-onlyProcessChildren')) then
|
||||
updateActiveUnit(self, 'OnAttributeChanged')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local frame_metatable = {
|
||||
__index = CreateFrame('Button')
|
||||
}
|
||||
Private.frame_metatable = frame_metatable
|
||||
|
||||
for k, v in next, {
|
||||
--[[ frame:EnableElement(name, unit)
|
||||
Used to activate an element for the given unit frame.
|
||||
|
||||
* self - unit frame for which the element should be enabled
|
||||
* name - name of the element to be enabled (string)
|
||||
* unit - unit to be passed to the element's Enable function. Defaults to the frame's unit (string?)
|
||||
--]]
|
||||
EnableElement = function(self, name, unit)
|
||||
argcheck(name, 2, 'string')
|
||||
argcheck(unit, 3, 'string', 'nil')
|
||||
|
||||
local element = elements[name]
|
||||
if(not element or self:IsElementEnabled(name)) then return end
|
||||
|
||||
if(element.enable(self, unit or self.unit)) then
|
||||
activeElements[self][name] = true
|
||||
|
||||
if(element.update) then
|
||||
table.insert(self.__elements, element.update)
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
--[[ frame:DisableElement(name)
|
||||
Used to deactivate an element for the given unit frame.
|
||||
|
||||
* self - unit frame for which the element should be disabled
|
||||
* name - name of the element to be disabled (string)
|
||||
--]]
|
||||
DisableElement = function(self, name)
|
||||
argcheck(name, 2, 'string')
|
||||
|
||||
local enabled = self:IsElementEnabled(name)
|
||||
if(not enabled) then return end
|
||||
|
||||
local update = elements[name].update
|
||||
for k, func in next, self.__elements do
|
||||
if(func == update) then
|
||||
table.remove(self.__elements, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
activeElements[self][name] = nil
|
||||
|
||||
return elements[name].disable(self)
|
||||
end,
|
||||
|
||||
--[[ frame:IsElementEnabled(name)
|
||||
Used to check if an element is enabled on the given frame.
|
||||
|
||||
* self - unit frame
|
||||
* name - name of the element (string)
|
||||
--]]
|
||||
IsElementEnabled = function(self, name)
|
||||
argcheck(name, 2, 'string')
|
||||
|
||||
local element = elements[name]
|
||||
if(not element) then return end
|
||||
|
||||
local active = activeElements[self]
|
||||
return active and active[name]
|
||||
end,
|
||||
|
||||
--[[ frame:Enable(asState)
|
||||
Used to toggle the visibility of a unit frame based on the existence of its unit. This is a reference to
|
||||
`RegisterUnitWatch`.
|
||||
|
||||
* self - unit frame
|
||||
* asState - if true, the frame's "state-unitexists" attribute will be set to a boolean value denoting whether the
|
||||
unit exists; if false, the frame will be shown if its unit exists, and hidden if it does not (boolean)
|
||||
--]]
|
||||
Enable = RegisterUnitWatch,
|
||||
--[[ frame:Disable()
|
||||
Used to UnregisterUnitWatch for the given frame and hide it.
|
||||
|
||||
* self - unit frame
|
||||
--]]
|
||||
Disable = function(self)
|
||||
UnregisterUnitWatch(self)
|
||||
self:Hide()
|
||||
end,
|
||||
--[[ frame:IsEnabled()
|
||||
Used to check if a unit frame is registered with the unit existence monitor. This is a reference to
|
||||
`UnitWatchRegistered`.
|
||||
|
||||
* self - unit frame
|
||||
--]]
|
||||
IsEnabled = UnitWatchRegistered,
|
||||
--[[ frame:UpdateAllElements(event)
|
||||
Used to update all enabled elements on the given frame.
|
||||
|
||||
* self - unit frame
|
||||
* event - event name to pass to the elements' update functions (string)
|
||||
--]]
|
||||
UpdateAllElements = function(self, event)
|
||||
local unit = self.unit
|
||||
if(not unitExists(unit)) then return end
|
||||
|
||||
assert(type(event) == 'string', "Invalid argument 'event' in UpdateAllElements.")
|
||||
|
||||
if(self.PreUpdate) then
|
||||
--[[ Callback: frame:PreUpdate(event)
|
||||
Fired before the frame is updated.
|
||||
|
||||
* self - the unit frame
|
||||
* event - the event triggering the update (string)
|
||||
--]]
|
||||
self:PreUpdate(event)
|
||||
end
|
||||
|
||||
for _, func in next, self.__elements do
|
||||
func(self, event, unit)
|
||||
end
|
||||
|
||||
if(self.PostUpdate) then
|
||||
--[[ Callback: frame:PostUpdate(event)
|
||||
Fired after the frame is updated.
|
||||
|
||||
* self - the unit frame
|
||||
* event - the event triggering the update (string)
|
||||
--]]
|
||||
self:PostUpdate(event)
|
||||
end
|
||||
end,
|
||||
} do
|
||||
frame_metatable.__index[k] = v
|
||||
end
|
||||
|
||||
local function onShow(self)
|
||||
if(not updateActiveUnit(self, 'OnShow')) then
|
||||
return self:UpdateAllElements('OnShow')
|
||||
end
|
||||
end
|
||||
|
||||
local function updatePet(self, event, unit)
|
||||
local petUnit
|
||||
if(unit == 'target') then
|
||||
return
|
||||
elseif(unit == 'player') then
|
||||
petUnit = 'pet'
|
||||
else
|
||||
-- Convert raid26 -> raidpet26
|
||||
petUnit = unit:gsub('^(%a+)(%d+)', '%1pet%2')
|
||||
end
|
||||
|
||||
if(self.unit ~= petUnit) then return end
|
||||
if(not updateActiveUnit(self, event)) then
|
||||
return self:UpdateAllElements(event)
|
||||
end
|
||||
end
|
||||
|
||||
local function updateRaid(self, event)
|
||||
local unitGUID = UnitGUID(self.unit)
|
||||
if(unitGUID and unitGUID ~= self.unitGUID) then
|
||||
self.unitGUID = unitGUID
|
||||
|
||||
self:UpdateAllElements(event)
|
||||
end
|
||||
end
|
||||
|
||||
local function initObject(unit, style, styleFunc, header, ...)
|
||||
local num = select('#', ...)
|
||||
for i = 1, num do
|
||||
local object = select(i, ...)
|
||||
local objectUnit = object:GetAttribute('oUF-guessUnit') or unit
|
||||
local suffix = object:GetAttribute('unitsuffix')
|
||||
|
||||
object.__elements = {}
|
||||
object.style = style
|
||||
object = setmetatable(object, frame_metatable)
|
||||
|
||||
-- Expose the frame through oUF.objects.
|
||||
table.insert(objects, object)
|
||||
|
||||
-- We have to force update the frames when PEW fires.
|
||||
object:RegisterEvent('PLAYER_ENTERING_WORLD', object.UpdateAllElements, true)
|
||||
|
||||
-- Handle the case where someone has modified the unitsuffix attribute in
|
||||
-- oUF-initialConfigFunction.
|
||||
if(suffix and not objectUnit:match(suffix)) then
|
||||
objectUnit = objectUnit .. suffix
|
||||
end
|
||||
|
||||
if(not (suffix == 'target' or objectUnit and objectUnit:match('target'))) then
|
||||
object:RegisterEvent('UNIT_ENTERED_VEHICLE', updateActiveUnit)
|
||||
object:RegisterEvent('UNIT_EXITED_VEHICLE', updateActiveUnit)
|
||||
|
||||
-- We don't need to register UNIT_PET for the player unit. We register it
|
||||
-- mainly because UNIT_EXITED_VEHICLE and UNIT_ENTERED_VEHICLE doesn't always
|
||||
-- have pet information when they fire for party and raid units.
|
||||
if(objectUnit ~= 'player') then
|
||||
object:RegisterEvent('UNIT_PET', updatePet)
|
||||
end
|
||||
end
|
||||
|
||||
if(not header) then
|
||||
-- No header means it's a frame created through :Spawn().
|
||||
object:SetAttribute('*type1', 'target')
|
||||
object:SetAttribute('*type2', 'togglemenu')
|
||||
|
||||
-- No need to enable this for *target frames.
|
||||
if(not (unit:match('target') or suffix == 'target')) then
|
||||
object:SetAttribute('toggleForVehicle', true)
|
||||
end
|
||||
|
||||
-- Other boss and target units are handled by :HandleUnit().
|
||||
if(suffix == 'target') then
|
||||
enableTargetUpdate(object)
|
||||
else
|
||||
oUF:HandleUnit(object)
|
||||
end
|
||||
else
|
||||
-- update the frame when its prev unit is replaced with a new one
|
||||
-- updateRaid relies on UnitGUID to detect the unit change
|
||||
object:RegisterEvent('GROUP_ROSTER_UPDATE', updateRaid, true)
|
||||
|
||||
if(num > 1) then
|
||||
if(object:GetParent() == header) then
|
||||
object.hasChildren = true
|
||||
else
|
||||
object.isChild = true
|
||||
end
|
||||
end
|
||||
|
||||
if(suffix == 'target') then
|
||||
enableTargetUpdate(object)
|
||||
end
|
||||
end
|
||||
|
||||
activeElements[object] = {} -- ElvUI: styleFunc on headers break before this is set when they try to enable elements before it's set.
|
||||
|
||||
Private.UpdateUnits(object, objectUnit)
|
||||
|
||||
styleFunc(object, objectUnit, not header)
|
||||
|
||||
object:HookScript('OnAttributeChanged', onAttributeChanged)
|
||||
|
||||
-- NAME_PLATE_UNIT_ADDED fires after the frame is shown, so there's no
|
||||
-- need to call UAE multiple times
|
||||
if(not object.isNamePlate) then
|
||||
object:SetScript('OnShow', onShow)
|
||||
end
|
||||
|
||||
for element in next, elements do
|
||||
object:EnableElement(element, objectUnit)
|
||||
end
|
||||
|
||||
for _, func in next, callback do
|
||||
func(object)
|
||||
end
|
||||
|
||||
-- Make Clique kinda happy
|
||||
if(not object.isNamePlate) then
|
||||
_G.ClickCastFrames = ClickCastFrames or {}
|
||||
ClickCastFrames[object] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function walkObject(object, unit)
|
||||
local parent = object:GetParent()
|
||||
local style = parent.style or style
|
||||
local styleFunc = styles[style]
|
||||
|
||||
local header = parent:GetAttribute('oUF-headerType') and parent
|
||||
|
||||
-- Check if we should leave the main frame blank.
|
||||
if(object:GetAttribute('oUF-onlyProcessChildren')) then
|
||||
object.hasChildren = true
|
||||
object:HookScript('OnAttributeChanged', onAttributeChanged)
|
||||
return initObject(unit, style, styleFunc, header, object:GetChildren())
|
||||
end
|
||||
|
||||
return initObject(unit, style, styleFunc, header, object, object:GetChildren())
|
||||
end
|
||||
|
||||
--[[ oUF:RegisterInitCallback(func)
|
||||
Used to add a function to a table to be executed upon unit frame/header initialization.
|
||||
|
||||
* self - the global oUF object
|
||||
* func - function to be added
|
||||
--]]
|
||||
function oUF:RegisterInitCallback(func)
|
||||
table.insert(callback, func)
|
||||
end
|
||||
|
||||
--[[ oUF:RegisterMetaFunction(name, func)
|
||||
Used to make a (table of) function(s) available to all unit frames.
|
||||
|
||||
* self - the global oUF object
|
||||
* name - unique name of the function (string)
|
||||
* func - function or a table of functions (function or table)
|
||||
--]]
|
||||
function oUF:RegisterMetaFunction(name, func)
|
||||
argcheck(name, 2, 'string')
|
||||
argcheck(func, 3, 'function', 'table')
|
||||
|
||||
if(frame_metatable.__index[name]) then
|
||||
return
|
||||
end
|
||||
|
||||
frame_metatable.__index[name] = func
|
||||
end
|
||||
|
||||
--[[ oUF:RegisterStyle(name, func)
|
||||
Used to register a style with oUF. This will also set the active style if it hasn't been set yet.
|
||||
|
||||
* self - the global oUF object
|
||||
* name - name of the style
|
||||
* func - function(s) defining the style (function or table)
|
||||
--]]
|
||||
function oUF:RegisterStyle(name, func)
|
||||
argcheck(name, 2, 'string')
|
||||
argcheck(func, 3, 'function', 'table')
|
||||
|
||||
if(styles[name]) then return error('Style [%s] already registered.', name) end
|
||||
if(not style) then style = name end
|
||||
|
||||
styles[name] = func
|
||||
end
|
||||
|
||||
--[[ oUF:SetActiveStyle(name)
|
||||
Used to set the active style.
|
||||
|
||||
* self - the global oUF object
|
||||
* name - name of the style (string)
|
||||
--]]
|
||||
function oUF:SetActiveStyle(name)
|
||||
argcheck(name, 2, 'string')
|
||||
if(not styles[name]) then return error('Style [%s] does not exist.', name) end
|
||||
|
||||
style = name
|
||||
end
|
||||
|
||||
--[[ oUF:GetActiveStyle()
|
||||
Used to get the active style.
|
||||
|
||||
* self - the global oUF object
|
||||
--]]
|
||||
function oUF:GetActiveStyle()
|
||||
return style
|
||||
end
|
||||
|
||||
do
|
||||
local function iter(_, n)
|
||||
-- don't expose the style functions.
|
||||
return (next(styles, n))
|
||||
end
|
||||
|
||||
--[[ oUF:IterateStyles()
|
||||
Returns an iterator over all registered styles.
|
||||
|
||||
* self - the global oUF object
|
||||
--]]
|
||||
function oUF.IterateStyles()
|
||||
return iter, nil, nil
|
||||
end
|
||||
end
|
||||
|
||||
local getCondition
|
||||
do
|
||||
local conditions = {
|
||||
raid40 = '[@raid26,exists] show;',
|
||||
raid25 = '[@raid11,exists] show;',
|
||||
raid10 = '[@raid6,exists] show;',
|
||||
raid = '[group:raid] show;',
|
||||
party = '[group:party,nogroup:raid] show;',
|
||||
solo = '[@player,exists,nogroup:party] show;',
|
||||
}
|
||||
|
||||
function getCondition(...)
|
||||
local cond = ''
|
||||
|
||||
for i = 1, select('#', ...) do
|
||||
local short = select(i, ...)
|
||||
|
||||
local condition = conditions[short]
|
||||
if(condition) then
|
||||
cond = cond .. condition
|
||||
end
|
||||
end
|
||||
|
||||
return cond .. 'hide'
|
||||
end
|
||||
end
|
||||
|
||||
local function generateName(unit, ...)
|
||||
local name = 'oUF_' .. style:gsub('^oUF_?', ''):gsub('[^%a%d_]+', '')
|
||||
|
||||
local raid, party, groupFilter, unitsuffix
|
||||
for i = 1, select('#', ...), 2 do
|
||||
local att, val = select(i, ...)
|
||||
if(att == 'oUF-initialConfigFunction') then
|
||||
unitsuffix = val:match('unitsuffix[%p%s]+(%a+)')
|
||||
elseif(att == 'showRaid') then
|
||||
raid = val ~= false and val ~= nil
|
||||
elseif(att == 'showParty') then
|
||||
party = val ~= false and val ~= nil
|
||||
elseif(att == 'groupFilter') then
|
||||
groupFilter = val
|
||||
end
|
||||
end
|
||||
|
||||
local append
|
||||
if(raid) then
|
||||
if(groupFilter) then
|
||||
if(type(groupFilter) == 'number' and groupFilter > 0) then
|
||||
append = 'Raid' .. groupFilter
|
||||
elseif(groupFilter:match('MAINTANK')) then
|
||||
append = 'MainTank'
|
||||
elseif(groupFilter:match('MAINASSIST')) then
|
||||
append = 'MainAssist'
|
||||
else
|
||||
local _, count = groupFilter:gsub(',', '')
|
||||
if(count == 0) then
|
||||
append = 'Raid' .. groupFilter
|
||||
else
|
||||
append = 'Raid'
|
||||
end
|
||||
end
|
||||
else
|
||||
append = 'Raid'
|
||||
end
|
||||
elseif(party) then
|
||||
append = 'Party'
|
||||
elseif(unit) then
|
||||
append = unit:gsub('^%l', string.upper)
|
||||
end
|
||||
|
||||
if(append) then
|
||||
name = name .. append .. (unitsuffix or '')
|
||||
end
|
||||
|
||||
-- Change oUF_LilyRaidRaid into oUF_LilyRaid
|
||||
name = name:gsub('(%u%l+)([%u%l]*)%1', '%1')
|
||||
-- Change oUF_LilyTargettarget into oUF_LilyTargetTarget
|
||||
name = name:gsub('t(arget)', 'T%1')
|
||||
name = name:gsub('p(et)', 'P%1')
|
||||
name = name:gsub('f(ocus)', 'F%1')
|
||||
|
||||
local base = name
|
||||
local i = 2
|
||||
while(_G[name]) do
|
||||
name = base .. i
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
return name
|
||||
end
|
||||
|
||||
do
|
||||
local function styleProxy(self, frame, ...)
|
||||
return walkObject(_G[frame])
|
||||
end
|
||||
|
||||
-- There has to be an easier way to do this.
|
||||
local initialConfigFunction = [[
|
||||
local header = self:GetParent()
|
||||
local frames = table.new()
|
||||
table.insert(frames, self)
|
||||
self:GetChildList(frames)
|
||||
for i = 1, #frames do
|
||||
local frame = frames[i]
|
||||
local unit
|
||||
-- There's no need to do anything on frames with onlyProcessChildren
|
||||
if(not frame:GetAttribute('oUF-onlyProcessChildren')) then
|
||||
RegisterUnitWatch(frame)
|
||||
|
||||
-- Attempt to guess what the header is set to spawn.
|
||||
local groupFilter = header:GetAttribute('groupFilter')
|
||||
|
||||
if(type(groupFilter) == 'string' and groupFilter:match('MAIN[AT]')) then
|
||||
local role = groupFilter:match('MAIN([AT])')
|
||||
if(role == 'T') then
|
||||
unit = 'maintank'
|
||||
else
|
||||
unit = 'mainassist'
|
||||
end
|
||||
elseif(header:GetAttribute('showRaid')) then
|
||||
unit = 'raid'
|
||||
elseif(header:GetAttribute('showParty')) then
|
||||
unit = 'party'
|
||||
end
|
||||
|
||||
local headerType = header:GetAttribute('oUF-headerType')
|
||||
local suffix = frame:GetAttribute('unitsuffix')
|
||||
if(unit and suffix) then
|
||||
if(headerType == 'pet' and suffix == 'target') then
|
||||
unit = unit .. headerType .. suffix
|
||||
else
|
||||
unit = unit .. suffix
|
||||
end
|
||||
elseif(unit and headerType == 'pet') then
|
||||
unit = unit .. headerType
|
||||
end
|
||||
|
||||
frame:SetAttribute('*type1', 'target')
|
||||
frame:SetAttribute('*type2', 'togglemenu')
|
||||
frame:SetAttribute('oUF-guessUnit', unit)
|
||||
end
|
||||
|
||||
local body = header:GetAttribute('oUF-initialConfigFunction')
|
||||
if(body) then
|
||||
frame:Run(body, unit)
|
||||
end
|
||||
end
|
||||
|
||||
header:CallMethod('styleFunction', self:GetName())
|
||||
|
||||
local clique = header:GetFrameRef('clickcast_header')
|
||||
if(clique) then
|
||||
clique:SetAttribute('clickcast_button', self)
|
||||
clique:RunAttribute('clickcast_register')
|
||||
end
|
||||
]]
|
||||
|
||||
--[[ oUF:SpawnHeader(overrideName, template, visibility, ...)
|
||||
Used to create a group header and apply the currently active style to it.
|
||||
|
||||
* self - the global oUF object
|
||||
* overrideName - unique global name to be used for the header. Defaults to an auto-generated name based on the name
|
||||
of the active style and other arguments passed to `:SpawnHeader` (string?)
|
||||
* template - name of a template to be used for creating the header. Defaults to `'SecureGroupHeaderTemplate'`
|
||||
(string?)
|
||||
* visibility - macro conditional(s) which define when to display the header (string).
|
||||
* ... - further argument pairs. Consult [Group Headers](http://wowprogramming.com/docs/secure_template/Group_Headers.html)
|
||||
for possible values.
|
||||
|
||||
In addition to the standard group headers, oUF implements some of its own attributes. These can be supplied by the
|
||||
layout, but are optional.
|
||||
|
||||
* oUF-initialConfigFunction - can contain code that will be securely run at the end of the initial secure
|
||||
configuration (string?)
|
||||
* oUF-onlyProcessChildren - can be used to force headers to only process children (boolean?)
|
||||
--]]
|
||||
function oUF:SpawnHeader(overrideName, template, visibility, ...)
|
||||
if(not style) then return error('Unable to create frame. No styles have been registered.') end
|
||||
|
||||
template = (template or 'SecureGroupHeaderTemplate')
|
||||
|
||||
local isPetHeader = template:match('PetHeader')
|
||||
local name = overrideName or generateName(nil, ...)
|
||||
local header = CreateFrame('Frame', name, PetBattleFrameHider, template)
|
||||
|
||||
header:SetAttribute('template', 'SecureUnitButtonTemplate, SecureHandlerStateTemplate, SecureHandlerEnterLeaveTemplate')
|
||||
for i = 1, select('#', ...), 2 do
|
||||
local att, val = select(i, ...)
|
||||
if(not att) then break end
|
||||
header:SetAttribute(att, val)
|
||||
end
|
||||
|
||||
header.style = style
|
||||
header.styleFunction = styleProxy
|
||||
header.visibility = visibility
|
||||
|
||||
-- Expose the header through oUF.headers.
|
||||
table.insert(headers, header)
|
||||
|
||||
-- We set it here so layouts can't directly override it.
|
||||
header:SetAttribute('initialConfigFunction', initialConfigFunction)
|
||||
header:SetAttribute('_initialAttributeNames', '_onenter,_onleave,refreshUnitChange,_onstate-vehicleui')
|
||||
header:SetAttribute('_initialAttribute-_onenter', [[
|
||||
local snippet = self:GetAttribute('clickcast_onenter')
|
||||
if(snippet) then
|
||||
self:Run(snippet)
|
||||
end
|
||||
]])
|
||||
header:SetAttribute('_initialAttribute-_onleave', [[
|
||||
local snippet = self:GetAttribute('clickcast_onleave')
|
||||
if(snippet) then
|
||||
self:Run(snippet)
|
||||
end
|
||||
]])
|
||||
header:SetAttribute('_initialAttribute-refreshUnitChange', [[
|
||||
local unit = self:GetAttribute('unit')
|
||||
if(unit) then
|
||||
RegisterStateDriver(self, 'vehicleui', '[@' .. unit .. ',unithasvehicleui]vehicle; novehicle')
|
||||
else
|
||||
UnregisterStateDriver(self, 'vehicleui')
|
||||
end
|
||||
]])
|
||||
header:SetAttribute('_initialAttribute-_onstate-vehicleui', [[
|
||||
local unit = self:GetAttribute('unit')
|
||||
if(newstate == 'vehicle' and unit and UnitPlayerOrPetInRaid(unit) and not UnitTargetsVehicleInRaidUI(unit)) then
|
||||
self:SetAttribute('toggleForVehicle', false)
|
||||
else
|
||||
self:SetAttribute('toggleForVehicle', true)
|
||||
end
|
||||
]])
|
||||
header:SetAttribute('oUF-headerType', isPetHeader and 'pet' or 'group')
|
||||
|
||||
if(Clique) then
|
||||
SecureHandlerSetFrameRef(header, 'clickcast_header', Clique.header)
|
||||
end
|
||||
|
||||
if(header:GetAttribute('showParty')) then
|
||||
self:DisableBlizzard('party')
|
||||
end
|
||||
|
||||
if(visibility) then
|
||||
local type, list = string.split(' ', visibility, 2)
|
||||
if(list and type == 'custom') then
|
||||
RegisterAttributeDriver(header, 'state-visibility', list)
|
||||
header.visibility = list
|
||||
else
|
||||
local condition = getCondition(string.split(',', visibility))
|
||||
RegisterAttributeDriver(header, 'state-visibility', condition)
|
||||
header.visibility = condition
|
||||
end
|
||||
end
|
||||
|
||||
return header
|
||||
end
|
||||
end
|
||||
|
||||
--[[ oUF:Spawn(unit, overrideName)
|
||||
Used to create a single unit frame and apply the currently active style to it.
|
||||
|
||||
* self - the global oUF object
|
||||
* unit - the frame's unit (string)
|
||||
* overrideName - unique global name to use for the unit frame. Defaults to an auto-generated name based on the unit
|
||||
(string?)
|
||||
|
||||
oUF implements some of its own attributes. These can be supplied by the layout, but are optional.
|
||||
|
||||
* oUF-enableArenaPrep - can be used to toggle arena prep support. Defaults to true (boolean)
|
||||
--]]
|
||||
function oUF:Spawn(unit, overrideName, overrideTemplate) -- ElvUI adds overrideTemplate
|
||||
argcheck(unit, 2, 'string')
|
||||
if(not style) then return error('Unable to create frame. No styles have been registered.') end
|
||||
|
||||
unit = unit:lower()
|
||||
|
||||
local name = overrideName or generateName(unit)
|
||||
local object = CreateFrame('Button', name, PetBattleFrameHider, overrideTemplate or 'SecureUnitButtonTemplate')
|
||||
Private.UpdateUnits(object, unit)
|
||||
|
||||
self:DisableBlizzard(unit)
|
||||
walkObject(object, unit)
|
||||
|
||||
object:SetAttribute('unit', unit)
|
||||
RegisterUnitWatch(object)
|
||||
|
||||
return object
|
||||
end
|
||||
|
||||
--[[ oUF:SpawnNamePlates(prefix, callback, variables)
|
||||
Used to create nameplates and apply the currently active style to them.
|
||||
|
||||
* self - the global oUF object
|
||||
* prefix - prefix for the global name of the nameplate. Defaults to an auto-generated prefix (string?)
|
||||
* callback - function to be called after a nameplate unit or the player's target has changed. The arguments passed to
|
||||
the callback are the updated nameplate, if any, the event that triggered the update, and the new unit
|
||||
(function?)
|
||||
* variables - list of console variable-value pairs to be set when the player logs in (table?)
|
||||
--]]
|
||||
function oUF:SpawnNamePlates(namePrefix, nameplateCallback, nameplateCVars)
|
||||
argcheck(nameplateCallback, 3, 'function', 'nil')
|
||||
argcheck(nameplateCVars, 4, 'table', 'nil')
|
||||
if(not style) then return error('Unable to create frame. No styles have been registered.') end
|
||||
if(oUF_NamePlateDriver) then return error('oUF nameplate driver has already been initialized.') end
|
||||
|
||||
local style = style
|
||||
local prefix = namePrefix or generateName()
|
||||
|
||||
-- Because there's no way to prevent nameplate settings updates without tainting UI,
|
||||
-- and because forbidden nameplates exist, we have to allow default nameplate
|
||||
-- driver to create, update, and remove Blizz nameplates.
|
||||
-- Disable only not forbidden nameplates.
|
||||
NamePlateDriverFrame:HookScript('OnEvent', function(_, event, unit)
|
||||
if(event == 'NAME_PLATE_UNIT_ADDED' and unit) then
|
||||
self:DisableBlizzard(unit)
|
||||
end
|
||||
end)
|
||||
|
||||
local eventHandler = CreateFrame('Frame', 'oUF_NamePlateDriver')
|
||||
eventHandler:RegisterEvent('NAME_PLATE_UNIT_ADDED')
|
||||
eventHandler:RegisterEvent('NAME_PLATE_UNIT_REMOVED')
|
||||
eventHandler:RegisterEvent('PLAYER_TARGET_CHANGED')
|
||||
eventHandler:RegisterEvent('UNIT_FACTION')
|
||||
|
||||
if(IsLoggedIn()) then
|
||||
if(nameplateCVars) then
|
||||
for cvar, value in next, nameplateCVars do
|
||||
SetCVar(cvar, value)
|
||||
end
|
||||
end
|
||||
else
|
||||
eventHandler:RegisterEvent('PLAYER_LOGIN')
|
||||
end
|
||||
|
||||
eventHandler:SetScript('OnEvent', function(_, event, unit)
|
||||
if(event == 'PLAYER_LOGIN') then
|
||||
if(nameplateCVars) then
|
||||
for cvar, value in next, nameplateCVars do
|
||||
SetCVar(cvar, value)
|
||||
end
|
||||
end
|
||||
elseif(event == 'PLAYER_TARGET_CHANGED') then
|
||||
local nameplate = C_NamePlate.GetNamePlateForUnit('target')
|
||||
if(nameplateCallback) then
|
||||
nameplateCallback(nameplate and nameplate.unitFrame, event, 'target')
|
||||
end
|
||||
|
||||
-- UAE is called after the callback to reduce the number of
|
||||
-- ForceUpdate calls layout devs have to do themselves
|
||||
if(nameplate) then
|
||||
nameplate.unitFrame:UpdateAllElements(event)
|
||||
end
|
||||
elseif(event == 'UNIT_FACTION' and unit) then
|
||||
local nameplate = C_NamePlate.GetNamePlateForUnit(unit)
|
||||
if(not nameplate) then return end
|
||||
|
||||
if(nameplateCallback) then
|
||||
nameplateCallback(nameplate.unitFrame, event, unit)
|
||||
end
|
||||
elseif(event == 'NAME_PLATE_UNIT_ADDED' and unit) then
|
||||
local nameplate = C_NamePlate.GetNamePlateForUnit(unit)
|
||||
if(not nameplate) then return end
|
||||
|
||||
if(not nameplate.unitFrame) then
|
||||
nameplate.style = style
|
||||
|
||||
nameplate.unitFrame = CreateFrame('Button', prefix..nameplate:GetName(), nameplate)
|
||||
nameplate.unitFrame:EnableMouse(false)
|
||||
nameplate.unitFrame.isNamePlate = true
|
||||
|
||||
Private.UpdateUnits(nameplate.unitFrame, unit)
|
||||
|
||||
walkObject(nameplate.unitFrame, unit)
|
||||
else
|
||||
Private.UpdateUnits(nameplate.unitFrame, unit)
|
||||
end
|
||||
|
||||
nameplate.unitFrame:SetAttribute('unit', unit)
|
||||
|
||||
if(nameplateCallback) then
|
||||
nameplateCallback(nameplate.unitFrame, event, unit)
|
||||
end
|
||||
|
||||
-- UAE is called after the callback to reduce the number of
|
||||
-- ForceUpdate calls layout devs have to do themselves
|
||||
nameplate.unitFrame:UpdateAllElements(event)
|
||||
elseif(event == 'NAME_PLATE_UNIT_REMOVED' and unit) then
|
||||
local nameplate = C_NamePlate.GetNamePlateForUnit(unit)
|
||||
if(not nameplate) then return end
|
||||
|
||||
nameplate.unitFrame:SetAttribute('unit', nil)
|
||||
|
||||
if(nameplateCallback) then
|
||||
nameplateCallback(nameplate.unitFrame, event, unit)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--[[ oUF:AddElement(name, update, enable, disable)
|
||||
Used to register an element with oUF.
|
||||
|
||||
* self - the global oUF object
|
||||
* name - unique name of the element (string)
|
||||
* update - used to update the element (function?)
|
||||
* enable - used to enable the element for a given unit frame and unit (function?)
|
||||
* disable - used to disable the element for a given unit frame (function?)
|
||||
--]]
|
||||
function oUF:AddElement(name, update, enable, disable)
|
||||
argcheck(name, 2, 'string')
|
||||
argcheck(update, 3, 'function', 'nil')
|
||||
argcheck(enable, 4, 'function', 'nil')
|
||||
argcheck(disable, 5, 'function', 'nil')
|
||||
|
||||
if(elements[name]) then return error('Element [%s] is already registered.', name) end
|
||||
elements[name] = {
|
||||
update = update;
|
||||
enable = enable;
|
||||
disable = disable;
|
||||
}
|
||||
end
|
||||
|
||||
oUF.version = _VERSION
|
||||
--[[ oUF.objects
|
||||
Array containing all unit frames created by `oUF:Spawn`.
|
||||
--]]
|
||||
oUF.objects = objects
|
||||
--[[ oUF.headers
|
||||
Array containing all group headers created by `oUF:SpawnHeader`.
|
||||
--]]
|
||||
oUF.headers = headers
|
||||
|
||||
if(global) then
|
||||
if(parent ~= 'oUF' and global == 'oUF') then
|
||||
error('%s is doing it wrong and setting its global to "oUF".', parent)
|
||||
elseif(_G[global]) then
|
||||
error('%s is setting its global to an existing name "%s".', parent, global)
|
||||
else
|
||||
_G[global] = oUF
|
||||
end
|
||||
end
|
||||
63
Libraries/oUF/private.lua
Normal file
63
Libraries/oUF/private.lua
Normal file
@@ -0,0 +1,63 @@
|
||||
local parent, ns = ...
|
||||
local Private = ns.oUF.Private
|
||||
|
||||
function Private.argcheck(value, num, ...)
|
||||
assert(type(num) == 'number', "Bad argument #2 to 'argcheck' (number expected, got " .. type(num) .. ')')
|
||||
|
||||
for i = 1, select('#', ...) do
|
||||
if(type(value) == select(i, ...)) then return end
|
||||
end
|
||||
|
||||
local types = strjoin(', ', ...)
|
||||
local name = debugstack(2,2,0):match(": in function [`<](.-)['>]")
|
||||
error(string.format("Bad argument #%d to '%s' (%s expected, got %s)", num, name, types, type(value)), 3)
|
||||
end
|
||||
|
||||
function Private.print(...)
|
||||
print('|cff33ff99oUF:|r', ...)
|
||||
end
|
||||
|
||||
function Private.error(...)
|
||||
Private.print('|cffff0000Error:|r ' .. string.format(...))
|
||||
end
|
||||
|
||||
function Private.unitExists(unit)
|
||||
return unit and (UnitExists(unit) or ShowBossFrameWhenUninteractable(unit))
|
||||
end
|
||||
|
||||
local validator = CreateFrame('Frame')
|
||||
|
||||
function Private.validateUnit(unit)
|
||||
local isOK, _ = pcall(validator.RegisterUnitEvent, validator, 'UNIT_HEALTH', unit)
|
||||
if(isOK) then
|
||||
_, unit = validator:IsEventRegistered('UNIT_HEALTH')
|
||||
validator:UnregisterEvent('UNIT_HEALTH')
|
||||
|
||||
return not not unit
|
||||
end
|
||||
end
|
||||
|
||||
local selectionTypes = {
|
||||
[ 0] = 0,
|
||||
[ 1] = 1,
|
||||
[ 2] = 2,
|
||||
[ 3] = 3,
|
||||
[ 4] = 4,
|
||||
[ 5] = 5,
|
||||
[ 6] = 6,
|
||||
[ 7] = 7,
|
||||
[ 8] = 8,
|
||||
[ 9] = 9,
|
||||
-- [10] = 10, -- unavailable to players
|
||||
-- [11] = 11, -- unavailable to players
|
||||
-- [12] = 12, -- inconsistent due to bugs and its reliance on cvars
|
||||
[13] = 13,
|
||||
}
|
||||
|
||||
function Private.unitSelectionType(unit, considerHostile)
|
||||
if(considerHostile and UnitThreatSituation('player', unit)) then
|
||||
return 0
|
||||
else
|
||||
return selectionTypes[UnitSelectionType(unit, true)]
|
||||
end
|
||||
end
|
||||
187
Libraries/oUF/units.lua
Normal file
187
Libraries/oUF/units.lua
Normal file
@@ -0,0 +1,187 @@
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local enableTargetUpdate = Private.enableTargetUpdate
|
||||
|
||||
local function updateArenaPreparationElements(self, event, elementName, specID)
|
||||
local element = self[elementName]
|
||||
if(element and self:IsElementEnabled(elementName)) then
|
||||
if(element.OverrideArenaPreparation) then
|
||||
--[[ Override: Health.OverrideArenaPreparation(self, event, specID)
|
||||
Used to completely override the internal update function for arena preparation.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* specID - the specialization ID for the opponent (number)
|
||||
--]]
|
||||
--[[ Override: Power.OverrideArenaPreparation(self, event, specID)
|
||||
Used to completely override the internal update function for arena preparation.
|
||||
|
||||
* self - the parent object
|
||||
* event - the event triggering the update (string)
|
||||
* specID - the specialization ID for the opponent (number)
|
||||
--]]
|
||||
element.OverrideArenaPreparation(self, event, specID)
|
||||
return
|
||||
end
|
||||
|
||||
element:SetMinMaxValues(0, 1)
|
||||
element:SetValue(1)
|
||||
if(element.UpdateColorArenaPreparation) then
|
||||
--[[ Override: Health:UpdateColor(specID)
|
||||
Used to completely override the internal function for updating the widget's colors
|
||||
during arena preparation.
|
||||
|
||||
* self - the Health element
|
||||
* specID - the specialization ID for the opponent (number)
|
||||
--]]
|
||||
--[[ Override: Power:UpdateColor(specID)
|
||||
Used to completely override the internal function for updating the widget's colors
|
||||
during arena preparation.
|
||||
|
||||
* self - the Power element
|
||||
* specID - the specialization ID for the opponent (number)
|
||||
--]]
|
||||
element:UpdateColorArenaPreparation(specID)
|
||||
else
|
||||
-- this section just replicates the color options available to the Health and Power elements
|
||||
local r, g, b, t, _
|
||||
-- if(element.colorPower and elementName == 'Power') then
|
||||
-- FIXME: no idea if we can get power type here without the unit
|
||||
if(element.colorClass) then
|
||||
local _, _, _, _, _, class = GetSpecializationInfoByID(specID)
|
||||
t = self.colors.class[class]
|
||||
elseif(element.colorReaction) then
|
||||
t = self.colors.reaction[2]
|
||||
elseif(element.colorSmooth) then
|
||||
_, _, _, _, _, _, r, g, b = unpack(element.smoothGradient or self.colors.smooth)
|
||||
elseif(element.colorHealth and elementName == 'Health') then
|
||||
t = self.colors.health
|
||||
end
|
||||
|
||||
if(t) then
|
||||
r, g, b = t[1], t[2], t[3]
|
||||
end
|
||||
|
||||
if(r or g or b) then
|
||||
element:SetStatusBarColor(r, g, b)
|
||||
|
||||
local bg = element.bg
|
||||
if(bg) then
|
||||
local mu = bg.multiplier or 1
|
||||
bg:SetVertexColor(r * mu, g * mu, b * mu)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(element.PostUpdateArenaPreparation) then
|
||||
--[[ Callback: Health:PostUpdateArenaPreparation(event, specID)
|
||||
Called after the element has been updated during arena preparation.
|
||||
|
||||
* self - the Health element
|
||||
* event - the event triggering the update (string)
|
||||
* specID - the specialization ID for the opponent (number)
|
||||
--]]
|
||||
--[[ Callback: Power:PostUpdateArenaPreparation(event, specID)
|
||||
Called after the element has been updated during arena preparation.
|
||||
|
||||
* self - the Power element
|
||||
* event - the event triggering the update (string)
|
||||
* specID - the specialization ID for the opponent (number)
|
||||
--]]
|
||||
element:PostUpdateArenaPreparation(event, specID)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateArenaPreparation(self, event)
|
||||
if(not self:GetAttribute('oUF-enableArenaPrep')) then
|
||||
return
|
||||
end
|
||||
|
||||
if(event == 'ARENA_OPPONENT_UPDATE' and not self:IsEnabled()) then
|
||||
self:Enable()
|
||||
self:UpdateAllElements('ArenaPreparation')
|
||||
self:UnregisterEvent(event, updateArenaPreparation)
|
||||
|
||||
-- show elements that don't handle their own visibility
|
||||
if(self:IsElementEnabled('Auras')) then
|
||||
if(self.Auras) then self.Auras:Show() end
|
||||
if(self.Buffs) then self.Buffs:Show() end
|
||||
if(self.Debuffs) then self.Debuffs:Show() end
|
||||
end
|
||||
|
||||
if(self.Portrait and self:IsElementEnabled('Portrait')) then
|
||||
self.Portrait:Show()
|
||||
end
|
||||
elseif(event == 'PLAYER_ENTERING_WORLD' and not UnitExists(self.unit)) then
|
||||
-- semi-recursive call for when the player zones into an arena
|
||||
updateArenaPreparation(self, 'ARENA_PREP_OPPONENT_SPECIALIZATIONS')
|
||||
elseif(event == 'ARENA_PREP_OPPONENT_SPECIALIZATIONS') then
|
||||
if(self.PreUpdate) then
|
||||
self:PreUpdate(event)
|
||||
end
|
||||
|
||||
local id = tonumber(self.id)
|
||||
if(not self:IsEnabled() and GetNumArenaOpponentSpecs() < id) then
|
||||
-- hide the object if the opponent leaves
|
||||
self:Hide()
|
||||
end
|
||||
|
||||
local specID = GetArenaOpponentSpec(id)
|
||||
if(specID) then
|
||||
if(self:IsEnabled()) then
|
||||
-- disable the unit watch so we can forcefully show the object ourselves
|
||||
self:Disable()
|
||||
self:RegisterEvent('ARENA_OPPONENT_UPDATE', updateArenaPreparation)
|
||||
end
|
||||
|
||||
-- update Health and Power (if available) with "fake" data
|
||||
updateArenaPreparationElements(self, event, 'Health', specID)
|
||||
updateArenaPreparationElements(self, event, 'Power', specID)
|
||||
|
||||
-- hide all other (relevant) elements (they have no effect during arena prep)
|
||||
if(self.Auras) then self.Auras:Hide() end
|
||||
if(self.Buffs) then self.Buffs:Hide() end
|
||||
if(self.Debuffs) then self.Debuffs:Hide() end
|
||||
if(self.Castbar) then self.Castbar:Hide() end
|
||||
if(self.CombatIndicator) then self.CombatIndicator:Hide() end
|
||||
if(self.PartyIndicator) then self.PartyIndicator:Hide() end
|
||||
if(self.GroupRoleIndicator) then self.GroupRoleIndicator:Hide() end
|
||||
if(self.Portrait) then self.Portrait:Hide() end
|
||||
if(self.PvPIndicator) then self.PvPIndicator:Hide() end
|
||||
if(self.RaidTargetIndicator) then self.RaidTargetIndicator:Hide() end
|
||||
|
||||
self:Show()
|
||||
self:UpdateTags()
|
||||
end
|
||||
|
||||
if(self.PostUpdate) then
|
||||
self:PostUpdate(event)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Handles unit specific actions.
|
||||
function oUF:HandleUnit(object, unit)
|
||||
local unit = object.unit or unit
|
||||
if(unit == 'target') then
|
||||
object:RegisterEvent('PLAYER_TARGET_CHANGED', object.UpdateAllElements, true)
|
||||
elseif(unit == 'mouseover') then
|
||||
object:RegisterEvent('UPDATE_MOUSEOVER_UNIT', object.UpdateAllElements, true)
|
||||
elseif(unit == 'focus') then
|
||||
object:RegisterEvent('PLAYER_FOCUS_CHANGED', object.UpdateAllElements, true)
|
||||
elseif(unit:match('boss%d?$')) then
|
||||
object:RegisterEvent('INSTANCE_ENCOUNTER_ENGAGE_UNIT', object.UpdateAllElements, true)
|
||||
object:RegisterEvent('UNIT_TARGETABLE_CHANGED', object.UpdateAllElements)
|
||||
elseif(unit:match('arena%d?$')) then
|
||||
object:RegisterEvent('ARENA_OPPONENT_UPDATE', object.UpdateAllElements, true)
|
||||
object:RegisterEvent('ARENA_PREP_OPPONENT_SPECIALIZATIONS', updateArenaPreparation, true)
|
||||
object:SetAttribute('oUF-enableArenaPrep', true)
|
||||
-- the event handler only fires for visible frames, so we have to hook it for arena prep
|
||||
object:HookScript('OnEvent', updateArenaPreparation)
|
||||
elseif(unit:match('%w+target')) then
|
||||
enableTargetUpdate(object)
|
||||
end
|
||||
end
|
||||
82
Libraries/oUF/utils/changelog
Normal file
82
Libraries/oUF/utils/changelog
Normal file
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local tags = {}
|
||||
do
|
||||
for tag in io.popen('git tag'):lines() do
|
||||
local split = tag:gmatch('[^.]+')
|
||||
local release, api, bugfix = split(), split(), split() or 0
|
||||
table.insert(
|
||||
tags,
|
||||
{
|
||||
string = tag,
|
||||
release = release,
|
||||
api = api,
|
||||
bugfix = bugfix,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
table.sort(tags, function(a,b)
|
||||
a = a.release * 1e4 + a.api * 100 + a.bugfix
|
||||
b = b.release * 1e4 + b.api * 100 + b.bugfix
|
||||
|
||||
return a > b
|
||||
end)
|
||||
end
|
||||
|
||||
local generateLog = function(prevTag, currentTag)
|
||||
local ti = table.insert
|
||||
local sf = string.format
|
||||
|
||||
local out = {}
|
||||
local i = 0
|
||||
|
||||
ti(out, sf('**Changes in %s:**\n', currentTag))
|
||||
|
||||
for line in io.popen(sf('git shortlog --no-merges --reverse %s..%s', prevTag, currentTag)):lines() do
|
||||
if(line:sub(1, 6) == ' ') then
|
||||
local offset = line:match('() ', 7)
|
||||
if(offset) then
|
||||
line = line:sub(7, offset - 1)
|
||||
else
|
||||
line = line:sub(7)
|
||||
end
|
||||
line = line:gsub('#(%d+)', '[#%1](https://github.com/oUF-wow/oUF/issues/%1)')
|
||||
|
||||
i = i + 1
|
||||
ti(out, sf(' %s. %s', i, line))
|
||||
elseif(#line ~= 0) then
|
||||
i = 0
|
||||
ti(out, sf('- _%s_', line))
|
||||
end
|
||||
end
|
||||
|
||||
local p = assert(io.popen(sf('git diff --shortstat %s..%s', prevTag, currentTag)))
|
||||
local stat = p:read'*a'
|
||||
p:close()
|
||||
|
||||
ti(out, sf('- %s\n', stat:sub(2, -2)))
|
||||
|
||||
return table.concat(out, '\n')
|
||||
end
|
||||
|
||||
local stop
|
||||
local to = ...
|
||||
if(to) then
|
||||
for i=1, #tags do
|
||||
if(tags[i].string == to) then
|
||||
stop = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
if(not stop) then stop = #tags end
|
||||
else
|
||||
stop = #tags
|
||||
end
|
||||
|
||||
for i=2, stop do
|
||||
local current, prev = tags[i -1], tags[i]
|
||||
print(generateLog(prev.string, current.string))
|
||||
end
|
||||
|
||||
-- vim: set filetype=lua :
|
||||
254
Libraries/oUF/utils/docs
Normal file
254
Libraries/oUF/utils/docs
Normal file
@@ -0,0 +1,254 @@
|
||||
#!/usr/bin/env lua
|
||||
-- docs
|
||||
-- oUF documentation generator
|
||||
--
|
||||
-- This is really just a quick and dirty way of generating documentation for
|
||||
-- oUF[1]. The syntax is inspired by TomDoc[2], but a lot of the non-oUF and
|
||||
-- non-Lua things aren't implemented.
|
||||
--
|
||||
-- Why implement my own documentation generator?
|
||||
-- It was mainly done because oUF is kind-of special, but also because the
|
||||
-- available alternatives aren't good enough or have issues I can't workaround.
|
||||
--
|
||||
-- Things that need fixing:
|
||||
-- - No highlighting of Lua code.
|
||||
-- - Doesn't validate that comments are documentation strings.
|
||||
-- - Doesn't parse its own documentation header.
|
||||
-- - Close to zero error handling.
|
||||
--
|
||||
-- Usage
|
||||
--
|
||||
-- docs [docs path] [file...]
|
||||
--
|
||||
-- Links
|
||||
--
|
||||
-- [1] https://github.com/haste/oUF
|
||||
-- [2] http://tomdoc.org/
|
||||
|
||||
local out
|
||||
local lines
|
||||
|
||||
local tisf = function(fmt, ...)
|
||||
table.insert(out, fmt:format(...))
|
||||
end
|
||||
|
||||
local trim = function(str)
|
||||
return str:match('^()%s*$') and '' or str:match('^%s*(.*%S)')
|
||||
end
|
||||
|
||||
local findNextEmpty = function(start, stop)
|
||||
for i=start, stop or #lines do
|
||||
if(lines[i] == '') then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local findNextHeader = function(offest)
|
||||
for i=offest, #lines do
|
||||
local pre, header, post = unpack(lines, i, i + 2)
|
||||
-- Single lines without punctuation are headers.
|
||||
if(pre == '' and post == '' and not header:match'%.') then
|
||||
return i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local findNextArguent = function(start, stop, padding, pattern)
|
||||
for i=start, stop do
|
||||
local match, pad = lines[i]:match(pattern)
|
||||
if(match and pad == padding) then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local replaceMarkup = function(str)
|
||||
return str
|
||||
-- `in-line code` to <code>in-line code</code>
|
||||
:gsub('`([^`]+)`', '<code>%1</code>')
|
||||
-- [Link](http://example.com) to <a href="http://example.com">Link</a>
|
||||
:gsub('%[([^%]]+)%]%(([^)]+)%)', '<a href="%2">%1</a>')
|
||||
end
|
||||
|
||||
local handleArguments = function(start, stop, pattern)
|
||||
tisf('<dl>')
|
||||
repeat
|
||||
-- Tear out the argument name and offset of where the description begins.
|
||||
local def, padding, offset = lines[start]:match(pattern)
|
||||
tisf('<dt>%s</dt>', def)
|
||||
|
||||
-- Insert the first line of the description.
|
||||
tisf('<dd>')
|
||||
tisf(lines[start]:sub(offset))
|
||||
|
||||
-- Find the next argument in the list or continue to the end of the
|
||||
-- current section.
|
||||
local nextarg = findNextArguent(start + 1, stop, padding, pattern)
|
||||
nextarg = (nextarg or stop + 1) - 1
|
||||
for i=start + 1, nextarg do
|
||||
tisf(trim(lines[i]))
|
||||
end
|
||||
tisf('</dd>')
|
||||
|
||||
start = nextarg + 1
|
||||
until start > stop
|
||||
tisf('</dl>')
|
||||
end
|
||||
|
||||
local handleExamples = function(start, stop)
|
||||
-- An extra line gets added if we don't do this.
|
||||
tisf('<pre><code>%s', lines[start]:sub(3))
|
||||
for i=start + 1, stop do
|
||||
tisf(lines[i]:sub(3))
|
||||
end
|
||||
tisf('</code></pre>')
|
||||
end
|
||||
|
||||
local handleParagraph = function(start, stop)
|
||||
tisf('<p>')
|
||||
for i=start, stop do
|
||||
tisf(trim(lines[i]))
|
||||
end
|
||||
tisf('</p>')
|
||||
end
|
||||
|
||||
local handleSection = function(start, stop)
|
||||
while(start) do
|
||||
-- Find the next empty line or continue until the end of the section.
|
||||
-- findNextEmpty() returns the position of the empty line, so we need to
|
||||
-- subtract one from it.
|
||||
local nextEmpty = findNextEmpty(start + 1, stop)
|
||||
if(nextEmpty) then
|
||||
nextEmpty = nextEmpty - 1
|
||||
else
|
||||
nextEmpty = stop
|
||||
end
|
||||
|
||||
local line = lines[start]
|
||||
if(not line) then
|
||||
return
|
||||
elseif(line:match('^%S+%s*%- ')) then
|
||||
handleArguments(start, nextEmpty, '(%S+)%s*()%- ()')
|
||||
elseif(line:sub(1, 2) == ' ') then
|
||||
handleExamples(start, nextEmpty)
|
||||
else
|
||||
handleParagraph(start, nextEmpty)
|
||||
end
|
||||
|
||||
start = findNextEmpty(nextEmpty, stop)
|
||||
if(start) then start = start + 1 end
|
||||
end
|
||||
end
|
||||
|
||||
local generateDocs = function(str, level)
|
||||
lines = {}
|
||||
out = {}
|
||||
|
||||
for line in str:gmatch('([^\n]*)\n') do
|
||||
table.insert(lines, line:gsub('\t*', ''):sub(2))
|
||||
end
|
||||
|
||||
-- The first line is always the main header.
|
||||
tisf('<h%d>%s</h%d>', level, lines[1], level)
|
||||
|
||||
-- Then comes the main description.
|
||||
local offset = findNextHeader(1)
|
||||
|
||||
-- Continue until two lines before the header or to the end of the comment.
|
||||
if(offset) then
|
||||
offset = offset - 2
|
||||
else
|
||||
offset = #lines
|
||||
end
|
||||
|
||||
local init = findNextEmpty(1) + 1
|
||||
if(init > offset) then
|
||||
init = 2
|
||||
end
|
||||
|
||||
handleSection(init, offset)
|
||||
|
||||
while(true) do
|
||||
offset = findNextHeader(offset)
|
||||
if(not offset) then break end
|
||||
|
||||
-- Every section has a header.
|
||||
tisf('<h%d>%s</h%d>', level + 1, lines[offset], level + 1)
|
||||
|
||||
-- Find out the size of the section.
|
||||
local start = findNextEmpty(offset) + 1
|
||||
if(not lines[start]) then
|
||||
-- There's no section here, only a headline.
|
||||
break
|
||||
end
|
||||
|
||||
local stop
|
||||
local nextHeader = findNextHeader(start)
|
||||
if(nextHeader) then
|
||||
stop = nextHeader - 2
|
||||
else
|
||||
local nextEmpty = findNextEmpty(start)
|
||||
if(nextEmpty) then
|
||||
stop = nextEmpty - 1
|
||||
else
|
||||
stop = #lines
|
||||
end
|
||||
end
|
||||
|
||||
handleSection(start, stop)
|
||||
offset = stop + 1
|
||||
end
|
||||
|
||||
return table.concat(out, '\n')
|
||||
end
|
||||
|
||||
local handleFile = function(path)
|
||||
local file = io.open(path, 'r')
|
||||
local content = file:read'*a'
|
||||
file:close()
|
||||
|
||||
local out = {}
|
||||
local init = 1
|
||||
repeat
|
||||
local _, comStart, depth = content:find('%-%-%[(=*)%[ ', init)
|
||||
if(comStart) then
|
||||
local comEnd = content:find('%]' .. depth .. '%]', comStart)
|
||||
local comment = content:sub(comStart, comEnd - 1)
|
||||
|
||||
-- Convert markup to html.
|
||||
comment = replaceMarkup(comment)
|
||||
|
||||
-- The first comment uses h1 and h2, while the subsequent ones uses h3
|
||||
-- and h4.
|
||||
local level = init == 1 and 1 or 3
|
||||
table.insert(out, generateDocs(comment, init == 1 and 1 or 3))
|
||||
|
||||
init = comEnd
|
||||
end
|
||||
until not comStart
|
||||
|
||||
return table.concat(out, '\n')
|
||||
end
|
||||
|
||||
local destination = (...)
|
||||
for i=2, select('#', ...) do
|
||||
local file = select(i, ...)
|
||||
local path, filename = file:match('(.+)/(.+)$')
|
||||
|
||||
if(path:sub(1,3) == '../') then
|
||||
path = path:sub(4)
|
||||
end
|
||||
|
||||
if(#path == 0) then path = nil end
|
||||
filename = filename:gsub('lua', 'html')
|
||||
|
||||
local doc = handleFile(file)
|
||||
if(doc) then
|
||||
local dfPath = string.format('%s/%s', destination, path or '')
|
||||
os.execute(string.format('mkdir -p %s', dfPath))
|
||||
local docFile = io.open(string.format('%s/%s', dfPath, filename), 'w+')
|
||||
docFile:write(doc)
|
||||
docFile:close()
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user