From 68949b26f15a475569d55c02fd8f6135942ef8a8 Mon Sep 17 00:00:00 2001 From: Michieal Date: Wed, 11 Oct 2023 13:07:31 -0400 Subject: [PATCH] LuaFunctionRef update to Wiki example (#14) --- docs/examples/dotnet/example1.md | 55 ++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/docs/examples/dotnet/example1.md b/docs/examples/dotnet/example1.md index f7b25aa..5ebdab2 100644 --- a/docs/examples/dotnet/example1.md +++ b/docs/examples/dotnet/example1.md @@ -6,12 +6,26 @@ All future examples will be in the [Wiki](https://luaapi.weaselgames.info/latest Getting Started Example (In C#) ------- -In this example, we recreate the main GDScript example from the README.md file. I have fully commented this -example, to explain what each part does. Specific differences and a special note on this example: In C# you -cannot assign a Method to a `Variant` for use with `LuaAPI.PushVariant`. So, to get around that, and make the -example work, we will first wrap our called function in a `Callable` variable (wrapper). Please note the line +In this example, we recreate the main GDScript example from the README.md file. I have fully commented this +example, to explain what each part does. Specific differences and a special note on this example: In C# you +cannot assign a Method to a `Variant` for use with `LuaAPI.PushVariant`. So, to get around that, and make the +example work, we will first wrap our called function in a `Callable` variable (wrapper). Please note the line `Callable print = new Callable(this, MethodName.LuaPrint);` in the example below. +* Notes on Using `LuaFunctionRef`: It is the preferred way to call functions from within your Lua code base, if you do + not know the function name ahead of time, or if the function is not global. `LuaFunctionRef` will still be invokable + if it is a global function, and that global function was overwritten, as it is copied into the lua state, and then + referenced inside of C#. Removing all references to the LuaFunctionRef will release it out of the lua state and free + up the state's memory. This means that `LuaAPI.CallFunction()` uses less resources in the lua state, so keep that in mind. + +This example also shows how to use the newly added `LuaFunctionRef` class to `invoke` a lua function. This allows +for creating a call back function to respond to things like events. Note how we use `.As()` to cast +the Variant `val` into a `LuaFunctionRef` variable (`get_message`). Additionally, we do not need to use the nullable +invoke style common to most event firing, as the `get_message` variable is not null. The `.Invoke()` method takes a +`Godot.Collections.Array` as its only parameter. In this example, we make use of the shorthand to create a `new` object +for the Godot Array class. This shorthand is only possible because of the way that Godot defines the `Array` class, and +is not a normal C# `new Object()` creation style. + ```csharp using Godot; @@ -27,11 +41,11 @@ public partial class Node2D : Godot.Node2D { // All builtin libraries are available to bind with. Use OS and IO at your own risk. // BindLibraries requires a "Godot Array" so, let's build one. - Godot.Collections.Array libraries = new Godot.Collections.Array(); - libraries.Add("base"); // Base Lua commands - libraries.Add("table"); // Table functionality. - libraries.Add("string"); // String Specific functionality. - + 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. @@ -64,23 +78,30 @@ public partial class Node2D : Godot.Node2D { GD.Print("An error occurred calling DoString."); GD.Print("ERROR %d: %s", error.Type, error.Message); } - + + // Let's pull our lua function from the lua code. var val = lua.PullVariant("get_message"); - // Check to see if it returned an error, or a value. if (val.GetType() == typeof(LuaError)) { GD.Print("ERROR %d: %s", error.Type, error.Message); return; } - // LuaAPI.CallFunction requires a Godot.Collections.Array as the container - // for the parameters passed in, for the lua function. - Godot.Collections.Array Params = new Godot.Collections.Array(); + // We create a LuaFunctionRef as our reference to the Lua code's function, + // then we use .As() to cast it as a LuaFunctionRef. + LuaFunctionRef get_message = val.As(); + if (get_message == null) { + GD.Print("ERROR: get_message is null."); + return; + } - // We use .CallFunction to actually call the lua function within the Lua State. - var message = lua.CallFunction("get_message", Params); + // Calling Lua (code) functions requires a Godot.Collections.Array as the container + // for the parameters passed in. + Godot.Collections.Array Params = new(); + // We use .Invoke to actually call the lua function within the Lua State. // And, finally, we log the output of the function to Godot Output Console. - GD.Print(message); + GD.Print(get_message.Invoke(Params)); + } } ``` \ No newline at end of file