8.1 UI Templates Addon changes?

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)