Jump to content

Metatables introduction?


botanist

Recommended Posts

Posted

Hello thar,

I've been told a few days ago that I could use metatables to track variable changes and call an event for this. Now, I'm not told HOW so It'd be nice to get some introduction to it.

Here's what I'm trying to do, and I thought metatables could solve it afaik:

I want to use a text variable in a GUI elements, and whenever this variable change, the GUI gets triggered to change too. Ofcourse I can do guiSetText each time after I changed the variable, but that's a hell to do if you have a lot.

So my first thought was to create a DX GUI system, so every render would automatically update the text if it's variable is changed. But a DX GUi is a little bit a lot of work..

So basically, I want to change the gui text when the text variable has been changed.

Posted

I'm not sure about variables changes but as someone told you, metatables are the way to go. One thing I'd advice you as well is OOP in Lua. If you want to know how to track your variable change, visit this website: http://www.lua.org/pil/13.4.4.html

Also, have a read here: http://www.lua.org/pil/13.4.1.html to know more about __index

and http://www.lua.org/pil/13.4.2.html for __newindex.

After visiting the first link, you should know enough how it works, but I suggest you read them all lessons to have better understanding. I hope it helps.

Posted

Difficult, but I've read it. I don't really get the proxy part; where is that needed for? First the 't' table gets created, then localized, and then created again. What the hell is the point of that?

And basically, this would change the window title?

  
_guiCreateWindow = guiCreateWindow 
function guiCreateWindow ( posX, posY, width, height, text, relative ) 
    local element = _guiCreateWindow ( posX, posY, width, height, text, relative ) 
    local tbl = { 
        element=element, 
        posX=posX, 
        posY=posY, 
        width=width, 
        height=height, 
        text=text 
    } 
    return tbl 
end 
  
resourceGui = {} 
local _t = resourceGui   
  
local meta = { 
    __newindex = function (t,k,v) 
        if k == "text" then 
            guiSetText ( t.element, v ) 
        end 
        _t[k] = v 
    end 
} 
setmetatable(resourceGui, meta) 
  
resourceGui.window = guiCreateWindow ( blah ) 
resourceGui.window.text = "NewTitle" 

Posted

The point of proxy is to track any action that took part in the table (that is, set values or get values). What the hell is the point of that? I'm telling you now, you may probably know already that when you assign a table variable to another variable, it will copy the reference of the table. That means, if you do any modifications to the referenced table, the changes will take place in the original table as well. For instance:

t = { 1, 2, 3 }; 
local _t = t; -- assign the reference of table "t" to table "_t" (that is proxy) 
print( t[ 1 ] ); -- it will print 1 
_t[ 1 ] = 5; -- change the value of t[ 1 ]  Yes, that is right, t[ 1 ]! 
print( t[ 1 ] ); -- it will print 5 
  

I hope you understand now.

Posted

Right, still pretty weird to do

t = {} 
_t = t 
t = {} 

But that's not the point anymore, I tested the script above and it results in a C stack overflow at line 24, which contains the

_t[k] = v 

part. I don't get it, what is here the reason for?

Posted

i'm not very experienced on this topic. But I noticed that you create a table, set it's proxy and metatable and then add a another table to the table. I'm guessing you need to set the metatable on that new table.

resourceGui.window = guiCreateWindow ( blah ) 
setmetatable(resourceGui.window, meta) 
resourceGui.window.text = "NewTitle" 

Posted

SDK: Already tried that by doing the metatable inside the custom function. Didn't make errors, but didn't work either.

JR10: Why do you ask that? My script is exactly as it is there.

Posted

Thought you edited it.

_guiCreateWindow = guiCreateWindow 
function guiCreateWindow ( posX, posY, width, height, text, relative ) 
    local element = _guiCreateWindow ( posX, posY, width, height, text, relative ) 
    local tbl = { 
        element=element, 
        posX=posX, 
        posY=posY, 
        width=width, 
        height=height, 
        text=text 
    } 
    return tbl 
end 
  
resourceGui = {} 
local _t = resourceGui   
  
resourceGui = {} 
  
local meta = { 
    __index = function ( t,k ) 
        return _t [ k ] 
    end , 
    __newindex = function (t,k,v) 
        if k == "text" then 
            guiSetText ( t.element, v ) 
        end 
        _t[k] = v 
    end 
} 
setmetatable(resourceGui, meta) 
  
resourceGui.window = guiCreateWindow ( blah ) 
resourceGui.window.text = "NewTitle" 

Try that.

Posted

Ok, tested and figured it out.

The biggest problem was that you were making a proxy of the resourceGui table, while you needed the resourceGui.window table.

You also need the __index in the metatable because when you set the window text, you're retrieving "t.element".

resourceGui = {} 
  
local meta = { 
    __newindex = function (t,k,v) 
        if k == "text" then 
            guiSetText ( t.element, v ) 
        end 
        _t[k] = v 
    end, 
    __index = function (t,k) 
        return _t[k] 
    end 
} 
resourceGui.window = guiCreateWindow ( 0.25,0.25,0.5,0.5,"OldTitle", true ) 
_t = resourceGui.window 
resourceGui.window = {} 
setmetatable(resourceGui.window, meta) 
  
resourceGui.window.text = "NewTitle" 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...