From 828e1c092fa706d4392363435950960261765ba4 Mon Sep 17 00:00:00 2001
From: Juan Linietsky <reduzio@gmail.com>
Date: Wed, 7 Sep 2016 19:39:02 -0300
Subject: [PATCH] Renamed the bind_native functions to bind_vararg, should make
 it show the documentation more clearly and also make it easier to bind to C#

---
 core/func_ref.cpp                             |  6 +----
 core/method_bind.h                            | 19 +++++++++------
 core/object.cpp                               | 24 ++++---------------
 core/object_type_db.h                         |  4 ++--
 core/undo_redo.cpp                            | 16 ++++---------
 modules/gdscript/gd_function.cpp              |  2 +-
 modules/gdscript/gd_script.cpp                |  2 +-
 modules/visual_script/visual_script.cpp       |  2 +-
 .../visual_script_func_nodes.cpp              |  8 +++++++
 scene/main/node.cpp                           | 10 ++++----
 scene/main/scene_main_loop.cpp                |  8 ++-----
 tools/doc/doc_data.cpp                        |  5 ++++
 tools/editor/editor_help.cpp                  |  9 +++++++
 13 files changed, 55 insertions(+), 60 deletions(-)

diff --git a/core/func_ref.cpp b/core/func_ref.cpp
index 644d8b5b63c..ca890111be9 100644
--- a/core/func_ref.cpp
+++ b/core/func_ref.cpp
@@ -61,11 +61,7 @@ void FuncRef::_bind_methods() {
 		MethodInfo mi;
 		mi.name="call_func";
 		Vector<Variant> defargs;
-		for(int i=0;i<10;i++) {
-			mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
-			defargs.push_back(Variant());
-		}
-		ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_func:Variant",&FuncRef::call_func,mi,defargs);
+		ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_func:Variant",&FuncRef::call_func,mi,defargs);
 
 	}
 
diff --git a/core/method_bind.h b/core/method_bind.h
index 072953743cb..04ff5c22c6a 100644
--- a/core/method_bind.h
+++ b/core/method_bind.h
@@ -52,6 +52,7 @@ enum MethodFlags {
 	METHOD_FLAG_REVERSE=16, // used for events
 	METHOD_FLAG_VIRTUAL=32,
 	METHOD_FLAG_FROM_SCRIPT=64,
+	METHOD_FLAG_VARARG=128,
 	METHOD_FLAGS_DEFAULT=METHOD_FLAG_NORMAL,
 };
 
@@ -229,7 +230,7 @@ public:
 	Vector<StringName> get_argument_names() const;
 #endif
 	void set_hint_flags(uint32_t p_hint) { hint_flags=p_hint; }
-	uint32_t get_hint_flags() const { return hint_flags|(is_const()?METHOD_FLAG_CONST:0); }
+	uint32_t get_hint_flags() const { return hint_flags|(is_const()?METHOD_FLAG_CONST:0)|(is_vararg()?METHOD_FLAG_VARARG:0); }
 	virtual String get_instance_type() const=0;
 
 	_FORCE_INLINE_ int get_argument_count() const { return argument_count; };
@@ -267,7 +268,7 @@ public:
 	_FORCE_INLINE_ int get_method_id() const { return method_id; }
 	_FORCE_INLINE_ bool is_const() const { return _const; }
 	_FORCE_INLINE_ bool has_return() const { return _returns; }
-
+	virtual bool is_vararg() const { return false; }
 
 	void set_default_arguments(const Vector<Variant>& p_defargs);
 
@@ -277,7 +278,7 @@ public:
 
 
 template<class T>
-class MethodBindNative : public MethodBind {
+class MethodBindVarArg : public MethodBind {
 public:
 	typedef Variant (T::*NativeCall)(const Variant**,int ,Variant::CallError &);
 protected:
@@ -319,7 +320,9 @@ public:
 	}
 
 #ifdef PTRCALL_ENABLED
-	virtual void ptrcall(Object* p_object,const void** p_args,void* r_ret) {} //todo
+	virtual void ptrcall(Object* p_object,const void** p_args,void* r_ret) {
+		ERR_FAIL(); //can't call
+	} //todo
 #endif
 
 
@@ -327,14 +330,16 @@ public:
 	virtual bool is_const() const { return false; }
 	virtual String get_instance_type() const { return T::get_type_static(); }
 
-	MethodBindNative() { call_method=NULL; _set_returns(true);}
+	virtual bool is_vararg() const { return true; }
+
+	MethodBindVarArg() { call_method=NULL; _set_returns(true);}
 };
 
 
 template<class T   >
-MethodBind* create_native_method_bind( Variant (T::*p_method)(const Variant**,int ,Variant::CallError &), const MethodInfo& p_info ) {
+MethodBind* create_vararg_method_bind( Variant (T::*p_method)(const Variant**,int ,Variant::CallError &), const MethodInfo& p_info ) {
 
-	MethodBindNative<T   > * a = memnew( (MethodBindNative<T   >) );
+	MethodBindVarArg<T   > * a = memnew( (MethodBindVarArg<T   >) );
 	a->set_method(p_method);
 	a->set_method_info(p_info);
 	return a;
diff --git a/core/object.cpp b/core/object.cpp
index b036efa501f..81fdc2a90ca 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1693,42 +1693,26 @@ void Object::_bind_methods() {
 		MethodInfo mi;
 		mi.name="emit_signal";
 		mi.arguments.push_back( PropertyInfo( Variant::STRING, "signal"));
-		Vector<Variant> defargs;
-		for(int i=0;i<VARIANT_ARG_MAX;i++) {
-			mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
-			defargs.push_back(Variant());
-		}
 
-
-		ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"emit_signal",&Object::_emit_signal,mi,defargs);
+		ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"emit_signal",&Object::_emit_signal,mi);
 	}
 
 	{
 		MethodInfo mi;
 		mi.name="call";
 		mi.arguments.push_back( PropertyInfo( Variant::STRING, "method"));
-		Vector<Variant> defargs;
-		for(int i=0;i<10;i++) {
-			mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
-			defargs.push_back(Variant());
-		}
 
 
-		ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call:Variant",&Object::_call_bind,mi,defargs);
+
+		ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call:Variant",&Object::_call_bind,mi);
 	}
 
 	{
 		MethodInfo mi;
 		mi.name="call_deferred";
 		mi.arguments.push_back( PropertyInfo( Variant::STRING, "method"));
-		Vector<Variant> defargs;
-		for(int i=0;i<VARIANT_ARG_MAX;i++) {
-			mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
-			defargs.push_back(Variant());
-		}
 
-
-		ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_deferred",&Object::_call_deferred_bind,mi,defargs);
+		ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_deferred",&Object::_call_deferred_bind,mi);
 	}
 
 	ObjectTypeDB::bind_method(_MD("callv:Variant","method","arg_array"),&Object::callv);
diff --git a/core/object_type_db.h b/core/object_type_db.h
index 3fcd38aa314..725b424c9a1 100644
--- a/core/object_type_db.h
+++ b/core/object_type_db.h
@@ -415,13 +415,13 @@ public:
 
 #endif
 	template<class M>
-	static MethodBind* bind_native_method(uint32_t p_flags, StringName p_name, M p_method,const MethodInfo& p_info=MethodInfo(),const Vector<Variant>& p_default_args=Vector<Variant>()) {
+	static MethodBind* bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method,const MethodInfo& p_info=MethodInfo(),const Vector<Variant>& p_default_args=Vector<Variant>()) {
 
 		GLOBAL_LOCK_FUNCTION;
 
 
 
-		MethodBind *bind = create_native_method_bind(p_method,p_info);
+		MethodBind *bind = create_vararg_method_bind(p_method,p_info);
 		ERR_FAIL_COND_V(!bind,NULL);
 
 		String rettype;
diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp
index 99740b365c5..e8a71d49916 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -490,13 +490,9 @@ void UndoRedo::_bind_methods() {
 		mi.name="add_do_method";
 		mi.arguments.push_back( PropertyInfo( Variant::OBJECT, "object"));
 		mi.arguments.push_back( PropertyInfo( Variant::STRING, "method"));
-		Vector<Variant> defargs;
-		for(int i=0;i<VARIANT_ARG_MAX;++i) {
-			mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
-			defargs.push_back(Variant());
-		}
 
-		ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"add_do_method",&UndoRedo::_add_do_method,mi,defargs);
+
+		ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"add_do_method",&UndoRedo::_add_do_method,mi);
 	}
 
 	{
@@ -504,13 +500,9 @@ void UndoRedo::_bind_methods() {
 		mi.name="add_undo_method";
 		mi.arguments.push_back( PropertyInfo( Variant::OBJECT, "object"));
 		mi.arguments.push_back( PropertyInfo( Variant::STRING, "method"));
-		Vector<Variant> defargs;
-		for(int i=0;i<VARIANT_ARG_MAX;++i) {
-			mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
-			defargs.push_back(Variant());
-		}
 
-		ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"add_undo_method",&UndoRedo::_add_undo_method,mi,defargs);
+
+		ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"add_undo_method",&UndoRedo::_add_undo_method,mi);
 	}
 
 	ObjectTypeDB::bind_method(_MD("add_do_property","object", "property", "value:Variant"),&UndoRedo::add_do_property);
diff --git a/modules/gdscript/gd_function.cpp b/modules/gdscript/gd_function.cpp
index b2cc6341c14..094e21bb4fe 100644
--- a/modules/gdscript/gd_function.cpp
+++ b/modules/gdscript/gd_function.cpp
@@ -1437,7 +1437,7 @@ void GDFunctionState::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("resume:Variant","arg"),&GDFunctionState::resume,DEFVAL(Variant()));
 	ObjectTypeDB::bind_method(_MD("is_valid"),&GDFunctionState::is_valid);
-	ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&GDFunctionState::_signal_callback,MethodInfo("_signal_callback"));
+	ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&GDFunctionState::_signal_callback,MethodInfo("_signal_callback"));
 
 }
 
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index b97a0fcbb67..0ea10950dfd 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -751,7 +751,7 @@ void GDScript::_get_property_list(List<PropertyInfo> *p_properties) const {
 
 void GDScript::_bind_methods() {
 
-	ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"new",&GDScript::_new,MethodInfo(Variant::OBJECT,"new"));
+	ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"new",&GDScript::_new,MethodInfo(Variant::OBJECT,"new"));
 
 	ObjectTypeDB::bind_method(_MD("get_as_byte_code"),&GDScript::get_as_byte_code);
 
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index 94f9a6a6b50..bd042c8989e 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -2439,7 +2439,7 @@ void VisualScriptFunctionState::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("connect_to_signal","obj","signals","args"),&VisualScriptFunctionState::connect_to_signal);
 	ObjectTypeDB::bind_method(_MD("resume:Array","args"),&VisualScriptFunctionState::resume,DEFVAL(Variant()));
 	ObjectTypeDB::bind_method(_MD("is_valid"),&VisualScriptFunctionState::is_valid);
-	ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&VisualScriptFunctionState::_signal_callback,MethodInfo("_signal_callback"));
+	ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&VisualScriptFunctionState::_signal_callback,MethodInfo("_signal_callback"));
 }
 
 VisualScriptFunctionState::VisualScriptFunctionState() {
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index de99beacafc..5a21cb40e92 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -417,6 +417,14 @@ void VisualScriptFunctionCall::_update_method_cache() {
 
 		method_cache.return_val = mb->get_argument_info(-1);
 #endif
+
+		if (mb->is_vararg()) {
+			//for vararg just give it 10 arguments (should be enough for most use cases)
+			for(int i=0;i<10;i++) {
+				method_cache.arguments.push_back(PropertyInfo(Variant::NIL,"arg"+itos(i)));
+				use_default_args++;
+			}
+		}
 	} else if (script.is_valid() && script->has_method(function)) {
 
 		method_cache = script->get_method_info(function);
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 086b69c1c55..18922404269 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2903,16 +2903,16 @@ void Node::_bind_methods() {
 
 
 		mi.name="rpc";
-		ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"rpc",&Node::_rpc_bind,mi);
+		ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"rpc",&Node::_rpc_bind,mi);
 		mi.name="rpc_unreliable";
-		ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"rpc_unreliable",&Node::_rpc_unreliable_bind,mi);
+		ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"rpc_unreliable",&Node::_rpc_unreliable_bind,mi);
 
-		mi.arguments.push_front( PropertyInfo( Variant::INT, "peer_") );
+		mi.arguments.push_front( PropertyInfo( Variant::INT, "peer_id") );
 
 		mi.name="rpc_id";
-		ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"rpc_id",&Node::_rpc_id_bind,mi);
+		ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"rpc_id",&Node::_rpc_id_bind,mi);
 		mi.name="rpc_unreliable_id";
-		ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"rpc_unreliable_id",&Node::_rpc_unreliable_id_bind,mi);
+		ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"rpc_unreliable_id",&Node::_rpc_unreliable_id_bind,mi);
 
 
 	}
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index 4c7b7c13992..e3472c074a8 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -2200,13 +2200,9 @@ void SceneTree::_bind_methods() {
 	mi.arguments.push_back( PropertyInfo( Variant::INT, "flags"));
 	mi.arguments.push_back( PropertyInfo( Variant::STRING, "group"));
 	mi.arguments.push_back( PropertyInfo( Variant::STRING, "method"));
-	Vector<Variant> defargs;
-	for(int i=0;i<VARIANT_ARG_MAX;i++) {
-		mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
-		defargs.push_back(Variant());
-	}
 
-	ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_group",&SceneTree::_call_group,mi,defargs);
+
+	ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_group",&SceneTree::_call_group,mi);
 
 	ObjectTypeDB::bind_method(_MD("set_current_scene","child_node:Node"),&SceneTree::set_current_scene);
 	ObjectTypeDB::bind_method(_MD("get_current_scene:Node"),&SceneTree::get_current_scene);
diff --git a/tools/doc/doc_data.cpp b/tools/doc/doc_data.cpp
index 479b99a03dc..4a8fdfb215f 100644
--- a/tools/doc/doc_data.cpp
+++ b/tools/doc/doc_data.cpp
@@ -198,6 +198,11 @@ void DocData::generate(bool p_basic_types) {
 				if (method.qualifiers!="")
 					method.qualifiers+=" ";
 				method.qualifiers+="const";
+
+			} else if (E->get().flags&METHOD_FLAG_VARARG) {
+				if (method.qualifiers!="")
+					method.qualifiers+=" ";
+				method.qualifiers+="vararg";
 			}
 
 			for(int i=-1;i<E->get().arguments.size();i++) {
diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp
index 8f486ba0c24..4f83dc2f662 100644
--- a/tools/editor/editor_help.cpp
+++ b/tools/editor/editor_help.cpp
@@ -882,6 +882,15 @@ Error EditorHelp::_goto_desc(const String& p_class,int p_vscr) {
 				class_desc->pop();
 			}
 
+			if (cd.methods[i].qualifiers.find("vararg")!=-1) {
+				class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
+				class_desc->add_text(",");
+				class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color"));
+				class_desc->add_text(" ... ");
+				class_desc->pop();
+				class_desc->pop();
+			}
+
 			class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color"));
 			class_desc->add_text(cd.methods[i].arguments.size()?" )":")");
 			class_desc->pop();