Cooldown API Question

I’m really hoping to avoid a GWOT (yeah, I know).

function f:CooldownLayer(deviceName, keyName)

	local actionSlot	= tonumber(AOS.BoundButtons[deviceName][keyName])
	local iconFrameName	= keyName.."_ICON"
	local cdFrameName	= keyName.."_CD"
	local cd			= _G[cdFrameName]
	local cdTexture		= _G[cdFrameName.."_TEXTURE"]
	local icon			= _G[iconFrameName]

	if cd then

		cd:ClearAllPoints()
		cd:SetHeight(icon:GetHeight())
		cd:SetWidth(icon:GetWidth())
		cdTexture:SetTexture(f:IconTextureOrString(deviceName, keyName))
		cd:Show()

	else

		local cd		= CreateFrame("Cooldown", cdFrameName, icon)
		cd:SetFrameStrata(icon:GetFrameStrata())
		cd:SetHeight(icon:GetHeight())
		cd:SetWidth(icon:GetWidth())
		local cdTexture	= cd:CreateTexture(cdFrameName.."_TEXTURE")
		cdTexture:SetTexture(f:IconTextureOrString(deviceName, keyName))
		cdTexture:SetAllPoints(cd)
		cd.texture		= cdTexture
		cd:SetPoint("center", icon)
		cd:Show()

	end

end

Anything jump out at you about this?

The “icon” layer shows just fine. The cooldown layer gets created and updated (verified using VDT) but doesn’t appear on the screen.

So far as I can tell from VDT, every element is in place.

I’ve got height, width, anchor points, a texture, time elements in the relevant cooldown frames (not shown here - trying to avoid that GWOT - they’re there in my tests).

Everything seems to be in place except it doesn’t show on the screen.

What am I missing?

I’ll be happy to post more code, but this thing is . . . it’s not short.

Edited to add: https://imgur.com/a/hdFEhc9

Long day… I’ll take another look.

newFrame = CreateFrame(“frameType”[, “frameName”[, parentFrame[, “inheritsFrame”[, id]]]]);

First parameter is the frame type (“Cooldown”).

SECOND parameter is the name.

I didn’t start out making global names for these but in order to hunt them down in VDT, I needed globals so I did it as a diagnostic tool.

Using $parent automatically adds the parent name
CreateFrame("frametype", "$parentname",...)
It’s what caught my eye without properly thinking, hence the bad post.

if cd then
    cd:ClearAllPoints()

With no following SetPoint(), if you move the anchor frame then cd is not going with it.

Definitely a problem, but not the issue.

I don’t have anything in place that allows movement of the frames just yet.

I need to, but that part isn’t written yet.

I was building this from memory from what I had in place a couple of years ago (mostly from you).

I lost the drive that was on and I’m just now getting back to that part of the process (the “put it on the screen” part).

It’s maddening because I had all this working back then.

Key
– Icon
---- Cooldown

That’s the hierarchy I have here.

Icons have IconTextures.
Cooldowns have CooldownTextures.

Those don’t need to be globally named, ultimately, because I can refer to IconTextures via Icon.texture (I think) and CooldownTextures via Cooldown.texture (I think).

Keys don’t change (they’re frames within “devices” that provide stable anchor points for Icons (which represent abilities or other bound actions).

Those change every time the action bars change.

Cooldowns change in rhythm with icons changing (I scan for cooldown updates every time I scan for icon changes - same event for both).

I don’t really want to open-post the code somewhere, but I will if you need to see it all in context.

Or, I think I still have an email address for you.

function f:CooldownLayer(deviceName, keyName)
	local actionSlot	= tonumber(AOS.BoundButtons[deviceName][keyName])
	local iconFrameName	= keyName.."_ICON"
	local cdFrameName	= keyName.."_CD"
	local cd			= _G[cdFrameName]
	local cdTexture		= _G[cdFrameName.."_TEXTURE"]
	local icon			= _G[iconFrameName]

	if cd then
		cd:ClearAllPoints()
		cd:SetHeight(icon:GetHeight())
		cd:SetWidth(icon:GetWidth())
		cdTexture:SetTexture(f:IconTextureOrString(deviceName, keyName))
		cdTexture:SetVertexColor(0, 1, 1)
		cd:Show()

	else
		local cd = CreateFrame("Cooldown", cdFrameName, icon)
		cd:SetFrameStrata(icon:GetFrameStrata())
		cd:SetHeight(icon:GetHeight())
		cd:SetWidth(icon:GetWidth())
		local cdTexture	= cd:CreateTexture(cdFrameName.."_TEXTURE")
		cdTexture:SetTexture(f:IconTextureOrString(deviceName, keyName))
		cdTexture:SetVertexColor(1, 1, 0)
		cdTexture:SetAllPoints(cd)
		cd.texture = cdTexture
		cd:SetPoint("center", icon)
		cd:Show()
		CooldownFrame_Set(cd, GetTime(), 1000, true)
	end
end

This is just setting an initial value to test.

cdTexture:SetVertexColor(1, 1, 0)

That’s the thing I should add?

I was just checking the function and needed a texture/colour I could see

CooldownFrame_Set(cd, GetTime(), 1000, true)

Gives the initial value so the function seems to work fine.

Hahahah. I added it and it turned the icon green.

Useful, but strange.

I also added a SetPoint.

function f:CooldownLayer(deviceName, keyName)

	local actionSlot	= tonumber(AOS.BoundButtons[deviceName][keyName])
	local iconFrameName	= keyName.."_ICON"
	local cdFrameName	= keyName.."_CD"
	local cd			= _G[cdFrameName]
	local cdTexture		= _G[cdFrameName.."_TEXTURE"]
	local icon			= _G[iconFrameName]

	if cd then

		cd:ClearAllPoints()
		cd:SetHeight(icon:GetHeight())
		cd:SetWidth(icon:GetWidth())
		cdTexture:SetTexture(f:IconTextureOrString(deviceName, keyName))
		cdTexture:SetVertexColor(1, 1, 0)
		cdTexture:SetAllPoints(cd)
		cd:SetPoint("center", icon)
		cd:Show()

	else

		local cd		= CreateFrame("Cooldown", cdFrameName, icon)
		cd:SetFrameStrata(icon:GetFrameStrata())
		cd:SetHeight(icon:GetHeight())
		cd:SetWidth(icon:GetWidth())
		local cdTexture	= cd:CreateTexture(cdFrameName.."_TEXTURE")
		cdTexture:SetTexture(f:IconTextureOrString(deviceName, keyName))
		cdTexture:SetVertexColor(1, 1, 0)
		cdTexture:SetAllPoints(cd)
		cd.texture		= cdTexture
		cd:SetPoint("center", icon)
		cd:Show()

	end

end

This is my test:

    local f = {}

    function f:IconTextureOrString(deviceName, keyName)
    	return("Interface/BUTTONS/WHITE8X8")
    end

    function f:CooldownLayer(deviceName, keyName)
--    	local actionSlot	= tonumber(AOS.BoundButtons[deviceName][keyName])
    	local iconFrameName	= keyName.."_ICON"
    	local cdFrameName	= keyName.."_CD"
    	local cd			= _G[cdFrameName]
    	local cdTexture		= _G[cdFrameName.."_TEXTURE"]
    	local icon			= _G[iconFrameName]

    	if cd then
    		cd:ClearAllPoints()
    		cd:SetHeight(icon:GetHeight())
    		cd:SetWidth(icon:GetWidth())
    		cdTexture:SetTexture(f:IconTextureOrString(deviceName, keyName))
    		cdTexture:SetVertexColor(0, 1, 1)
    		cd:Show()

    	else
    		local cd = CreateFrame("Cooldown", cdFrameName, icon)
    		cd:SetFrameStrata(icon:GetFrameStrata())
    		cd:SetHeight(icon:GetHeight())
    		cd:SetWidth(icon:GetWidth())
    		local cdTexture	= cd:CreateTexture(cdFrameName.."_TEXTURE")
    		cdTexture:SetTexture(f:IconTextureOrString(deviceName, keyName))
    		cdTexture:SetVertexColor(1, 1, 0)
    		cdTexture:SetAllPoints(cd)
    		cd.texture = cdTexture
    		cd:SetPoint("center", icon)
    		cd:Show()
    		CooldownFrame_Set(cd, GetTime(), 1000, true)
    	end
    end

    local a = CreateFrame("Frame", "FizzleTest", UIParent)
    a.t = a:CreateTexture()
    a.t:SetAllPoints()
    a.t:SetTexture("Interface/BUTTONS/WHITE8X8")
    a:SetSize(20, 20)
    a:SetPoint("CENTER")
    a.icon = CreateFrame("Frame", "$parent_ICON", a)
    a.icon:SetSize(20, 20)
    a.icon:SetPoint("LEFT", a, "RIGHT")
    f:CooldownLayer("x", "FizzleTest", "FizzleTest")

Gah! My brain hurts.

local f = CreateFrame("Frame", "SomeName", UIParent)
...
f.i = CreateFrame("Frame", nil, f)
...
f.c = CreateFrame("Cooldown", nil, f.i)
...

Is that the right pattern?

Should result in this, correct?

f (key frame)
f.t (the frame's texture)
f.i (icon frame)
f.i.t (the icon's texture)
f.c (cooldown)
f.c.t (the cooldown's texture)

But with only one global for the “key” frame.

Will that work? Can I attach the cooldown directly to the frame, but parent it to the icon?

Ugh. I need a nap. I’ll be back on in a few hours. Thanks, Fizzie. And anyone else who chimes in.

local f = CreateFrame("Frame", "SomeName", UIParent)

The frame can be called local using f or globally using SomeName or _G["SomeName"]

f.i = CreateFrame("Frame", "$parent_ICON", f)

called using f.i local or globally SomeName.i or SomeName_ICON or _G["SomeName"].i or _G["SomeName_ICON"]

f.c = CreateFrame("Cooldown", nil, f.i)

called using f.c local or globally SomeName.c or _G["SomeName"].c

You can:
f.c = CreateFrame("Cooldown", nil, f.i)
with f.c being the lookup reference but it will inherit properties (alpha, scale etc.) from the parent f.i

Frames are just tables with special properties so anything you can do with keys on a {} table applies to keys on a frame.

I’ll back up and use that structure and see if it fixes the problem. I still can’t see the cooldowns happening and I KNOW this can work (it did before). I just have to find the secret Lua/API handshake to make it so.

Put my test in a standalone addon and if you see the cd, the problem is somewhere other than the function.

My copy of the function is exactly the same as your original post with the initialisation call added.

Not seeing anything remotely like a normal cooldown sweep.

What I see is a doubled square (a rectangle two squares wide) in one color that changes to another after some time.

I’ll back up and redo the frame definitions from the Key down (key pretty much has to stay the same as it’s what I anchor the different icons to within the “device” (a one-higher-order frame).

You said you couldn’t see the cd. This code dosn’t make the cd count down, just visible.

If you remove the line:

CooldownFrame_Set(cd, GetTime(), 1000, true)

you will have your function initialising a cd but not visible.

or should I say, creating a cd but not initialising it.

Monitor blew up before I could update my post.

Just plugged in a TV (after pulling it down from a wall-mount) so I’m back on, but still not 100% as the resolution is far less than my monitor was an nothing looks quite the same .

Okay, refresh my memory:

MyFrameSizeVariable = 48
MyFrameXLocation = 100
MyFrameYLocation = 100
TextureNumber = "/SomeTexturePath/SomeTexture.tga"

local function MakeOrMoveOrResizeMyFrame(frameName)

  if _G[frameName] then
    f:ClearAllPoints()
    f:SetHeight(MyFrameSizeVariable)
    f:SetWidth(MyFrameSizeVariable)
    f:SetPoint("center", $parent, "center", MyFrameXLocation, MyFrameYLocation)
    f:Show()
  else
    local f = CreateFrame("Frame", frameName, UIParent)
    f:SetFrameStrata("BACKGROUND")
    f:SetHeight(MyFrameSizeVariable)
    f:SetWidth(MyFrameSizeVariable)
    f.t = f:CreateTexture()
    f.t:SetTexture(MyFrameTexture )
    f.t:SetAllPoints(f)
    f:SetPoint("center", $parent, "center", MyFrameXLocation, MyFrameYLocation)
    f:Show()
  end

end

That’s pretty much how you manage a frame and its texture. Change the size and x and y variable and then call the frame manager function (these could just as easily be passed in as defined globally and I’d never actually define them globally, but I to tend to define addon-scoped tables that hold the preferred and current parameters of each frame).

The issue I have is with child frames.

MyFrameSizeVariable = 48
MyFrameXLocation = 100
MyFrameYLocation = 100
MyFrameTexture = "/SomeTexturePath/SomeTexture.tga"

local function MakeOrMoveOrResizeMyFrame(frameName)

  if _G[frameName] then
    f:ClearAllPoints()
    f:SetHeight(MyFrameSizeVariable)
    f:SetWidth(MyFrameSizeVariable)
    f:SetPoint("center", $parent, "center", MyFrameXLocation, MyFrameYLocation)
    f.i:ClearAllPoints()  -- Because "f.i" is not sized identically to "f"
    f.i:SetHeight(MyFrameSizeVariable - 8)
    f.i:SetWidth(MyFrameSizeVariable - 8)
    --  Here's where it sort of goes off the rails for me
    --  Do I need to "ClearAllPoints" and "SetAllPoints() for f.i.t?
    --  It's sized identically to f.i - does it automatically resize or 
    --    do I need to 
    --  force it to reset its points?    
    --  ------------------------------------------------------------------
    f:Show()
  else
    local f = CreateFrame("Frame", frameName, UIParent)
    f:SetFrameStrata("BACKGROUND")
    f:SetHeight(MyFrameSizeVariable)
    f:SetWidth(MyFrameSizeVariable)
    f.t = f:CreateTexture()
    f.t:SetTexture(MyFrameTexture )
    f.t:SetAllPoints(f)
    f:SetPoint("center", $parent, "center", MyFrameXLocation, MyFrameYLocation)
    f:Show()
    f.i = CreateFrame("Frame", nil, f)
    f.i:SetFrameStrata("BACKGROUND")
    f.i:SetHeight(MyFrameSizeVariable - 8)
    f.i:SetWidth(MyFrameSizeVariable - 8)
    f.i.t = f.i:CreateTexture()
    f.i.t:SetTexture(SomeFunctionThatReturnsAndIconNumber())
    f.i.t:SetAllPoints(f.i)
    f.i:SetPoint("center", f)
    f.i:Show()
  end

end

One other question:

How do you capture the Portrait texture.

I found a function that would assign it to a frame.texture but I haven’t found out how to simply generate it.

MyFrameSizeVariable = 48
MyFrameXLocation = 100
MyFrameYLocation = 100
MyFrameTexture = "/SomeTexturePath/SomeTexture.tga"

local function MakeOrMoveOrResizeMyFrame(frameName)

  if _G[frameName] then
    f:ClearAllPoints()
    f:SetHeight(MyFrameSizeVariable)
    f:SetWidth(MyFrameSizeVariable)
    f:SetPoint("CENTER", $parent, "CENTER", MyFrameXLocation, MyFrameYLocation)
    f.i:ClearAllPoints()  -- Because "f.i" is not sized identically to "f"
    f.i:SetHeight(MyFrameSizeVariable - 8)
    f.i:SetWidth(MyFrameSizeVariable - 8)
    --  Here's where it sort of goes off the rails for me
    --  Do I need to "ClearAllPoints" and "SetAllPoints() for f.i.t?
    --  It's sized identically to f.i - does it automatically resize or 
    --    do I need to 
    --  force it to reset its points?    
    --  ------------------------------------------------------------------
    f:Show() -- not required as frames/regions are shown by default when created
  else
    local f = CreateFrame("Frame", frameName, UIParent)
    f:SetFrameStrata("BACKGROUND")
    f:SetSize(MyFrameSizeVariable, MyFrameSizeVariable)
    f.t = f:CreateTexture()
    f.t:SetTexture(MyFrameTexture )
    f.t:SetAllPoints(f) -- the (f) not needed but no biggie because the parent is the default anchor 
--    f:SetPoint("CENTER", $parent, "CENTER", MyFrameXLocation, MyFrameYLocation) -- $parent is used in naming frames not as a reference replacement
    f:SetPoint("CENTER", MyFrameXLocation, MyFrameYLocation) -- This will use UIParent (the defined parent) anchor and is the same as
--    f:SetPoint("CENTER", UIParent, "CENTER", MyFrameXLocation, MyFrameYLocation)
    f:Show()
    f.i = CreateFrame("Frame", nil, f)
    f.i:SetFrameStrata("BACKGROUND")
    f.i:SetSize(MyFrameSizeVariable - 8, MyFrameSizeVariable - 8)
    f.i.t = f.i:CreateTexture()
    f.i.t:SetTexture(SomeFunctionThatReturnsAndIconNumber())
    f.i.t:SetAllPoints(f.i) -- (f.i) not needed as above,
--    f.i:SetPoint("CENTER", f) -- not needed as SetAllPoints anchors all points to the corresponding parent points
    f.i:Show()-- shown by default at this stage
  end

end

ClearAllPoints is commonly used to do just that and as a safety mechanism as most people will the re-set all the points required.

If you have set one or more points but only want to change one then you CAN just SetPoint that one without ClearAllPoints.

If you have SetAllPoints() and want to change them all then ClearAllPoints is the easiest way to make sure you are starting with a clean sheet.

I found a function that sets a texture’s texture value to the character’s portrait, but I can’t find a way to simply extract the character portrait texture.

Any clue on that?

It’s an awkward edge case for me to have to deal with directly setting a texture rather than looking up the value and passing it back to be dropped into a SetTexture() function.