Thread Tools Display Modes
12-22-22, 08:20 AM   #1
EvilMaddness
An Aku'mai Servant
 
EvilMaddness's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2015
Posts: 33
Alright guys I need your help on this one.

It's been many years since I posted on here. But I'm back and need a lot of help with this code.
We all know WeakAuras has a ring feature for Unit Frames health, mana, power or anything you can think of for it but I'm trying to make a stand alone add-on just for the Unit Frames.
This code works but the animation doesn't run as smoothly as it does in WeakAuras or have key features like a option display in game so we can set the start and end angles where we need them to be, which color to pick, ect.

So I'm asking for anyone who would like to help build this code up more and get it to that level of greatness.
That's what it's all about. Someone here might be an expert on how to display options in game for this or someone else might know how to make the animation run smoother.

Your welcome to have a crack at it. Lots of credit goes to Fizzlemizz she helped me with most of the code while I would be in game putting it in place. Sorry I don't have the textures to share to see it in game but if you know anyway to add in a start and end angle option or make this run smoother with the animation please do! Thank you!!!
Code:
-- Usage:
-- spinner = CreateSpinner(parent)
-- spinner:SetTexture('texturePath')
-- spinner:SetBlendMode('blendMode')
-- spinner:SetVertexColor(r, g, b)
-- spinner:SetClockwise(boolean) -- true to fill clockwise, false to fill counterclockwise
-- spinner:SetReverse(boolean) -- true to empty the bar instead of filling it
-- spinner:SetValue(percent) -- value between 0 and 1 to fill the bar to
 
-- Some math stuff
local cos, sin, pi2, halfpi = math.cos, math.sin, math.rad(360), math.rad(90)
local function Transform(tx, x, y, angle, aspect) -- Translates texture to x, y and rotates about its center
    local c, s = cos(angle), sin(angle)
    local y, oy = y / aspect, 0.5 / aspect
    local ULx, ULy = 0.5 + (x - 0.5) * c - (y - oy) * s, (oy + (y - oy) * c + (x - 0.5) * s) * aspect
    local LLx, LLy = 0.5 + (x - 0.5) * c - (y + oy) * s, (oy + (y + oy) * c + (x - 0.5) * s) * aspect
    local URx, URy = 0.5 + (x + 0.5) * c - (y - oy) * s, (oy + (y - oy) * c + (x + 0.5) * s) * aspect
    local LRx, LRy = 0.5 + (x + 0.5) * c - (y + oy) * s, (oy + (y + oy) * c + (x + 0.5) * s) * aspect
    tx:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy)
end
 
-- Permanently pause our rotation animation after it starts playing
local function OnPlayUpdate(self)
    self:SetScript('OnUpdate', nil)
    self:Pause()
end
 
local function OnPlay(self)
    self:SetScript('OnUpdate', OnPlayUpdate)
end
 
local function SetValue(self, value)
    -- Correct invalid ranges, preferably just don't feed it invalid numbers
    if value > 1 then value = 1
    elseif value < 0 then value = 0 end
    
    -- Reverse our normal behavior
    if self._reverse then
        value = 1 - value
    end
    
    -- Determine which quadrant we're in
    local q, quadrant = self._clockwise and (1 - value) or value -- 4 - floor(value / 0.25)
    if q >= 0.75 then
        quadrant = 1
    elseif q >= 0.5 then
        quadrant = 2
    elseif q >= 0.25 then
        quadrant = 3
    else
        quadrant = 4
    end
    
    if self._quadrant ~= quadrant then
        self._quadrant = quadrant
        -- Show/hide necessary textures if we need to
        if self._clockwise then
            for i = 1, 4 do
                self._textures[i]:SetShown(i < quadrant)
            end
        else
            for i = 1, 4 do
                self._textures[i]:SetShown(i > quadrant)
            end
        end
        -- Move scrollframe/wedge to the proper quadrant
        self._scrollframe:SetAllPoints(self._textures[quadrant])    
    end
 
    -- Rotate the things
    local rads = value * pi2
    if not self._clockwise then rads = -rads + halfpi end
    Transform(self._wedge, -0.5, -0.5, rads, self._aspect)
    self._rotation:SetRadians(-rads)
end
 
local function SetClockwise(self, clockwise)
    self._clockwise = clockwise
end
 
local function SetReverse(self, reverse)
    self._reverse = reverse
end
 
local function OnSizeChanged(self, width, height)
    self._wedge:SetSize(width, height) -- it's important to keep this texture sized correctly
    self._aspect = width / height -- required to calculate the texture coordinates
end
 
-- Creates a function that calls a method on all textures at once
local function CreateTextureFunction(func, self, ...)
    return function(self, ...)
        for i = 1, 4 do
            local tx = self._textures[i]
            tx[func](tx, ...)
        end
        self._wedge[func](self._wedge, ...)
    end
end
 
-- Pass calls to these functions on our frame to its textures
local TextureFunctions = {
    SetTexture = CreateTextureFunction('SetTexture'),
    SetBlendMode = CreateTextureFunction('SetBlendMode'),
    SetVertexColor = CreateTextureFunction('SetVertexColor'),
}
 
local function CreateSpinner(parent)
    local spinner = CreateFrame('Frame', nil, parent)
    
    -- ScrollFrame clips the actively animating portion of the spinner
    local scrollframe = CreateFrame('ScrollFrame', nil, spinner)
    scrollframe:SetPoint('BOTTOMLEFT', spinner, 'CENTER')
    scrollframe:SetPoint('TOPRIGHT')
    spinner._scrollframe = scrollframe
    
    local scrollchild = CreateFrame('frame', nil, scrollframe)
    scrollframe:SetScrollChild(scrollchild)
    scrollchild:SetAllPoints(scrollframe)
    
    -- Wedge thing
    local wedge = scrollchild:CreateTexture()
    wedge:SetPoint('BOTTOMRIGHT', spinner, 'CENTER')
    spinner._wedge = wedge
    
    -- Top Right
    local trTexture = spinner:CreateTexture()
    trTexture:SetPoint('BOTTOMLEFT', spinner, 'CENTER')
    trTexture:SetPoint('TOPRIGHT')
    trTexture:SetTexCoord(0.5, 1, 0, 0.5)
    
    -- Bottom Right
    local brTexture = spinner:CreateTexture()
    brTexture:SetPoint('TOPLEFT', spinner, 'CENTER')
    brTexture:SetPoint('BOTTOMRIGHT')
    brTexture:SetTexCoord(0.5, 1, 0.5, 1)
    
    -- Bottom Left
    local blTexture = spinner:CreateTexture()
    blTexture:SetPoint('TOPRIGHT', spinner, 'CENTER')
    blTexture:SetPoint('BOTTOMLEFT')
    blTexture:SetTexCoord(0, 0.5, 0.5, 1)
    
    -- Top Left
    local tlTexture = spinner:CreateTexture()
    tlTexture:SetPoint('BOTTOMRIGHT', spinner, 'CENTER')
    tlTexture:SetPoint('TOPLEFT')
    tlTexture:SetTexCoord(0, 0.5, 0, 0.5)
    
    -- /4|1\ -- Clockwise texture arrangement
    -- \3|2/ --
 
    spinner._textures = {trTexture, brTexture, blTexture, tlTexture}
    spinner._quadrant = nil -- Current active quadrant
    spinner._clockwise = true -- fill clockwise
    spinner._reverse = false -- Treat the provided value as its inverse, eg. 75% will display as 25%
    spinner._aspect = 1 -- aspect ratio, width / height of spinner frame
    spinner:HookScript('OnSizeChanged', OnSizeChanged)
    
    for method, func in pairs(TextureFunctions) do
        spinner[method] = func
    end
    
    spinner.SetClockwise = SetClockwise
    spinner.SetReverse = SetReverse
    spinner.SetValue = SetValue
    
    local group = wedge:CreateAnimationGroup()
    local rotation = group:CreateAnimation('Rotation')
    spinner._rotation = rotation
	rotation:SetSmoothing("IN_OUT")
    rotation:SetDuration(0)
    rotation:SetEndDelay(1)
    rotation:SetOrigin('BOTTOMRIGHT', 0, 0)
    group:SetScript('OnPlay', OnPlay)
    group:Play()
    
    return spinner
end

local spinner1 = CreateSpinner(UIParent)
spinner1:SetPoint('CENTER', TargetFrame.TargetFrameContainer.Portrait)
spinner1:SetSize(116, 108)
spinner1:SetTexture("Interface\\Addons\\Images\\Ring_20px")
spinner1:SetVertexColor(0, 1, 0)
spinner1:SetClockwise(false)
spinner1:SetReverse(false)
spinner1:Hide()

spinner1.Background = spinner1:CreateTexture()
spinner1.Background:SetDrawLayer("BACKGROUND", -1)
spinner1.Background:SetSize(155, 142)
spinner1.Background:SetPoint("CENTER", TargetFrame.TargetFrameContainer.Portrait)
spinner1.Background:SetTexture("Interface\\Addons\\Images\\FullCircleFrameTwo")



local CenterOverlay = CreateFrame("Frame", nil, spinner1)
CenterOverlay:SetFrameLevel(0)
CenterOverlay:SetSize(100, 100)
CenterOverlay:SetPoint("CENTER")
CenterOverlay.Texture = CenterOverlay:CreateTexture()
CenterOverlay.Texture:SetAllPoints()
CenterOverlay.Texture:SetTexture("Interface\\Masks\\CircleMaskScalable")
CenterOverlay.Texture:SetVertexColor(0, 0, 0)

local healthmax = 0
local health = 0
spinner1:RegisterUnitEvent("UNIT_HEALTH", target)
spinner1:RegisterEvent("PLAYER_TARGET_CHANGED")
spinner1:SetScript("OnEvent", function(self, event, ...)
	if event == "PLAYER_TARGET_CHANGED" then
		if not UnitExists("target") then
			spinner1:Hide()
			return
		end
		spinner1:Show()
	end
	healthmax = UnitHealthMax("target")
	health = UnitHealth("target")
	local h = health / healthmax
	spinner1:SetValue(h)
end)

local spinner2 = CreateSpinner(UIParent)
spinner2:SetPoint('CENTER', TargetFrame.TargetFrameContainer.Portrait)
spinner2:SetSize(158, 148)
spinner2:SetTexture("Interface\\Addons\\Images\\DragonCircleBackgroundTwo")
spinner2:SetVertexColor(1, 1, 1)
spinner2:SetClockwise(true)
spinner2:SetReverse(false)
spinner2:Hide()

local powermax = 0
local power = 0
spinner2:RegisterUnitEvent("UNIT_POWER_FREQUENT", target)
spinner2:RegisterEvent("PLAYER_TARGET_CHANGED")
spinner2:SetScript("OnEvent", function(self, event, ...)
	if event == "PLAYER_TARGET_CHANGED" then
		if not UnitExists("target") then
			spinner2:Hide()
			return
		end
		spinner2:Show()
	end
	powermax = UnitPowerMax("target")
	power = UnitPower("target")
	local p = power / powermax
	spinner2:SetValue(p)
end)

local spinner3 = CreateSpinner(UIParent)
spinner3:SetFrameLevel(1)
spinner3:SetSize(90, 90)
spinner3:SetPoint('CENTER', TargetFrame.TargetFrameContainer.Portrait)
spinner3:SetTexture("Interface\\Masks\\CircleMaskScalable")
spinner3:SetVertexColor(0.2, 0.2, 0.8)
spinner3:SetClockwise(true)
spinner3:SetReverse(false)
spinner3:Hide()
local manamax = 0
local mana = 0
spinner3:RegisterUnitEvent("UNIT_POWER_UPDATE", "target")
spinner3:RegisterEvent("PLAYER_TARGET_CHANGED")
spinner3:SetScript("OnEvent", function(self, event, ...)
	if event == "PLAYER_TARGET_CHANGED" then
		if not UnitExists("target") then
			spinner3:Hide()
			return
		end
		spinner3:Show()
	end
	local mana = UnitPower("target", Enum.PowerType.Mana)
	if not mana or mana == 0 then
		spinner3:SetValue(0)
		return
	end
	local manaMax = UnitPowerMax("target", Enum.PowerType.Mana)
	spinner3:SetValue(mana / manaMax)
end)

local spinner1 = CreateSpinner(UIParent)
spinner1:SetPoint('CENTER', TargetFrame.TargetFrameContainer.Portrait)
spinner1:SetSize(116, 108)
spinner1:SetTexture("Interface\\Addons\\Images\\Ring_20px")
spinner1:SetVertexColor(0, 1, 0)
spinner1:SetClockwise(false)
spinner1:SetReverse(false)
spinner1:Hide()

spinner1.Background = spinner1:CreateTexture()
spinner1.Background:SetDrawLayer("BACKGROUND", -1)
spinner1.Background:SetSize(155, 142)
spinner1.Background:SetPoint("CENTER", TargetFrame.TargetFrameContainer.Portrait)
spinner1.Background:SetTexture("Interface\\Addons\\Images\\FullCircleFrameTwo")



local CenterOverlay = CreateFrame("Frame", nil, spinner1)
CenterOverlay:SetFrameLevel(0)
CenterOverlay:SetSize(100, 100)
CenterOverlay:SetPoint("CENTER")
CenterOverlay.Texture = CenterOverlay:CreateTexture()
CenterOverlay.Texture:SetAllPoints()
CenterOverlay.Texture:SetTexture("Interface\\Masks\\CircleMaskScalable")
CenterOverlay.Texture:SetVertexColor(0, 0, 0)

local healthmax = 0
local health = 0
spinner1:RegisterUnitEvent("UNIT_HEALTH", target)
spinner1:RegisterEvent("PLAYER_TARGET_CHANGED")
spinner1:SetScript("OnEvent", function(self, event, ...)
	if event == "PLAYER_TARGET_CHANGED" then
		if not UnitExists("target") then
			spinner1:Hide()
			return
		end
		spinner1:Show()
	end
	healthmax = UnitHealthMax("target")
	health = UnitHealth("target")
	local h = health / healthmax
	spinner1:SetValue(h)
end)

local spinner2 = CreateSpinner(UIParent)
spinner2:SetPoint('CENTER', TargetFrame.TargetFrameContainer.Portrait)
spinner2:SetSize(158, 148)
spinner2:SetTexture("Interface\\Addons\\Images\\DragonCircleBackgroundTwo")
spinner2:SetVertexColor(1, 1, 1)
spinner2:SetClockwise(true)
spinner2:SetReverse(false)
spinner2:Hide()

local powermax = 0
local power = 0
spinner2:RegisterUnitEvent("UNIT_POWER_FREQUENT", target)
spinner2:RegisterEvent("PLAYER_TARGET_CHANGED")
spinner2:SetScript("OnEvent", function(self, event, ...)
	if event == "PLAYER_TARGET_CHANGED" then
		if not UnitExists("target") then
			spinner2:Hide()
			return
		end
		spinner2:Show()
	end
	powermax = UnitPowerMax("target")
	power = UnitPower("target")
	local p = power / powermax
	spinner2:SetValue(p)
end)

local spinner1 = CreateSpinner(UIParent)
spinner1:SetPoint('CENTER', TargetFrame.TargetFrameContainer.Portrait)
spinner1:SetSize(116, 108)
spinner1:SetTexture("Interface\\Addons\\Images\\Ring_20px")
spinner1:SetVertexColor(0, 1, 0)
spinner1:SetClockwise(false)
spinner1:SetReverse(false)
spinner1:Hide()

spinner1.Background = spinner1:CreateTexture()
spinner1.Background:SetDrawLayer("BACKGROUND", -1)
spinner1.Background:SetSize(155, 142)
spinner1.Background:SetPoint("CENTER", TargetFrame.TargetFrameContainer.Portrait)
spinner1.Background:SetTexture("Interface\\Addons\\Images\\FullCircleFrameTwo")



local CenterOverlay = CreateFrame("Frame", nil, spinner1)
CenterOverlay:SetFrameLevel(0)
CenterOverlay:SetSize(100, 100)
CenterOverlay:SetPoint("CENTER")
CenterOverlay.Texture = CenterOverlay:CreateTexture()
CenterOverlay.Texture:SetAllPoints()
CenterOverlay.Texture:SetTexture("Interface\\Masks\\CircleMaskScalable")
CenterOverlay.Texture:SetVertexColor(0, 0, 0)

local healthmax = 0
local health = 0
spinner1:RegisterUnitEvent("UNIT_HEALTH", target)
spinner1:RegisterEvent("PLAYER_TARGET_CHANGED")
spinner1:SetScript("OnEvent", function(self, event, ...)
	if event == "PLAYER_TARGET_CHANGED" then
		if not UnitExists("target") then
			spinner1:Hide()
			return
		end
		spinner1:Show()
	end
	healthmax = UnitHealthMax("target")
	health = UnitHealth("target")
	local h = health / healthmax
	spinner1:SetValue(h)
end)

local spinner2 = CreateSpinner(UIParent)
spinner2:SetPoint('CENTER', TargetFrame.TargetFrameContainer.Portrait)
spinner2:SetSize(158, 148)
spinner2:SetTexture("Interface\\Addons\\Images\\DragonCircleBackgroundTwo")
spinner2:SetVertexColor(1, 1, 1)
spinner2:SetClockwise(true)
spinner2:SetReverse(false)
spinner2:Hide()

local powermax = 0
local power = 0
spinner2:RegisterUnitEvent("UNIT_POWER_FREQUENT", target)
spinner2:RegisterEvent("PLAYER_TARGET_CHANGED")
spinner2:SetScript("OnEvent", function(self, event, ...)
	if event == "PLAYER_TARGET_CHANGED" then
		if not UnitExists("target") then
			spinner2:Hide()
			return
		end
		spinner2:Show()
	end
	powermax = UnitPowerMax("target")
	power = UnitPower("target")
	local p = power / powermax
	spinner2:SetValue(p)
end)

local spinner3 = CreateSpinner(UIParent)
spinner3:SetFrameLevel(1)
spinner3:SetSize(90, 90)
spinner3:SetPoint('CENTER', TargetFrame.TargetFrameContainer.Portrait)
spinner3:SetTexture("Interface\\Masks\\CircleMaskScalable")
spinner3:SetVertexColor(0.2, 0.2, 0.8)
spinner3:SetClockwise(true)
spinner3:SetReverse(false)
spinner3:Hide()
local manamax = 0
local mana = 0
spinner3:RegisterUnitEvent("UNIT_POWER_UPDATE", "target")
spinner3:RegisterEvent("PLAYER_TARGET_CHANGED")
spinner3:SetScript("OnEvent", function(self, event, ...)
	if event == "PLAYER_TARGET_CHANGED" then
		if not UnitExists("target") then
			spinner3:Hide()
			return
		end
		spinner3:Show()
	end
	local mana = UnitPower("target", Enum.PowerType.Mana)
	if not mana or mana == 0 then
		spinner3:SetValue(0)
		return
	end
	local manaMax = UnitPowerMax("target", Enum.PowerType.Mana)
	spinner3:SetValue(mana / manaMax)
end)

local spinner4 = CreateSpinner(UIParent)
spinner4:SetPoint('CENTER', PlayerFrame.PlayerFrameContainer.PlayerPortraitMask)
spinner4:SetSize(116, 108)
spinner4:SetTexture("Interface\\Addons\\Images\\Ring_20px")
spinner4:SetVertexColor(0, 1, 0)
spinner4:SetClockwise(true)
spinner4:SetReverse(false)
spinner4:Hide()

spinner4.Background = spinner1:CreateTexture()
spinner4.Background:SetDrawLayer("BACKGROUND", -1)
spinner4.Background:SetSize(155, 142)
spinner4.Background:SetPoint("CENTER", PlayerFrame.PlayerFrameContainer.PlayerPortraitMask)
spinner4.Background:SetTexture("Interface\\Addons\\Images\\FullCircleFrameTwo")



local CenterOverlay = CreateFrame("Frame", nil, spinner4)
CenterOverlay:SetFrameLevel(0)
CenterOverlay:SetSize(100, 100)
CenterOverlay:SetPoint("CENTER", PlayerFrame.PlayerFrameContainer.PlayerPortraitMask)
CenterOverlay.Texture = CenterOverlay:CreateTexture()
CenterOverlay.Texture:SetAllPoints()
CenterOverlay.Texture:SetTexture("Interface\\Masks\\CircleMaskScalable")
CenterOverlay.Texture:SetVertexColor(0, 0, 0)

local healthmax = 0
local health = 0
spinner4:RegisterUnitEvent("UNIT_HEALTH", player)
spinner4:RegisterEvent("PLAYER_ENTERING_WORLD")
spinner4:SetScript("OnEvent", function(self, event, ...)
	if event == "PLAYER_ENTERING_WORLD" then
		if not UnitExists("player") then
			spinner6:Show()
			return
		end
		spinner4:Show()
	end
	healthmax = UnitHealthMax("player")
	health = UnitHealth("player")
	local h = health / healthmax
	spinner4:SetValue(h)
end)

local spinner5 = CreateSpinner(UIParent)
spinner5:SetPoint('CENTER', PlayerFrame.PlayerFrameContainer.PlayerPortraitMask)
spinner5:SetSize(158, 148)
spinner5:SetTexture("Interface\\Addons\\Images\\DragonCircleBackgroundPlayer")
spinner5:SetVertexColor(1, 1, 1)
spinner5:SetClockwise(true)
spinner5:SetReverse(false)
spinner5:Hide()

spinner5.Background = spinner1:CreateTexture()
spinner5.Background:SetDrawLayer("BACKGROUND", -1)
spinner5.Background:SetSize(155, 142)
spinner5.Background:SetPoint("CENTER", PlayerFrame.PlayerFrameContainer.PlayerPortraitMask)
spinner5.Background:SetTexture("Interface\\Addons\\Images\\DragonCircleBackgroundPlayer")
spinner5.Background:SetVertexColor(0, 0, 0)

local powermax = 0
local power = 0
spinner5:RegisterUnitEvent("UNIT_POWER_FREQUENT", player)
spinner5:RegisterEvent("PLAYER_ENTERING_WORLD")
spinner5:SetScript("OnEvent", function(self, event, ...)
	if event == "PLAYER_ENTERING_WORLD" then
		if not UnitExists("player") then
			spinner5:Hide()
			return
		end
		spinner5:Show()
	end
	powermax = UnitPowerMax("player")
	power = UnitPower("player")
	local p = power / powermax
	spinner5:SetValue(p)
end)

local spinner6 = CreateSpinner(UIParent)
spinner6:SetFrameLevel(1)
spinner6:SetSize(90, 90)
spinner6:SetPoint('CENTER', PlayerFrame.PlayerFrameContainer.PlayerPortraitMask)
spinner6:SetTexture("Interface\\Masks\\CircleMaskScalable")
spinner6:SetVertexColor(0.2, 0.2, 0.8)
spinner6:SetClockwise(true)
spinner6:SetReverse(false)
spinner6:Hide()
local manamax = 0
local mana = 0
spinner6:RegisterUnitEvent("UNIT_POWER_UPDATE", "player")
spinner6:RegisterEvent("PLAYER_ENTERING_WORLD")
spinner6:SetScript("OnEvent", function(self, event, ...)
	if event == "PLAYER_ENTERING_WORLD" then
		if not UnitExists("player") then
			spinner6:Hide()
			return
		end
		spinner6:Show()
	end
	local mana = UnitPower("player", Enum.PowerType.Mana)
	if not mana or mana == 0 then
		spinner6:SetValue(0)
		return
	end
	local manaMax = UnitPowerMax("player", Enum.PowerType.Mana)
	spinner6:SetValue(mana / manaMax)
end)
__________________
The Maddness Within lua
  Reply With Quote
12-22-22, 10:53 AM   #2
Tim
A Rage Talon Dragon Guard
 
Tim's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2008
Posts: 309
Take a look at zork's old project "RingThing"
https://www.wowinterface.com/downloa...heRingMod.html
__________________
AddOns: Tim @ WoWInterface
Battle Tag: Mysterio#11164
Current PC Setup: PCPartPicker List
  Reply With Quote
12-31-22, 05:34 AM   #3
watchout
A Fallenroot Satyr
Join Date: Mar 2008
Posts: 20
Fascinating title

You can also take a look at my HUD here https://github.com/watchout-mods/Elementary

Particularily at the inline libraries ArcBar and LibRotate.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Alright guys I need your help on this one.


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off