Thread Tools Display Modes
02-23-13, 11:47 AM   #1
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
How to create a copy of an object without reference? [SOLVED]

I have a problem that I cannot solve.

For my UI panel I want a "reset" feature. Thus I have a reset button that can be called to load the database defaults.

The problem I'm having is that as soon as I do this the default data becomes a reference. Thus on a second click on reset it will not work anymore. Because of the reference issue.

Here is my code:
Lua Code:
  1. --object container
  2.   local db = CreateFrame("Frame")
  3.   ns.db = db
  4.   db.default = {}
  5.  
  6.   ---------------------------------------------
  7.   --DEFAULTS
  8.   ---------------------------------------------
  9.  
  10.   --default orb setup
  11.   db.default.orb = {
  12.     --health
  13.     ["HEALTH"] = {
  14.       --filling
  15.       filling = {
  16.         texture     = "Interface\\AddOns\\oUF_Diablo\\media\\orb_filling15",
  17.         color       = { r = 1, g = 0, b = 0, },
  18.         colorAuto   = false, --automatic coloring based on class/powertype
  19.       },
  20.     },--health end
  21.     --power
  22.     ["POWER"] = {
  23.       --filling
  24.       filling = {
  25.         texture     = "Interface\\AddOns\\oUF_Diablo\\media\\orb_filling15",
  26.         color       = { r = 0, g = 0, b = 1, },
  27.         colorAuto   = false, --automatic coloring based on class/powertype
  28.       },
  29.     },--power end
  30.   } --default end
  31.  
  32.   db.getDefaultOrbHealth = function() return db.default.orb["HEALTH"] end
  33.   db.getDefaultOrbPower = function() return db.default.orb["POWER"] end
  34.   db.getDefaultOrb = function() return db.default.orb end
  35.  
  36.   ---------------------------------------------
  37.   --CHARACTER DATA
  38.   ---------------------------------------------
  39.  
  40.   --load character data defaults
  41.   db.loadCharacterDataDefaults = function(type)
  42.     if type then
  43.       if type == "HEALTH" then
  44.         OUF_DIABLO_DB_CHAR[type] = db.getDefaultOrbHealth()
  45.         print(addon..": health orb reseted to default")
  46.       elseif type == "POWER" then
  47.         OUF_DIABLO_DB_CHAR[type] = db.getDefaultOrbPower()
  48.         print(addon..": power orb reseted to default")
  49.       end
  50.     else
  51.       OUF_DIABLO_DB_CHAR = db.getDefaultOrb()
  52.       print(addon..": character data defaults loaded")
  53.     end
  54.     db.char = OUF_DIABLO_DB_CHAR
  55.     --update the orb view
  56.     ns.panel.updateOrbView()
  57.   end

OUF_DIABLO_DB_CHAR is my saved variable per character.

Basically when I click the reset button I call
Code:
  db.loadCharacterDataDefaults("HEALTH")
I cannot copy the table data via ipairs. Assoc tables cannot be looped. The following will return 0:
Code:
print(# db.default.orb["HEALTH"])
Any idea?

Tuller uses sth like
Lua Code:
  1. local function copyDefaults(tbl, defaults)
  2.     for k, v in pairs(defaults) do
  3.         if type(v) == 'table' then
  4.             tbl[k] = copyDefaults(tbl[k] or {}, v)
  5.         elseif tbl[k] == nil then
  6.             tbl[k] = v
  7.         end
  8.     end
  9.     return tbl
  10. end

Maybe I'm missing sth...

Oh...his GetDefault funnction is looking like:
Lua Code:
  1. function tullaRange:GetDefaults()
  2.     return {
  3.         normal = {1, 1, 1},
  4.         oor = {1, 0.3, 0.1},
  5.         oom = {0.1, 0.3, 1}
  6.     }
  7. end

Hmmm...so this could be an idea. I do not create a default table variable in first place that could get referenced later on.

I will try that.

Perfect that did it!

What I'm now doing is:
Lua Code:
  1. --default orb setup
  2.   function db:GetOrbDefaults()
  3.     return {
  4.       --health
  5.       ["HEALTH"] = {
  6.         --filling
  7.         filling = {
  8.           texture     = "Interface\\AddOns\\oUF_Diablo\\media\\orb_filling15",
  9.           color       = { r = 1, g = 0, b = 0, },
  10.           colorAuto   = false, --automatic coloring based on class/powertype
  11.         },
  12.       },--health end
  13.       --power
  14.       ["POWER"] = {
  15.         --filling
  16.         filling = {
  17.           texture     = "Interface\\AddOns\\oUF_Diablo\\media\\orb_filling15",
  18.           color       = { r = 0, g = 0, b = 1, },
  19.           colorAuto   = false, --automatic coloring based on class/powertype
  20.         },
  21.       },--power end
  22.     } --default end
  23.   end
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 02-23-13 at 12:18 PM. Reason: SOLVED
  Reply With Quote
02-23-13, 12:32 PM   #2
pelf
Sentient Plasmoid
 
pelf's Avatar
Premium Member
Join Date: May 2008
Posts: 133
I feel like I remember seeing "default settings" tables in code, before. I assume they're usually used to initialize, but they could just as easily be used to reset. Nice.
  Reply With Quote
02-23-13, 12:43 PM   #3
ravagernl
Proceritate Corporis
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,176
One thing you could also do if your options are not very complicated is make use of metatables:

http://www.lua.org/pil/13.4.3.html

Then when resetting, just loop over the options database table and set all keys to nil.
  Reply With Quote
02-23-13, 04:08 PM   #4
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
I use the following function to copy a table by value:

Code:
local function copyTable(source, target)
	for key, value in pairs(source) do
		if type(value) == "table" then
			target[key] = {}
			copyTable(value, target[key])
		else
			target[key] = value
		end
	end
end
  Reply With Quote
02-23-13, 04:23 PM   #5
pelf
Sentient Plasmoid
 
pelf's Avatar
Premium Member
Join Date: May 2008
Posts: 133
If that works, then what is this talking about?

I cannot copy the table data via ipairs. Assoc tables cannot be looped.
  Reply With Quote
02-23-13, 05:19 PM   #6
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
I don't see the problem there. Why not use:

Code:
 for key, value in pairs(db.default.orb["HEALTH"]) do
	...
 end
Any table with only keys in it rather than indexes will have #table return zero. That doesn't mean you can't iterate it.
  Reply With Quote
02-23-13, 06:17 PM   #7
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
Ah damn. I think I tried to iterate over the table length. I think I mixed sth up when using # table.

The loop Haleth posted actually does work.

Thanks.

*edit*

Thanks a bunch it is working now!
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 02-23-13 at 06:50 PM.
  Reply With Quote
02-23-13, 06:23 PM   #8
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
You can use either pairs or next to loop over a dictionary table.

Lua only returns a length for numerically indexed tables (or at least the highest consecutive index).

Last edited by semlar : 02-23-13 at 06:26 PM.
  Reply With Quote
02-24-13, 01:19 AM   #9
pelf
Sentient Plasmoid
 
pelf's Avatar
Premium Member
Join Date: May 2008
Posts: 133
I love it when I go down another path almost to completion to avoid a problem I didn't have when I'm coding. Always fun .
  Reply With Quote
02-24-13, 02:53 AM   #10
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
Just incase you missed it ... CopyTable is a global function since quite some time now

Lua Code:
  1. function CopyTable(settings)
  2.     local copy = {};
  3.     for k, v in pairs(settings) do
  4.         if ( type(v) == "table" ) then
  5.             copy[k] = CopyTable(v);
  6.         else
  7.             copy[k] = v;
  8.         end
  9.     end
  10.     return copy;
  11. end

http://wowprogramming.com/utils/xmlb...L/UIParent.lua
__________________
The cataclysm broke the world ... and the pandas could not fix it!
  Reply With Quote
02-24-13, 03:44 AM   #11
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
Oh, interesting. There's quite a few useful function in UIParent.lua. However I noticed this...

Code:
    if ( tempName == "LeftButton" ) then
        tempName = "BUTTON1";
    elseif ( tempName == "RightButton" ) then
        tempName = "BUTTON2";
    elseif ( tempName == "MiddleButton" ) then
        tempName = "BUTTON3";
    elseif ( tempName == "Button4" ) then
        tempName = "BUTTON4";
    elseif ( tempName == "Button5" ) then
        tempName = "BUTTON5";
    elseif ( tempName == "Button6" ) then
        tempName = "BUTTON6";
    elseif ( tempName == "Button7" ) then
        tempName = "BUTTON7";
    elseif ( tempName == "Button8" ) then
        tempName = "BUTTON8";
    elseif ( tempName == "Button9" ) then
        tempName = "BUTTON9";
    elseif ( tempName == "Button10" ) then
        tempName = "BUTTON10";
    elseif ( tempName == "Button11" ) then
        tempName = "BUTTON11";
    elseif ( tempName == "Button12" ) then
        tempName = "BUTTON12";
    elseif ( tempName == "Button13" ) then
        tempName = "BUTTON13";
    elseif ( tempName == "Button14" ) then
        tempName = "BUTTON14";
    elseif ( tempName == "Button15" ) then
        tempName = "BUTTON15";
    elseif ( tempName == "Button16" ) then
        tempName = "BUTTON16";
    elseif ( tempName == "Button17" ) then
        tempName = "BUTTON17";
    elseif ( tempName == "Button18" ) then
        tempName = "BUTTON18";
    elseif ( tempName == "Button19" ) then
        tempName = "BUTTON19";
    elseif ( tempName == "Button20" ) then
        tempName = "BUTTON20";
    elseif ( tempName == "Button21" ) then
        tempName = "BUTTON21";
    elseif ( tempName == "Button22" ) then
        tempName = "BUTTON22";
    elseif ( tempName == "Button23" ) then
        tempName = "BUTTON23";
    elseif ( tempName == "Button24" ) then
        tempName = "BUTTON24";
    elseif ( tempName == "Button25" ) then
        tempName = "BUTTON25";
    elseif ( tempName == "Button26" ) then
        tempName = "BUTTON26";
    elseif ( tempName == "Button27" ) then
        tempName = "BUTTON27";
    elseif ( tempName == "Button28" ) then
        tempName = "BUTTON28";
    elseif ( tempName == "Button29" ) then
        tempName = "BUTTON29";
    elseif ( tempName == "Button30" ) then
        tempName = "BUTTON30";
    elseif ( tempName == "Button31" ) then
        tempName = "BUTTON31";
    end
  Reply With Quote
02-24-13, 08:44 AM   #12
pelf
Sentient Plasmoid
 
pelf's Avatar
Premium Member
Join Date: May 2008
Posts: 133
Well, if Button4 ever changes to RightRightButton, we'll be ready.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » How to create a copy of an object without reference?

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