WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Frames and metatables (https://www.wowinterface.com/forums/showthread.php?t=53928)

Benalish 07-19-16 10:33 AM

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)

Fizzlemizz 07-19-16 10:58 AM

You haven't actually set a backdrop to colour.

semlar 07-19-16 11:23 AM

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)

SDPhantom 07-19-16 12:03 PM

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

kurapica.igas 07-19-16 08:58 PM

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)


All times are GMT -6. The time now is 01:13 PM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI