Quantcast Finding Frames of other Addons and overwriting their position - WoWInterface
Thread Tools Display Modes
06-22-19, 06:36 AM   #1
Lybrial
A Theradrim Guardian
AddOn Compiler - Click to view compilations
Join Date: Jan 2010
Posts: 66
Finding Frames of other Addons and overwriting their position

Hi,

Im using several AddOns and some of them do not allow to anchor to certain frames.
So what I really would like to do is to be able to find those frames and to overwrite them.
Yet I could not find any way to do this. At first I would need to find frames by its name:

Code:
local children = { UIParent:GetChildren() }

for _, child in ipairs(children) do
     print("child: " .. child:GetName());
end
--> Does not work

Code:
local frame = EnumerateFrames();

while frame do
    print("child: " .. frame:GetName());

    frame = EnumerateFrames(frame));
end
--> Also does not work

Is there no way to iterate over all frames and to find the frame I need by its name?

Last edited by Lybrial : 06-22-19 at 06:38 AM.
  Reply With Quote
06-22-19, 06:56 AM   #2
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,122
If the frame does have a name, you should be able to type /fstack in-game and mouse over the frame. Type /fstack again to turn it off.

You might also want to install FrameStackGlobalizer
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
06-22-19, 07:00 AM   #3
Lybrial
A Theradrim Guardian
AddOn Compiler - Click to view compilations
Join Date: Jan 2010
Posts: 66
Hi,

this is not what I need. I mean it is what I need to find the names BUT
I need to get a frame by its name in luca code. Not ingame. I need something like:

Code:
local frame = FindFrameByName("Grid2LayoutFrame"); -- example
frame:SetPoint("CENTER", myFrame, "CENTER, 0, 0);

Last edited by Lybrial : 06-22-19 at 07:13 AM.
  Reply With Quote
06-22-19, 07:22 AM   #4
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,326
This code you showed, will work but it will error out if that particular child doesn't have a name
Code:
local children = { UIParent:GetChildren() }

for _, child in ipairs(children) do
     print("child: " .. child:GetName());
end
Change it to the following and see what output you get then.
Code:
local children = { UIParent:GetChildren() }

for _, child in ipairs(children) do
     local name = child:GetName()
     if name then print(name) else print("Not Named") end
end
You could then expand that as a recursive function to repeat the process for every frame... then instead of printing the name out, simply create a table of frames with a name containing the frame handle ... then you can use that table for a search by name tool.

I've not needed to do this myself but theoretically it is sound.
__________________
  Reply With Quote
06-22-19, 07:41 AM   #5
Lybrial
A Theradrim Guardian
AddOn Compiler - Click to view compilations
Join Date: Jan 2010
Posts: 66
Hi, thx for your quick reply.

Yes, the code works. But it only prints out 223 children of 398

Code:
print("amount children: " .. UIParent:GetNumChildren());
	
local children = { UIParent:GetChildren() };
	
for key, child in ipairs(children) do
	local name = child:GetName() or child:GetDebugName();
			
	if name then 
		print(key .. ": " .. name);
	else 
		print(key .. ": " .. "Not Named");
	end
end
I know the names of some frames. "Grid2LayoutFrame" frame for
example is a child of UIParent. Thats what im getting with /framestack.
But this frame is not appearing in the list of frames im printing.

Btw. Not Named is never printed out. Its erroring out after 223 items.

Last edited by Lybrial : 06-22-19 at 07:44 AM.
  Reply With Quote
06-22-19, 08:35 AM   #6
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,122
Are you getting an error for trying to access a forbidden object?
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
06-22-19, 08:43 AM   #7
Lybrial
A Theradrim Guardian
AddOn Compiler - Click to view compilations
Join Date: Jan 2010
Posts: 66
No, no error. Its just silently crashing. The code after the loop is also not continuing.

Code:
print("amount children: " .. UIParent:GetNumChildren());
	
local children = { UIParent:GetChildren() };
	
for key, child in ipairs(children) do
	local name = child:GetName() or child:GetDebugName();
			
	if name then 
		print(key .. ": " .. name);
	else 
		print(key .. ": " .. "Not Named");
	end
end

print("done");
So in thise case after child number 223 it is silently erroring out and the done
is never getting printed.
  Reply With Quote
06-22-19, 08:49 AM   #8
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,122
Do you have BugGrabber and BugSack installed?

It shouldn't be that silent.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
06-22-19, 08:53 AM   #9
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,122
I think you need to be a bit more specific about what you are trying to anchor too or start your child search at Grid2LayoutFrame.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
06-22-19, 09:03 AM   #10
Lybrial
A Theradrim Guardian
AddOn Compiler - Click to view compilations
Join Date: Jan 2010
Posts: 66
You are right, with BugSack I get an error:

Code:
1x Lybrial_Anchors\init.lua:90: Attempt to access forbidden object from code tainted by an AddOn
[C]: in function `GetName'
Lybrial_Anchors\init.lua:90: in function <Lybrial_Anchors\init.lua:78>
[C]: ?
...aceMasque\Libs\AceAddon-3.0\AceAddon-3.0-12.lua:70: in function <...aceMasque\Libs\AceAddon-3.0\AceAddon-3.0.lua:65>
...aceMasque\Libs\AceAddon-3.0\AceAddon-3.0-12.lua:527: in function `EnableAddon'
...aceMasque\Libs\AceAddon-3.0\AceAddon-3.0-12.lua:540: in function `EnableAddon'
...aceMasque\Libs\AceAddon-3.0\AceAddon-3.0-12.lua:620: in function <...aceMasque\Libs\AceAddon-3.0\AceAddon-3.0.lua:605>
[C]: in function `LoadAddOn'
FrameXML\UIParent.lua:446: in function `UIParentLoadAddOn'
FrameXML\UIParent.lua:565: in function `TimeManager_LoadUI'
FrameXML\UIParent.lua:1192: in function <FrameXML\UIParent.lua:1090>
And to be specific with what I want to achieve:

I have created WeakAuras which are anchored to the personal player resource nameplate.
So when the nameplate moves my WeakAuras move too. I want to do this for other AddOns
too. Raven for example supports this functionality out of the box. In the options frame I can
choose an anchor. Other AddOns like Grid2 or Hekili are not providing such a functionality.

That is why I wanted to implement a small Addon which picks up the frames of some predefined
AddOns and overwrites their anchor and position on the screen.

So for example I have the Grid2LayoutFrame which is the root frame of Grid2 and a child
of UIParent. So my Idea was to iterate over all frames of the UIParent to get the
Grid2LayoutFrame and to be able to modify its attributes.

Without iterating the children of UIParent and comparing the frame names I do not see
any possiblity to access the frames that I need.

Last edited by Lybrial : 06-22-19 at 09:07 AM.
  Reply With Quote
06-22-19, 10:01 AM   #11
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,122
Grid2LayoutFrame is the name of the frame. You don't have to "find" it.

Code:
/run print(Grid2LayoutFrame)
For clarity, for any frame that has been given a name, that name (and associated frame) is stored as a global

If you are creating names from strings build from the name you can locate them in the global table
Code:
/run print(_G["Grid2LayoutFrame"])
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
06-22-19, 10:06 AM   #12
Lybrial
A Theradrim Guardian
AddOn Compiler - Click to view compilations
Join Date: Jan 2010
Posts: 66
Holy moly you are right.
That makes stuff a lot easier. Thank you!
  Reply With Quote
06-22-19, 10:14 AM   #13
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,122
Makes /fstack look a whole lot more useful
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
06-22-19, 10:21 AM   #14
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,326
Rofl Fizzle .. I actually do it that way but for some reason didn't equate why I do it to why he does but I do it for the same reason... I think the loop exanple confused me .. yes, lets go with that rofl.
__________________
  Reply With Quote
06-23-19, 09:14 PM   #15
MooreaTv
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: May 2019
Posts: 19
Not what the OP wanted which is solved (as named frames are global)

But what if you want to see all frames, or rather all frames you are allowed to see,
how would one skip over the forbidden one and get the loop above to not fail in the middle?
  Reply With Quote
06-23-19, 09:33 PM   #16
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,122
IsForbidden
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
06-24-19, 03:50 AM   #17
MooreaTv
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: May 2019
Posts: 19
Thanks Fizzlemizz!
  Reply With Quote
06-26-19, 12:16 PM   #18
Lybrial
A Theradrim Guardian
AddOn Compiler - Click to view compilations
Join Date: Jan 2010
Posts: 66
I was able to anchor my frames perfectly to the player resource bar:

Code:
	if (self.anchorFrame) then
		return;
	end
	
	self.anchorFrame = CreateFrame("Frame", "LybrialUIAnchor", UIParent);
	self.anchorFrame:Hide();
	self.anchorFrame.attachedVisibleFrames = {};
	self.anchorFrame:RegisterEvent("NAME_PLATE_UNIT_ADDED");
	self.anchorFrame:RegisterEvent("NAME_PLATE_UNIT_REMOVED");			
	self.anchorFrame.Attach = function(self, frame, frameTopLeft, frameBottomRight)
		self:SetParent(frame);
		self:ClearAllPoints();
		self:SetPoint("TOPLEFT", frameTopLeft, "TOPLEFT", 0, 0);
		self:SetPoint("BOTTOMRIGHT", frameBottomRight, "BOTTOMRIGHT", 0, 0);
		self:Show();
	end
	self.anchorFrame.Detach = function(self, frame)
		self:ClearAllPoints();
		self:Hide();
	end
	self.anchorFrame.eventHandler = function(self, event, nameplate)
		if (event == "NAME_PLATE_UNIT_ADDED") then
			if (UnitIsUnit(nameplate, "player")) then
				local frame = C_NamePlate.GetNamePlateForUnit("player");
				
				if (frame) then
					if (frame.kui and frame.kui.bg and frame.kui:IsShown()) then
						LybrialAnchors.anchorFrame:Attach(frame.kui, KuiNameplatesPlayerAnchor, KuiNameplatesPlayerAnchor);
					elseif (ElvUIPlayerNamePlateAnchor) then
						LybrialAnchors.anchorFrame:Attach(ElvUIPlayerNamePlateAnchor, ElvUIPlayerNamePlateAnchor, ElvUIPlayerNamePlateAnchor);
					else
						LybrialAnchors.anchorFrame:Attach(frame, frame.UnitFrame.healthBar, NamePlateDriverFrame.classNamePlatePowerBar);
					end
					
					LybrialAnchors.anchorFrame:Show();
					LybrialAnchors:OnUpdate();
				else
					LybrialAnchors.anchorFrame:Detach();
					LybrialAnchors.anchorFrame:Hide();
					LybrialAnchors:OnUpdate();
				end
			end
		elseif (event == "NAME_PLATE_UNIT_REMOVED") then
			if (UnitIsUnit(nameplate, "player")) then
				LybrialAnchors.anchorFrame:Detach();
				LybrialAnchors.anchorFrame:Hide();
				LybrialAnchors:OnUpdate();
			end
		end
	end
	self.anchorFrame:SetScript("OnEvent", self.anchorFrame.eventHandler);
To anchor raven to my frame I do this:

Code:
function Raven:SetupFrames()
	if (self.isLoaded and self.db.profile.enabled) then
		table.foreach(self.frames, function(key, value)
			local frame = _G[value];
			
			if (frame) then
				frame:ClearAllPoints();
				
				if (value == "RavenBarGroupShort_Buffs") then
					frame:SetPoint("CENTER", LybrialAnchors.anchorFrame, "CENTER", -215, -59);
				elseif (value == "RavenBarGroupDebuffs") then
					frame:SetPoint("CENTER", LybrialAnchors.anchorFrame, "CENTER", -215, -134);
				elseif (value == "RavenBarGroupZiel") then
					frame:SetPoint("CENTER", LybrialAnchors.anchorFrame, "CENTER", 217, -59);
				elseif (value == "RavenBarGroupCooldowns") then
					frame:SetPoint("CENTER", LybrialAnchors.anchorFrame, "CENTER", 0, -224);
				end
			end
		end);
	end
end
But here we are now at Patch 8.2 and as expected:

Code:
7x Raven\Nest.lua:918: Action[FrameMeasurement] failed because[Can't measure restricted regions]: attempted from: RavenBarGroupDebuffs:GetLeft().
[C]: in function `GetLeft'
Raven\Nest.lua:918: in function `Nest_GetAnchorPoint'
Raven\Bars.lua:677: in function `UpdatePositions'
Raven\Bars.lua:2099: in function `UpdateBars'
Raven\Main.lua:1109: in function `Update'
Raven\Main.lua:820: in function <Raven\Main.lua:816>

Locals:
(*temporary) = RavenBarGroupDebuffs {
 0 = <userdata>
}
Is there any way around this?
  Reply With Quote
06-26-19, 11:21 PM   #19
Lybrial
A Theradrim Guardian
AddOn Compiler - Click to view compilations
Join Date: Jan 2010
Posts: 66
So nameplates are "restricted frames now" so if I would attach raven
to nameplates I would not be able to call functions like GetCenter(),
GetLeft() etc on nameplates frame, right? But that is not what im
doing here. Im creating another frame, an "anchorFrame" and
attach this frame to the nameplates. Raven is then getting attached
to the anchorFrame.

The error says that raven was not able to call GetLeft() etc. on
that anchor frame.

So is a child frame of a restricted frame automatically restricted too?
Hell that would suck
  Reply With Quote
06-26-19, 11:39 PM   #20
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,122
Yes. Being able to attach an "unrestricted intermediary" frame wold defeat the purpose of restricting nameplates in the first place.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Finding Frames of other Addons and overwriting their position

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