Skip to content

Commit 20d6d43

Browse files
committed
Move instance implementations to LuaScriptInstance
1 parent ead3dcb commit 20d6d43

File tree

7 files changed

+73
-151
lines changed

7 files changed

+73
-151
lines changed

src/LuaFunction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Variant LuaFunction::invoke_method(LuaScriptInstance *self, const Variant **args
7373
error.error = GDEXTENSION_CALL_OK;
7474

7575
lua_State *L = lua_object.lua_state();
76-
sol::stack::push(L, self);
76+
std::ignore = to_lua(L, self);
7777
for (int i = 0; i < arg_count; i++) {
7878
std::ignore = to_lua(L, *args[i]);
7979
}

src/script-language/LuaScript.cpp

Lines changed: 22 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,14 @@ String LuaScript::_get_class_icon_path() const {
130130
}
131131

132132
bool LuaScript::_has_method(const StringName &p_method) const {
133-
return methods.has(p_method);
133+
if (metatable.is_valid()) {
134+
Variant value = metatable->get_value(p_method);
135+
LuaFunction *method = Object::cast_to<LuaFunction>(value);
136+
return method != nullptr;
137+
}
138+
else {
139+
return false;
140+
}
134141
}
135142

136143
bool LuaScript::_has_static_method(const StringName &p_method) const {
@@ -171,7 +178,13 @@ ScriptLanguage *LuaScript::_get_language() const {
171178
}
172179

173180
bool LuaScript::_has_script_signal(const StringName &p_signal) const {
174-
return signals.has(p_signal);
181+
if (metatable.is_valid()) {
182+
Variant value = metatable->get_value(p_signal);
183+
return value.get_type() == Variant::Type::SIGNAL;
184+
}
185+
else {
186+
return false;
187+
}
175188
}
176189

177190
TypedArray<Dictionary> LuaScript::_get_script_signal_list() const {
@@ -241,89 +254,8 @@ Variant LuaScript::_new(const Variant **args, GDExtensionInt arg_count, GDExtens
241254
return new_instance;
242255
}
243256

244-
bool LuaScript::_instance_set(LuaScriptInstance *instance, const StringName& p_name, const Variant& p_value) const {
245-
if (const Ref<LuaFunction> *_set = methods.getptr("_set"); _set && _set->is_valid()) {
246-
Variant result = _set->ptr()->call_method(instance, p_name, p_value);
247-
if (LuaError *lua_error = Object::cast_to<LuaError>(result)) {
248-
ERR_FAIL_V_MSG(false, lua_error->get_message());
249-
}
250-
return true;
251-
}
252-
253-
if (const LuaScriptProperty *lua_prop = properties.getptr(p_name)) {
254-
if (lua_prop->setter.is_valid()) {
255-
lua_prop->setter->call_method(instance, p_value);
256-
}
257-
else {
258-
instance->properties[p_name] = p_value;
259-
}
260-
return true;
261-
}
262-
else {
263-
return false;
264-
}
265-
}
266-
267-
bool LuaScript::_instance_get(LuaScriptInstance *instance, const StringName& p_name, Variant& p_value) const {
268-
if (const Ref<LuaFunction> *_get = methods.getptr("_get"); _get && _get->is_valid()) {
269-
p_value = _get->ptr()->call_method(instance, p_name);
270-
if (LuaError *lua_error = Object::cast_to<LuaError>(p_value)) {
271-
ERR_FAIL_V_MSG(false, lua_error->get_message());
272-
}
273-
if (p_value != Variant()) {
274-
return true;
275-
}
276-
}
277-
278-
if (const LuaScriptProperty *lua_prop = properties.getptr(p_name)) {
279-
if (lua_prop->getter.is_valid()) {
280-
p_value = lua_prop->getter->call_method(instance);
281-
}
282-
else {
283-
p_value = instance->properties.get(p_name, lua_prop->default_value);
284-
}
285-
return true;
286-
}
287-
else if (instance->properties.has(p_name)) {
288-
p_value = instance->properties[p_name];
289-
return true;
290-
}
291-
else {
292-
return false;
293-
}
294-
}
295-
296-
Variant LuaScript::_instance_call(LuaScriptInstance *instance, const StringName& p_name, const Variant **p_args, GDExtensionInt p_argument_count, GDExtensionCallError& r_error) const {
297-
if (const Ref<LuaFunction> *method = methods.getptr(p_name)) {
298-
return method->ptr()->invoke_method(instance, p_args, p_argument_count, r_error);
299-
}
300-
else {
301-
r_error.error = GDEXTENSION_CALL_ERROR_INVALID_METHOD;
302-
}
303-
return {};
304-
}
305-
306-
void LuaScript::_instance_notification(LuaScriptInstance *instance, int32_t what, GDExtensionBool reversed) const {
307-
if (const Ref<LuaFunction> *method = methods.getptr("_notification")) {
308-
Variant result = method->ptr()->call_method(instance, what, reversed);
309-
if (LuaError *lua_error = Object::cast_to<LuaError>(result)) {
310-
ERR_FAIL_MSG(lua_error->get_message());
311-
}
312-
}
313-
}
314-
315-
bool LuaScript::_instance_tostring(LuaScriptInstance *instance, String& str) const {
316-
if (const Ref<LuaFunction> *method = methods.getptr("__tostring")) {
317-
Variant result = method->ptr()->call_method(instance);
318-
if (LuaError *lua_error = Object::cast_to<LuaError>(result)) {
319-
ERR_FAIL_V_MSG(false, lua_error->get_message());
320-
}
321-
str = result;
322-
return true;
323-
}
324-
else {
325-
return false;
326-
}
257+
Ref<LuaTable> LuaScript::get_metatable() {
258+
return metatable;
327259
}
328260

329261
void LuaScript::_bind_methods() {
@@ -341,53 +273,12 @@ void LuaScript::process_script_result(const Variant& result) {
341273
}
342274

343275
metatable.reference_ptr(table);
344-
methods.clear();
345-
properties.clear();
346-
signals.clear();
347-
if (!metatable.is_valid()) {
348-
return;
349-
}
350276

351-
for (Variant key : *table) {
352-
if (key == "extends") {
353-
StringName class_name = table->get_value(key);
354-
if (!ClassDB::class_exists(class_name)) {
355-
WARN_PRINT(String("Specified base class '%s' does not exist. Unsetting 'extends'") % Array::make(class_name));
356-
table->set_value(key, Variant());
357-
}
358-
// skip, not considered property
359-
continue;
360-
}
361-
362-
// skip special keys, they are not considered properties
363-
if (key.in(Array::make("class_name", "icon", "tool"))) {
364-
continue;
365-
}
366-
367-
// methods, signals and properties must have string key
368-
if (key.get_type() != Variant::STRING && key.get_type() != Variant::STRING_NAME) {
369-
continue;
370-
}
371-
372-
Variant value = table->get_value(key);
373-
switch (value.get_type()) {
374-
case Variant::SIGNAL:
375-
signals[key] = value;
376-
break;
377-
378-
case Variant::OBJECT:
379-
if (LuaFunction *method = Object::cast_to<LuaFunction>(value)) {
380-
methods[key].reference_ptr(method);
381-
}
382-
// fallthrough
383-
default:
384-
// TODO: add support for property metadata
385-
properties[key] = LuaScriptProperty {
386-
.type = value.get_type(),
387-
.default_value = value,
388-
};
389-
break;
390-
}
277+
// Remove "extends" field if it's invalid
278+
Variant base_class = table->get_value("extends");
279+
if (base_class && !ClassDB::class_exists(base_class)) {
280+
WARN_PRINT(String("Specified base class '%s' does not exist. Unsetting 'extends'") % Array::make(base_class));
281+
table->set_value("extends", Variant());
391282
}
392283
}
393284

src/script-language/LuaScript.hpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,23 +87,14 @@ class LuaScript : public ScriptExtension {
8787

8888
// Script methods
8989
Variant _new(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error);
90-
91-
// Methods called by ScriptInstance
92-
bool _instance_set(LuaScriptInstance *instance, const StringName& p_name, const Variant& p_value) const;
93-
bool _instance_get(LuaScriptInstance *instance, const StringName& p_name, Variant& p_value) const;
94-
Variant _instance_call(LuaScriptInstance *instance, const StringName& p_name, const Variant **p_args, GDExtensionInt p_argument_count, GDExtensionCallError& r_error) const;
95-
void _instance_notification(LuaScriptInstance *instance, int32_t what, GDExtensionBool reversed) const;
96-
bool _instance_tostring(LuaScriptInstance *instance, String& str) const;
90+
Ref<LuaTable> get_metatable();
9791

9892
protected:
9993
static void _bind_methods();
10094
virtual String _to_string() const;
10195

10296
String source_code;
10397
Ref<LuaTable> metatable;
104-
HashMap<StringName, Ref<LuaFunction>> methods;
105-
HashMap<StringName, LuaScriptProperty> properties;
106-
HashMap<StringName, Signal> signals;
10798

10899
private:
109100
void process_script_result(const Variant& result);

src/script-language/LuaScriptInstance.cpp

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace luagdextension {
3232
LuaScriptInstance::LuaScriptInstance(Object *owner, Ref<LuaScript> script)
3333
: owner(owner)
3434
, script(script)
35-
, properties()
35+
, data(LuaScriptLanguage::get_singleton()->get_lua_state()->create_table())
3636
{
3737
known_instances.insert(owner, this);
3838
}
@@ -42,11 +42,28 @@ LuaScriptInstance::~LuaScriptInstance() {
4242
}
4343

4444
GDExtensionBool set_func(LuaScriptInstance *p_instance, const StringName *p_name, const Variant *p_value) {
45-
return p_instance->script->_instance_set(p_instance, *p_name, p_value);
45+
if (ClassDB::class_set_property(p_instance->owner, *p_name, *p_value) == OK) {
46+
return true;
47+
}
48+
49+
p_instance->data->set_value(*p_name, *p_value);
50+
return true;
4651
}
4752

4853
GDExtensionBool get_func(LuaScriptInstance *p_instance, const StringName *p_name, Variant *p_value) {
49-
return p_instance->script->_instance_get(p_instance, *p_name, *p_value);
54+
// access own data
55+
if (auto data_value = p_instance->data->try_get_value(*p_name)) {
56+
*p_value = *data_value;
57+
return true;
58+
}
59+
60+
// fallback to value in script
61+
if (auto script_value = p_instance->script->get_metatable()->try_get_value(*p_name)) {
62+
*p_value = *script_value;
63+
return true;
64+
}
65+
66+
return false;
5067
}
5168

5269
GDExtensionScriptInstanceGetPropertyList get_property_list_func;
@@ -56,7 +73,7 @@ GDExtensionScriptInstanceGetClassCategory get_class_category_func;
5673
GDExtensionScriptInstancePropertyCanRevert property_can_revert_func;
5774
GDExtensionScriptInstancePropertyGetRevert property_get_revert_func;
5875

59-
void *get_owner_func(LuaScriptInstance *p_instance) {
76+
Object *get_owner_func(LuaScriptInstance *p_instance) {
6077
return p_instance->owner;
6178
}
6279

@@ -73,15 +90,31 @@ GDExtensionBool has_method_func(LuaScriptInstance *p_instance, const StringName
7390
GDExtensionScriptInstanceGetMethodArgumentCount get_method_argument_count_func;
7491

7592
void call_func(LuaScriptInstance *p_instance, const StringName *p_method, const Variant **p_args, GDExtensionInt p_argument_count, Variant *r_return, GDExtensionCallError *r_error) {
76-
*r_return = p_instance->script->_instance_call(p_instance, *p_method, p_args, p_argument_count, *r_error);
93+
Variant value = p_instance->script->get_metatable()->get_value(*p_method);
94+
if (LuaFunction *method = Object::cast_to<LuaFunction>(value)) {
95+
*r_return = method->invoke_method(p_instance, p_args, p_argument_count, *r_error);
96+
}
97+
else {
98+
r_error->error = GDEXTENSION_CALL_ERROR_INVALID_METHOD;
99+
}
77100
}
78101

79102
void notification_func(LuaScriptInstance *p_instance, int32_t p_what, GDExtensionBool p_reversed) {
80-
p_instance->script->_instance_notification(p_instance, p_what, p_reversed);
103+
Variant value = p_instance->script->get_metatable()->get_value("_notification");
104+
if (LuaFunction *method = Object::cast_to<LuaFunction>(value)) {
105+
method->call_method(p_instance, p_what, p_reversed);
106+
}
81107
}
82108

83109
void to_string_func(LuaScriptInstance *p_instance, GDExtensionBool *r_is_valid, String *r_out) {
84-
*r_is_valid = p_instance->script->_instance_tostring(p_instance, *r_out);
110+
Variant value = p_instance->script->get_metatable()->get_value("_to_string");
111+
if (LuaFunction *method = Object::cast_to<LuaFunction>(value)) {
112+
*r_out = method->call_method(p_instance);
113+
*r_is_valid = true;
114+
}
115+
else {
116+
*r_is_valid = false;
117+
}
85118
}
86119

87120
void refcount_incremented_func(LuaScriptInstance *) {

src/script-language/LuaScriptInstance.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#ifndef __LUA_SCRIPT_INSTANCE_HPP__
2323
#define __LUA_SCRIPT_INSTANCE_HPP__
2424

25-
#include <godot_cpp/classes/object.hpp>
2625
#include <godot_cpp/classes/ref.hpp>
2726
#include <godot_cpp/templates/hash_map.hpp>
2827

@@ -31,6 +30,7 @@ using namespace godot;
3130
namespace luagdextension {
3231

3332
class LuaScript;
33+
class LuaTable;
3434

3535
struct LuaScriptInstance {
3636
LuaScriptInstance(Object *owner, Ref<LuaScript> script);
@@ -41,7 +41,7 @@ struct LuaScriptInstance {
4141

4242
Object *owner;
4343
Ref<LuaScript> script;
44-
Dictionary properties;
44+
Ref<LuaTable> data;
4545

4646
private:
4747
static HashMap<Object *, LuaScriptInstance *> known_instances;

src/utils/convert_godot_lua.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "../LuaLightUserdata.hpp"
2828
#include "../LuaTable.hpp"
2929
#include "../LuaUserdata.hpp"
30+
#include "../script-language/LuaScriptInstance.hpp"
3031
#include "Class.hpp"
3132
#include "DictionaryIterator.hpp"
3233
#include "VariantArguments.hpp"
@@ -176,6 +177,10 @@ sol::stack_object to_lua(lua_State *lua_state, const Variant& value) {
176177
return sol::stack_object(lua_state, -1);
177178
}
178179

180+
sol::stack_object to_lua(lua_State *lua_state, LuaScriptInstance *value) {
181+
return to_lua(lua_state, value->data);
182+
}
183+
179184
Array to_array(const sol::variadic_args& args) {
180185
Array arr;
181186
for (auto it : args) {

src/utils/convert_godot_lua.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ using namespace godot;
3131
namespace luagdextension {
3232

3333
class LuaTable;
34+
class LuaScriptInstance;
3435

3536
Variant to_variant(const sol::object& object);
3637
Variant to_variant(const sol::stack_object& object);
@@ -39,6 +40,7 @@ Variant to_variant(const sol::protected_function_result& function_result);
3940
Variant to_variant(const sol::load_result& load_result);
4041
Variant to_variant(lua_State *L, int index);
4142
sol::stack_object to_lua(lua_State *lua_state, const Variant& value);
43+
sol::stack_object to_lua(lua_State *lua_state, LuaScriptInstance *value);
4244

4345
Array to_array(const sol::variadic_args& args);
4446
Array to_array(const sol::table& table);

0 commit comments

Comments
 (0)