Thread Tools Display Modes
07-19-16, 10:33 AM   #1
Benalish
A Flamescale Wyrmkin
 
Benalish's Avatar
Join Date: Dec 2012
Posts: 122
Frames and metatables

If I have a frame, and the put a metatable on this all this methods, e.g. SetBackdropColor(), are overwritten. There's a solution to overcame this problem?

Lua Code:
  1. local frm = CreateFrame("Frame")
  2.  
  3. local mt = { __index =
  4.     {
  5.         foo = function() print("bar") end
  6.     }
  7. }
  8.    
  9. setmetatable(frm, mt)
  10.  
  11. frm:SetBackdropColor(0,0.5,1)

Error message: attempt to call method 'SetBackdropColor' (a nil value)

Last edited by Benalish : 07-19-16 at 10:42 AM.
  Reply With Quote
07-19-16, 10:58 AM   #2
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
You haven't actually set a backdrop to colour.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
07-19-16, 11:23 AM   #3
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
You can get the original metatable of the frame and set that as your new metatable's metatable, eg.
Lua Code:
  1. local f = CreateFrame('frame')
  2. local mt = {
  3.     foo = function()
  4.         print('bar')
  5.     end
  6. }
  7. setmetatable(f, { __index = setmetatable(mt, getmetatable(f)) })
  8. f.foo()
  9. print(f.SetBackdropColor)
  Reply With Quote
07-19-16, 12:03 PM   #4
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
You can also copy functions from the old metatable to the new one. This will impose a longer setup time and use up more memory, but will save CPU usage during runtime. Taint is also a problem if the frame is protected, but it's unclear whether the replacement of the frame's metatable would cause taint by itself anyway.

Lua Code:
  1. local frame=CreateFrame("Frame")
  2. local meta={__index={}};
  3.  
  4. -- Define functions after these lines
  5. for name,func in pairs(getmetatable(frame).__index) do meta.__index[name]=func; end
  6. setmetatable(frame,meta);
  7.  
  8. function meta.__index:foo()
  9.     print("bar");
  10. end
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 07-19-16 at 12:07 PM.
  Reply With Quote
07-19-16, 08:58 PM   #5
kurapica.igas
A Chromatic Dragonspawn
Join Date: Aug 2011
Posts: 152
It may cause taint, you don't need to replace the frame's meta, it is better to creating a wrapper of the frame like :

Lua Code:
  1. local metaF = {
  2.     __index = {
  3.         foo = function() print("bar") end
  4.     },
  5. }
  6.  
  7. function BuildFrame(...)
  8.     local f = CreateFrame("Frame", ...)
  9.  
  10.     -- Only create the meta once
  11.     if not metaF.Inited then
  12.         metaF.Inited = true
  13.         for k, v in pairs(getmetatable(f).__index) do
  14.             if not metaF.__index[k] then
  15.                 metaF.__index[k] = v
  16.             end
  17.         end
  18.     end
  19.  
  20.     -- Create the wrapper
  21.     local w = setmetatable({}, metaF)
  22.     w[0] = f[0]   -- Copy the userdata, make sure the widget API can works well with the wrapper
  23.     -- w.RealUI = f   -- You may add a ref to the real frame
  24.  
  25.     return w
  26. end
  27.  
  28. -- Now you can use it without taint
  29. local frm = BuildFrame()
  30. frm:SetBackdropColor(0,0.5,1)
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Frames and metatables

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