Is the proper way to free up a frame so that it gets garbage collected simply to set it's reference to nil? (ie. self.someFrame = nil), or is there some sort of handler function I need to call to have it properly garbage collected?
Alright, I haven't done this in a while, but I think I implemented this properly. Mind taking a look to make sure this actually does recycle the frames like I think it does?
onInitialize:
-- Create a frame to show things on
self:CreateFrame()
-- Storage array for frame recycling
self.debuffFrames = {}
self:CreateFrame() is generating self.debuffBarFrame that everything is anchored to, and thus isn't dynamic.
frame creation:
function Overlord:AddDebuff(texture, offset)
if self.debuffFrames[offset] == nil then
self.debuffFrames[offset] = CreateFrame("FRAME", nil, self.debuffBarFrame)
end
self.debuffFrames[offset]:SetBackdrop({
bgFile = "Interface\\Icons\\" .. texture,
edgeFile = nil,
insets = nil,
})
self.debuffFrames[offset]:SetWidth(16)
self.debuffFrames[offset]:SetHeight(16)
self.debuffFrames[offset]:ClearAllPoints()
self.debuffFrames[offset]:SetPoint("TOPLEFT", self.debuffBarFrame, "TOPLEFT", 2 + (18 * offset), -2)
self.debuffBarFrame:SetWidth(20 + (18 * offset))
end
clearing frames for next use:
function Overlord:ClearDebuffs()
for _, debuff in ipairs(self.debuffFrames) do
debuff:SetBackdrop(nil)
end
end
local debuffFrames = {}
Overlord.debuffFrames = debuffFrames
local backdropTemplate = {
bgFile = "Interface\\Icons\\" .. texture,
edgeFile = nil,
insets = nil,
}
function Overlord:AddDebuff(texture, offset)
local frame = debuffFrames[offset] or CreateFrame("FRAME", nil, self.debuffBarFrame)
frame:SetBackdrop(backdropTemplate)
frame:SetWidth(16)
frame:SetHeight(16)
frame:ClearAllPoints()
frame:SetPoint("TOPLEFT", self.debuffBarFrame, "TOPLEFT", 2 + (18 * offset), -2)
frame:SetWidth(20 + (18 * offset))
debuffFrames[offset] = frame
end
*One more code edit :)
I'd do it like that, to reduce lookup times.
Edit:
If there is one thing i learnd about working wtih frames in Lua, if you are going to use it a lot, make a local reference in scope and to block it arround a do-end loop.
Alright, now this is weird... My cleanup code doesn't seem to be running.
it enters the function, but never executes an itteration of the for ipairs. It's acting as if the self.debuffFrames array is empty, even though it shouldn't be.
prints out "Starting Cleanup" in all the right places, but never prints out "Cleaning debuff slot"
function Overlord:ClearDebuffs()
self.Print("Starting Cleanup")
for i, debuff in ipairs(self.debuffFrames) do
self.Print("Clearing debuff slot: " .. i)
debuff:SetBackdrop(nil)
end
end
edit: tacked on a #self.debuffFrames and it IS empty... yet it's filled the second it shows any of the frames, which it IS doing).
Fixed it. Because I was using OrionShock's suggestion of storing them into a local, it wasn't ever actually updating self.debuffFrames so it was actually empty. repalced all the local frame calls with self.debuffFrames again and it works fine now.
So here's my question then, how is that more efficient than just working with the same variable? The way i'm seeing it, it's creating a new local variable every time the function is run, just to do some stuff and put it back into a variable we already had... Shouldn't it be more efficient to just do the work on the variable directly, or is there some nuance of WoW's Lua implementation that I'm missing?
first its easier to read
second if using the local frame should be faster since if you where to adjust debuffFrames[offset] itself then lua would have to lookup what debuffFrames[offset] is each time whereas if you save the reference of debuffFrames[offset] to frame lua know what to do wit it much faster since upvalues (locals) are saved on the stack
especially when you deal with buffs debuffs code speed is usually important especially when you are raiding and lots of buffs/debuffs are flying around
second if using the local frame should be faster since if you where to adjust debuffFrames[offset] itself then lua would have to lookup what debuffFrames[offset] is each time whereas if you save the reference of debuffFrames[offset] to frame lua know what to do wit it much faster since upvalues (locals) are saved on the stack
That's the explanation I was looking for, thank you XD
Frames don't get GC'ed, even if all references are nil'ed and they go out of scope.
Edit: You can still access them with EnumerateFrames(), so I guess they never go out of scope.
WoW keeps a reference to all frames, which is why they don't get reclaimed. So in effect the statement that frames never get reclaimed, "even if all references are nil'ed and they go out of scope" is not true. It's just that you can't remove all references to frames.
Rollback Post to RevisionRollBack
To post a comment, please login or register a new account.
Edit: You can still access them with EnumerateFrames(), so I guess they never go out of scope.
Implement by hand.
However, UIParent.lua (default UI) has also implemented a Frame recycling scheme you might want to look at. It's decent enough.
http://www.wowace.com/projects/ace3/pages/api/ace-gui-3-0/
onInitialize:
self:CreateFrame() is generating self.debuffBarFrame that everything is anchored to, and thus isn't dynamic.
frame creation:
clearing frames for next use:
You are creating a new table there every time, instead of reusing an existing table.
*One more code edit :)
I'd do it like that, to reduce lookup times.
Edit:
If there is one thing i learnd about working wtih frames in Lua, if you are going to use it a lot, make a local reference in scope and to block it arround a do-end loop.
Changed it to:
oninitialize:
on frame creation:
it enters the function, but never executes an itteration of the for ipairs. It's acting as if the self.debuffFrames array is empty, even though it shouldn't be.
prints out "Starting Cleanup" in all the right places, but never prints out "Cleaning debuff slot"
edit: tacked on a #self.debuffFrames and it IS empty... yet it's filled the second it shows any of the frames, which it IS doing).
second if using the local frame should be faster since if you where to adjust debuffFrames[offset] itself then lua would have to lookup what debuffFrames[offset] is each time whereas if you save the reference of debuffFrames[offset] to frame lua know what to do wit it much faster since upvalues (locals) are saved on the stack
especially when you deal with buffs debuffs code speed is usually important especially when you are raiding and lots of buffs/debuffs are flying around
That's the explanation I was looking for, thank you XD
WoW keeps a reference to all frames, which is why they don't get reclaimed. So in effect the statement that frames never get reclaimed, "even if all references are nil'ed and they go out of scope" is not true. It's just that you can't remove all references to frames.