Thread Tools Display Modes
02-12-17, 08:55 AM   #1
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 358
Would like to ask some advice regarding AceAddon-3.0

Hi all,

First of all, I would like to ask an excuse as this thread is more related to Ace3 framework than generic lua questions.

Tracker.lua
Lua Code:
  1. local N, T = ...;
  2.  
  3. local E = LibStub("AceAddon-3.0"):NewAddon(N);
  4.  
  5. T[1] = E
  6. T[2] = {};
  7.  
  8. _G[N] = T;
  9.  
  10. function E:OnInitialize()
  11.     if not TrackerDB then
  12.         TrackerDB = {};
  13.     end
  14.  
  15.     self.db = TrackerDB;
  16. end

Experience.lua
Lua Code:
  1. local E, L = unpack(select(2, ...));
  2.  
  3. local LSM = LibStub("LibSharedMedia-3.0");
  4. local font = LSM:Fetch("font", "MeatEdition");
  5.  
  6. local Experience = E:NewModule("Experience", "AceEvent-3.0");
  7.  
  8. local function CommaValue(value)
  9.     local left, num, right = string.match(value, '^([^%d]*%d)(%d*)(.-)$');
  10.  
  11.     return left .. (num:reverse():gsub('(%d%d%d)', '%1,'):reverse()) .. right;
  12. end
  13.  
  14. function Experience:UpdateText()
  15.     local level = UnitLevel("player");
  16.     local curXP, maxXP = UnitXP("player"), UnitXPMax("player");
  17.     local perXP = curXP / maxXP * 100;
  18.  
  19.     self.Frame.NameText:SetText(UnitName("player"));
  20.     self.Frame.ExpText:SetFormattedText("|cffeda900Level:|r %d, |cffeda900Exp:|r %s / %s (%.2f%%)", level, CommaValue(curXP), CommaValue(maxXP), perXP);
  21. end
  22.  
  23. function Experience:ADDON_LOADED(event, name)
  24.     if name == E:GetName() then
  25.         local point, relativeFrame, relativePoint, ofsx, ofsy;
  26.         if E.db.pos then
  27.             point, relativeFrame, relativePoint, ofsx, ofsy = unpack(E.db.pos);
  28.         else
  29.             point, relativeFrame, relativePoint, ofsx, ofsy = "CENTER", "UIParent", "CENTER", 0, 200;
  30.         end
  31.  
  32.         local Frame = CreateFrame("Frame", "Experience", UIParent);
  33.         Frame:SetSize(280, 50);
  34.         Frame:SetPoint(point, relativeFrame, relativePoint, ofsx, ofsy);
  35.         Frame:SetTemplate(true); -- Custom frame function that sets template of frame
  36.  
  37.         local r, g, b = Frame.template:GetBackdropColor();
  38.         Frame.template:SetBackdropColor(r, g, b, 0.7);
  39.  
  40.         local _, class = UnitClass("player");
  41.         local color = RAID_CLASS_COLORS[class];
  42.  
  43.         local NameText = Frame:CreateFontString(nil, "OVERLAY");
  44.         NameText:SetFont(font, 16, "OUTLINE");
  45.         NameText:SetPoint("TOP", 0, -5);
  46.         NameText:SetTextColor(color.r, color.g, color.b);
  47.         NameText:SetText("");
  48.  
  49.         local ExpText = Frame:CreateFontString(nil, "OVERLAY");
  50.         ExpText:SetFont(font, 14, "OUTLINE");
  51.         ExpText:SetPoint("BOTTOM", 0, 5);
  52.         ExpText:SetTextColor(1, 1, 1);
  53.         ExpText:SetFormattedText("|cffeda900Level:|r %d, |cffeda900Exp:|r %s / %s (%.2f%%)", 0, 0, 0, 0);
  54.  
  55.         self.Frame = Frame;
  56.  
  57.         Frame.NameText = NameText;
  58.         Frame.ExpText = ExpText;
  59.     end
  60. end
  61.  
  62. function Experience:PLAYER_LOGIN()
  63.     self:UpdateText();
  64. end
  65.  
  66. function Experience:PLAYER_XP_UPDATE()
  67.     self:UpdateText();
  68. end
  69.  
  70. function Experience:PLAYER_LOGOUT()
  71.     local point, relativeFrame, relativePoint, ofsx, ofsy = self.Frame:GetPoint();
  72.  
  73.     if relativeFrame == UIParent then
  74.         relativeFrame = "UIParent";
  75.     end
  76.  
  77.     E.db.pos = {
  78.         point,
  79.         relativeFrame,
  80.         relativePoint,
  81.         ofsx,
  82.         ofsy,
  83.     }
  84. end
  85.  
  86. Experience:RegisterEvent("ADDON_LOADED");
  87. Experience:RegisterEvent("PLAYER_LOGIN");
  88. Experience:RegisterEvent("PLAYER_XP_UPDATE");
  89. Experience:RegisterEvent("PLAYER_LOGOUT");

As I have hinted above, I am currently playing around with Ace3 & SavedVariables and making super simple addon which just displays player's name, level and exp amount.
(Yeah... I am aware of that this kind of addon is useless, it's just for studying )

Q: Why am I using Ace3?
A: Like I've said, I am using it for studying(?) purpose, and was interested in its AceEvent-3.0 functions as well.

Q: What is saved in SavedVariables?
A: It currently stores the point data of the frame like point, relativeFrame, relativePoint, ofsx, ofsy.

However, as you can see above, my code structures are currently messed up (not optimized) and am still not confident of using them. Thus, I would like to ask some advice to those who are using either of them.

The reason that I've utilized ADDON_LOADED event is because of the db, SavedVariables.

If I am understanding correctly, the loading is done by the following orders.

1. Load lua files
2. :OnInitialize() function gets called
3. ADDON_LOADED event gets called

So, if I pull those initialization codes out from :ADDON_LOADED() function, it will just crash as it cannot find db.

That's pretty much all of what I can explain(?) so far.

Could I please get some advice regarding what I have done?
(Especially in terms of optimization)

Thank you!

Last edited by Layback_ : 02-12-17 at 09:08 AM.
  Reply With Quote
02-12-17, 04:37 PM   #2
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,240
OnIntialize() == ADDON_LOADED, except that OnInit() already takes care of the unregistering and filtering out for your addon. You do not need both.

You would want to set up your DB in OnInit() because it only fires once. Same with setting up things like keybindings, creating frames, etc.

OnEnable() is for registering events and library callbacks, along with other set up things that you might want to track on and off.

OnDisable() is for unregistering events and callbacks, and clearing out variables (not saved variables) that you want wiped or assign to nil when the addon is in "standby" mode.
  Reply With Quote
02-12-17, 05:05 PM   #3
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 358
Originally Posted by myrroddin View Post
OnIntialize() == ADDON_LOADED, except that OnInit() already takes care of the unregistering and filtering out for your addon. You do not need both.

You would want to set up your DB in OnInit() because it only fires once. Same with setting up things like keybindings, creating frames, etc.

OnEnable() is for registering events and library callbacks, along with other set up things that you might want to track on and off.

OnDisable() is for unregistering events and callbacks, and clearing out variables (not saved variables) that you want wiped or assign to nil when the addon is in "standby" mode.
Hi myrroddin,

Thank you for your advice.

So, once I set up my DB in :OnInitialize() function, the best place to create and set up those frame and font strings in ADDON_LOADED() function would be :OnEnable() function?

Moreover, is it okay to create multiple :OnEnable() functions in different lua files within a single addon?
  Reply With Quote
02-12-17, 07:58 PM   #4
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,240
1) No. Because OnEnable can fire multiple times, and you should be creating frames once, then reusing them. Same with font strings, or any other create once, reuse element.

OnEnable can fire when you reload the UI, or when the user toggles your addon on/off if you have such a feature.

2) No. Mainly because that doesn't exist. There is only one OnInitialize function, one OnEnable, and one OnDisable.

You should look at the full Ace3 documentation; it is very thorough, except for handling modules. Also, ignore the parts about embeds.xml and list any files and libraries directly in the .toc file. https://www.wowace.com/projects/ace3...etting-started
  Reply With Quote
02-12-17, 08:35 PM   #5
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 358
Originally Posted by myrroddin View Post
1) No. Because OnEnable can fire multiple times, and you should be creating frames once, then reusing them. Same with font strings, or any other create once, reuse element.

OnEnable can fire when you reload the UI, or when the user toggles your addon on/off if you have such a feature.

2) No. Mainly because that doesn't exist. There is only one OnInitialize function, one OnEnable, and one OnDisable.

You should look at the full Ace3 documentation; it is very thorough, except for handling modules. Also, ignore the parts about embeds.xml and list any files and libraries directly in the .toc file. https://www.wowace.com/projects/ace3...etting-started
Hi again myrroddin,

I get the idea where I should create frames, fontstrings and so on once and re-use them when they are needed, but still ain't sure of where would be the best spot to do so...

Would it be just top of the lua file? A function that is called on event fires? Or any other places?

I guess the answer could vary based on the structure of the addon, but would like to know some cases.

Last edited by Layback_ : 02-12-17 at 08:39 PM.
  Reply With Quote
02-12-17, 08:55 PM   #6
briskman3000
A Flamescale Wyrmkin
 
briskman3000's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 108
Originally Posted by Layback_ View Post
Hi again myrroddin,

I get the idea where I should create frames, fontstrings and so on once and re-use them when they are needed, but still ain't sure of where would be the best spot to do so...

Would it be just top of the lua file? A function that is called on event fires? Or any other places?

I guess the answer could vary based on the structure of the addon, but would like to know some cases.
The way I see it, I prefer to use the top of the lua file.

Since it is something that only needs to be done once when the addon is loaded, it doesn't need any events to create it.

For Example I'll use the frame code in my addon:

This is literally the top part of my lua file

You can ignore the events and {} in the first line, since I used a table to register my events and that sets up the empty table.

My addon does not use Ace, but it's one example for you anyways.

Code:
--Create the Frame
local Addon, events = CreateFrame("Frame", "LegionHonor", UIParent), {};
Addon:SetWidth(175);
Addon:SetHeight(180);
Addon:SetPoint("CENTER", UIParent, "CENTER");
Addon:SetMovable(true);
Addon:EnableMouse(true);
Addon:RegisterForDrag("LeftButton");
Addon:SetScript("OnDragStart", Addon.StartMoving);
Addon:SetScript("OnDragStop", Addon.StopMovingOrSizing);
Addon:SetClampedToScreen(true);
Addon.Title = Addon:CreateFontString("LegionHonor_Title", "OVERLAY", "GameFontNormal");
Addon.Title:SetPoint("TOP");
Addon.Title:SetText("Legion Honor");
local tex = Addon:CreateTexture(nil, "BACKGROUND")
tex:SetAllPoints()
tex:SetColorTexture(0, 0, 0, 0.5)

--Add the text
Addon.PrestigeLevelText = Addon:CreateFontString("LegionHonor_PrestigeText", "OVERLAY", "GameFontNormal");
Addon.PrestigeLevelText:SetPoint("LEFT", 0, 60);
Addon.PrestigeLevelText:SetText("Prestige Level");
Addon.HonorLevelText = Addon:CreateFontString("LegionHonor_HonorLevelText", "OVERLAY", "GameFontNormal");
Addon.HonorLevelText:SetPoint("LEFT", 0, 30);
Addon.HonorLevelText:SetText("Honor Level");
Addon.HonorAmountText = Addon:CreateFontString("LegionHonor_HonorText", "OVERLAY", "GameFontNormal");
Addon.HonorAmountText:SetPoint("LEFT", 0, 0);
Addon.HonorAmountText:SetText("Current Honor");
Addon.HonorGoalText = Addon:CreateFontString("LegionHonor_HonorGoalText", "OVERLAY", "GameFontNormal");
Addon.HonorGoalText:SetPoint("LEFT", 0, -30);
Addon.HonorGoalText:SetText("Honor to Farm");
Addon.HonorPerHourText = Addon:CreateFontString("LegionHonor_HonorPerHourText", "OVERLAY", "GameFontNormal");
Addon.HonorPerHourText:SetPoint("LEFT", 0, -60);
Addon.HonorPerHourText:SetText("Honor per Hour");
Addon.PlayerPrestigeLevel = Addon:CreateFontString("LegionHonor_PlayerPrestigeLevel", "OVERLAY", "GameFontNormal");
Addon.PlayerPrestigeLevel:SetPoint("RIGHT", 0, 60);
Addon.PlayerHonorLevel = Addon:CreateFontString("LegionHonor_PlayerHonorLevel", "OVERLAY", "GameFontNormal");
Addon.PlayerHonorLevel:SetPoint("RIGHT", 0, 30);
Addon.PlayerHonorAmount = Addon:CreateFontString("LegionHonor_PlayerHonor", "OVERLAY", "GameFontNormal");
Addon.PlayerHonorAmount:SetPoint("RIGHT", 0, 0);
Addon.HonorGoalAmount = Addon:CreateFontString("LegionHonor_HonorGoalAmount", "OVERLAY", "GameFontNormal");
Addon.HonorGoalAmount:SetPoint("RIGHT", 0, -30);
Addon.HonorPerHourAmount = Addon:CreateFontString("LegionHonor_HonorPerHourAmount", "OVERLAY", "GameFontNormal");
Addon.HonorPerHourAmount:SetPoint("RIGHT", 0, -60);
Addon.HonorPerHourAmount:SetText("Unknown");
__________________
My Addons: Convert Ratings Honor Track

Last edited by briskman3000 : 02-12-17 at 08:59 PM.
  Reply With Quote
02-12-17, 09:28 PM   #7
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 358
Hi Briskman3000,

Thank you for your suggestion and example code

Here's my edited version of Experience.lua:
Lua Code:
  1. local LSM = LibStub("LibSharedMedia-3.0");
  2. local font = LSM:Fetch("font", "MeatEdition");
  3.  
  4. local E, L = unpack(select(2, ...));
  5.  
  6. local Experience = E:NewModule("Experience", "AceEvent-3.0");
  7.  
  8. Experience.Frame = CreateFrame("Frame", nil, UIParent);
  9. Experience.Frame:SetMovable(true);
  10. Experience.Frame:EnableMouse(true);
  11. Experience.Frame:RegisterForDrag("LeftButton");
  12. Experience.Frame:SetScript("OnDragStart", Experience.Frame.StartMoving);
  13. Experience.Frame:SetScript("OnDragStop", Experience.Frame.StopMovingOrSizing);
  14. Experience.Frame:SetSize(280, 50);
  15.  
  16. Experience.Frame:SetTemplate(true); -- custom function
  17. local r, g, b = Experience.Frame.template:GetBackdropColor();
  18. Experience.Frame.template:SetBackdropColor(r, g, b, 0.7);
  19.  
  20. local _, class = UnitClass("player");
  21. local color = RAID_CLASS_COLORS[class];
  22.  
  23. Frame.NameText = Experience.Frame:CreateFontString(nil, "OVERLAY");
  24. Frame.NameText:SetFont(font, 16, "OUTLINE");
  25. Frame.NameText:SetPoint("TOP", 0, -5);
  26. Frame.NameText:SetTextColor(color.r, color.g, color.b);
  27. Frame.NameText:SetText("");
  28.  
  29. Frame.ExpText = Experience.Frame:CreateFontString(nil, "OVERLAY");
  30. Frame.ExpText:SetFont(font, 14, "OUTLINE");
  31. Frame.ExpText:SetPoint("BOTTOM", 0, 5);
  32. Frame.ExpText:SetTextColor(1, 1, 1);
  33. Frame.ExpText:SetFormattedText("Level: %d, Exp: %d / %d (%.2f%%)", 0, 0, 0, 0);
  34.  
  35. local function CommaValue(value)
  36.     local left, num, right = string.match(value, '^([^%d]*%d)(%d*)(.-)$');
  37.  
  38.     return left .. (num:reverse():gsub('(%d%d%d)', '%1,'):reverse()) .. right;
  39. end
  40.  
  41. function Experience:UpdateText()
  42.     local level = UnitLevel("player");
  43.     local curXP, maxXP = UnitXP("player"), UnitXPMax("player");
  44.     local perXP = curXP / maxXP * 100;
  45.  
  46.     self.Frame.NameText:SetText(UnitName("player"));
  47.     self.Frame.ExpText:SetFormattedText("|cffeda900Level:|r %d, |cffeda900Exp:|r %s / %s (%.2f%%)", level, CommaValue(curXP), CommaValue(maxXP), perXP);
  48. end
  49.  
  50. function Experience:PLAYER_LOGIN()
  51.     local point, relativeFrame, relativePoint, ofsx, ofsy;
  52.        
  53.     if E.db.pos then
  54.         point, relativeFrame, relativePoint, ofsx, ofsy = unpack(E.db.pos);
  55.     else
  56.         point, relativeFrame, relativePoint, ofsx, ofsy = "CENTER", "UIParent", "CENTER", 0, 200;
  57.     end
  58.  
  59.     self.Frame:SetPoint(point, relativeFrame, relativePoint, ofsx, ofsy);
  60.  
  61.     self:UpdateText();
  62. end
  63.  
  64. function Experience:PLAYER_XP_UPDATE()
  65.     self:UpdateText();
  66. end
  67.  
  68. function Experience:PLAYER_LOGOUT()
  69.     local point, relativeFrame, relativePoint, ofsx, ofsy = self.Frame:GetPoint();
  70.  
  71.     if relativeFrame == UIParent then
  72.         relativeFrame = "UIParent";
  73.     end
  74.  
  75.     E.db.pos = {
  76.         point,
  77.         relativeFrame,
  78.         relativePoint,
  79.         ofsx,
  80.         ofsy,
  81.     }
  82. end
  83.  
  84. Experience:RegisterEvent("PLAYER_LOGIN");
  85. Experience:RegisterEvent("PLAYER_XP_UPDATE");
  86. Experience:RegisterEvent("PLAYER_LOGOUT");

I tried to get rid of ADDON_LOADED function, but once I remove that function, it won't be able to access db as it recognize db as 'nil'

EDIT: Got rid of ADDON_LOADED function and immigrated stuffs into PLAYER_LOGIN function due to db issue.

Last edited by Layback_ : 02-12-17 at 09:50 PM.
  Reply With Quote
02-12-17, 10:15 PM   #8
briskman3000
A Flamescale Wyrmkin
 
briskman3000's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 108
Why exactly are you setting your frame's position with a db?

Offsets are usually saved by the client automatically, so you don't need to manually do so.

They should be saved to:

\World of Warcraft\WTF\Account\{AccountName}\{Server}\{Character}\layout-local.txt
__________________
My Addons: Convert Ratings Honor Track

Last edited by briskman3000 : 02-12-17 at 10:22 PM.
  Reply With Quote
02-12-17, 11:01 PM   #9
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 358
I stored them to keep the same position for all other characters in this account
  Reply With Quote
02-16-17, 11:41 PM   #10
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 358
BUMP with new question regarding AceDB-3.0

Decided to re-use this post as OP was originally a Ace3.0 related question and as I don't want to spam my threads

So, I have tried to use AceDB-3.0 for the first time and faced an issue which I can't understand.

Tracker.lua
Lua Code:
  1. local N, T = ...;
  2.  
  3. local E = LibStub("AceAddon-3.0"):NewAddon(N, "AceEvent-3.0");
  4.  
  5. T[1] = E -- Engine
  6. T[2] = {}; -- Locale
  7.  
  8. _G[N] = T;
  9.  
  10. local defaults = {
  11.     global = {
  12.         experience = {
  13.             point = "CENTER",
  14.             relativeFrame = "UIParent",
  15.             relativePoint = "CENTER",
  16.             ofsx = 0,
  17.             ofsy = 200,
  18.         },
  19.     },
  20. }
  21.  
  22. function E:OnInitialize()
  23.     self.db = LibStub("AceDB-3.0"):New(N .. "DB", defaults);
  24. end

I have gone through AceDB-3.0 tutorial and decided to use 'global' as a data type.

However, it doesn't seem to be working at the moment
(maybe I'm doing something wrong)

So, here's the code for where data in db are called:
Lua Code:
  1. -- Set points to default if global db table does not exist
  2. -- If it exists, use that
  3. function Experience:PLAYER_ENTERING_WORLD()
  4.     local db = E.db;
  5.     local point, relativeFrame, relativePoint, ofsx, ofsy;
  6.  
  7.     if type(db.global) == "nil" then
  8.         point = db.defaults.global.experience.point;
  9.         relativeFrame = db.defaults.global.experience.relativeFrame;
  10.         relativePoint = db.defaults.global.experience.relativePoint;
  11.         ofsx = db.defaults.global.experience.ofsx;
  12.         ofsy = db.defaults.global.experience.ofsy;
  13.     else
  14.         point = db.global.experience.point;
  15.         relativeFrame = db.global.experience.relativeFrame;
  16.         relativePoint = db.global.experience.relativePoint;
  17.         ofsx = db.global.experience.ofsx;
  18.         ofsy = db.global.experience.ofsy;
  19.     end
  20.  
  21.     self.Indicator:SetPoint(point, relativeFrame, relativePoint, ofsx, ofsy);
  22. end

while these lines of code are intended to save data into db:
Lua Code:
  1. -- Initialization of a movable frame
  2. -- Store data into db when frame stops moving
  3. do
  4.     local Indicator = CreateFrame("Frame", nil, UIParent);
  5.     Indicator:SetMovable(true);
  6.     Indicator:EnableMouse(true);
  7.     Indicator:RegisterForDrag("LeftButton");
  8.     Indicator:SetScript("OnDragStart", Indicator.StartMoving);
  9.     Indicator:SetScript("OnDragStop", function(self)
  10.         self:StopMovingOrSizing();
  11.  
  12.         Experience:UpdateDB();
  13.     end);
  14.     Indicator:SetSize(280, 50);
  15.     Indicator:SetTemplate(true);
  16.     local r, g, b = Indicator.template:GetBackdropColor();
  17.     Indicator.template:SetBackdropColor(r, g, b, 0.7);
  18.  
  19.     Experience.Indicator = Indicator;
  20. end
  21.  
  22. -- Function that updates db
  23. function Experience:UpdateDB()
  24.     local point, relativeFrame, relativePoint, ofsx, ofsy = self.Indicator:GetPoint();
  25.  
  26.     if relativeFrame == UIParent then
  27.         relativeFrame = "UIParent";
  28.     end
  29.  
  30.     E.db.global = {
  31.         experience = {
  32.             ["point"] = point,
  33.             ["relativeFrame"] = relativeFrame,
  34.             ["relativePoint"] = relativePoint,
  35.             ["ofsx"] = ofsx,
  36.             ["ofsy"] = ofsy,
  37.         },
  38.     }
  39. end
  40.  
  41. -- Experience is a module of this addon created by AceAddon-3.0
  42. -- Un-register all events, store data into db and remove(?) all frames when player reaches level 110
  43. function Experience:PLAYER_LEVEL_UP(level, hp, mp, talentPoints, strength, agility, stamina, intellect, spirit)
  44.     if level == 110 then
  45.         self:UnregisterEvent("PLAYER_LOGIN");
  46.         self:UnregisterEvent("PLAYER_XP_UPDATE");
  47.         self:UnregisterEvent("PLAYER_UPDATE_RESTING");
  48.         self:UnregisterEvent("PLAYER_LEVEL_UP");
  49.         self:UnregisterEvent("PLAYER_LOGOUT");
  50.  
  51.         self:UpdateDB();
  52.  
  53.         self.XPBar.background = nil;
  54.         self.XPBar.template = nil;
  55.         for i = 1, #(self.XPBar.Line) do
  56.             self.XPBar.Line[i] = nil;
  57.         end
  58.         self.XPBar = nil;
  59.  
  60.         self.Indicator.XPText = nil;
  61.         self.Indicator.NameText = nil;
  62.  
  63.         self.Indicator.template = nil;
  64.         self.Indicator = nil;
  65.     end
  66. end
  67.  
  68. -- Store data into db when player logs out
  69. function Experience:PLAYER_LOGOUT()
  70.     self:UpdateDB();
  71. end

This currently doesn't work as I expected, but only uses default data set in Tracker.lua even if I move frame.

I'm honestly unsure of what is going wrong with my codes

EDIT: I've succeeded on using pure savedvariables btw.

Last edited by Layback_ : 02-16-17 at 11:58 PM.
  Reply With Quote
02-17-17, 02:31 PM   #11
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,240
With AceDB-3.0, you set up default values that are hard coded as a table. That table is passed, in OnInitialize, to AceDB.

From then on, AceDB does not write your saved variables to file unless the user changes an option. And yes, I know technically AceDB, like any AddOn, is not doing the actual writing.

The moment the user changes one of the options, say self.db.global.cute from "tabby" to "Persian", then AceDB-3.0 will save that one line in your saved variables. The rest of the file will contain empty tables, because no other option has been altered from the defaults.

Here is a very basic, yet working, example of how to use AceDB-3.0.

Keep in mind, every question asked in this thread has been answered via example and documentation on the Ace3 API page.
Lua Code:
  1. local defaults = {
  2.     profile = {
  3.         loveCats = true
  4.     },
  5.     global = {
  6.         king = "lion",
  7.         cute = "tabby"
  8.     },
  9.     char = {
  10.         ownedCats = 0
  11.     }
  12. }
  13.  
  14. -- have a variable for when user switches profiles
  15. local db
  16.  
  17. function MyAddOn:OnInitialize()
  18.     -- self refers to MyAddOn
  19.     -- the true at the end means all characters share the same defaults table
  20.     self.db = LibStub("AceDB-3.0"):New("MyAddOnDB", defaults, true)
  21.     db = self.db.profile -- shortcut for new/reset profiles
  22.    
  23.     -- db update callbacks
  24.     -- you could name Refresh to anything you like like "ConfigChanged" or "UpdateProfile"
  25.     self.db.RegisterCallback(self, "OnProfileChanged", "Refresh")
  26.     self.db.RegisterCallback(self, "OnProfileCopied", "Refresh")
  27.     self.db.RegisterCallback(self, "OnProfileReset", "Refresh")
  28. end
  29.  
  30. function MyAddOn:Refresh()
  31.     -- profile is new/reset so update the variable
  32.     db = self.db.profile
  33. end
  Reply With Quote
02-17-17, 04:20 PM   #12
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 358
Hi myrroddin,

Thank you for your reply.

Yeah, I have gone through Ace3 tutorials, but with my lack of understandings, I wasn't able to fully understand stuffs. I apologize about that ...

So, via debugging tool (addon), ViragDevTool, I could've seen that self.db.global.experience has been updated from defaults table to new data on OnDragStop event (#9 ~ #13 of 3rd code block).
(Before I moved a frame, self.db.global had same data as self.db.defaults.global)

defaults:

Lua Code:
  1. self.db.defaults = {
  2.     global = {
  3.         experience = {
  4.             point = "CENTER",
  5.             relativeFrame = "UIParent",
  6.             relativePoint = "CENTER",
  7.             ofsx = 0,
  8.             ofsy = 200,
  9.         },
  10.     },
  11. }

Updated:

Lua Code:
  1. self.db = {
  2.     global = {
  3.         experience = {
  4.             point = "LEFT",
  5.             relativePoint = "LEFT",
  6.             ofsx = 304.99993896484,
  7.             ofsy = 208.00001525879,
  8.         },
  9.     },
  10. }

As you have advised,

The moment the user changes one of the options, say self.db.global.cute from "tabby" to "Persian", then AceDB-3.0 will save that one line in your saved variables. The rest of the file will contain empty tables, because no other option has been altered from the defaults.
relativeFrame seems to be removed from updated db (which is "UIParent", string value) since it has same data as defaults table.

However, the problem is that the newly updated db does not seem to be stored in SavedVariables on '/reload' or even with a log out.

Since, I am not using 'profile' data type (am currently using 'global'), I guess I don't need to deal with those callbacks tho...

Last edited by Layback_ : 02-17-17 at 04:27 PM.
  Reply With Quote
02-19-17, 05:42 AM   #13
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 358
According WowWiki description about '/reload ui' it says the following:

Reloading the interface saves the current settings to disk, and updates any addon files previously loaded by the game. In order to load new files (or addons), the game must be restarted.
But, it doesn't seem like it's updating db as I've stated on my previous reply.

As I have mentioned, I could've seen that self.db.global.experience has been updated as I move the frame, but the changed value doesn't seem to be updated in (applied to) SavedVariables.

Everytime, I '/reload ui', the frame utilizes defaults values to set its position, and self.db.global.experience re-copies the default values.

I am so confused now

The code hasn't been changed since my last reply (which is right above), and have only been testing and researching since yesterday...

EDIT: Just found that even those defaults data are removed from SavedVariables as I log out my toon and I guess this is because those data are same as default values like myrroddin explained above (if I am getting it correctly).

Last edited by Layback_ : 02-19-17 at 05:55 AM.
  Reply With Quote
02-19-17, 10:19 AM   #14
briskman3000
A Flamescale Wyrmkin
 
briskman3000's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 108
Maybe I am not seeing it because you have only posted snippets (or because I don't understand ace3), but I don't see where the db variables are declared in the global namespace to allow them to be writable to savedvariables.
__________________
My Addons: Convert Ratings Honor Track
  Reply With Quote
02-19-17, 02:16 PM   #15
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 358
Hi briskman3000,

I have the following lines of code in my Tracker.lua

Lua Code:
  1. local N, T = ...;
  2.  
  3. local E = LibStub("AceAddon-3.0"):NewAddon(N, "AceEvent-3.0");
  4.  
  5. T[1] = E -- Engine
  6. T[2] = {}; -- Locale
  7.  
  8. _G[N] = T;
  9.  
  10. local defaults = {
  11.     global = {
  12.         experience = {
  13.             point = "CENTER",
  14.             relativeFrame = "UIParent",
  15.             relativePoint = "CENTER",
  16.             ofsx = 0,
  17.             ofsy = 200,
  18.         },
  19.     },
  20. }
  21.  
  22. function E:OnInitialize()
  23.     self.db = LibStub("AceDB-3.0"):New(N .. "DB", defaults);
  24. end

So, my db is located inside the Engine, that Engine is located inside addon's namespace table and finally that table is globalized with name of this addon

But, would this matter?

Last edited by Layback_ : 02-19-17 at 02:28 PM.
  Reply With Quote
02-19-17, 05:51 PM   #16
Ketho
A Pyroguard Emberseer
 
Ketho's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,026
Show us your TOC
  Reply With Quote
02-19-17, 06:21 PM   #17
briskman3000
A Flamescale Wyrmkin
 
briskman3000's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 108
I don't see any global variables, all locals, which can't be written to SV file
__________________
My Addons: Convert Ratings Honor Track
  Reply With Quote
02-19-17, 06:38 PM   #18
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 358
Originally Posted by Ketho View Post
Show us your TOC
my TOC is super simple as this is only for studying:
Code:
## Interface: 70100
## Title: Tracker
## SavedVariables: TrackerDB

Tracker.lua
experience.lua

-------------------------------------------------------


Originally Posted by briskman3000 View Post
I don't see any global variables, all locals, which can't be written to SV file
You mean that db itself has to be global?

mmmmm.... Give me a sec I'll re-check it!

EDIT: Did you mean by that you don't see TrackerDB which I declared as SV in TOC file?

I thought that using AceDB-3.0 would manage it by itself as I give it a correct name, wouldn't it?

Maybe I was wrong D:...

EDIT2: The code that I've posted are entire parts which interact with db and as the rest are only initialization part of frames, fontstrings, etc.

Last edited by Layback_ : 02-19-17 at 06:54 PM.
  Reply With Quote
02-19-17, 09:20 PM   #19
briskman3000
A Flamescale Wyrmkin
 
briskman3000's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 108
I took a quick look at the acedb3 info, and from what I can tell (I never used Ace so my complete understanding might be off), you have 2 issues.


This code is where you set up the addon variable to use Ace.
Lua Code:
  1. local E = LibStub("AceAddon-3.0"):NewAddon(N, "AceEvent-3.0");

This variable "E" is being localized and cannot be saved to the SV file.

In addition, (if my understanding of how Ace works is correct), you are attempting to use the SV of "TrackerDB", but since you are defining the variable "E" into Ace, it is actually using the variable "EDB" as the database variable.

I may be wrong with the Ace related stuff, but that is how I see it.

Try changing that line to:

Lua Code:
  1. Tracker = LibStub("AceAddon-3.0"):NewAddon(N, "AceEvent-3.0");

and see if that fixes it

EDIT:

You may also have to change any other "E" references to "Tracker" in your code.
__________________
My Addons: Convert Ratings Honor Track

Last edited by briskman3000 : 02-19-17 at 09:25 PM.
  Reply With Quote
02-19-17, 10:05 PM   #20
Ketho
A Pyroguard Emberseer
 
Ketho's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,026
I don't see anything wrong when looking through your code, but it's a bit confusing to read this thread
The AceDB example by myrroddin (#11) should be good

Can you zip it up, paste, or push it to a repository so we can test it?

Last edited by Ketho : 02-19-17 at 10:26 PM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Would like to ask some advice regarding AceAddon-3.0

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off