GDScript: Allow using self in lambdas

This commit is contained in:
George Marques 2022-04-20 14:22:22 -03:00
parent 690fefe43e
commit 01d13ab2c1
No known key found for this signature in database
GPG key ID: 046BD46A3201E43D
16 changed files with 251 additions and 23 deletions

View file

@ -93,3 +93,81 @@ GDScriptLambdaCallable::GDScriptLambdaCallable(Ref<GDScript> p_script, GDScriptF
h = (uint32_t)hash_djb2_one_64((uint64_t)this);
}
bool GDScriptLambdaSelfCallable::compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) {
// Lambda callables are only compared by reference.
return p_a == p_b;
}
bool GDScriptLambdaSelfCallable::compare_less(const CallableCustom *p_a, const CallableCustom *p_b) {
// Lambda callables are only compared by reference.
return p_a < p_b;
}
uint32_t GDScriptLambdaSelfCallable::hash() const {
return h;
}
String GDScriptLambdaSelfCallable::get_as_text() const {
if (function->get_name() != StringName()) {
return function->get_name().operator String() + "(lambda)";
}
return "(anonymous lambda)";
}
CallableCustom::CompareEqualFunc GDScriptLambdaSelfCallable::get_compare_equal_func() const {
return compare_equal;
}
CallableCustom::CompareLessFunc GDScriptLambdaSelfCallable::get_compare_less_func() const {
return compare_less;
}
ObjectID GDScriptLambdaSelfCallable::get_object() const {
return object->get_instance_id();
}
void GDScriptLambdaSelfCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
#ifdef DEBUG_ENABLED
if (object->get_script_instance() == nullptr || object->get_script_instance()->get_language() != GDScriptLanguage::get_singleton()) {
ERR_PRINT("Trying to call a lambda with an invalid instance.");
r_call_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
return;
}
#endif
int captures_amount = captures.size();
if (captures_amount > 0) {
Vector<const Variant *> args;
args.resize(p_argcount + captures_amount);
for (int i = 0; i < captures_amount; i++) {
args.write[i] = &captures[i];
}
for (int i = 0; i < p_argcount; i++) {
args.write[i + captures_amount] = p_arguments[i];
}
r_return_value = function->call(static_cast<GDScriptInstance *>(object->get_script_instance()), args.ptrw(), args.size(), r_call_error);
r_call_error.argument -= captures_amount;
} else {
r_return_value = function->call(static_cast<GDScriptInstance *>(object->get_script_instance()), p_arguments, p_argcount, r_call_error);
}
}
GDScriptLambdaSelfCallable::GDScriptLambdaSelfCallable(Ref<RefCounted> p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures) {
reference = p_self;
object = p_self.ptr();
function = p_function;
captures = p_captures;
h = (uint32_t)hash_djb2_one_64((uint64_t)this);
}
GDScriptLambdaSelfCallable::GDScriptLambdaSelfCallable(Object *p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures) {
object = p_self;
function = p_function;
captures = p_captures;
h = (uint32_t)hash_djb2_one_64((uint64_t)this);
}