WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Legion Beta archived threads (https://www.wowinterface.com/forums/forumdisplay.php?f=177)
-   -   Reuse frame (https://www.wowinterface.com/forums/showthread.php?t=53738)

maqjav 06-20-16 10:18 AM

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.

semlar 06-20-16 10:53 AM

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.

maqjav 06-20-16 11:26 AM

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:


semlar 06-20-16 11:39 AM

Quote:

Originally Posted by maqjav (Post 315834)
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.

maqjav 06-20-16 11:56 AM

Quote:

Originally Posted by semlar (Post 315835)
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.

maqjav 06-20-16 01:08 PM

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.

dssd 06-20-16 01:19 PM

Quote:

Originally Posted by maqjav (Post 315840)
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.

maqjav 06-21-16 11:13 AM

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.

semlar 06-21-16 11:40 AM

Quote:

Originally Posted by dssd (Post 315841)
You can use GetItemInfoInstant(itemID) to get the texture file ID immediately.

GetItemInfoInstant is not a function, did you mean something else?

dssd 06-21-16 12:25 PM

Quote:

Originally Posted by semlar (Post 315879)
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.

semlar 06-21-16 12:55 PM

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.

maqjav 06-21-16 12:58 PM

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.


All times are GMT -6. The time now is 07:37 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI