vanilla-wow-addons – Rev 1
?pathlinks?
-- ArcHUDRingTemplate_ Ring Template
----------------------------------------------------------------------
--
-- Template code for partial ring display
--
-- Divides the ring up into four quadrants:
-- Q1-TopRight Q2-BottomRight Q3-BottomLeft Q4-TopLeft
--
-- Other terminology:
-- self.radius - The outer radius of the ring (Also the texture width)
-- self.ringFactor - The ratio of inner radius/outer radius
---------------------------------------------------------------------------
-- QUADRANT MAPPING FUNCTIONS
-- The subsetting code is all written relative to the first quandrant, but
-- each quadrant has a pair of functions to manage mapping location and
-- texture operations from that 'normalized' coordinate system into the
-- appropriate one for the quadrant in question
--
-- SUBSET FUNCTION
-- self function displays a subset of a quadrant, using a subset of a
-- texture (The texture subsetting is optional, so the same function
-- can be used for slice stretching). Note self does not issue a
-- ClearAllPoints.
--
-- setSubsetFuncs[quadrant](tex, parname, radius, xlo, xhi, ylo, yhi, notex)
--
-- Parameters:
-- tex - The texture object
-- parname - The name of the texture's parent (for SetPoint use)
-- radius - The outer radius of the ring (i.e. texture width & height)
-- xlo, xhi - X Coordinate bounds (from center of the ring)
-- ylo, yhi - Y Coordinate bounds (From center of the ring)
-- notex - (OPTIONAL) If present and true, do not set texture coords.
-- just change points.
--
-- SLICE FUNCTION
-- self function sets the texture coordinates for a slice texture, so that
-- it's correctly oriented for the quadrant.
--
-- setSliceFuncs[quadrant](tex)
--
-- Parameters:
-- tex - The slice texture object
--
local setSubsetFuncs = {}
local setSliceFuncs = {}
ArcHUDRingTemplate = {}
-- Q3: BOTTOM LEFT
setSubsetFuncs[1] = function(tex, parname, radius, xlo, xhi, ylo, yhi, notex)
if (not notex) then
tex:SetTexCoord(xhi, xlo, ylo, yhi)
end
tex:SetPoint("BOTTOMRIGHT", parname, "BOTTOMLEFT", -xlo*radius, -yhi*radius)
tex:SetPoint("TOPLEFT", parname, "BOTTOMLEFT", -xhi*radius, -ylo*radius)
end
-- Q4: TOP LEFT
setSubsetFuncs[2] = function(tex, parname, radius, xlo, xhi, ylo, yhi, notex)
if (not notex) then
tex:SetTexCoord(yhi, ylo, xhi, xlo)
end
tex:SetPoint("BOTTOMLEFT", parname, "BOTTOMLEFT", -yhi*radius, xlo*radius)
tex:SetPoint("TOPRIGHT", parname, "BOTTOMLEFT", -ylo*radius, xhi*radius)
end
-- Q1: TOP RIGHT
setSubsetFuncs[3] = function(tex, parname, radius, xlo, xhi, ylo, yhi, notex)
if (not notex) then
tex:SetTexCoord(xlo, xhi, yhi, ylo)
end
tex:SetPoint("TOPLEFT", parname, "BOTTOMLEFT", xlo*radius, yhi*radius)
tex:SetPoint("BOTTOMRIGHT", parname, "BOTTOMLEFT", xhi*radius, ylo*radius)
end
-- Q2: BOTTOM RIGHT
setSubsetFuncs[4] = function(tex, parname, radius, xlo, xhi, ylo, yhi, notex)
if (not notex) then
tex:SetTexCoord(ylo, yhi, xlo, xhi)
end
tex:SetPoint("TOPRIGHT", parname, "BOTTOMLEFT", yhi*radius, -xlo*radius)
tex:SetPoint("BOTTOMLEFT", parname, "BOTTOMLEFT", ylo*radius, -xhi*radius)
end
-- Slice text coord setting funcs
setSliceFuncs[1] = function(tex) tex:SetTexCoord(0, 1, 1, 0) end
setSliceFuncs[2] = function(tex) tex:SetTexCoord(1, 0, 1, 0) end
setSliceFuncs[3] = function(tex) tex:SetTexCoord(1, 0, 0, 1) end
setSliceFuncs[4] = function(tex) tex:SetTexCoord(0, 1, 0, 1) end
-- The 'Work' function, which handles subset rendering for a single
-- quadrant (normalized to Q1)
--
-- Params:
-- self - The ring template instance
-- A - The angle within the quadrant (degrees, 0 <= A < 90)
-- T - The main texture for the quadrant
-- SS - The texture subset mapping function for the quadrant
function ArcHUDRingTemplate:DoQuadrantReversed(A, T, SS)
-- Grab local references to important textures
local C = self.chip
local S = self.slice
-- If no part of self quadrant is visible, just hide all the textures
-- and be done.
if (A == 0) then
T:Hide()
C:Hide()
S:Hide()
return
end
-- More local references, grab the ring dimensions, and the frame name.
local RF = self.ringFactor
local OR = self.radius
--local name = self.name
-- Drawing scheme uses three locations
-- E (Ex,Ey) - The 'End' position (Nx=1, Ny=0)
-- O (Ox,Oy) - Intersection of angle line with Outer edge
-- I (Ix,Iy) - Intersection of angle line with Inner edge
-- Calculated locations:
-- Arad - Angle in radians
-- Ox,Oy - O coordinates
-- Ix,Iy - I coordinates
local Arad = math.rad(A)
local Ox = math.cos(Arad)
local Oy = math.sin(Arad)
local Ix = Ox * RF
local Iy = Oy * RF
-- Treat first and last halves differently to maximize size of main
-- texture subset.
if (A <= 45) then
-- Main subset is from N to I
SS(T, self, OR, Ix, 1, 0, Iy)
-- Chip is subset from (Ix,Oy) to (Ox,Ny) (Right edge of main)
SS(C, self, OR, Ox, 1, Iy, Oy)
else
-- Main subset is from N to O
SS(T, self, OR, Ox, 1, 0, Oy)
-- Chip is subset from (Nx,Iy) to (Ix,Oy) (Bottom edge of main)
SS(C, self, OR, Ix, Ox, 0, Iy)
end
-- Strech slice between I and O
SS(S, self, OR, Ix, Ox, Iy, Oy, 1)
-- All three textures are visible
T:Show()
C:Show()
S:Show()
end
function ArcHUDRingTemplate:DoQuadrant(A, T, SS)
-- Grab local references to important textures
local C = self.chip
local S = self.slice
-- If no part of self quadrant is visible, just hide all the textures
-- and be done.
if (A == 0) then
T:Hide()
C:Hide()
S:Hide()
return
end
-- More local references, grab the ring dimensions, and the frame name.
local RF = self.ringFactor
local OR = self.radius
--local name = self.name
-- Drawing scheme uses three locations
-- N (Nx,Ny) - The 'Noon' position (Nx=0, Ny=1)
-- O (Ox,Oy) - Intersection of angle line with Outer edge
-- I (Ix,Iy) - Intersection of angle line with Inner edge
-- Calculated locations:
-- Arad - Angle in radians
-- Ox,Oy - O coordinates
-- Ix,Iy - I coordinates
local Arad = math.rad(A)
local Ox = math.sin(Arad)
local Oy = math.cos(Arad)
local Ix = Ox * RF
local Iy = Oy * RF
-- Treat first and last halves differently to maximize size of main
-- texture subset.
if (A <= 45) then
-- Main subset is from N to I
SS(T, self, OR, 0, Ix, Iy, 1)
-- Chip is subset from (Ix,Oy) to (Ox,Ny) (Right edge of main)
SS(C, self, OR, Ix, Ox, Oy, 1)
else
-- Main subset is from N to O
SS(T, self, OR, 0, Ox, Oy, 1)
-- Chip is subset from (Nx,Iy) to (Ix,Oy) (Bottom edge of main)
SS(C, self, OR, 0, Ix, Iy, Oy)
end
-- Strech slice between I and O
SS(S, self, OR, Ix, Ox, Iy, Oy, 1)
-- All three textures are visible
T:Show()
C:Show()
S:Show()
end
-- Method function to set the angle to display
--
-- Param:
-- self - The ring template instance
-- angle - The angle in degrees (0 <= angle <= 180)
function ArcHUDRingTemplate:SetAngle(angle)
-- Bounds checking on the angle so that it's between 0 and 180 (inclusive)
if (angle < 0) then
angle = 0
end
if (angle > 180) then
angle = 180
end
-- Avoid duplicate work
if (self.angle == angle and not self.dirty) then
return
end
-- Determine the quadrant, and angle within the quadrant
-- (Quadrant 5 means 'all quadrants filled')
local quad = math.floor(angle / 90) + 1
local A = math.mod(angle, 90)
local quadOfs = self.quadOffset or 0
local effQuad
if (self.reversed) then
effQuad = math.mod((4-quad)+quadOfs, 4)+1
else
effQuad = math.mod(quad+quadOfs-1, 4)+1
end
-- Check to see if we've changed quandrants since the last time we were
-- called. Quadrant changes re-configure some textures.
if (quad ~= self.lastQuad or self.dirty) then
-- Loop through all quadrants
for i=1,2 do
T=self.quadrants[i]
if (self.reversed) then
qi = math.mod((4-i)+quadOfs, 4)+1
else
qi = math.mod(i+quadOfs-1, 4)+1
end
if (i < quad) then
-- If self quadrant is full shown, then show all of the texture
T:ClearAllPoints()
--if (self.reversed) then
--setSubsetFuncs[i+2](T, self.name, self.radius, 0.0, 1.0, 0.0, 1.0)
--else
setSubsetFuncs[qi](T, self, self.radius, 0.0, 1.0, 0.0, 1.0)
--end
T:Show()
elseif (i == quad) then
-- If self quadrant is partially or fully shown, begin by
-- showing all of the texture. Also configure the slice
-- texture's orientation.
T:ClearAllPoints()
setSubsetFuncs[qi](T, self, self.radius, 0.0, 0.8, 0.4, 1.0)
--[[
if (self.reversed) then
setSubsetFuncs[qi](T, self.name, self.radius, 0.0, 0.8, 0.4, 1.0)
else
setSubsetFuncs[i](T, self.name, self.radius, 0.0, 0.8, 0.4, 1.0)
end
]]
T:Show()
if (self.reversed) then
setSliceFuncs[math.mod(qi+1,4)+1](self.slice)
else
setSliceFuncs[qi](self.slice)
end
--[[
if (self.reversed) then
setSliceFuncs[i+2](self.slice)
else
setSliceFuncs[i](self.slice)
end
]]
else
-- If self quadrant is not shown at all, hide it.
T:Hide()
end
end
-- Hide the chip and slice textures, and de-anchor them (They'll be
-- re-anchored as necessary later).
self.chip:Hide()
self.chip:ClearAllPoints()
self.slice:Hide()
self.slice:ClearAllPoints()
-- Remember self for next time
self.lastQuad = quad
end
-- Remember the angle for next time
self.angle = angle
-- Extra bounds check for paranoia (also handles quad 5 case)
if ((quad < 1) or (quad > 2)) then
return
end
-- Get quadrant-specific elements
local T = self.quadrants[quad]
--local SS = setSubsetFuncs[quad]
local SS = setSubsetFuncs[effQuad]
-- Call the quadrant function to do the work
if SS ~= nil then
if (self.reversed) then
self:DoQuadrantReversed(A, T, SS)
else
self:DoQuadrant(A, T, SS)
end
end
self.dirty = false
end
---------------------------------------------------------------------------
-- Some handy method functions
-- StatsRingRingTemplate:CallTextureMethod(method, ...)
--
-- Invokes the named method on all of the textures in the ring,
-- passing in whatever arguments are given.
--
-- e.g. ring:CallTextureMethod("SetVertexColor", 1.0, 0.5, 0.2, 1.0)
function ArcHUDRingTemplate:CallTextureMethod(method, ...)
self.quadrants[1][method](self.quadrants[1], unpack(arg))
self.quadrants[2][method](self.quadrants[2], unpack(arg))
self.chip[method](self.chip, unpack(arg))
self.slice[method](self.slice, unpack(arg))
end
-- StatsRingRingTemplate:SetRingTextures(ringFactor,ringTexFile,sliceTexFile)
--
-- Sets the textures to use for self ring
--
-- Param:
-- ringFactor - The ring factor (Inner Radius / Outer Radius)
-- ringTexFile - The ring texture filename
-- sliceTexFile - The slice texture filename
function ArcHUDRingTemplate:SetRingTextures(ringFactor,
ringTexture,
sliceTexture)
DEFAULT_CHAT_FRAME:AddMessage("called setringtextures")
local savedAngle = self.angle
self.angle = nil
self.lastQuad = nil
self.ringFactor = ringFactor
for i=1,2 do
self.quadrants[i]:SetTexture(ringTexture)
end
self.chip:SetTexture(ringTexture)
self.slice:SetTexture(sliceTexture)
if (savedAngle) then
self:SetAngle(savedAngle)
end
end
-- Method function to set whether or not ring growth is reversed.
--
-- Param:
-- self - The ring template instance
-- isReversed - Whether to reverse or not
function ArcHUDRingTemplate:SetReversed(isReversed)
if (isReversed) then
isReversed = true
else
isReversed = nil
end
if (isReversed == self.reversed) then
return
end
self.reversed = isReversed
self.dirty = true
end
function ArcHUDRingTemplate:SetMax(max)
if max == nil then max = 1 end
self.maxValue = max
end
function ArcHUDRingTemplate:SetValue(value)
if value == nil then value = 0 end
if value == 0 then
value = self.maxValue / 10000
end
if self.casting == 1 then
self.startValue = value end
self.endValue = value
self.fadeTime = 0
end
function ArcHUDRingTemplate:DoFadeUpdate(tdelta)
tdelta = arg1
if self.fadeTime < self.maxFadeTime then
self.fadeTime = self.fadeTime + tdelta
if self.fadeTime > self.maxFadeTime then
self.fadeTime = self.maxFadeTime
end
local delta = self.endValue - self.startValue
local diff = delta * (self.fadeTime / self.maxFadeTime)
self.startValue = self.startValue + diff
local angle = self.startValue / self.maxValue * 180
if angle <= 90 then
self.ringFactor = 0.9 + ((90 - angle) / (90/0.1))
elseif angle <= 180 then
self.ringFactor = 0.9 + ((angle - 90) / (90/0.1))
--[[
elseif angle <= 270 then
self.ringFactor = 0.9 + ((270 - angle) / (90/0.1))
elseif angle > 270 then
self.ringFactor = 0.9 + ((angle - 270) / (90/0.1))
]]
end
self:SetAngle((self.startValue / self.maxValue) * 180)
end
end
function ArcHUDRingTemplate:AlphaUpdate()
--[[
if getglobal(self:GetName() .. "MoveAnchor"):IsVisible() then
self:SetAlpha(0.8)
self:SetAngle(180)
return
end
]]
if(not self.fadeIn) then
self.fadeIn = 1
end
if(not self.fadeOut) then
self.fadeOut = 1
end
local destAlpha = self.destAlpha
if (not destAlpha) then
return
end
local nowAlpha = self:GetAlpha()
if (nowAlpha < destAlpha) then
nowAlpha = nowAlpha + (arg1/self.fadeIn)
if (nowAlpha > destAlpha) then
nowAlpha = destAlpha
end
elseif (nowAlpha > destAlpha) then
nowAlpha = nowAlpha - (arg1/self.fadeOut)
if (nowAlpha < destAlpha) then
nowAlpha = destAlpha
end
end
self:SetAlpha(nowAlpha)
if (destAlpha == nowAlpha) then
self.destAlpha = nil
end
end
function ArcHUDRingTemplate:SetRingAlpha(destAlpha, instant)
if (destAlpha < 0) then
destAlpha = 0.0
elseif (destAlpha > 1) then
destAlpha = 1.0
end
if (instant) then
self:SetAlpha(destAlpha)
self.destAlpha = nil
return
end
if (self:GetAlpha() == destAlpha) then
return
end
if (self.destAlpha == destAlpha) then
return
end
self.destAlpha = destAlpha
end
function ArcHUDRingTemplate:UpdateColor(color)
if color == nil then
color = {["r"] = 1, ["g"] = 0.6, ["b"] = 0.1}
end
if (color) then
self:CallTextureMethod("SetVertexColor",color.r, color.g, color.b,1)
end
end
function ArcHUDRingTemplate:UpdateAlpha()
local isInCombat = false
if(self == self.parent:GetModule("PetHealth") or self == self.parent:GetModule("PetMana")) then
isInCombat = self.parent.PetIsInCombat
elseif(string.find(self.name, "Party")) then
isInCombat = self.isInCombat or false
else
isInCombat = self.parent.PlayerIsInCombat
end
if(self.f.pulse) then
self.f.alphaPulse = self.f.alphaPulse + (arg1/2)
local camt = math.cos(self.f.alphaPulse * self.f.twoPi) * 0.3
self.f:SetAlpha(0.5-camt)
else
if(self.parent.db.profile.RingVisibility == 1 or self.parent.db.profile.RingVisibility == 3) then
if(self.parent.db.profile.RingVisibility == 3 and isInCombat) then
if(self == self.parent:GetModule("TargetHealth") and UnitIsDead("target")) then
self.f:SetRingAlpha(self.parent.db.profile.FadeFull)
elseif(self == self.parent:GetModule("TargetMana") and (UnitIsDead("target") or self.f.maxValue == 0)) then
self.f:SetRingAlpha(0)
elseif((self == self.parent:GetModule("TargetHealth") or self == self.parent:GetModule("TargetMana")) and not UnitExists("target")) then
self.f:SetRingAlpha(0)
elseif((self == self.parent:GetModule("PetHealth") or self == self.parent:GetModule("PetMana")) and not UnitExists("pet")) then
self.f:SetRingAlpha(0)
else
self.f:SetRingAlpha(self.parent.db.profile.FadeIC)
end
else
if(string.find(self.name, "Mana") and self ~= self.parent:GetModule("PetMana") and UnitPowerType(self.unit or self:GetParent().unit or "player") == 1 and self.f.maxValue > 0) then
if(math.floor(self.f.startValue) > 0) then
self.f:SetRingAlpha(self.parent.db.profile.FadeOOC)
elseif(math.floor(self.f.startValue) == 0) then
self.f:SetRingAlpha(self.parent.db.profile.FadeFull)
end
else
if(self == self.parent:GetModule("TargetHealth") and UnitIsDead("target")) then
self.f:SetRingAlpha(self.parent.db.profile.FadeFull)
elseif(self == self.parent:GetModule("TargetMana") and (UnitIsDead("target") or self.f.maxValue == 0)) then
self.f:SetRingAlpha(0)
elseif((self == self.parent:GetModule("TargetHealth") or self == self.parent:GetModule("TargetMana")) and not UnitExists("target")) then
self.f:SetRingAlpha(0)
elseif((self == self.parent:GetModule("PetHealth") or self == self.parent:GetModule("PetMana")) and not UnitExists("pet")) then
self.f:SetRingAlpha(0)
else
if(self.f.startValue < self.f.maxValue) then
self.f:SetRingAlpha(self.parent.db.profile.FadeOOC)
elseif(self.f.startValue == self.f.maxValue) then
self.f:SetRingAlpha(self.parent.db.profile.FadeFull)
end
end
end
end
elseif(self.parent.db.profile.RingVisibility == 2) then
if(self == self.parent:GetModule("TargetHealth") and UnitIsDead("target")) then
self.f:SetRingAlpha(self.parent.db.profile.FadeFull)
elseif(self == self.parent:GetModule("TargetMana") and (UnitIsDead("target") or self.f.maxValue == 0)) then
self.f:SetRingAlpha(0)
elseif((self == self.parent:GetModule("TargetHealth") or self == self.parent:GetModule("TargetMana")) and not UnitExists("target")) then
self.f:SetRingAlpha(0)
elseif((self == self.parent:GetModule("PetHealth") or self == self.parent:GetModule("PetMana")) and not UnitExists("pet")) then
self.f:SetRingAlpha(0)
else
if(isInCombat) then
self.f:SetRingAlpha(self.parent.db.profile.FadeIC)
else
self.f:SetRingAlpha(self.parent.db.profile.FadeFull)
end
end
end
end
end
function ArcHUDRingTemplate:GhostMode(state, unit)
local color = {["r"] = 0.75, ["g"] = 0.75, ["b"] = 0.75}
local fh, fm
if(unit == "player") then
fh, fm = ArcHUD:GetModule("Health"), ArcHUD:GetModule("Mana")
else
fh, fm = ArcHUD:GetModule("TargetHealth"), ArcHUD:GetModule("TargetMana")
end
if(state) then
-- Prepare health ring
if(fh and not fh.f.pulse) then
fh.f:UpdateColor(color)
fh.f.alphaPulse = 0
fh.f:SetMax(1)
fh.f:SetValue(1)
if(unit == "player") then
fh.HPText:SetText("Dead")
fh.HPText:SetTextColor(1, 0, 0)
fh.HPPerc:SetText("")
else
fh.HPPerc:SetText("Dead")
end
-- Enable pulsing
fh.f.pulse = true
end
-- Prepare mana ring
if(fm and unit == "player" and not fm.f.pulse) then
fm.f:UpdateColor(color)
fm.f.alphaPulse = 0
fm.f:SetMax(1)
fm.f:SetValue(1)
fm.MPText:SetText("")
fm.MPPerc:SetText("")
-- Enable pulsing
fm.f.pulse = true
end
else
if(fh and fh.f.pulse) then
fh.f.pulse = false
fh.f:SetMax(UnitHealthMax(unit))
fh.f:SetValue(UnitHealth(unit))
end
if(fm and fm.f.pulse) then
fm.f.pulse = false
fm.f:SetMax(UnitManaMax(unit))
fm.f:SetValue(UnitMana(unit))
fm.f:UpdateColor(ManaBarColor[UnitPowerType(unit)])
end
end
end
-- The OnLoad method, call self for each template object to set it up and
-- get things going
function ArcHUDRingTemplate:OnLoad(frame)
-- Just do global self resolution once.
--local self = self
-- Grab texture references and frame name
--frame.name = frame
if(not frame.quadrants) then
frame.quadrants = {}
frame.quadrants[1] = getglobal(frame.name .. "TQ1")
frame.quadrants[2] = getglobal(frame.name .. "TQ2")
frame.chip = getglobal(frame.name .. "TC")
frame.slice = getglobal(frame.name .. "TS")
end
-- Initialize size and default texture ringFactor
frame.radius = (frame:GetWidth() * 0.5)
frame.ringFactor = 0.94
-- Add ring methods
frame.DoQuadrant = self.DoQuadrant
frame.DoQuadrantReversed = self.DoQuadrantReversed
frame.SetAngle = self.SetAngle
frame.CallTextureMethod = self.CallTextureMethod
frame.SetRingTextures = self.SetRingTextures
frame.SetMax = self.SetMax
frame.SetValue = self.SetValue
frame.Update = self.Update
frame.AddUpdateFunction = self.AddUpdateFunction
frame.RemoveUpdateFunction = self.RemoveUpdateFunction
frame.UpdateColor = self.UpdateColor
frame.SetReversed = self.SetReversed
frame.SetRingAlpha = self.SetRingAlpha
frame.GhostMode = self.GhostMode
frame.startValue = 0
frame.endValue = 0
frame.maxValue = 0
frame.fadeTime = 0
frame.maxFadeTime = 1
frame.alphaState = -1
frame.PI = 3.14159265
frame.twoPi = (frame.PI * 2)
frame.pulse = false
frame.alphaPulse = 0
-- Set angle to zero (initializes texture visibility)
frame:SetAngle(0)
end
function ArcHUDRingTemplate:OnLoadBG(frame)
-- Grab texture references and frame name
--frame.name = frame
-- frame.name = frame
if(not frame.quadrants) then
frame.quadrants = {}
frame.quadrants[1] = getglobal(frame.name .. "TQ1")
frame.quadrants[2] = getglobal(frame.name .. "TQ2")
frame.chip = getglobal(frame.name .. "TC")
frame.slice = getglobal(frame.name .. "TS")
end
-- Initialize size and default texture ringFactor
frame.radius = (frame:GetWidth() * 0.5)
frame.ringFactor = 0.94
-- Add ring methods
frame.DoQuadrant = self.DoQuadrant
frame.DoQuadrantReversed = self.DoQuadrantReversed
frame.SetAngle = self.SetAngle
frame.CallTextureMethod = self.CallTextureMethod
frame.UpdateColor = self.UpdateColor
frame.SetReversed = self.SetReversed
-- Set angle to 180 degrees (initializes texture visibility)
frame:SetAngle(180)
-- Set color and then remove the method again
frame:UpdateColor({r = 0, g = 0, b = 0})
frame.UpdateColor = nil
frame.CallTextureMethod = nil
end