Page 1 of 2

Using metatables and metamethods on system tables

Posted: Wed Oct 04, 2017 10:30 am
by liisi.laasik
I am trying to use metatables to have callback functionality on some Lua table modifications (through __index and __newindex metamethods).

Everything is working nicely, but some changes will not invoke the metamethods. I suspect the data update, on some occasions, is being done through the rawset metamethod.

Mostly I am interested in DialogueEntry.userScript expressions:
Are they executed through the rawset method?
Could there be any other reason, why when DebugLevel is set to Info, the console displays "Dialogue System: Lua(Variable["XXX"] = true)" but no callback is executed. However when the same is called from project code through DialogueLua.SetVariable(), callback works.

I am using the NLua interpreter.

Re: Using metatables and metamethods on system tables

Posted: Wed Oct 04, 2017 7:14 pm
by Tony Li
Hi,

When working with NLua, the Dialogue System maintains an instance of a Lua VM (LuaInterface.Lua class). The public property for this VM is NLua_Lua.VM.

It runs all Lua through LuaInterface.Lua.DoString(). Nothing uses rawset. The full signature of Lua.Run is:

Lua.Run(string code, bool debug=false, bool reportExceptions=false)

When Debug Level is set to Info, userScript passes debug=true.

If it's any help, the source code is in Scripts/SourceCode.unitypackage. (Import it into a separate project, not your main project, and delete the DLLS so they don't conflict.) There's a subpackage to import for the NLua code.

Can you share the code you're using for callbacks? I can try to reproduce the same thing here and suggest a solution.

Re: Using metatables and metamethods on system tables

Posted: Thu Oct 05, 2017 8:22 am
by liisi.laasik
I updated Dialogue System (DialogueSystem_1_7_6_Unity56plus).

Just for testing I added https://www.lua.org/pil/13.4.4.html in Dialogue Database startup script for Variable table (and emptied the Variable table for testing).

Still, some calls invoke the callback and some do not. For example DialogueLua.SetParticipants invokes them and now DialogueLua.SetVariable does not. Or at least that is how it looks from my end.

I imported both dialogue system and nlua sources to a separate project and looked through some of the code, but honestly I don't know enough about Lua to understand the specifics.

If you have any suggestions, it would be nice. However, developing the callback is more of a nice-to-have functionality. We can use some combination of LuaWatchItem and some manual queries - that would just be somewhat less efficient and foolproof.

Re: Using metatables and metamethods on system tables

Posted: Thu Oct 05, 2017 8:38 am
by Tony Li
LuaWatchItems are rather inefficient. Today is the last day of Unite Austin. When I get back from it, I'll dig into this and post an answer here, but it will probably not be until tomorrow.

Re: Using metatables and metamethods on system tables

Posted: Fri Oct 06, 2017 3:52 am
by liisi.laasik
Next week is perfectly fine too. Thank you!

Re: Using metatables and metamethods on system tables

Posted: Sun Oct 08, 2017 10:53 pm
by Tony Li
I'm afraid I wasn't able to reproduce this one, either. Here's a test scene that I used: TestNLua_2017-10-08.unitypackage. (Exported in Unity 5.3.0.)

It uses this Lua script, which I tested in the dialogue database's Global User Script as well as in a separate script included in the package above.

Code: Select all

    -- keep a private access to original table
    _t = Variable
    
    -- create proxy
    Variable = {}
    
    -- create metatable
    mt = {
      __index = function (t,k)
        printstr("*access to element " .. tostring(k))
        return _t[k]   -- access the original table
      end,
    
      __newindex = function (t,k,v)
        printstr("*update of element " .. tostring(k) ..
                             " to " .. tostring(v))
        _t[k] = v   -- update original table
      end
    }
    setmetatable(Variable, mt)
(The printstr function is added by a test script. It simply prints to the Unity console in yellow text.)

I will include the minor optimizations to GetTableField and SetTableField in the next release of the Dialogue System. If you can point me to a way to reproduce the issue you're seeing, I'll also include any necessary fixes in the next release. (Let me know what I can do to help.)

Re: Using metatables and metamethods on system tables

Posted: Sun Oct 08, 2017 11:01 pm
by Tony Li
Maybe a clue: If you're using the default Lua, DialogueLua.SetVariable() does use a raw set, so it won't generate an __index callback.

However, if you've switched to NLua, DialogueLua.SetVariable() does a regular set.

Are you sure you're using NLua? (The compiler define "USE_NLUA" should be set.)

Re: Using metatables and metamethods on system tables

Posted: Tue Oct 10, 2017 3:23 am
by liisi.laasik
To switch to NLua, I followed the instructions here: http://www.pixelcrushers.com/dialogue_s ... n_lua.html
1) imported import Third Party Support/NLua Support.unitypackage
2) deleted DLLs/LuaInterpreter.dll

I am not building dialogue system from source, so I didn't set any compiler defines. Should I?

Re: Using metatables and metamethods on system tables

Posted: Tue Oct 10, 2017 8:39 am
by Tony Li
You did the right steps. You don't need to do anything else. (I mentioned the compiler directive in case you were building from source, which I don't recommend because it's a needless hassle.)

Did the example scene in my previous post work for you?

Re: Using metatables and metamethods on system tables

Posted: Tue Oct 10, 2017 10:04 am
by liisi.laasik
Your scene has a missing prefab.

I am trying to make an example scene of my own, but it might take a day or two.