Circonians Saved Variables Tutorial

From ESOUI Wiki

Jump to: navigation, search



Contents

Tutorial Preface

In this tutorial we will be building on the previous tutorial Circonians Stamina Bar Tutorial. If you have not worked through it first I suggest you start there. You can find it here: [Circonians Stamina Bar Tutorial] We will be adding the ability to remember the location that a user has moved the stamina bar to on the screen. This way when our addon loads up it will be in the same place the user left it.


Tutorial Prerequisites

This tutorial carries on where Circonians Stamina Bar Tutorial left off. It is expected that you have all ready worked through that tutorial and have the completed addon working. We will be adding features to that addon and we will not be covering any information that was all ready covered in that previous tutorial. If you have not yet worked through that tutorial, don't have the code for it, or just need to look back at it as a refresher you can find it here: [Circonians Stamina Bar Tutorial]




Saved Variables Location

When ESO saves variables for your addon it saves them in: C:\Users\<user>\Documents\Elder Scrolls Online\live\SavedVariables in a lua file named after your addon. In our case our addon is called CirconianStaminaBar, so in the SavedVariables folder it will create a lua file called CirconianStaminaBar.lua
You do not have to create this file yourself. Once you tell ESO that you want to save variables (and actually save something) it will create this file for you.


The txt File

The way that we tell ESO that we want to save variables is by adding a special line to our txt file.

## SavedVariables: <table name to save variables under>

Remember that variables are saved in a file named after your addon. The name that we give it above is the table name INSIDE of that saved variables file that it saves the variables in. So in our example we are going to used:

## SavedVariables: CirconianStaminaBarVars

Once we do that AND actually save some variable ESO will automatically create the SavedVariables file for us. I want to reiterate this line alone will not force the creation of your SavedVariable files UNTIL you actually save something. So if you add this line and go looking in the SavedVariables folder and wonder why its not there it is because you must actually save something first before it will create the file.


Your txt file should now look like this:

## Title: Circonians Stamina Bar
## Description: Circonians Stamina Bar Version 1.0
## APIVersion: 100008
## SavedVariables: CirconianStaminaBarVars
 
CirconianStaminaBar.lua
CirconianStaminaBar.xml



The Lua File

Version Number

First lets change the version number for our addon.

-- Find this line
-- CirconianStaminaBar.version = 1
-- change it to this, version 2
CirconianStaminaBar.version = 2

Default Settings

First we will create a table to hold the default settings for our addon. We all ready have a table: CirconianStaminaBar in our lua code file so lets create out default settings table inside of that. We will name it Default. In your CirconianStaminaBar.lua file add the following lines of code near the top under CirconianStaminaBar = { }

CirconianStaminaBar = {}
 
-- Add these lines here:
CirconianStaminaBar.Default = {
	OffsetX = 20,
	OffsetY = 75
}

This creates a table named Default INSIDE of the table CirconianStaminaBar. Our new table contains two variables: OffsetX and OffsetY OffsetX has a value of 20 and OffsetY has a value of 75. These will be used for the offset of the starting location for our stamina bar relative to the TOPLEFT corner of GuiRoot (the main screen).

These values will be used to offset the X-Axis and Y-Axis when we re-anchor our control.

If you forget what anchoring is go back to [Circonians Stamina Bar Tutorial] and have a look at the <anchor> tag in the section on xml Structure.

ZO_SavedVars

In order to actually save variables to our SavedVariables file we must tell ESO how to recognize the variables in our code that we want to save. We do this by adding a single line to our initialization function:

CirconianStaminaBar.savedVariables = ZO_SavedVars:New("CirconianStaminaBarVars", CirconianStaminaBar.version, nil, CirconianStaminaBar.Default)



Lets break that down and see what it all means:

CirconianStaminaBar.savedVariables

This part tells ESO what we are going to call the SavedVariables table in our code. Anything that we put into that table will automatically be saved to our SavedVariables file.


ZO_SavedVars:New(...)

This part calls the New function on ZO_SavedVars (a built in control used for saving variables).


"CirconianStaminaBarVars"

This part tells ESO what table name to use inside of our SavedVariables file to save our variables in. So in our case our SavedVariables file (remember it has the same name as your addon) is called CirconianStaminaBar.lua Inside of it ESO will create a table called CirconianStaminaBarVars to save our variables in.
The table name that you use here MUST match the SavedVariables name you used in your txt file. If it does not then it will not save your variables


This part of the code:

CirconianStaminaBar.version

Tells ESO what version our addon is.


The third parameter which I have listed as:

nil

This parameter is an optional string namespace used to separate other variables using the same table. (Thanks Garkin)


The fourth parameter which I have listed as:

CirconianStaminaBar.Default

Is used to pass a table of default variables to ZO_SavedVars. If anything inside of that default table does NOT exist inside of your SavedVariables file then it will be added to the file. However if the variable all ready exists in the SavedVariables file then it will NOT be used.


After adding the new line of code your initialization function should look like this:

function CirconianStaminaBar:Initialize()
	CirconianStaminaBar.savedVariables = ZO_SavedVars:New("CirconianStaminaBarVars", CirconianStaminaBar.version, nil, CirconianStaminaBar.Default)
 
        local ourName = GetUnitName("player")
 	CirconianStaminaBarWindowLabel:SetText(ourName)
 
	local current, max, effectiveMax = GetUnitPower("player", POWERTYPE_STAMINA)
	CirconianStaminaBarWindowStatusBar:SetMinMax(0, max)
	CirconianStaminaBarWindowStatusBar:SetValue(current)
 
	EVENT_MANAGER:UnregisterForEvent(CirconianStaminaBar.name, EVENT_ADD_ON_LOADED)
end


Saving A Location

In order to save the location that a user drags our stamina bar to we need to create a function to take care of that work. We will call it: CirconianStaminaBar.SaveLoc() In your CirconianStaminaBar.lua file create the following new function:

function CirconianStaminaBar.SaveLoc()
	CirconianStaminaBar.savedVariables.OffsetX = CirconianStaminaBarWindow:GetLeft()
	CirconianStaminaBar.savedVariables.OffsetY = CirconianStaminaBarWindow:GetTop()
end



CirconianStaminaBar.savedVariables.OffsetX = CirconianStaminaBarWindow:GetLeft()

In this line we call the GetLeft() function of the control CirconianStaminaBarWindow (remember that is what we named our TopLevelControl in our xml file). This function returns the position of the Left side of the control relative to GuiRoot (that is the main screen). Left is actually referring to the X offset from the LEFT side of GuiRoot.

That value is then placed into our CirconianStaminaBar.savedVariables table under than name OffsetX.


CirconianStaminaBar.savedVariables.OffsetY = CirconianStaminaBarWindow:GetTop()

In this line we call the GetTop() function of the control CirconianStaminaBarWindow (remember that is what we named our TopLevelControl in our xml file). This function returns the position of the Top of the control relative to GuiRoot (that is the main screen) Top is actually referring to the Y offset from the TOP of GuiRoot.

That value is then placed into our CirconianStaminaBar.savedVariables table under than name OffsetY.

Restoring Positions

The next thing we need to do in our lua file is to restore the stamina bars position when our addon loads. We will be doing this by adding a couple of lines of code to our initialization function to re-anchor the control.

If you forget what anchoring is go back to [Circonians Stamina Bar Tutorial] and read the section on xml structure.

In your CirconianStaminaBar:Initialize() function add the following lines of code:

CirconianStaminaBarWindow:ClearAnchors()
CirconianStaminaBarWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, CirconianStaminaBar.savedVariables.OffsetX, CirconianStaminaBar.savedVariables.OffsetY)



The first new line that we added:

CirconianStaminaBarWindow:ClearAnchors()

Clears any anchor points currently on the CirconianStaminaBarWindow. When you use the SetAnchor function it does NOT remove old anchors so you always want to clear any old anchors first, before you set your new achor.

Remember functions are called on controls by first stating the controls name followed by a colon : and then the function.
<control_name>:<function_name>(<optional_parameters>)



The second line we added:

CirconianStaminaBarWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, CirconianStaminaBar.savedVariables.OffsetX, CirconianStaminaBar.savedVariables.OffsetY)
If you forget what anchoring is go back to [Circonians Stamina Bar Tutorial] and read about the anchoring tag in the section on xml structure.

In short this anchors the TOPLEFT corner of our window relative to the GuiRoot TOPLEFT corner, and offsets the X-axis by the amount saved in our saved variable CirconianStaminaBar.savedVariables.OffsetX, and offsets the Y-Axis by the amount saved in our saved variable CirconianStaminaBar.savedVariables.OffsetY

Your initialization function should now look like this:

function CirconianStaminaBar:Initialize()
	CirconianStaminaBar.savedVariables = ZO_SavedVars:New("CirconianStaminaBarVars", CirconianStaminaBar.version, nil, CirconianStaminaBar.Default)
 
	local ourName = GetUnitName("player")
        CirconianStaminaBarWindowLabel:SetText(ourName)
 
	local current, max, effectiveMax = GetUnitPower("player", POWERTYPE_STAMINA)
	CirconianStaminaBarWindowStatusBar:SetMinMax(0, max)
	CirconianStaminaBarWindowStatusBar:SetValue(current)
 
	-- Added the following lines
	CirconianStaminaBarWindow:ClearAnchors()
	CirconianStaminaBarWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, CirconianStaminaBar.savedVariables.OffsetX, CirconianStaminaBar.savedVariables.OffsetY)
 
	EVENT_MANAGER:UnregisterForEvent(CirconianStaminaBar.name, EVENT_ADD_ON_LOADED)
end



The xml File

In the previous section we created a function to save the location of our stamina bar into our saved variables. Now we need to find a way to make that function run whenever the user moves the stamina bar. To do this we are going to add a couple of lines to our xml file.

Add the following lines of code into your xml file in the location shown:
Do note there is much more code than this in your xml file. In order to save space I am only showing enough lines of code so you can see where to put it

<GuiXml> 
   <Controls>
      <TopLevelControl name="CirconianStaminaBarWindow" clampedToScreen="true" mouseEnabled="true" movable="true" hidden="false" >
         <Dimensions x="300" y="50" />
         <Anchor point="TOPLEFT" relativeTo="GuiRoot" relativePoint="CENTER" offsetX="0" offsetY="0"/>
 
         <OnMoveStop>
            CirconianStaminaBar.SaveLoc()
         </OnMoveStop>


The lines of code that we added are:

<OnMoveStop>
	CirconianStaminaBar.SaveLoc()
</OnMoveStop>



<OnMoveStop>
 
</OnMoveStop>

These tags are used to process code when the control that it belongs to stops moving. First make sure you understand how we know what control it belongs to.

<GuiXml> 
   <Controls>
      <TopLevelControl name="CirconianStaminaBarWindow" clampedToScreen="true" mouseEnabled="true" movable="true" hidden="false" >
         <Dimensions x="300" y="50" />
         <Anchor point="TOPLEFT" relativeTo="GuiRoot" relativePoint="CENTER" offsetX="0" offsetY="0"/>
 
         <!-- Notice it is in between the opening <TopLevelControl> and closing </TopLevelControl tags -->
         <!-- But it is not inside any other CONTROLS opening and closing tags -->
         <OnMoveStop>
            CirconianStaminaBar.SaveLoc()
         </OnMoveStop>
 
         <Controls>
 
            <Backdrop name="$(parent)Backdrop" edgeColor="00000000" layer="0" level="0" centerColor="6495ED" alpha="0.6"  hidden="false">
	       <Dimensions x="300" y="50" />
	       <Anchor point="TOPLEFT"  relativeTo="$(parent)" relativePoint="TOPLEFT"/>
	       <Edge edgeSize="0" />
	    </Backdrop> 	 
 
		<!-- There is much more code but I think that is enough to get the idea -->
         </Controls>
   </TopLevelControl>
   </Controls>
</GuiXml>

Since it is placed inside of the TopLevelControl tags and is NOT inside any other control tags it is refering to when the TopLevelControl stops moving. Whenver that happens any code that is in between those two tags will be processed.


Where did I find out about this <OnMoveStop> ? If you go to the UI XML page on esoui here: [XML Top Level Control] ...You will not see <OnMoveStop>...instead you will see this:
TopLevelControl 
	Inherits: Control 
	Child: allowBringToTop 
	Child: topmost 

See that part that says: Inherits: Control ?
That means that whatever tags are listed for Control (on the same page UI XML) can also be used for any TopLevelControl. If you scroll up on that page to the section on Control you can see what tags it allows or click here: [Control] there you will see OnMoveStop listed under Control.


In our code that we added

<OnMoveStop>
	CirconianStaminaBar.SaveLoc()
</OnMoveStop>

This says that once the TopLevelControl stops moving the function CirconianStaminaBar.SaveLoc() will be run. This is the function that we will created earlier to save the new location of our stamina bar.


Congratulations you should now be able to move your stamina bar around the screen and it should remember its last position when you reload your game or ui.




Troubleshooting Default Settings

There is one last thing I want to mention. If your testing out default positions for your UI do keep in mind that once you have saved a value into your saved variables the default values will not override them.

So if I decided that I didn't like the default position OffsetX = 20 and OffsetY = 75 AFTER I had all ready logged into the game and moved the stamina bar around and I attempted to change the default values and reload the UI nothing would happen. Those values have all ready been saved into the saved variables and will not be overwritten by the new default values.

I can tell you two ways to get around this:


If anyone has a better way of doing it edit this & add it the list!

glhfdgb ;)



NEXT TUTORIAL: Tutorial 3: Settings Menus

Circonians Tutorials Page: Tutorials Index



Personal tools
Namespaces
Variants
Actions
Menu
Wiki
Toolbox