One of my favorite addons stopped working correctly after the 8.1 update while the addon itself hasn’t changed since just after 8.0 went live. Yes, I have posted on the addon’s curseforge page but the code that is broken now previously did work and its just so “out there” that I feel compelled (I AM BIDDEN!) to understand how it ever worked and maybe why its not working now.
Obviously, it has a lot to do with my lack of familiarity with Lua and WoW API’s.
Basically the addon has an XML to define its primary UI including its main frame like this:
<Frame name="MyFrameName" toplevel="true" movable="true" parent="UIParent" enableMouse="true" hidden="true" inherits="ButtonFrameTemplate">
lots of other stuff
<Scripts>
<OnLoad function="MyFrameName_onLoad"/>
</Scripts>
</Frame>
The onload function begins like this:
MyFrameName_onLoad = function( self )
MyFrameNameTopBorder:SetVertexColor(1, .75, .2, 1);
It’s this object reference that’s causing it to fail MyFrameNameTopBorder
with this error:
attempt to index global 'MyFrameNameTopBorder' (a nil value)
No where in the code or xml is there an explicit MyFrameNameTopBorder
object/variable actually defined, so how did it ever work?
My guess is that MyFrame was relying on ButtonFrameTemplate
to create the object reference in a implicittable[_FrameName_ .. _ElementName_]
sort of way and the Lua language allows a shortcut reference to that through self so instead of implicittable["KeyName"]:Method()
it’s allowing KeyName:Method()
directly.
If that’s how it was working pre-8.1, why did it stop working in 8.1?
Undocumented changes in ButtonFrameTemplate? Anyone know what that would be?
Or was my fav addon’s author not doing the correct initialization to begin with and it’s just now caught up with him? And how should these items be initialized?
<Frame name="MyFrame" ... >
<Texture name="$parentTopBorder" ... />
</Frame>
$parent denotes that the sub-frame’s name inherits the parent’s name hence MyFrameTopBorder. Same using CreateFrame
local f = CreateFrame(“Frame”, “$parentTopBorder”, MyFrame)
f will have the name “MyFrameTopBorder”
Many sub-elements are getting rid of using name and being added to the parent as a key
<Frame name="MyFrame" ... >
<Texture parentKey="TopBorder" ... />
</Frame>
This will be access using dot notation ie. MyFrame.TopBorder.
1 Like
The “$parentTopBorder” makes sense and since I’m not seeing anything like that in the addon’s xml it must have been originally inherited from ButtonFrameTemplate. I’ll need to find a current copy of ButtonFrameTemplate and see what’s in it.
Yep, Blizz removed a ton of stuff from this template.
https://www.townlong-yak.com/framexml/live/SharedUIPanelTemplates.xml/diff
https://www.townlong-yak.com/framexml/live/SharedUIPanelTemplates.lua/diff
I haven’t taken an extensive look but if any frame/template inherits from DefaultPanelTemplate then $parentTopBorder
changed to $parentTitleBg
with a parent key of .TitleBg ie. ParentFrame.TitleBg
Edits: It looks like the current base template of ButtonFrameTemplate
(PortraitFrameTemplateNoCloseButton) is using textures build up using the NineSlice mixin rather than the fixed xml entities of 8.0.1 and earlier.
Frames inheriting ButtonFrameTemplate
and anything else that inherits PortraitFrameTemplateNoCloseButton will have a table called “NineSlice” which holds the individual pieces. You can see them using
for k,v in pairs(FrameName.NineSlice) do
print(k, v)
end
Where FrameName is your frames global table name entry.
They can be shown/hidden/SetVertexColor etc. using FrameName.NineSlice.Entity:Hide()
where Entity is one of
TopLeftCorner
TopRightCorner
BottomLeftCorner
BottomRightCorner
TopEdge
BottomEdge
LeftEdge
RightEdge
Center (if it exists)