ElvUI/Libraries/oUF_Plugins/oUF_Cutaway/oUF_Cutaway.lua

304 lines
7.1 KiB
Lua

local _, ns = ...
local oUF = _G.oUF or ns.oUF
assert(oUF, "oUF_Cutaway was unable to locate oUF install.")
--[[
Configuration values for both health and power:
.enabled: enable cutaway for this element, defaults to disabled
.fadeOutTime: How long it takes the cutaway health to fade, defaults to 0.6 seconds
.lengthBeforeFade: How long it takes before the cutaway begins to fade, defaults to 0.3 seconds
]]
-- GLOBALS: ElvUI
local max = math.max
local assert = assert
local hooksecurefunc = hooksecurefunc
local UnitHealthMax = UnitHealthMax
local UnitPowerMax = UnitPowerMax
local UnitIsTapDenied = UnitIsTapDenied
local UnitGUID = UnitGUID
local E -- placeholder
local function checkElvUI()
if not E then
E = ElvUI and ElvUI[1]
assert(E, "oUF_Cutaway was not able to locate ElvUI and it is required.")
end
end
local function closureFunc(self)
self.ready = nil
self.playing = nil
self.cur = nil
end
local function fadeClosure(element)
if not element.FadeObject then
element.FadeObject = {
finishedFuncKeep = true,
finishedArg1 = element,
finishedFunc = closureFunc
}
end
E:UIFrameFadeOut(element, element.fadeOutTime, element.__parentElement:GetAlpha(), 0)
end
local function Shared_PreUpdate(self, element, unit)
element.unit = unit
local oldGUID, newGUID = element.guid, UnitGUID(unit)
element.guid = newGUID
if not oldGUID or oldGUID ~= newGUID then
return
end
element.cur = self.cur
element.ready = true
end
local function UpdateSize(self, element, curV, maxV)
local isVertical = self:GetOrientation() == 'VERTICAL'
local pm = (isVertical and self:GetHeight()) or self:GetWidth()
local oum = (1 / maxV) * pm
local c = max(element.cur - curV, 0)
local mm = c * oum
if isVertical then
element:Height(mm)
else
element:Width(mm)
end
end
local PRE, POST = 0, 1
local function Shared_UpdateCheckReturn(self, element, updateType, ...)
if not element:IsVisible() then
return true
end
if updateType == PRE then
local maxV = ...
return (not element.enabled or not self.cur) or element.ready or not maxV or maxV == 0
elseif updateType == POST then
local curV, maxV, unit = ...
return (not element.enabled or not element.cur) or (not element.ready or not curV or not maxV or maxV == 0) or element.unit ~= unit
end
end
local function Health_PreUpdate(self, unit)
local element = self.__owner.Cutaway.Health
local maxV = (element.GetHealthMax or UnitHealthMax)(unit)
if Shared_UpdateCheckReturn(self, element, PRE, maxV) or UnitIsTapDenied(unit) then
return
end
Shared_PreUpdate(self, element, unit)
end
local function Health_PostUpdate(self, unit, curHealth, maxHealth)
local element = self.__owner.Cutaway.Health
if Shared_UpdateCheckReturn(self, element, POST, curHealth, maxHealth, unit) then
return
end
UpdateSize(self, element, curHealth, maxHealth)
if element.playing then
return
end
if (element.cur - curHealth) > (maxHealth * 0.01) then
element:SetAlpha(self:GetAlpha())
E:Delay(element.lengthBeforeFade, fadeClosure, element)
element.playing = true
else
element:SetAlpha(0)
closureFunc(element)
end
end
local function Health_PostUpdateColor(self, r, g, b)
self.__owner.Cutaway.Health:SetVertexColor(r * 1.5, g * 1.5, b * 1.5)
end
local function Power_PreUpdate(self, unit)
local element = self.__owner.Cutaway.Power
local maxV = (element.GetPowerMax or UnitPowerMax)(unit)
if Shared_UpdateCheckReturn(self, element, PRE, maxV) then
return
end
Shared_PreUpdate(self, element, unit)
end
local function Power_PostUpdate(self, unit, curPower, _, maxPower)
local element = self.__owner.Cutaway.Power
if Shared_UpdateCheckReturn(self, element, POST, curPower, maxPower, unit) then
return
end
UpdateSize(self, element, curPower, maxPower)
if element.playing then
return
end
if (element.cur - curPower) > (maxPower * 0.01) then
element:SetAlpha(self:GetAlpha())
E:Delay(element.lengthBeforeFade, fadeClosure, element)
element.playing = true
else
element:SetAlpha(0)
closureFunc(element)
end
end
local function Power_PostUpdateColor(self, r, g, b)
self.__owner.Cutaway.Power:SetVertexColor(r * 1.5, g * 1.5, b * 1.5)
end
local defaults = {
health = {
enabled = false,
lengthBeforeFade = 0.3,
fadeOutTime = 0.6
},
power = {
enabled = false,
lengthBeforeFade = 0.3,
fadeOutTime = 0.6
}
}
local function UpdateConfigurationValues(self, db)
local hs, ps = false, false
if self.Health then
local health = self.Health
local hdb = db.health
hs = hdb.enabled
health.enabled = hs
if hs then
health.lengthBeforeFade = hdb.lengthBeforeFade
health.fadeOutTime = hdb.fadeOutTime
health:Show()
else
health:Hide()
end
end
if self.Power then
local power = self.Power
local pdb = db.power
ps = pdb.enabled
power.enabled = ps
if ps then
power.lengthBeforeFade = pdb.lengthBeforeFade
power.fadeOutTime = pdb.fadeOutTime
power:Show()
else
power:Hide()
end
end
return hs, ps
end
local function Enable(self)
local element = self and self.Cutaway
if element then
checkElvUI()
if element.Health and element.Health:IsObjectType("Texture") and not element.Health:GetTexture() then
element.Health:SetTexture([[Interface\TargetingFrame\UI-StatusBar]])
end
if element.Power and element.Power:IsObjectType("Texture") and not element.Power:GetTexture() then
element.Power:SetTexture([[Interface\TargetingFrame\UI-StatusBar]])
end
if not element.defaultsSet then
UpdateConfigurationValues(element, defaults)
element.defaultsSet = true
end
if element.Health and self.Health then
self.Health.__owner = self
element.Health.__parentElement = self.Health
element.Health:SetAlpha(0)
if not element.Health.hasCutawayHook then
if self.Health.PreUpdate then
hooksecurefunc(self.Health, "PreUpdate", Health_PreUpdate)
else
self.Health.PreUpdate = Health_PreUpdate
end
if self.Health.PostUpdate then
hooksecurefunc(self.Health, "PostUpdate", Health_PostUpdate)
else
self.Health.PostUpdate = Health_PostUpdate
end
hooksecurefunc(self.Health, "SetStatusBarColor", Health_PostUpdateColor)
element.Health.hasCutawayHook = true
end
end
if element.Power and self.Power then
self.Power.__owner = self
element.Power.__parentElement = self.Power
element.Power:SetAlpha(0)
if not element.Power.hasCutawayHook then
if self.Power.PreUpdate then
hooksecurefunc(self.Power, "PreUpdate", Power_PreUpdate)
else
self.Power.PreUpdate = Power_PreUpdate
end
if self.Power.PostUpdate then
hooksecurefunc(self.Power, "PostUpdate", Power_PostUpdate)
else
self.Power.PostUpdate = Power_PostUpdate
end
hooksecurefunc(self.Power, "SetStatusBarColor", Power_PostUpdateColor)
element.Power.hasCutawayHook = true
end
end
if not element.UpdateConfigurationValues then
element.UpdateConfigurationValues = UpdateConfigurationValues
end
return true
end
end
local function disableElement(element)
if element then
element.enabled = false
element:Hide()
end
end
local function Disable(self)
if self and self.Cutaway then
disableElement(self.Cutaway.Health)
disableElement(self.Cutaway.Power)
end
end
oUF:AddElement("Cutaway", nil, Enable, Disable)