diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 4fa48de..6134475 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -191,23 +191,23 @@ jobs:
include:
- name: Linux
runner-os: ubuntu-latest
- godot-release: 4.4-stable/Godot_v4.4-stable_linux.x86_64.zip
- godot-bin: ./Godot_v4.4-stable_linux.x86_64
+ godot-release: 4.4.1-stable/Godot_v4.4.1-stable_linux.x86_64.zip
+ godot-bin: ./Godot_v4.4.1-stable_linux.x86_64
- name: Linux (arm64)
runner-os: ubuntu-24.04-arm
- godot-release: 4.4-stable/Godot_v4.4-stable_linux.arm64.zip
- godot-bin: ./Godot_v4.4-stable_linux.arm64
+ godot-release: 4.4.1-stable/Godot_v4.4.1-stable_linux.arm64.zip
+ godot-bin: ./Godot_v4.4.1-stable_linux.arm64
- name: Windows
runner-os: windows-latest
- godot-release: 4.4-stable/Godot_v4.4-stable_win64.exe.zip
- godot-bin: ./Godot_v4.4-stable_win64.exe
+ godot-release: 4.4.1-stable/Godot_v4.4.1-stable_win64.exe.zip
+ godot-bin: ./Godot_v4.4.1-stable_win64.exe
- name: Windows (arm64)
runner-os: windows-11-arm
- godot-release: 4.4-stable/Godot_v4.4-stable_windows_arm64.exe.zip
- godot-bin: ./Godot_v4.4-stable_windows_arm64.exe
+ godot-release: 4.4.1-stable/Godot_v4.4.1-stable_windows_arm64.exe.zip
+ godot-bin: ./Godot_v4.4.1-stable_windows_arm64.exe
- name: macOS
runner-os: macos-latest
- godot-release: 4.4-stable/Godot_v4.4-stable_macos.universal.zip
+ godot-release: 4.4.1-stable/Godot_v4.4.1-stable_macos.universal.zip
godot-bin: ./Godot.app/Contents/MacOS/Godot
env:
GODOT_BIN: ${{ matrix.godot-bin }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2b04656..40cfe06 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog
## [Unreleased](https://github.com/gilzoide/lua-gdextension/compare/0.6.0...HEAD)
+### Changed
+- Opening `GODOT_CLASSES` now registers all classes at once instead of setting up a lazy getter in `_G`'s metatable
+- Opening `GODOT_SINGLETONS` now registers all singletons at once instead of setting up a lazy getter in `_G`'s metatable
+
## [0.6.0](https://github.com/gilzoide/lua-gdextension/releases/tag/0.6.0)
diff --git a/doc_classes/LuaState.xml b/doc_classes/LuaState.xml
index bd8e1b6..506e152 100644
--- a/doc_classes/LuaState.xml
+++ b/doc_classes/LuaState.xml
@@ -285,7 +285,7 @@
[b]Note: This may override some Lua functions like [code]print[/code].[/b]
- Godot singletons library.
+ Godot singletons library. Adds global singletons like [Engine] and [ResourceLoader] to _G.
Godot classes library. Adds Godot classes like [Node] to _G.
@@ -293,7 +293,7 @@
[gdscript]
var lua_state = LuaState.new()
lua_state.open_libraries(LuaState.Library.LUA_BASE | LuaState.Library.GODOT_CLASSES)
- var vec3 = lua_state.do_string("""
+ var node = lua_state.do_string("""
-- Create a Node in Lua
local node = Node:new()
return node
diff --git a/src/LuaState.cpp b/src/LuaState.cpp
index 1295fb7..a307217 100644
--- a/src/LuaState.cpp
+++ b/src/LuaState.cpp
@@ -25,7 +25,6 @@
#include "LuaTable.hpp"
#include "LuaThread.hpp"
#include "luaopen/godot.hpp"
-#include "utils/_G_metatable.hpp"
#include "utils/convert_godot_lua.hpp"
#include "utils/module_names.hpp"
@@ -75,7 +74,6 @@ LuaState::LuaState()
: lua_state(lua_panic_handler, lua_alloc)
#endif
{
- setup_G_metatable(lua_state);
#ifdef HAVE_LUA_WARN
lua_setwarnf(lua_state, lua_warn_handler, this);
#endif
@@ -153,12 +151,12 @@ void LuaState::open_libraries(BitField libraries) {
if (libraries.has_flag(GODOT_UTILITY_FUNCTIONS)) {
lua_state.require(module_names::utility_functions, &luaopen_godot_utility_functions, false);
}
- if (libraries.has_flag(GODOT_SINGLETONS)) {
- lua_state.require(module_names::singleton_access, &luaopen_godot_singleton_access, false);
- }
if (libraries.has_flag(GODOT_CLASSES)) {
lua_state.require(module_names::classes, &luaopen_godot_classes, false);
}
+ if (libraries.has_flag(GODOT_SINGLETONS)) {
+ lua_state.require(module_names::singleton_access, &luaopen_godot_singleton_access, false);
+ }
if (libraries.has_flag(GODOT_ENUMS)) {
lua_state.require(module_names::enums, &luaopen_godot_enums, false);
}
diff --git a/src/luaopen/classes.cpp b/src/luaopen/classes.cpp
index 2512d74..0f93bac 100644
--- a/src/luaopen/classes.cpp
+++ b/src/luaopen/classes.cpp
@@ -19,19 +19,20 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
#include "../utils/Class.hpp"
-#include "../utils/module_names.hpp"
-#include
+#include
using namespace luagdextension;
extern "C" int luaopen_godot_classes(lua_State *L) {
sol::state_view state = L;
- state.registry()[module_names::classes] = true;
Class::register_usertype(state);
+ ClassDBSingleton *classdb = ClassDBSingleton::get_singleton();
+ for (auto&& class_name : classdb->get_class_list()) {
+ state.set(class_name.ascii().get_data(), Class(class_name));
+ }
return 0;
}
diff --git a/src/luaopen/godot.cpp b/src/luaopen/godot.cpp
index 47a78cd..6cca070 100644
--- a/src/luaopen/godot.cpp
+++ b/src/luaopen/godot.cpp
@@ -33,8 +33,8 @@ extern "C" int luaopen_godot(lua_State *L) {
state.require(module_names::variant, &luaopen_godot_variant, false);
state.require(module_names::utility_functions, &luaopen_godot_utility_functions, false);
- state.require(module_names::singleton_access, &luaopen_godot_singleton_access, false);
state.require(module_names::classes, &luaopen_godot_classes, false);
+ state.require(module_names::singleton_access, &luaopen_godot_singleton_access, false);
state.require(module_names::enums, &luaopen_godot_enums, false);
state.require(module_names::local_paths, &luaopen_godot_local_paths, false);
diff --git a/src/luaopen/singleton_access.cpp b/src/luaopen/singleton_access.cpp
index 41963c2..9da4d2d 100644
--- a/src/luaopen/singleton_access.cpp
+++ b/src/luaopen/singleton_access.cpp
@@ -19,17 +19,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+#include "../utils/custom_sol.hpp"
-#include "../utils/module_names.hpp"
+#include
-#include
-
-using namespace luagdextension;
+using namespace godot;
extern "C" int luaopen_godot_singleton_access(lua_State *L) {
- sol::state_view state = L;
-
- state.registry()[module_names::singleton_access] = true;
-
+ sol::state_view state(L);
+ Engine *engine = Engine::get_singleton();
+ for (auto&& singleton_name : engine->get_singleton_list()) {
+ state.set(singleton_name.ascii().get_data(), engine->get_singleton(singleton_name));
+ }
return 0;
}
diff --git a/src/utils/_G_metatable.cpp b/src/utils/_G_metatable.cpp
deleted file mode 100644
index 6b7eae8..0000000
--- a/src/utils/_G_metatable.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Copyright (C) 2025 Gil Barbosa Reis.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the “Software”), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#include "_G_metatable.hpp"
-
-#include "Class.hpp"
-#include "convert_godot_lua.hpp"
-#include "module_names.hpp"
-
-#include
-#include
-
-using namespace godot;
-
-namespace luagdextension {
-
-sol::object __index(sol::this_state state, sol::global_table _G, sol::stack_object key) {
- static Engine *engine = Engine::get_singleton();
-
- if (key.get_type() != sol::type::string) {
- return sol::nil;
- }
-
- auto registry = sol::state_view(state).registry();
- if (registry.get_or(module_names::singleton_access, false)) {
- auto class_name = key.as();
- if (engine->has_singleton(class_name)) {
- Variant singleton = engine->get_singleton(class_name);
- return _G[key] = to_lua(state, singleton);
- }
- }
- if (registry.get_or(module_names::classes, false)) {
- StringName class_name = key.as();
- if (ClassDB::class_exists(class_name)) {
- Class cls(class_name);
- return _G[key] = sol::make_object(state, cls);
- }
- }
- return sol::nil;
-}
-
-void setup_G_metatable(sol::state_view& state) {
- state.globals()[sol::metatable_key] = state.create_table_with(
- sol::meta_function::index, &__index
- );
-}
-
-}
-
diff --git a/src/utils/_G_metatable.hpp b/src/utils/_G_metatable.hpp
deleted file mode 100644
index 64659bd..0000000
--- a/src/utils/_G_metatable.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * Copyright (C) 2025 Gil Barbosa Reis.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the “Software”), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef __UTILS_G_METATABLE_HPP__
-#define __UTILS_G_METATABLE_HPP__
-
-#include
-
-namespace luagdextension {
-
-void setup_G_metatable(sol::state_view& state);
-
-}
-
-#endif // __UTILS_G_METATABLE_HPP__
diff --git a/test/test_entrypoint.gd b/test/test_entrypoint.gd
index 2588e08..d5db46f 100644
--- a/test/test_entrypoint.gd
+++ b/test/test_entrypoint.gd
@@ -4,7 +4,7 @@ const LUA_TEST_DIR = "res://lua_tests"
const GDSCRIPT_TEST_DIR = "res://gdscript_tests"
func _initialize():
- var all_success = true
+ var error_count = 0
print("Starting Lua GDExtension tests (runtime: ", LuaState.get_lua_runtime(), ")")
for lua_script in DirAccess.get_files_at(LUA_TEST_DIR):
@@ -16,7 +16,7 @@ func _initialize():
var file_name = str(LUA_TEST_DIR, "/", lua_script)
var result = lua_state.do_file(file_name)
if result is LuaError:
- all_success = false
+ error_count += 1
print("! ", lua_script)
push_error(result.message)
else:
@@ -38,11 +38,12 @@ func _initialize():
obj._setup()
# actual test
if not obj.call(method_name):
- all_success = false
+ error_count += 1
printerr(" ! ", method_name)
else:
print(" ✓ ", method_name)
if obj is Node:
obj.queue_free()
- quit(0 if all_success else -1)
+ print("\nFailed tests: ", error_count)
+ quit(0 if error_count == 0 else -1)