|
12-13-06, 02:57 PM | #1 |
Heh, saved variables?
I've been looking at other addons and I read the WoWWiki HOWTO on saved variables and I really can't figure out what I'm supposed to do in my addon to save the layout and load it percharacter.
Right now its just buttons with hide, show, lock, move, and scale options. I'd like it to actualy save where everything is, whats shown etc. ANyone have a link to a better guide than the one on WoWWiki by chance or if it's simple enough to explain in a paragraph have the time to gimme a lil knowledge? |
|
12-13-06, 03:56 PM | #2 |
SavedVariables in a nutshell:
When you log in, a sequence of things happen: (1) AddOn code is parsed and executed for each addon (2) "ADDON_LOADED" event is sent to each addon (3) Saved variables are loaded for each addon (more on this later) (4) "VARIABLES_LOADED" event is sent to each addon. This means that, prior to the VARIABLES_LOADED event being received, any variables that you saved in a previous session haven't been loaded yet. When you log out: (1) saved variables are written to disk. When you reload the UI, it's effectively the same as log out / log in. There are two types of saved variables that an addon can use: account-wide settings and character-wide settings. In order for a variable to be saved, you must declare it at the top of your .toc file like so: Code:
## SavedVariables: var1, var2, var3 (etc) ## SavedVariablesPerCharacter: cvar1, cvar2, (etc) account-wide: WTF/Account/<ACCOUNTNAME>/SavedVariables/<YourAddonName>.lua per-character: WTF/Account/<ACCOUNTNAME>/<RealmName>/<CharacterName>/SavedVariables/<YourAddonName>.lua When your "variables are loaded", that file is simply executed. It has the effect of setting a global variable, the same as specified in your.toc file, to the stored value. Take a look at some of those files for your installed addons. If you have both an account-wide saved variable and a per-character saved variable, both files are executed. So, what's the big deal? WoW correctly writes tables to the saved variables file. This means that your AddOn should really only have one saved variable, named something like MyAddOnVars, and it should be a table. You can then index that table however you like, and WoW will automatically save its contents from session to session. At the startup of your addon (after the VARIABLES_LOADED event has fired), you should check for the presence of your saved variable. If it doesn't exist yet, create it! and automagically its value will be saved across sessions. You can then put any manner of data in your saved variables, in any organization you want, and it will be persistent across sessions. Realistically speaking, the table can contain only numbers and strings, not functions or object references. But the nature of Lua tables being heterogeneous key-value maps means that you can organize a lot of data is an efficient manner, if you structure your saved variable table smartly. There are a few libraries out there that help you to manage saved variables: my favorite is part of Ace2 (AceDB-2.0), found at http://www.wowace.com. |
|
12-13-06, 03:59 PM | #3 |
1) In your .toc file you need a line like
## SavedVariablesPerCharacter: bandager_CONFIG 2) in your code you have your variable i.e. bandager_CONFIG = { enable = true; location = { 10, 10}; } where you replace bandager_CONFIG with your variable name when you log out they will be saved in the SavedVariables folder under your account in the WTF directory. this way saves per account not per character. Hope this helps |
|
12-13-06, 04:04 PM | #4 |
ugh, so given my application everytime i move a button, resize a button, show or hide a button it will have to write a variable?
Is there any global way to get the layout of all the positions and lock/hide/shown variables together? I'm too new at this to jump into a library like Ace I think... I don't really knwo much at all yet. |
|
12-13-06, 04:47 PM | #5 |
ok, I have a pretty simple set up. All my commands reference single buttons at the moment.
Could I set the saved variable to my slash commands action? (I assume I'll have to) I imagine if I record my locations when I lock a button, when I hide a button or show a button I record its hide/show state, and when I scale a button I record its scale size... I have no idea how to do that properly or if it'll even work how I'm thinking. I have Code:
SlashCmdList["ColonelBarCOMMAND"] = function (msg) local argT = {}; gsub(msg, "(%S+)", function(w) tinsert(argT, w) end) if (argT[1]) == "move" then if tonumber(argT[2]) > 0 then getglobal("EasyBarButton"..argT[2].."Cap"):Show(); end else if (argT[1]) == "lock" then if tonumber(argT[2]) > 0 then getglobal("EasyBarButton"..argT[2].."Cap"):Hide(); end end local argT = {}; gsub(msg, "(%S+)", function(w) tinsert(argT, w) end) if (argT[1]) == "hide" then if tonumber(argT[2]) > 0 then getglobal("EasyBarButton"..argT[2]):Hide(); end else if (argT[1]) == "display" then if tonumber(argT[2]) > 0 then getglobal("EasyBarButton"..argT[2]):Show(); end end local argT = {}; gsub(msg, "(%S+)", function(w) tinsert(argT, w) end) if (argT[1]) == "scale" then if tonumber(argT[2]) > 0 then getglobal("EasyBarButton"..argT[2]):SetScale(argT[3]); end end end end end SLASH_ColonelBarCOMMAND1 = "/eb" SLASH_ColonelBarCOMMAND2 = "/easybar" Could I do something like have the commands as normal like above and put a save command in as well? like... Code:
SlashCmdList["ColonelBarCOMMAND"] = function(input) if (input) == "saveloc" then for i = 1, 120 do getglobal("EasyBarButton"..i):GetCenter() end if (input) == "savescale" then for i = 1, 120 do getglobal("EasyBarButton"..i):GetScale() end end |
|
12-14-06, 05:44 PM | #6 |
Looking at your example code, you don't use any global variables at all - everything is done in the slash-command function locally. You're not storing the result of the commands anywhere, you're just executing them. For example, your second example does the following:
Code:
getglobal("EasyBarButton"..i):GetScale() If you want the effects of your slash-commands to persist across logins, you must store the state somewhere, and then set it up when the user logs in. That's where the SavedVariable comes in - it becomes that 'somewhere'. Here's a (very) basic example starting point. You need, at a bare minimum, 3 things to correctly save and restore state across logins:
So, this is the simplest modification I can make to your code to make it work. Shown are the .toc file and the .lua file (it's been abbreviated to only support the 'scale' command, you should be able to extend it from there) EasyBar.toc: Code:
## Interface: 20000 ## Title: EasyBar ## SavedVariablesPerCharacter: EasyBarVars EasyBar.lua Code:
-- The first section could be set up in an XML file, since you're just defining a frame. -- However, I'll do it here to show you how it can be done in Lua. -- As an added bonus, the frame is 'anonymous' - it doesn't have a global name, and -- it doesn't really need one. -- In order to get the VARIABLES_LOADED event, you need a Frame with an OnEvent handler. -- We'll set the frame to be blank and unnamed, as a child of UIParent local MyFrame = CreateFrame("Frame",nil,UIParent) -- You have to anchor the frame somewhere and show it to receive events, -- even though it's an empty frame MyFrame:SetAllPoints() MyFrame:Show() -- Register for the VARIABLES_LOADED event MyFrame:RegisterEvent(VARIABLES_LOADED) function MyEventHandler( evt ) -- the only event registered was VARIABLES_LOADED, if you want to register other events -- you'd need to do an if/else/elseif test here if EasyBarVars == nil then -- If this variable doesn't exist yet, then it's because it's the first time the user -- has used this AddOn. (or, they wiped their WTF folder and blew away their saved vars) -- Create it as a table with 1 field named 'scale' (which is also a table) EasyBarVars = { scale = { }, } else -- if it exists already, then that means that it was loaded as a SavedVariable. -- Wo, set up the saved state (scale settings) -- We index the EasyBarVars.scale table by the object name for convenience for objName, scale in pairs(EasyBarVars) do local obj = getglobal(objName) if obj then obj:SetScale(scale) end end end end -- this hooks the event handler to the frame MyFrame:SetScript("OnEvent", MyEventHandler) -- now here's your slash-command, abbreviated for just the scale setting SlashCmdList["ColonelBarCOMMAND"] = function (msg) local argT = {}; gsub(msg, "(%S+)", function(w) tinsert(argT, w) end) if (argT[1]) == "scale" then if tonumber(argT[2]) > 0 then local btnName = "EasyBarButton"..argT[2] local scale = tonumber(argT[3]) if scale ~= nil and scale > 0 then -- this is where you save the state so it can be loaded in the next session -- Remember, we indexed EasyBarVars.scale by the button name. EasyBarVars.scale[btnName] = scale getglobal(btnName):SetScale(scale); end end end end SLASH_ColonelBarCOMMAND1 = "/eb" SLASH_ColonelBarCOMMAND2 = "/easybar" |
|
WoWInterface » Developer Discussions » Lua/XML Help » Heh, saved variables? |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Switch to Linear Mode |
Hybrid Mode |
Switch to Threaded Mode |
|
|