Simple Frame XML Help

I’m trying to figure out the Lua code and cannot get it to show on the screen no matter what I try.

Can someone help me with some simple code that shows a frame using XML?

Here is what I tried:

MyAddOn.toc

## Interface: 110002
## Title: MyAddOn|cFF00AA00 v0.1.0|r
## Author: Akorm
## Notes: MyAddOn - Text
## Version: 0.1.0

Frame1.xml
Frame1.lua
MyAddOn.lua

Frame1.xml

<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\..\Blizzard_SharedXML\UI.xsd">
	<Frame name="MyAddOn_Frame">
		<Anchors>
			<Anchor point="CENTER" />
		</Anchors>
		<Frames>
			<Button name="MyAddOn_Button">
				<Anchors>
					<Anchor point="CENTER" />
				</Anchors>
			</Button>
		</Frames>
	</Frame>
</Ui>

Frame1.lua

print("MyAddOn - Frame1 - Start");
print("MyAddOn - Frame1 - End");

Edit:

I also tried this:

print("MyAddOn - Frame1 - Start");
MyAddOn_Frame:Show();
MyAddOn_Button:Show();
print("MyAddOn - Frame1 - End");

MyAddOn.lua

print("MyAddOn - Start");
print("MyAddOn - End");

Result:

MyAddOn - Frame1 - Start
MyAddOn - Frame1 - End
MyAddOn - Start
MyAddOn - End

The UI doesn’t show any frame though, any assistance would be appreciated. I’m a newbie when it comes to AddOn development, but learn best when I can get things working in a basic way to experiment with.

Frames (and other widgets like buttons) by themselves have nothing to display and by default have no size (width/height).

You can change your frame and button to inherit pre-definded templates that have these things (or you could add your own textures, fontstrings etc.) and give them a size as well and an anchor

<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\..\Blizzard_SharedXML\UI.xsd">
	<Frame name="MyAddOn_Frame" parent="UIParent" inherits="ButtonFrameTemplate">
		<Anchors>
			<Anchor point="CENTER" />
		</Anchors>
		<Frames>
			<Button name="MyAddOn_Button" inherits="UIPanelButtonTemplate">
				<Anchors>
					<Anchor point="CENTER" />
				</Anchors>
			</Button>
		</Frames>
	</Frame>
</Ui>

That will just show a frame and button in the middle of your screen.

1 Like

And to help with debugging, install both
https://www.curseforge.com/wow/addons/bug-grabber
and
https://www.curseforge.com/wow/addons/bugsack
if you haven’t already.

1 Like

Thanks! Can you help me with one more probably simple issue I cannot wrap my head around?

Calling a function from another file. I tried several examples I’ve found posted, but they don’t work. Here is one:

MyAddOn.toc

## Interface: 110002
## Title: MyAddOn|cFF00AA00 v0.1.0|r
## Author: Akorm
## Notes: MyAddOn - Text
## Version: 0.1.0

file2.lua
file3.lua
file1.lua

file1.lua

print("1");

requires "/file2.lua"
requires "/file3.lua"

print("2");

someFun = function()
  print("a")
  moreFun()
end

extraFun1 = function()
  local i = 0
  while i < 5 do
    i = i + 1
    moreFun()
  end
end

someFun()
extraFun1()
extraFun2()

file2.lua

morefun = function()
    print("b")
end

file3.lua

extraFun2 = function()
    i = 0
    while i < 10 do
      i = i + 1
      moreFun()
    end
  end

Expected Result:

1
2
someFun() → a & b
extraFun1() → b x 5
extraFun2() → b x 10

Actual Result:

1
(breaks)

So, it obviously breaks at requires "/file2.lua", but the example I was looking at says that is how to do it and when I try other examples I get similar results. Lua doesn’t seem to have much clear documentation or I am looking in the wrong spots. I’m not specifically trying to make anything right this moment, I’m trying to figure things out and it is frustrating when I do a search and people are saying do it one way and when I copy it exactly it doesn’t do anything.

Files are loaded in the order they appear in the .toc.

requires "/file2.lua"

will just error.

If you want to “share” functions/variables between files you either need to make them global (with the understanding that all addons including the default Blizz. UI share the same global space so anything you put there needs to have a unique name eg. prefixed with your addons name) or, you can use a private table that is assigned to and unique to each addon.

At the top of each .lua file add

local addonname, addontable = ...

( addonname and addontable can be any variable name)

addonname name will contain the name of your addon (from the folder) and addontable will contain the table shared with every .lua file under your addons folder.

file1.lua

local addonname, addontable = ...
function addontable.Func1(text)
    print(text)
end

file2.lua

local addonname, addontable = ...
for i=1, 5 do
    addontable.Func1("Line: " .. i)
end

This works if file1.lua is before file2.lua in the .toc.

1 Like

Would I literally put local addonname, addontable = ... or would I do something such as local addonname = "MyAddOn", addontable = {}?

Or would the {} be something such as MyAddOn where functions are called by:

MyAddOn.toc

## Interface: 110002
## Title: MyAddOn|cFF00AA00 v0.1.0|r
## Author: Akorm
## Notes: MyAddOn - Text
## Version: 0.1.0

fileCommon.lua
MyAddOn.lua

fileCommon.lua

local MyAddOn = {};

MyAddOn.Function1 = function()
    print("a");
end;

MyAddOn.Function2 = function()
    print("b");
end;

return MyAddOn;

MyAddOn.lua

MyAddOn.Function3 = function()
    print("c");
end;

MyAddOn.Function1();
MyAddOn.Function2();
MyAddOn.Function3();

Result:

a
b
c

? Apologies for the probably simple questions, trying to learn stuff right and not toss everything into 1 large file.

Think of each .lua file as a function
The ... is a variable number of arguments passed the function (file), currently just the two.

function fileCommon.lua(...)
    local addonname, addontable = ...
    -- The rest of your file code
end

and it’s called (loaded) like:

local addonsPrivateTable = {}
fileCommon.lua("addonfoldername", addonsPrivateTable)
1 Like

fileCommon.lua

local addonname, addontable = ...
local MyAddOn = {};
addontable.MyAddOn = MyAddOn

MyAddOn.Function1 = function()
    print("a");
end;

MyAddOn.Function2 = function()
    print("b");
end;

MyAddOn.lua

local addonname, addontable = ...
local MyAddOn = addontable.MyAddOn

MyAddOn.Function3 = function()
    print("c");
end;

MyAddOn.Function1();
MyAddOn.Function2();
MyAddOn.Function3();

You don’t need to got to/from local MyAddOn but it can save some typing in a large addon not having to prefix everything with addontable.

1 Like

Great! That gives me the ability to share functions between files. I have a few more questions to grasp this specific topic. I appreciate your patience.

In fileCommon.lua you have this (I modified it slightly):

local _, globalTable = ...;
local localTable = {};
globalTable.ThisCanBeAnything = localTable;

From what I understand, we define localTable as a table to hold the functions below. Then globalTable.ThisCanBeAnything stores a pointer to that localTable which can be shared to other files where they can be used, expanded on, or overridden.

It works with that and gives me (as expected):

a
b
c

I have a question though, I was able to change it from local addOnName, globalTable = ...; to local _, globalTable = ...; and it works (I saw that you can use _ to indicate unused), but if I remove _ it stops working even though the _ isn’t used in the rest of the code. Can you explain why it has to be there?

Go back to the part about the file being a function with the declaration

function fileCommon.lua(...)
    -- your code here
end

Each .lua file is always passed two parameters, 1, the addon name (folder name) and 2, the private table.

local _, globalTable = ...;

is just saying “I’m not interested in using the 1st addon name parameter so I’m just going to throw it away to _, but I do want the 2nd addon table parameter so assign that to globalTable

In lua you can create and assign multiple variables “in-line”

local a, b, c = 1, 2, 3
local arg1, _, arg3 = Return3orMoreValuesFunc() -- only want 1st and 3rd returns
1 Like

I get it now, thanks! Now that I know that is what happens behind the scenes it makes sense.