Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
BasedOnStyle: LLVM
IndentWidth: 4
TabWidth: 4
UseTab: Always
ColumnLimit: 200
AccessModifierOffset: -4
PointerAlignment: Left
FixNamespaceComments: false

IncludeBlocks: Regroup
SortIncludes: CaseSensitive
IncludeCategories:
- Regex: '^"[A-Za-z]'
Priority: 1
SortPriority: 1
- Regex: '^"\.\.'
Priority: 1
SortPriority: 2
- Regex: '^<'
Priority: 3
SortPriority: 3

BreakBeforeBraces: Attach
AllowShortBlocksOnASingleLine: Never
AllowShortFunctionsOnASingleLine: None

BreakConstructorInitializers: BeforeColon
PackConstructorInitializers: Never
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ function LuaBouncingLogo:_ready()

-- To connect a signal in Lua, you can use the method name just like in GDScript
self.bounced:connect(self._on_bounced)
-- Or you can use a Callable constructed from a lua function
self.ready:connect(Callable(function()
print("This works!")
end))
end

-- Called every frame. 'delta' is the elapsed time since the previous frame.
Expand Down
39 changes: 39 additions & 0 deletions src/utils/LuaCallable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "LuaCallable.hpp"
#include "godot_cpp/variant/callable.hpp"
#include "godot_cpp/variant/variant.hpp"

namespace luagdextension {

LuaCallable::CompareEqualFunc LuaCallable::get_compare_equal_func() const {
return nullptr;
}

LuaCallable::CompareLessFunc LuaCallable::get_compare_less_func() const {
return nullptr;
}

bool LuaCallable::is_valid() const {
return _lua_func->get_function().valid();
}

ObjectID LuaCallable::get_object() const {
return {};
}

String LuaCallable::get_as_text() const {
return "<LuaCallable>";
}

uint32_t LuaCallable::hash() const {
return get_as_text().hash();
}

void LuaCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const {
r_return_value = _lua_func->invoke(p_arguments, p_argcount, r_call_error);
}

Variant LuaCallable::construct(sol::function func) {
return Variant{Callable{memnew(LuaCallable(func))}};
};

}
25 changes: 25 additions & 0 deletions src/utils/LuaCallable.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include "../LuaFunction.hpp"

namespace luagdextension {

using namespace godot;

class LuaCallable : public CallableCustom {
Ref<LuaFunction> _lua_func;
public:
explicit LuaCallable(sol::protected_function func) : _lua_func{LuaObject::wrap_object<LuaFunction>(func)} {};
~LuaCallable() = default;

bool is_valid() const override;
String get_as_text() const override;
ObjectID get_object() const override;
CompareEqualFunc get_compare_equal_func() const override;
CompareLessFunc get_compare_less_func() const override;
uint32_t hash() const override;
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override;
static Variant construct(sol::function func);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also please use sol::protected_function here instead of sol::function.

};

}
29 changes: 19 additions & 10 deletions src/utils/VariantType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "VariantType.hpp"

#include "Class.hpp"
#include "LuaCallable.hpp"
#include "VariantArguments.hpp"
#include "convert_godot_lua.hpp"
#include "method_bind_impl.hpp"
Expand All @@ -31,6 +32,9 @@
#include <godot_cpp/classes/resource.hpp>
#include <godot_cpp/classes/script.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
#include <godot_cpp/variant/callable.hpp>
#include <sol/forward.hpp>
#include <sol/types.hpp>

namespace luagdextension {

Expand Down Expand Up @@ -138,16 +142,21 @@ Variant VariantType::construct(const sol::variadic_args& args) const {
if (args.size() == 0) {
return construct_default();
}
else if (args.size() == 1 && args.get_type(0) == sol::type::table) {
if (type == Variant::ARRAY) {
Array array = construct_default();
fill_array(array, args.get<sol::stack_table>());
return array;
}
else if (type == Variant::DICTIONARY) {
Dictionary dictionary = construct_default();
fill_dictionary(dictionary, args.get<sol::stack_table>());
return dictionary;
else if (args.size() == 1) {
sol::type first_arg_type = args.get_type(0);
if (first_arg_type == sol::type::table) {
if (type == Variant::ARRAY) {
Array array = construct_default();
fill_array(array, args.get<sol::stack_table>());
return array;
}
else if (type == Variant::DICTIONARY) {
Dictionary dictionary = construct_default();
fill_dictionary(dictionary, args.get<sol::stack_table>());
return dictionary;
}
} else if (first_arg_type == sol::type::function) {
return LuaCallable::construct(args.get<sol::protected_function>());
}
}

Expand Down
4 changes: 4 additions & 0 deletions test/bouncing_logo.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ function LuaBouncingLogo:_ready()

-- To connect a signal in Lua, you can use the method callable just like in GDScript
self.bounced:connect(self._on_bounced)
-- Or you can use a Callable constructed from a lua function
self.ready:connect(Callable(function()
print("This works!")
end))
end

-- Called every frame. 'delta' is the elapsed time since the previous frame.
Expand Down
10 changes: 10 additions & 0 deletions test/lua_tests/callable.lua
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
local callable = Callable(OS, "get_name")
assert(callable() == OS:get_name())
local a = 1
local custom_callable = Callable(function(val)
a = a + val
return a
end)
local result = custom_callable(5)
assert(a == 6 and result == 6)
custom_callable = custom_callable:bind(1)
custom_callable()
assert(a == 7)
3 changes: 3 additions & 0 deletions tools/code_generation/generate_lua_godot_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ def generate_builtin_classes(
lines.append(f"--- @overload fun(from: table): {cls['name']}")
for ctor in cls["constructors"]:
lines.append(f"--- @overload fun({', '.join(f"{arg['name']}: {arg['type']}" for arg in ctor.get('arguments', []))}): {cls['name']}")
if cls['name'] == 'Callable':
lines.append("--- @overload fun(from_lua: function): Callable")


# Other operators
for op in cls["operators"]:
Expand Down
Loading