WeaselGames / godot_luaAPI

Godot LuaAPI
https://luaapi.weaselgames.info
Other
348 stars 27 forks source link

Add LuaFuntionRef type #172

Closed Trey2k closed 9 months ago

Trey2k commented 9 months ago

Since C# does not currently support CallableCustoms this PR adds a setting to the LuaAPI class, luaAPI.use_callables. It defaults to true. When set to true Lua functions pulled from the Lua state will use the LuaCallable type which is a CallableCustom. For c# or even gdScript to get around #155 it can be set to false to use the LuaFunctionRef type instead which is a RefCounted. It behaves identical to the LuaCallable type but uses an invoke method instead.

This is what the README example would look like for c# now

using Godot;

using System;

public partial class Node2D : Godot.Node2D
{
    private LuaApi lua = new LuaApi();

    public void LuaPrint(string message) {
        GD.Print(message);
    }

    public override void _Ready() {
        lua.UseCallables = false;
        Godot.Collections.Array libraries = new()
        {
            "base",   // Base Lua commands
            "table",  // Table functionality.
            "string" // String Specific functionality.
        };

        lua.BindLibraries(libraries); // Assign the specified libraries to the LuaAPI object.

        // In C#, .PushVariant does not work with Methods, so we use Callable to wrap our function.
        Callable print = new Callable(this, MethodName.LuaPrint);
        // Assign the Callable, so that the API can call our function.
        // Note, the lua function "cs_print" is now callable within Lua script.
        lua.PushVariant("print", print);
        // Assign a Lua Variable named "message" and give it a value.
        lua.PushVariant("message", "Hello lua!");

        LuaError error = lua.DoString(@"
                                    for i=1,10,1 do
                                        print(message)
                                    end
                                    function get_message()
                                        return ""Hello gdScript!""
                                    end
                                  ");

        if (error != null && error.Message != "") {
            GD.Print("An error occurred calling DoString.");
            GD.Print("ERROR %d: %s", error.Type, error.Message);
        }

        var val = lua.PullVariant("get_message");
        if (val.GetType() == typeof(LuaError)) {
            GD.Print("ERROR %d: %s", error.Type, error.Message);
            return;
        }

        LuaFunctionRef get_message = val.As<LuaFunctionRef>();
        if (get_message == null) {
            GD.Print("ERROR: get_message is null.");
            return;
        }

        Godot.Collections.Array Params = new();
        GD.Print(get_message.Invoke(Params));
    }
}