Thread Tools Display Modes
08-08-16, 01:09 AM   #1
Ravenevar
A Defias Bandit
Join Date: Aug 2016
Posts: 2
Same background for multiple frames?

Hi there,

I've been using the same code to place the same background on different frames in my UI. It works fine but I'd like to figure out a more efficient way.

For example, on my PlayerFrame (courtesy of LynMinimap) I might have the following code:

Code:
	local bg = CreateFrame('Frame', nil, PlayerFrame)
	bg:SetPoint('TOPLEFT', PlayerFrame, 0, -26)
	bg:SetPoint('BOTTOMRIGHT', PlayerFrame, 0, 26)
	bg:SetBackdrop({
		bgFile = [[Interface/Buttons/WHITE8X8]],
		tiled = false,
		insets = {left = -3, right = -2, top = -3, bottom = -3}
	})
	bg:SetBackdropColor(0, 0, 0, 1)
	bg:SetFrameLevel(0)
	
	local trans = CreateFrame('Frame', nil, PlayerFrame)
	trans:SetBackdrop({
			bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
			tiled = false,
			insets = {left = -6, right = -5, top = -6, bottom = -6}
	})
	trans:SetPoint('TOPLEFT', PlayerFrame, 0, -26)
	trans:SetPoint('BOTTOMRIGHT', PlayerFrame, 0, 26)
	trans:SetFrameLevel(0)
	trans:SetFrameStrata('BACKGROUND')
	trans:SetBackdropColor(0, 0, 0, 0.6)
Now I want to use this same background for my TargetFrame. Currently I have just copy/pasted the above code and replaced PlayerFrame with TargetFrame and it works, but now I have double the code. Is there a way I can do it more efficiently? Looking at other addons I have tried using "for _,frame in next" and "for index,value in ipairs" but I can't seem to make them work.

Any help is greatly appreciated!
  Reply With Quote
08-08-16, 01:56 AM   #2
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,240
Create a wrapper function that passes a variable, in this case, your intended frame. You can also combine lines 2 & 3.
Code:
local player_frame = MyAddOn:SkinFrame(PlayerFrame)
local target_frame = MyAddOn:SkinFrame(TargetFrame)

function MyAddOn:SkinFrame(frame)
    local bg = CreateFrame('Frame', nil, frame)
    bg:SetPoint('TOPLEFT', frame, "BOTTOMRIGHT", 0, -26)
    -- do the rest of your code here
    return frame -- returns your skinned frame
end
  Reply With Quote
08-08-16, 01:57 AM   #3
Vlad
A Molten Giant
 
Vlad's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2005
Posts: 793
You are already on the right track, spotting the fact the code is the same except in a very few locations. So fixing this shouldn't be hard. We first wrap this in a function, then we give that function an argument we call "parentFrame", then we can easily call the same code as many times as we like, and just provide it with a new frame to work with and do the exact operations.

Code:
local function SkinFrame(parentFrame)
	local bg = CreateFrame('Frame', nil, parentFrame)
	bg:SetPoint('TOPLEFT', parentFrame, 0, -26)
	bg:SetPoint('BOTTOMRIGHT', parentFrame, 0, 26)
	bg:SetBackdrop({
		bgFile = [[Interface/Buttons/WHITE8X8]],
		tiled = false,
		insets = {left = -3, right = -2, top = -3, bottom = -3}
	})
	bg:SetBackdropColor(0, 0, 0, 1)
	bg:SetFrameLevel(0)

	local trans = CreateFrame('Frame', nil, parentFrame)
	trans:SetBackdrop({
		bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
		tiled = false,
		insets = {left = -6, right = -5, top = -6, bottom = -6}
	})
	trans:SetPoint('TOPLEFT', parentFrame, 0, -26)
	trans:SetPoint('BOTTOMRIGHT', parentFrame, 0, 26)
	trans:SetFrameLevel(0)
	trans:SetFrameStrata('BACKGROUND')
	trans:SetBackdropColor(0, 0, 0, 0.6)
end

SkinFrame(PlayerFrame)
SkinFrame(TargetFrame)
There is a final form of optimization we can do, though not a big thing considering it's ONLY used two times. Larger addons, let's say a raid frame with 80 potential units on screen, we could look at the two tables used in bg:SetBackdrop() and trans:SetBackdrop() and considering it's the same table used each time, we could make it so we just reuse the same table from memory, since the function creates a new table each time it is called.

Code:
local BG_BACKDROP = {
	bgFile = [[Interface/Buttons/WHITE8X8]],
	tiled = false,
	insets = {left = -3, right = -2, top = -3, bottom = -3}
}

local TRANS_BACKDROP = {
	bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
	tiled = false,
	insets = {left = -6, right = -5, top = -6, bottom = -6}
}

local function SkinFrame(parentFrame)
	-- <snip>
	bg:SetBackdrop(BG_BACKDROP)
	-- <snip>
	trans:SetBackdrop(TRANS_BACKDROP)
	-- <snip>
end
myrroddin was quicker and replied while I was typing this out, but I'll hit the post button regardless.
__________________
Profile: Curse | Wowhead
  Reply With Quote
08-08-16, 02:00 AM   #4
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,240
Vlad, no worries. I didn't even think about reusing the texture look up more effieciently. Good catch!
  Reply With Quote
08-08-16, 04:24 AM   #5
Ravenevar
A Defias Bandit
Join Date: Aug 2016
Posts: 2
Wow, thanks for the quick replies! Tried it and it works perfectly! And now I see how you guys did it, it makes perfect sense. Thanks so much!

However, I noticed that when two of the "trans" backdrops overlap, the alpha doubles and becomes darker. Is there anyway to avoid this? Let them blend smoothly?

Lastly, a side question, is there an easy way to show frames that are normally not shown, say if I wanted to put the same background on my party frames and wanted to see what it looks like? I'm no longer at my computer atm, but would it just be a case of PartyFrame1:Show() kind of deal?

Thanks again!
  Reply With Quote
08-08-16, 04:46 AM   #6
Vlad
A Molten Giant
 
Vlad's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2005
Posts: 793
Originally Posted by Ravenevar View Post
However, I noticed that when two of the "trans" backdrops overlap, the alpha doubles and becomes darker. Is there anyway to avoid this? Let them blend smoothly?
I don't want to say it's impossible, but I haven't seen any of my addons do something like this either.

Originally Posted by Ravenevar View Post
Lastly, a side question, is there an easy way to show frames that are normally not shown, say if I wanted to put the same background on my party frames and wanted to see what it looks like? I'm no longer at my computer atm, but would it just be a case of PartyFrame1:Show() kind of deal?
Yes. I recommend taking a look at:
http://wowprogramming.com/docs
http://wowprogramming.com/docs/widgets/VisibleRegion

Widgets are basically special tables Blizzard created with their own metatables, often inheriting methods from parent widgets, there is a graph on the site above to illustrate the relations. Note that stuff like "PlayerFrame" are defined in the FrameXML of the game, you can find the sources online here:
https://www.townlong-yak.com/framexml/beta
https://www.townlong-yak.com/framexm...yerFrame.xml#7

You either have the widgets defined/created in the XML files, or you can find lua calling CreateFrame and specifying a widget type to create.
http://wow.gamepedia.com/API_CreateFrame

When modifying the default interface, I recommend first looking the code up and see how it works, usually you want to modify it at certain times, like events or specific function calls, and you can hooksecurefunc/HookScript accordingly and do your own stuff right after Blizzards code does its own thing. It can get a bit tricky with secure frames, if you manage to taint it, secure functions will stop working, like targeting when it comes to unit frames.

Anyway that went far out of scope of the questions you asked. Sorry.
__________________
Profile: Curse | Wowhead
  Reply With Quote
08-08-16, 11:55 AM   #7
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Ravenevar View Post
Lastly, a side question, is there an easy way to show frames that are normally not shown, say if I wanted to put the same background on my party frames and wanted to see what it looks like? I'm no longer at my computer atm, but would it just be a case of PartyFrame1:Show() kind of deal?
For unit frames specifically, just calling :Show() on it will make it appear for about 1 frame, and then it will disappear again, because unit frames are automatically shown or hidden based on whether or not the unit they are assigned to show currently exists.

To work around this, you can temporarily set the frame to show the player unit:

Code:
PartyMemberFrame1.unit = "player"
PartyMemberFrame1:SetAttribute("unit", "player")
Just remember to re-set the unit back to the original one when you're done testing (or just reload the UI).

Here's a small addon that provides a /fakeunits command to toggle the unit on a bunch of Blizzard unit frames:

Code:
local frames = {
    "PetFrame",
    "PartyMemberFrame1",
    "PartyMemberFrame2",
    "PartyMemberFrame3",
    "PartyMemberFrame4",
    "Boss1TargetFrame",
    "Boss2TargetFrame",
    "Boss3TargetFrame",
    "Boss4TargetFrame",
    "ArenaEnemyFrame1",
    "ArenaEnemyFrame2",
    "ArenaEnemyFrame3",
    "ArenaEnemyFrame4",
}

local inFakeMode
function ToggleFakeUnits()
    if InCombatLockdown() then
        return print("Can't change frame units in combat.")
    end
    for i = 1, #frames do
        local f = _G[frames[i]]
        if inFakeMode then
            f.unit = f.__realunit
            f.__realunit = nil
            f:SetAttribute("unit", f.unit)
        else
            f.__realunit = f.unit
            f.unit = "player"
            f:SetAttribute("player")
        end
    end
    inFakeMode = not inFakeMode
end

SLASH_TOGGLEFAKEUNITS1 = "/fakeunits"
SlashCmdList.TOGGLEFAKEUNITS = ToggleFakeUnits

local ef = CreateFrame("Frame")
ef:RegisterEvent("PLAYER_REGEN_DISABLED")
ef:SetScript("OnEvent", function()
    if inFakeMode and UnitAffectingCombat("player") then
        ToggleFakeUnits()
    end
end)
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Same background for multiple frames?

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