Remove multilevel calls

In general they are more confusing to users because they expect
inheritance to fully override parent methods. This behavior can be
enabled by script writers using a simple super() call.
This commit is contained in:
George Marques 2020-07-24 14:13:58 -03:00
parent b7dc08fcf6
commit 2b9d9bc364
No known key found for this signature in database
GPG key ID: 046BD46A3201E43D
17 changed files with 19 additions and 264 deletions

View file

@ -680,84 +680,6 @@ Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Call
return Variant();
}
#ifdef DEBUG_ENABLED
static void _test_call_error(const StringName &p_func, const Callable::CallError &error) {
switch (error.error) {
case Callable::CallError::CALL_OK:
case Callable::CallError::CALL_ERROR_INVALID_METHOD:
break;
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: {
ERR_FAIL_MSG("Error calling function: " + String(p_func) + " - Invalid type for argument " + itos(error.argument) + ", expected " + Variant::get_type_name(Variant::Type(error.expected)) + ".");
break;
}
case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: {
ERR_FAIL_MSG("Error calling function: " + String(p_func) + " - Too many arguments, expected " + itos(error.argument) + ".");
break;
}
case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: {
ERR_FAIL_MSG("Error calling function: " + String(p_func) + " - Too few arguments, expected " + itos(error.argument) + ".");
break;
}
case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL:
break;
}
}
#else
#define _test_call_error(m_str, m_err)
#endif
void Object::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
if (p_method == CoreStringNames::get_singleton()->_free) {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(Object::cast_to<Reference>(this), "Can't 'free' a reference.");
ERR_FAIL_COND_MSG(_lock_index.get() > 1, "Object is locked and can't be freed.");
#endif
//must be here, must be before everything,
memdelete(this);
return;
}
//Variant ret;
OBJ_DEBUG_LOCK
Callable::CallError error;
if (script_instance) {
script_instance->call_multilevel(p_method, p_args, p_argcount);
//_test_call_error(p_method,error);
}
MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
if (method) {
method->call(this, p_args, p_argcount, error);
_test_call_error(p_method, error);
}
}
void Object::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) {
MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
Callable::CallError error;
OBJ_DEBUG_LOCK
if (method) {
method->call(this, p_args, p_argcount, error);
_test_call_error(p_method, error);
}
//Variant ret;
if (script_instance) {
script_instance->call_multilevel_reversed(p_method, p_args, p_argcount);
//_test_call_error(p_method,error);
}
}
bool Object::has_method(const StringName &p_method) const {
if (p_method == CoreStringNames::get_singleton()->_free) {
return true;
@ -820,21 +742,6 @@ Variant Object::call(const StringName &p_name, VARIANT_ARG_DECLARE) {
return ret;
}
void Object::call_multilevel(const StringName &p_name, VARIANT_ARG_DECLARE) {
VARIANT_ARGPTRS;
int argc = 0;
for (int i = 0; i < VARIANT_ARG_MAX; i++) {
if (argptr[i]->get_type() == Variant::NIL) {
break;
}
argc++;
}
//Callable::CallError error;
call_multilevel(p_name, argptr, argc);
}
Variant Object::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
r_error.error = Callable::CallError::CALL_OK;

View file

@ -655,10 +655,7 @@ public:
void get_method_list(List<MethodInfo> *p_list) const;
Variant callv(const StringName &p_method, const Array &p_args);
virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount);
virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount);
Variant call(const StringName &p_name, VARIANT_ARG_LIST); // C++ helper
void call_multilevel(const StringName &p_name, VARIANT_ARG_LIST); // C++ helper
void notification(int p_notification, bool p_reversed = false);
String to_string();

View file

@ -308,16 +308,6 @@ Variant ScriptInstance::call(const StringName &p_method, VARIANT_ARG_DECLARE) {
return call(p_method, argptr, argc, error);
}
void ScriptInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
Callable::CallError ce;
call(p_method, p_args, p_argcount, ce); // script may not support multilevel calls
}
void ScriptInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) {
Callable::CallError ce;
call(p_method, p_args, p_argcount, ce); // script may not support multilevel calls
}
void ScriptInstance::property_set_fallback(const StringName &, const Variant &, bool *r_valid) {
if (r_valid) {
*r_valid = false;
@ -331,19 +321,6 @@ Variant ScriptInstance::property_get_fallback(const StringName &, bool *r_valid)
return Variant();
}
void ScriptInstance::call_multilevel(const StringName &p_method, VARIANT_ARG_DECLARE) {
VARIANT_ARGPTRS;
int argc = 0;
for (int i = 0; i < VARIANT_ARG_MAX; i++) {
if (argptr[i]->get_type() == Variant::NIL) {
break;
}
argc++;
}
call_multilevel(p_method, argptr, argc);
}
ScriptInstance::~ScriptInstance() {
}

View file

@ -199,9 +199,6 @@ public:
virtual bool has_method(const StringName &p_method) const = 0;
virtual Variant call(const StringName &p_method, VARIANT_ARG_LIST);
virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = 0;
virtual void call_multilevel(const StringName &p_method, VARIANT_ARG_LIST);
virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount);
virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount);
virtual void notification(int p_notification) = 0;
virtual String to_string(bool *r_valid) {
if (r_valid) {
@ -428,8 +425,6 @@ public:
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant();
}
//virtual void call_multilevel(const StringName& p_method,VARIANT_ARG_LIST) { return Variant(); }
//virtual void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount,Callable::CallError &r_error) { return Variant(); }
virtual void notification(int p_notification) {}
virtual Ref<Script> get_script() const { return script; }

View file

@ -991,7 +991,8 @@ void NativeScriptInstance::notification(int p_notification) {
Variant value = p_notification;
const Variant *args[1] = { &value };
call_multilevel("_notification", args, 1);
Callable::CallError error;
call("_notification", args, 1, error);
}
String NativeScriptInstance::to_string(bool *r_valid) {
@ -1087,31 +1088,6 @@ ScriptLanguage *NativeScriptInstance::get_language() {
return NativeScriptLanguage::get_singleton();
}
void NativeScriptInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
NativeScriptDesc *script_data = GET_SCRIPT_DESC();
while (script_data) {
Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
if (E) {
godot_variant res = E->get().method.method((godot_object *)owner,
E->get().method.method_data,
userdata,
p_argcount,
(godot_variant **)p_args);
godot_variant_destroy(&res);
}
script_data = script_data->base_data;
}
}
void NativeScriptInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) {
NativeScriptDesc *script_data = GET_SCRIPT_DESC();
if (script_data) {
_ml_call_reversed(script_data, p_method, p_args, p_argcount);
}
}
NativeScriptInstance::~NativeScriptInstance() {
NativeScriptDesc *script_data = GET_SCRIPT_DESC();

View file

@ -231,9 +231,6 @@ public:
virtual ScriptLanguage *get_language();
virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount);
virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount);
virtual void refcount_incremented();
virtual bool refcount_decremented();

View file

@ -62,12 +62,6 @@ public:
virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
// Rely on default implementations provided by ScriptInstance for the moment.
// Note that multilevel call could be removed in 3.0 release, so stay tuned
// (see https://godotengine.org/qa/9244/can-override-the-_ready-and-_process-functions-child-classes)
//virtual void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount);
//virtual void call_multilevel_reversed(const StringName& p_method,const Variant** p_args,int p_argcount);
virtual void notification(int p_notification);
virtual Ref<Script> get_script() const;

View file

@ -1309,39 +1309,6 @@ Variant GDScriptInstance::call(const StringName &p_method, const Variant **p_arg
return Variant();
}
void GDScriptInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
GDScript *sptr = script.ptr();
Callable::CallError ce;
while (sptr) {
Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method);
if (E) {
E->get()->call(this, p_args, p_argcount, ce);
return;
}
sptr = sptr->_base;
}
}
void GDScriptInstance::_ml_call_reversed(GDScript *sptr, const StringName &p_method, const Variant **p_args, int p_argcount) {
if (sptr->_base) {
_ml_call_reversed(sptr->_base, p_method, p_args, p_argcount);
}
Callable::CallError ce;
Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method);
if (E) {
E->get()->call(this, p_args, p_argcount, ce);
}
}
void GDScriptInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) {
if (script.ptr()) {
_ml_call_reversed(script.ptr(), p_method, p_args, p_argcount);
}
}
void GDScriptInstance::notification(int p_notification) {
//notification is not virtual, it gets called at ALL levels just like in C.
Variant value = p_notification;

View file

@ -146,7 +146,6 @@ protected:
void _get_property_list(List<PropertyInfo> *p_properties) const;
Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
//void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount);
static void _bind_methods();
@ -258,8 +257,6 @@ class GDScriptInstance : public ScriptInstance {
SelfList<GDScriptFunctionState>::List pending_func_states;
void _ml_call_reversed(GDScript *sptr, const StringName &p_method, const Variant **p_args, int p_argcount);
public:
virtual Object *get_owner() { return owner; }
@ -271,8 +268,6 @@ public:
virtual void get_method_list(List<MethodInfo> *p_list) const;
virtual bool has_method(const StringName &p_method) const;
virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount);
virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount);
Variant debug_get_member_by_index(int p_idx) const { return members[p_idx]; }

View file

@ -897,7 +897,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// Call OnBeforeSerialize
if (csi->script->script_class->implements_interface(CACHED_CLASS(ISerializationListener))) {
obj->get_script_instance()->call_multilevel(string_names.on_before_serialize);
obj->get_script_instance()->call(string_names.on_before_serialize);
}
// Save instance info
@ -1133,7 +1133,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// Call OnAfterDeserialization
if (csi->script->script_class->implements_interface(CACHED_CLASS(ISerializationListener))) {
obj->get_script_instance()->call_multilevel(string_names.on_after_deserialize);
obj->get_script_instance()->call(string_names.on_after_deserialize);
}
}
}
@ -1866,41 +1866,6 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args,
return Variant();
}
void CSharpInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
GD_MONO_SCOPE_THREAD_ATTACH;
if (script.is_valid()) {
MonoObject *mono_object = get_mono_object();
ERR_FAIL_NULL(mono_object);
_call_multilevel(mono_object, p_method, p_args, p_argcount);
}
}
void CSharpInstance::_call_multilevel(MonoObject *p_mono_object, const StringName &p_method, const Variant **p_args, int p_argcount) {
GD_MONO_ASSERT_THREAD_ATTACHED;
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
GDMonoMethod *method = top->get_method(p_method, p_argcount);
if (method) {
method->invoke(p_mono_object, p_args);
return;
}
top = top->get_parent_class();
}
}
void CSharpInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) {
// Sorry, the method is the one that controls the call order
call_multilevel(p_method, p_args, p_argcount);
}
bool CSharpInstance::_reference_owner_unsafe() {
#ifdef DEBUG_ENABLED
CRASH_COND(!base_ref);

View file

@ -265,8 +265,6 @@ class CSharpInstance : public ScriptInstance {
friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *);
static CSharpInstance *create_for_managed_type(Object *p_owner, CSharpScript *p_script, const MonoGCHandleData &p_gchandle);
void _call_multilevel(MonoObject *p_mono_object, const StringName &p_method, const Variant **p_args, int p_argcount);
void get_properties_state_for_reloading(List<Pair<StringName, Variant>> &r_state);
void get_event_signals_state_for_reloading(List<Pair<StringName, Array>> &r_state);
@ -285,8 +283,6 @@ public:
/* TODO */ void get_method_list(List<MethodInfo> *p_list) const override {}
bool has_method(const StringName &p_method) const override;
Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) override;
void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) override;
void mono_object_disposed(MonoObject *p_obj);

View file

@ -174,7 +174,7 @@ void Node3D::_notification(int p_what) {
ERR_FAIL_COND(!data.viewport);
if (get_script_instance()) {
get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_enter_world, nullptr, 0);
get_script_instance()->call(SceneStringNames::get_singleton()->_enter_world);
}
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) {
@ -202,7 +202,7 @@ void Node3D::_notification(int p_what) {
#endif
if (get_script_instance()) {
get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_exit_world, nullptr, 0);
get_script_instance()->call(SceneStringNames::get_singleton()->_exit_world);
}
data.viewport = nullptr;

View file

@ -434,7 +434,7 @@ void CanvasItem::_update_callback() {
notification(NOTIFICATION_DRAW);
emit_signal(SceneStringNames::get_singleton()->draw);
if (get_script_instance()) {
get_script_instance()->call_multilevel_reversed(SceneStringNames::get_singleton()->_draw, nullptr, 0);
get_script_instance()->call(SceneStringNames::get_singleton()->_draw);
}
current_item_drawn = nullptr;
drawing = false;

View file

@ -55,15 +55,13 @@ void Node::_notification(int p_notification) {
case NOTIFICATION_PROCESS: {
if (get_script_instance()) {
Variant time = get_process_delta_time();
const Variant *ptr[1] = { &time };
get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_process, ptr, 1);
get_script_instance()->call(SceneStringNames::get_singleton()->_process, time);
}
} break;
case NOTIFICATION_PHYSICS_PROCESS: {
if (get_script_instance()) {
Variant time = get_physics_process_delta_time();
const Variant *ptr[1] = { &time };
get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_physics_process, ptr, 1);
get_script_instance()->call(SceneStringNames::get_singleton()->_physics_process, time);
}
} break;
@ -146,7 +144,7 @@ void Node::_notification(int p_notification) {
set_physics_process(true);
}
get_script_instance()->call_multilevel_reversed(SceneStringNames::get_singleton()->_ready, nullptr, 0);
get_script_instance()->call(SceneStringNames::get_singleton()->_ready);
}
} break;
@ -216,7 +214,7 @@ void Node::_propagate_enter_tree() {
notification(NOTIFICATION_ENTER_TREE);
if (get_script_instance()) {
get_script_instance()->call_multilevel_reversed(SceneStringNames::get_singleton()->_enter_tree, nullptr, 0);
get_script_instance()->call(SceneStringNames::get_singleton()->_enter_tree);
}
emit_signal(SceneStringNames::get_singleton()->tree_entered);
@ -264,7 +262,7 @@ void Node::_propagate_exit_tree() {
data.blocked--;
if (get_script_instance()) {
get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_exit_tree, nullptr, 0);
get_script_instance()->call(SceneStringNames::get_singleton()->_exit_tree);
}
emit_signal(SceneStringNames::get_singleton()->tree_exiting);

View file

@ -250,11 +250,7 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou
}
if (p_call_flags & GROUP_CALL_REALTIME) {
if (p_call_flags & GROUP_CALL_MULTILEVEL) {
nodes[i]->call_multilevel(p_function, VARIANT_ARG_PASS);
} else {
nodes[i]->call(p_function, VARIANT_ARG_PASS);
}
nodes[i]->call(p_function, VARIANT_ARG_PASS);
} else {
MessageQueue::get_singleton()->push_call(nodes[i], p_function, VARIANT_ARG_PASS);
}
@ -267,11 +263,7 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou
}
if (p_call_flags & GROUP_CALL_REALTIME) {
if (p_call_flags & GROUP_CALL_MULTILEVEL) {
nodes[i]->call_multilevel(p_function, VARIANT_ARG_PASS);
} else {
nodes[i]->call(p_function, VARIANT_ARG_PASS);
}
nodes[i]->call(p_function, VARIANT_ARG_PASS);
} else {
MessageQueue::get_singleton()->push_call(nodes[i], p_function, VARIANT_ARG_PASS);
}
@ -883,7 +875,7 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p
continue;
}
n->call_multilevel(p_method, (const Variant **)v, 1);
n->call(p_method, (const Variant **)v, 1);
//ERR_FAIL_COND(node_count != g.nodes.size());
}

View file

@ -223,7 +223,6 @@ public:
GROUP_CALL_REVERSE = 1,
GROUP_CALL_REALTIME = 2,
GROUP_CALL_UNIQUE = 4,
GROUP_CALL_MULTILEVEL = 8,
};
_FORCE_INLINE_ Window *get_root() const { return root; }

View file

@ -1607,7 +1607,7 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
}
if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) {
control->call_multilevel(SceneStringNames::get_singleton()->_gui_input, ev);
control->call(SceneStringNames::get_singleton()->_gui_input, ev);
}
if (!control->is_inside_tree() || control->is_set_as_toplevel()) {
@ -2306,7 +2306,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.key_focus) {
gui.key_event_accepted = false;
if (gui.key_focus->can_process()) {
gui.key_focus->call_multilevel(SceneStringNames::get_singleton()->_gui_input, p_event);
gui.key_focus->call(SceneStringNames::get_singleton()->_gui_input, p_event);
if (gui.key_focus) { //maybe lost it
gui.key_focus->emit_signal(SceneStringNames::get_singleton()->gui_input, p_event);
}
@ -2516,7 +2516,7 @@ void Viewport::_drop_mouse_focus() {
mb->set_global_position(c->get_local_mouse_position());
mb->set_button_index(i + 1);
mb->set_pressed(false);
c->call_multilevel(SceneStringNames::get_singleton()->_gui_input, mb);
c->call(SceneStringNames::get_singleton()->_gui_input, mb);
}
}
}
@ -2581,7 +2581,7 @@ void Viewport::_post_gui_grab_click_focus() {
mb->set_position(click);
mb->set_button_index(i + 1);
mb->set_pressed(false);
gui.mouse_focus->call_multilevel(SceneStringNames::get_singleton()->_gui_input, mb);
gui.mouse_focus->call(SceneStringNames::get_singleton()->_gui_input, mb);
}
}