Thread Tools Display Modes
06-20-16, 10:18 AM   #1
maqjav
A Theradrim Guardian
AddOn Author - Click to view addons
Join Date: Feb 2012
Posts: 60
Reuse frame

Hello.

I have a table with 5 frames pre-created that I want to reuse to show different icons.

Code:
local mainFrame = _G.CreateFrame("Frame", "ItemsBar", UIParent)
mainFrame:SetSize(200, 20)
mainFrame:SetPoint("BOTTOM", UIParent, 0, 300)

local itemFrames = {}
for i=1, 5 do 
	local frame = _G.CreateFrame("Frame", "ItemFrame"..i, mainFrame)
	frame:SetSize(20, 20)
	frame:SetPoint("LEFT", (5+16)* (i-1), 0)
	itemFrames[i] = frame
end
The idea is that when I type an ID, I read from another table a list of items, and I want to display its icons on my itemFrames.

Code:
function loadItems(itemsIds) then
	-- clear frames
	for i, frame in ipairs(itemFrames) then
		itemFrame:ClearAllPoints()
		itemFrame:Hide()
	end

	for i, itemId in ipairs(itemsIds) do
		local _, _, _, _, _, _, _, _, _, itemTexture, _ = GetItemInfo(itemId)
		if itemTexture and i <= 5 then
			local texture = itemFrames[i]:CreateTexture()
			texture:SetSize(18, 18)
			texture:SetTexture(itemTexture)
			texture:SetAllPoints(itemFrames[i])
			itemFrames[i]:Show()
		else break
		end
	end
end
If I use this method too many times it will consume a lot of memory, because I will be creating a Texture per icon every time, so the first question is: can I change a frame texture without creating a new one?

The second problem I have is that this code works fine the first time, the next times or it doesn't show icons at all, or some of them have the previous textures, or if my array has 5 items but the previous time it had 3, it will show only 3 ignoring the last 2. It seems to have a random behaviour.

Thanks.
 
06-20-16, 10:53 AM   #2
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
Create the texture when you create the frame, store a reference to the texture like frame.texture = texture, then set the texture like itemFrames[i].texture:SetTexture() instead of creating a new one every time you want to show it.

You're also clearing itemFrame's points when it's hidden but never setting them. If they're supposed to be static then there's no reason to clear their points, otherwise you need to clear and set them every time they need to move, but there isn't really any reason to do that when they're hidden.

Also this loop is going to break as soon as itemTexture returns nil, which means it can break before it gets to 5. I'm not sure if that's the intended behavior or not.
 
06-20-16, 11:26 AM   #3
maqjav
A Theradrim Guardian
AddOn Author - Click to view addons
Join Date: Feb 2012
Posts: 60
Thank you semlar for your answer.

I modified the code like this:

Code:
local itemFrames = {}
for i=1, 5 do 
	local frame = _G.CreateFrame("Frame", "ItemFrame"..i, mainFrame)
	frame:SetSize(20, 20)
	frame:SetPoint("LEFT", (5+16)* (i-1), 0)
	frame.texture = frame:CreateTexture()
	frame.texture:SetAllPoints(frame)
	itemFrames[i] = frame
end
In my method I removed ClearAllPoints, you were right about it, and now I only set the texture using the reference.

Code:
function loadItems(itemsIds) then
	-- clear frames
	for i, frame in ipairs(itemFrames) then
		itemFrame:Hide()
	end

	for i, itemId in ipairs(itemsIds) do
		local _, _, _, _, _, _, _, _, _, itemTexture, _ = GetItemInfo(itemId)
		if itemTexture and i <= 5 then
			print("In the loop")
			itemFrames[i]:texture:SetTexture(itemTexture)
			itemFrames[i]:Show()
		else break
		end
	end
end
Breaking the loop with itemTexture nil is the idea, that's correct.

With this change I keep having the random behaviour, some times it renders the icons and other times it doesn't, however I can see in the chat the log "In the loop" as many times as items I have.

At least now the memory is not increasing like crazy, however... after some tests wow client crash with the next message:


Last edited by maqjav : 06-20-16 at 11:28 AM.
 
06-20-16, 11:39 AM   #4
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
Originally Posted by maqjav View Post
itemFrames[i]:texture:SetTexture(itemTexture)
should be
Lua Code:
  1. itemFrames[i].texture:SetTexture(itemTexture)

But I can't say what's causing your erratic behavior without the rest of your code.
 
06-20-16, 11:56 AM   #5
maqjav
A Theradrim Guardian
AddOn Author - Click to view addons
Join Date: Feb 2012
Posts: 60
Originally Posted by semlar View Post
should be
Lua Code:
  1. itemFrames[i].texture:SetTexture(itemTexture)

But I can't say what's causing your erratic behavior without the rest of your code.
Sorry, it was a mistake writing on the forum, in my code I actually have it like you say. I guess the critical wow client error might be something with the PTR. I will keep testing it.

About the erratic behaviour I wonder if it's related with showing and hidding the mainFrame.

Whenever I type my NPC ID, I look for it in a table, then I call my method loadItems and right after I call "mainFrame:Show()".

Code:
local itemsIds = LIST[npcId]
loadItems(itemsIds)
mainFrame:Show()
My mainFrame has a closeButton, and only when I click the button the mainFrame is hidden.
If you type another NPC ID while the frame is open, the idea is that it has to refresh, that's why in my mehod loadItems the first thing I do is to Hide every itemFrame (just in case the itemsIds arrays is smaller than the previous one).

Code:
local CloseButton = _G.CreateFrame("Button", "CloseButton", mainFrame, "UIPanelCloseButton")
CloseButton:SetPoint("BOTTOMRIGHT")
CloseButton:SetSize(32, 32)
CloseButton:SetHitRectInsets(8, 8, 8, 8)
The rest of code I don't think it really matters.


Thank you very much for your time.
 
06-20-16, 01:08 PM   #6
maqjav
A Theradrim Guardian
AddOn Author - Click to view addons
Join Date: Feb 2012
Posts: 60
Ok I found what was causing the erratic issue.
The method GetItemInfo is asynchronous and it doesn't respond with information right away, and it seems WoW doesn't keep the cache between sessions anymore, so even if I tested with the same items the problem was still there.

In order to make it work I have to register the event GET_ITEM_INFO_RECEIVED and whenever I get the information then load the texture in my itemFrame.

The wow client crash is still there, it ocurrs radomnly whenever it tries to set a new fileID to an existing texture. I really hope this is just a bug and it will be fixed in future PTR releases.
 
06-20-16, 01:19 PM   #7
dssd
A Fallenroot Satyr
Join Date: May 2016
Posts: 25
Originally Posted by maqjav View Post
Ok I found what was causing the erratic issue.
The method GetItemInfo is asynchronous and it doesn't respond with information right away, and it seems WoW doesn't keep the cache between sessions anymore, so even if I tested with the same items the problem was still there.

In order to make it work I have to register the event GET_ITEM_INFO_RECEIVED and whenever I get the information then load the texture in my itemFrame.

The wow client crash is still there, it ocurrs radomnly whenever it tries to set a new fileID to an existing texture. I really hope this is just a bug and it will be fixed in future PTR releases.

You can use GetItemInfoInstant(itemID) to get the texture file ID immediately. You can't get the name or some other data as that's asynchronous as you discovered.

You should post the crash with code reduced to the smallest that can still reproduce on the Legion UI Bugs forum to make sure Blizz is aware.
 
06-21-16, 11:13 AM   #8
maqjav
A Theradrim Guardian
AddOn Author - Click to view addons
Join Date: Feb 2012
Posts: 60
I've been playing with tooltips and it seems that the client crash is related.

I can make it crash if I'm showing a list of icons, I put the mouse on top of one (the tooltip shows up) and then I try to reload the bar with new icons.

Code:
local itemFrames = {}
for i=1, 5 do 
	local frame = _G.CreateFrame("Frame", "ItemFrame"..i, mainFrame)
	frame:SetSize(20, 20)
	frame:SetPoint("LEFT", (5+16)* (i-1), 0)
	frame.texture = frame:CreateTexture()
	frame.texture:SetAllPoints(frame)

	-- set tooltip
	frame:SetScript("OnEnter", function(self)
		if self.link then
			GameTooltip:SetOwner(self, "ANCHOR_LEFT")
			GameTooltip:SetHyperlink(self.link)
			GameTooltip:Show()
		end
	end)
	frame:SetScript("OnLeave", function(self)
		if self.link then
			GameTooltip:Hide()
		end
	end)

	itemFrames[i] = frame
end
And in my loadItems method I update the hyperlink extracting it from GetItemInfo.

Without the "OnEnter" and "OnLeave" methods seems pretty stable, however with them, the crash always ocurrs with the second call to "loadItems" (only if the tooltip is visible).

I'm trying to make a little example to demostrate this crash, let's see what I get, this issue is making me crazy.
 
06-21-16, 11:40 AM   #9
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
Originally Posted by dssd View Post
You can use GetItemInfoInstant(itemID) to get the texture file ID immediately.
GetItemInfoInstant is not a function, did you mean something else?
 
06-21-16, 12:25 PM   #10
dssd
A Fallenroot Satyr
Join Date: May 2016
Posts: 25
Originally Posted by semlar View Post
GetItemInfoInstant is not a function, did you mean something else?
Hrm, nope. It's there on beta build 22000 and maybe earlier?

It was recently used in StaticPopupItemFrame_RetrieveInfo of StaticPopup.lua presumably to avoid the delayed texture lookup.
 
06-21-16, 12:55 PM   #11
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
It looks like they added it a week ago; it's not in simca's api diff and the beta servers have been too unstable to log into to check.
 
06-21-16, 12:58 PM   #12
maqjav
A Theradrim Guardian
AddOn Author - Click to view addons
Join Date: Feb 2012
Posts: 60
Ok, I found a workaround for the bug.

I found in the forum this old thread http://www.wowinterface.com/forums/s...260#post255260 where they (including you semlar) were talking about a crash produced by GameTooltip:Hide()

It seems the problem is connected (wasn't this bug fixed?), because if I add this little change
Code:
if self:IsShown() then
	GameTooltip:Hide()
end
seems to work just fine, although if I don't show any item in the next click, of course the popup will be shown forever. If there are items though the tooltip will refresh itself as soon as I move the mouse on top of a new icon.

I have to find a better solution for this.
 
 

WoWInterface » Site Forums » Archived Beta Forums » Legion Beta archived threads » Reuse frame

Thread Tools
Display Modes

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