summaryrefslogtreecommitdiff
path: root/modules/gdscript/gd_function.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gd_function.cpp')
-rw-r--r--modules/gdscript/gd_function.cpp71
1 files changed, 59 insertions, 12 deletions
diff --git a/modules/gdscript/gd_function.cpp b/modules/gdscript/gd_function.cpp
index 0e7ba981f4..13a7480a36 100644
--- a/modules/gdscript/gd_function.cpp
+++ b/modules/gdscript/gd_function.cpp
@@ -6,6 +6,7 @@
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -357,12 +358,12 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (a->get_type() != Variant::OBJECT || a->operator Object *() == NULL) {
- err_text = "Left operand of 'extends' is not an instance of anything.";
+ err_text = "Left operand of 'is' is not an instance of anything.";
break;
}
if (b->get_type() != Variant::OBJECT || b->operator Object *() == NULL) {
- err_text = "Right operand of 'extends' is not a class.";
+ err_text = "Right operand of 'is' is not a class.";
break;
}
#endif
@@ -400,7 +401,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (!nc) {
- err_text = "Right operand of 'extends' is not a class (type: '" + obj_B->get_class() + "').";
+ err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "').";
break;
}
@@ -887,8 +888,8 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
gdfs->state._class = _class;
gdfs->state.ip = ip + ipofs;
gdfs->state.line = line;
- gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_ID() : 0;
- gdfs->state.script_id = _class->get_instance_ID();
+ gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : 0;
+ gdfs->state.script_id = _class->get_instance_id();
//gdfs->state.result_pos=ip+ipofs-1;
gdfs->state.defarg = defarg;
gdfs->state.instance = p_instance;
@@ -1232,10 +1233,10 @@ int GDFunction::get_default_argument_count() const {
return default_arguments.size();
}
-int GDFunction::get_default_argument_addr(int p_arg) const {
+int GDFunction::get_default_argument_addr(int p_idx) const {
- ERR_FAIL_INDEX_V(p_arg, default_arguments.size(), -1);
- return default_arguments[p_arg];
+ ERR_FAIL_INDEX_V(p_idx, default_arguments.size(), -1);
+ return default_arguments[p_idx];
}
StringName GDFunction::get_name() const {
@@ -1427,14 +1428,42 @@ Variant GDFunctionState::_signal_callback(const Variant **p_args, int p_argcount
state.result = arg;
Variant ret = function->call(NULL, NULL, 0, r_error, &state);
+
+ bool completed = true;
+
+ // If the return value is a GDFunctionState reference,
+ // then the function did yield again after resuming.
+ if (ret.is_ref()) {
+ GDFunctionState *gdfs = ret.operator Object *()->cast_to<GDFunctionState>();
+ if (gdfs && gdfs->function == function)
+ completed = false;
+ }
+
function = NULL; //cleaned up;
state.result = Variant();
+
+ if (completed) {
+ emit_signal("completed", ret);
+ }
+
return ret;
}
-bool GDFunctionState::is_valid() const {
+bool GDFunctionState::is_valid(bool p_extended_check) const {
+
+ if (function == NULL)
+ return false;
+
+ if (p_extended_check) {
+ //class instance gone?
+ if (state.instance_id && !ObjectDB::get_instance(state.instance_id))
+ return false;
+ //script gone?
+ if (state.script_id && !ObjectDB::get_instance(state.script_id))
+ return false;
+ }
- return function != NULL;
+ return true;
}
Variant GDFunctionState::resume(const Variant &p_arg) {
@@ -1455,16 +1484,34 @@ Variant GDFunctionState::resume(const Variant &p_arg) {
state.result = p_arg;
Variant::CallError err;
Variant ret = function->call(NULL, NULL, 0, err, &state);
+
+ bool completed = true;
+
+ // If the return value is a GDFunctionState reference,
+ // then the function did yield again after resuming.
+ if (ret.is_ref()) {
+ GDFunctionState *gdfs = ret.operator Object *()->cast_to<GDFunctionState>();
+ if (gdfs && gdfs->function == function)
+ completed = false;
+ }
+
function = NULL; //cleaned up;
state.result = Variant();
+
+ if (completed) {
+ emit_signal("completed", ret);
+ }
+
return ret;
}
void GDFunctionState::_bind_methods() {
- ClassDB::bind_method(D_METHOD("resume:Variant", "arg"), &GDFunctionState::resume, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("is_valid"), &GDFunctionState::is_valid);
+ ClassDB::bind_method(D_METHOD("resume", "arg"), &GDFunctionState::resume, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("is_valid", "extended_check"), &GDFunctionState::is_valid, DEFVAL(false));
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "_signal_callback", &GDFunctionState::_signal_callback, MethodInfo("_signal_callback"));
+
+ ADD_SIGNAL(MethodInfo("completed", PropertyInfo(Variant::NIL, "result")));
}
GDFunctionState::GDFunctionState() {