Browse Source

-Added yield nodes to visual script
-Added input selection nodes to visual script
-Added script create icon for those who miss it, will only appear when it can be used.

Juan Linietsky 9 years ago
parent
commit
b77200728e

+ 15 - 9
core/io/resource_format_binary.cpp

@@ -447,13 +447,17 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v)  {
 		} break;
 		} break;
 		case VARIANT_INPUT_EVENT: {
 		case VARIANT_INPUT_EVENT: {
 
 
+			InputEvent ev;
+			ev.type=f->get_32(); //will only work for null though.
+			r_v=ev;
+
 		} break;
 		} break;
 		case VARIANT_DICTIONARY: {
 		case VARIANT_DICTIONARY: {
 
 
-            uint32_t len=f->get_32();
-            Dictionary d(len&0x80000000); //last bit means shared
-            len&=0x7FFFFFFF;
-            for(uint32_t i=0;i<len;i++) {
+			uint32_t len=f->get_32();
+			Dictionary d(len&0x80000000); //last bit means shared
+			len&=0x7FFFFFFF;
+			for(uint32_t i=0;i<len;i++) {
 				Variant key;
 				Variant key;
 				Error err = parse_variant(key);
 				Error err = parse_variant(key);
 				ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT);
 				ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT);
@@ -466,11 +470,11 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v)  {
 		} break;
 		} break;
 		case VARIANT_ARRAY: {
 		case VARIANT_ARRAY: {
 
 
-            uint32_t len=f->get_32();
-            Array a(len&0x80000000); //last bit means shared
-            len&=0x7FFFFFFF;
+			uint32_t len=f->get_32();
+			Array a(len&0x80000000); //last bit means shared
+			len&=0x7FFFFFFF;
 			a.resize(len);
 			a.resize(len);
-            for(uint32_t i=0;i<len;i++) {
+			for(uint32_t i=0;i<len;i++) {
 				Variant val;
 				Variant val;
 				Error err = parse_variant(val);
 				Error err = parse_variant(val);
 				ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT);
 				ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT);
@@ -1725,7 +1729,9 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant& p_property,
 		case Variant::INPUT_EVENT: {
 		case Variant::INPUT_EVENT: {
 
 
 			f->store_32(VARIANT_INPUT_EVENT);
 			f->store_32(VARIANT_INPUT_EVENT);
-			WARN_PRINT("Can't save InputEvent (maybe it could..)");
+			InputEvent event=p_property;
+			f->store_32(0); //event type none, nothing else suported for now.
+
 		} break;
 		} break;
 		case Variant::DICTIONARY: {
 		case Variant::DICTIONARY: {
 
 

+ 1 - 0
core/method_bind.h

@@ -156,6 +156,7 @@ VARIANT_ENUM_CAST( Orientation );
 VARIANT_ENUM_CAST( HAlign );
 VARIANT_ENUM_CAST( HAlign );
 VARIANT_ENUM_CAST( Variant::Type );
 VARIANT_ENUM_CAST( Variant::Type );
 VARIANT_ENUM_CAST( Variant::Operator );
 VARIANT_ENUM_CAST( Variant::Operator );
+VARIANT_ENUM_CAST( InputEvent::Type );
 
 
 class MethodBind {
 class MethodBind {
 
 

+ 17 - 0
core/object_type_db.cpp

@@ -549,6 +549,23 @@ bool ObjectTypeDB::has_signal(StringName p_type,StringName p_signal) {
 	return false;
 	return false;
 }
 }
 
 
+bool ObjectTypeDB::get_signal(StringName p_type,StringName p_signal,MethodInfo *r_signal) {
+
+	TypeInfo *type=types.getptr(p_type);
+	TypeInfo *check=type;
+	while(check) {
+		if (check->signal_map.has(p_signal)) {
+			if (r_signal) {
+				*r_signal=check->signal_map[p_signal];
+			}
+			return true;
+		}
+		check=check->inherits_ptr;
+	}
+
+	return false;
+}
+
 void ObjectTypeDB::add_property(StringName p_type,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index) {
 void ObjectTypeDB::add_property(StringName p_type,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index) {
 
 
 
 

+ 1 - 0
core/object_type_db.h

@@ -453,6 +453,7 @@ public:
 
 
 	static void add_signal(StringName p_type,const MethodInfo& p_signal);
 	static void add_signal(StringName p_type,const MethodInfo& p_signal);
 	static bool has_signal(StringName p_type,StringName p_signal);
 	static bool has_signal(StringName p_type,StringName p_signal);
+	static bool get_signal(StringName p_type,StringName p_signal,MethodInfo *r_signal);
 	static void get_signal_list(StringName p_type,List<MethodInfo> *p_signals,bool p_no_inheritance=false);
 	static void get_signal_list(StringName p_type,List<MethodInfo> *p_signals,bool p_no_inheritance=false);
 
 
 	static void add_property(StringName p_type,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index=-1);
 	static void add_property(StringName p_type,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index=-1);

+ 21 - 0
core/os/keyboard.cpp

@@ -429,6 +429,27 @@ static const _KeyCodeReplace _keycode_replace_neo[]={
 {0,0}
 {0,0}
 };
 };
 
 
+int keycode_get_count() {
+
+	const _KeyCodeText *kct =&_keycodes[0];
+
+	int count=0;
+	while(kct->text) {
+
+		count++;
+		kct++;
+	}
+	return count;
+}
+
+int keycode_get_value_by_index(int p_index) {
+	_keycodes[p_index].code;
+}
+
+const char* keycode_get_name_by_index(int p_index) {
+	return _keycodes[p_index].text;
+}
+
 
 
 int latin_keyboard_keycode_convert(int p_keycode) {
 int latin_keyboard_keycode_convert(int p_keycode) {
 
 

+ 3 - 0
core/os/keyboard.h

@@ -328,6 +328,9 @@ enum KeyModifierMask {
 String keycode_get_string(uint32_t p_code);
 String keycode_get_string(uint32_t p_code);
 bool keycode_has_unicode(uint32_t p_unicode);
 bool keycode_has_unicode(uint32_t p_unicode);
 int find_keycode(const String& p_code);
 int find_keycode(const String& p_code);
+int keycode_get_count();
+int keycode_get_value_by_index(int p_index);
+const char* keycode_get_name_by_index(int p_index);
 int latin_keyboard_keycode_convert(int p_keycode);
 int latin_keyboard_keycode_convert(int p_keycode);
 
 
 #endif
 #endif

+ 8 - 0
modules/visual_script/register_types.cpp

@@ -35,6 +35,7 @@
 #include "visual_script_func_nodes.h"
 #include "visual_script_func_nodes.h"
 #include "visual_script_builtin_funcs.h"
 #include "visual_script_builtin_funcs.h"
 #include "visual_script_flow_control.h"
 #include "visual_script_flow_control.h"
+#include "visual_script_yield_nodes.h"
 
 
 
 
 VisualScriptLanguage *visual_script_language=NULL;
 VisualScriptLanguage *visual_script_language=NULL;
@@ -44,6 +45,7 @@ void register_visual_script_types() {
 
 
 	ObjectTypeDB::register_type<VisualScript>();
 	ObjectTypeDB::register_type<VisualScript>();
 	ObjectTypeDB::register_virtual_type<VisualScriptNode>();
 	ObjectTypeDB::register_virtual_type<VisualScriptNode>();
+	ObjectTypeDB::register_virtual_type<VisualScriptFunctionState>();
 	ObjectTypeDB::register_type<VisualScriptFunction>();
 	ObjectTypeDB::register_type<VisualScriptFunction>();
 	ObjectTypeDB::register_type<VisualScriptOperator>();
 	ObjectTypeDB::register_type<VisualScriptOperator>();
 	ObjectTypeDB::register_type<VisualScriptVariableSet>();
 	ObjectTypeDB::register_type<VisualScriptVariableSet>();
@@ -70,6 +72,11 @@ void register_visual_script_types() {
 	ObjectTypeDB::register_type<VisualScriptWhile>();
 	ObjectTypeDB::register_type<VisualScriptWhile>();
 	ObjectTypeDB::register_type<VisualScriptIterator>();
 	ObjectTypeDB::register_type<VisualScriptIterator>();
 	ObjectTypeDB::register_type<VisualScriptSequence>();
 	ObjectTypeDB::register_type<VisualScriptSequence>();
+	ObjectTypeDB::register_type<VisualScriptInputFilter>();
+	ObjectTypeDB::register_type<VisualScriptInputSelector>();
+
+	ObjectTypeDB::register_type<VisualScriptYield>();
+	ObjectTypeDB::register_type<VisualScriptYieldSignal>();
 
 
 	ObjectTypeDB::register_type<VisualScriptBuiltinFunc>();
 	ObjectTypeDB::register_type<VisualScriptBuiltinFunc>();
 
 
@@ -81,6 +88,7 @@ void register_visual_script_types() {
 	register_visual_script_func_nodes();
 	register_visual_script_func_nodes();
 	register_visual_script_builtin_func_node();
 	register_visual_script_builtin_func_node();
 	register_visual_script_flow_control_nodes();
 	register_visual_script_flow_control_nodes();
+	register_visual_script_yield_nodes();
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	VisualScriptEditor::register_editor();
 	VisualScriptEditor::register_editor();

+ 280 - 78
modules/visual_script/visual_script.cpp

@@ -279,7 +279,9 @@ void VisualScript::_node_ports_changed(int p_id) {
 		}
 		}
 	}
 	}
 
 
+	set_edited(true); //something changed, let's set as edited
 	emit_signal("node_ports_changed",function,p_id);
 	emit_signal("node_ports_changed",function,p_id);
+
 }
 }
 
 
 void VisualScript::add_node(const StringName& p_func,int p_id, const Ref<VisualScriptNode>& p_node, const Point2 &p_pos) {
 void VisualScript::add_node(const StringName& p_func,int p_id, const Ref<VisualScriptNode>& p_node, const Point2 &p_pos) {
@@ -1354,95 +1356,30 @@ bool VisualScriptInstance::has_method(const StringName& p_method) const{
 //#define VSDEBUG(m_text) print_line(m_text)
 //#define VSDEBUG(m_text) print_line(m_text)
 #define VSDEBUG(m_text)
 #define VSDEBUG(m_text)
 
 
-Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error){
-
-	r_error.error=Variant::CallError::CALL_OK; //ok by default
+Variant VisualScriptInstance::_call_internal(const StringName& p_method, void* p_stack, int p_stack_size, VisualScriptNodeInstance* p_node, int p_flow_stack_pos, bool p_resuming_yield, Variant::CallError &r_error) {
 
 
 	Map<StringName,Function>::Element *F = functions.find(p_method);
 	Map<StringName,Function>::Element *F = functions.find(p_method);
-	if (!F) {
-		r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
-		return Variant();
-	}
-
-	VSDEBUG("CALLING: "+String(p_method));
-
+	ERR_FAIL_COND_V(!F,Variant());
 	Function *f=&F->get();
 	Function *f=&F->get();
 
 
-	int total_stack_size=0;
-
-	total_stack_size+=f->max_stack*sizeof(Variant); //variants
-	total_stack_size+=f->node_count*sizeof(bool);
-	total_stack_size+=(max_input_args+max_output_args)*sizeof(Variant*); //arguments
-	total_stack_size+=f->flow_stack_size*sizeof(int); //flow
-
-	VSDEBUG("STACK SIZE: "+itos(total_stack_size));
-	VSDEBUG("STACK VARIANTS: : "+itos(f->max_stack));
-	VSDEBUG("SEQBITS: : "+itos(f->node_count));
-	VSDEBUG("MAX INPUT: "+itos(max_input_args));
-	VSDEBUG("MAX OUTPUT: "+itos(max_output_args));
-	VSDEBUG("FLOW STACK SIZE: "+itos(f->flow_stack_size));
-
-	void *stack = alloca(total_stack_size);
-
-	Variant *variant_stack=(Variant*)stack;
+	//this call goes separate, so it can e yielded and suspended
+	Variant *variant_stack=(Variant*)p_stack;
 	bool *sequence_bits = (bool*)(variant_stack + f->max_stack);
 	bool *sequence_bits = (bool*)(variant_stack + f->max_stack);
 	const Variant **input_args=(const Variant**)(sequence_bits+f->node_count);
 	const Variant **input_args=(const Variant**)(sequence_bits+f->node_count);
 	Variant **output_args=(Variant**)(input_args + max_input_args);
 	Variant **output_args=(Variant**)(input_args + max_input_args);
 	int flow_max = f->flow_stack_size;
 	int flow_max = f->flow_stack_size;
 	int* flow_stack = flow_max? (int*)(output_args + max_output_args) : (int*)NULL;
 	int* flow_stack = flow_max? (int*)(output_args + max_output_args) : (int*)NULL;
 
 
-	for(int i=0;i<f->node_count;i++) {
-		sequence_bits[i]=false; //all starts as false
-	}
-
-
-	Map<int,VisualScriptNodeInstance*>::Element *E = instances.find(f->node);
-	if (!E) {
-		r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
-
-		ERR_EXPLAIN("No VisualScriptFunction node in function!");
-		ERR_FAIL_V(Variant());
-	}
-
-	VisualScriptNodeInstance *node = E->get();
-
-	int flow_stack_pos=0;
-	if (flow_stack)	{
-		flow_stack[0]=node->get_id();
-	}
-
-	VSDEBUG("ARGUMENTS: "+itos(f->argument_count)=" RECEIVED: "+itos(p_argcount));
-
-	if (p_argcount<f->argument_count) {
-		r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
-		r_error.argument=node->get_input_port_count();
-
-		return Variant();
-	}
-
-	if (p_argcount>f->argument_count) {
-		r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
-		r_error.argument=node->get_input_port_count();
-
-		return Variant();
-	}
-
-	//allocate variant stack
-	for(int i=0;i<f->max_stack;i++) {
-		memnew_placement(&variant_stack[i],Variant);
-	}
-
-	//allocate function arguments (must be copied for yield to work properly)
-	for(int i=0;i<p_argcount;i++) {
-		variant_stack[i]=*p_args[i];
-	}
-
 	String error_str;
 	String error_str;
 
 
+	VisualScriptNodeInstance* node=p_node;
 	bool error=false;
 	bool error=false;
 	int current_node_id=f->node;
 	int current_node_id=f->node;
 	Variant return_value;
 	Variant return_value;
 	Variant *working_mem=NULL;
 	Variant *working_mem=NULL;
+
+	int flow_stack_pos=p_flow_stack_pos;
+
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	if (ScriptDebugger::get_singleton()) {
 	if (ScriptDebugger::get_singleton()) {
 		VisualScriptLanguage::singleton->enter_function(this,&p_method,variant_stack,&working_mem,&current_node_id);
 		VisualScriptLanguage::singleton->enter_function(this,&p_method,variant_stack,&working_mem,&current_node_id);
@@ -1518,12 +1455,19 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_
 
 
 		//do step
 		//do step
 
 
-		bool start_sequence = flow_stack && !(flow_stack[flow_stack_pos] & VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT); //if there is a push bit, it means we are continuing a sequence
-
+		VisualScriptNodeInstance::StartMode start_mode;
+		{
+			if (p_resuming_yield)
+				start_mode=VisualScriptNodeInstance::START_MODE_RESUME_YIELD;
+			else if (flow_stack && !(flow_stack[flow_stack_pos] & VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT)) //if there is a push bit, it means we are continuing a sequence
+				start_mode=VisualScriptNodeInstance::START_MODE_BEGIN_SEQUENCE;
+			else
+				start_mode=VisualScriptNodeInstance::START_MODE_CONTINUE_SEQUENCE;
+		}
 
 
 		VSDEBUG("STEP - STARTSEQ: "+itos(start_sequence));
 		VSDEBUG("STEP - STARTSEQ: "+itos(start_sequence));
 
 
-		int ret = node->step(input_args,output_args,start_sequence,working_mem,r_error,error_str);
+		int ret = node->step(input_args,output_args,start_mode,working_mem,r_error,error_str);
 
 
 		if (r_error.error!=Variant::CallError::CALL_OK) {
 		if (r_error.error!=Variant::CallError::CALL_OK) {
 			//use error from step
 			//use error from step
@@ -1531,6 +1475,52 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_
 			break;
 			break;
 		}
 		}
 
 
+		if (ret&VisualScriptNodeInstance::STEP_YIELD_BIT) {
+			//yielded!
+			if (node->get_working_memory_size()==0) {
+				r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+				error_str=RTR("A node yielded without working memory, please read the docs on how to yield properly!");
+				error=true;
+				break;
+
+			} else {
+				Ref<VisualScriptFunctionState> state = *working_mem;
+				if (!state.is_valid()) {
+
+					r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+					error_str=RTR("Node yielded, but did not return a function state in the first working memory.");
+					error=true;
+					break;
+
+				}
+
+				//step 1, capture all state
+				state->instance_id=get_owner_ptr()->get_instance_ID();
+				state->script_id=get_script()->get_instance_ID();
+				state->instance=this;
+				state->function=p_method;
+				state->working_mem_index=node->working_mem_idx;
+				state->variant_stack_size=f->max_stack;
+				state->node=node;
+				state->flow_stack_pos=flow_stack_pos;
+				state->stack.resize(p_stack_size);
+				copymem(state->stack.ptr(),p_stack,p_stack_size);
+				//step 2, run away, return directly
+				r_error.error=Variant::CallError::CALL_OK;
+
+
+#ifdef DEBUG_ENABLED
+				//will re-enter later, so exiting
+				if (ScriptDebugger::get_singleton()) {
+					VisualScriptLanguage::singleton->exit_function();
+				}
+#endif
+
+				return state;
+
+			}
+		}
+
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 		if (ScriptDebugger::get_singleton()) {
 		if (ScriptDebugger::get_singleton()) {
 			// line
 			// line
@@ -1586,10 +1576,11 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_
 			}
 			}
 
 
 			next = node->sequence_outputs[output];
 			next = node->sequence_outputs[output];
-			if (next)
+			if (next) {
 				VSDEBUG("GOT NEXT NODE - "+itos(next->get_id()));
 				VSDEBUG("GOT NEXT NODE - "+itos(next->get_id()));
-			else
+			} else {
 				VSDEBUG("GOT NEXT NODE - NULL");
 				VSDEBUG("GOT NEXT NODE - NULL");
+			}
 		}
 		}
 
 
 		if (flow_stack) {
 		if (flow_stack) {
@@ -1742,6 +1733,95 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_
 	return return_value;
 	return return_value;
 }
 }
 
 
+
+Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error){
+
+	r_error.error=Variant::CallError::CALL_OK; //ok by default
+
+	Map<StringName,Function>::Element *F = functions.find(p_method);
+	if (!F) {
+		r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+		return Variant();
+	}
+
+	VSDEBUG("CALLING: "+String(p_method));
+
+	Function *f=&F->get();
+
+	int total_stack_size=0;
+
+	total_stack_size+=f->max_stack*sizeof(Variant); //variants
+	total_stack_size+=f->node_count*sizeof(bool);
+	total_stack_size+=(max_input_args+max_output_args)*sizeof(Variant*); //arguments
+	total_stack_size+=f->flow_stack_size*sizeof(int); //flow
+
+	VSDEBUG("STACK SIZE: "+itos(total_stack_size));
+	VSDEBUG("STACK VARIANTS: : "+itos(f->max_stack));
+	VSDEBUG("SEQBITS: : "+itos(f->node_count));
+	VSDEBUG("MAX INPUT: "+itos(max_input_args));
+	VSDEBUG("MAX OUTPUT: "+itos(max_output_args));
+	VSDEBUG("FLOW STACK SIZE: "+itos(f->flow_stack_size));
+
+	void *stack = alloca(total_stack_size);
+
+	Variant *variant_stack=(Variant*)stack;
+	bool *sequence_bits = (bool*)(variant_stack + f->max_stack);
+	const Variant **input_args=(const Variant**)(sequence_bits+f->node_count);
+	Variant **output_args=(Variant**)(input_args + max_input_args);
+	int flow_max = f->flow_stack_size;
+	int* flow_stack = flow_max? (int*)(output_args + max_output_args) : (int*)NULL;
+
+	for(int i=0;i<f->node_count;i++) {
+		sequence_bits[i]=false; //all starts as false
+	}
+
+
+	Map<int,VisualScriptNodeInstance*>::Element *E = instances.find(f->node);
+	if (!E) {
+		r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+
+		ERR_EXPLAIN("No VisualScriptFunction node in function!");
+		ERR_FAIL_V(Variant());
+	}
+
+	VisualScriptNodeInstance *node = E->get();
+
+
+	if (flow_stack)	{
+		flow_stack[0]=node->get_id();
+	}
+
+	VSDEBUG("ARGUMENTS: "+itos(f->argument_count)=" RECEIVED: "+itos(p_argcount));
+
+	if (p_argcount<f->argument_count) {
+		r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+		r_error.argument=node->get_input_port_count();
+
+		return Variant();
+	}
+
+	if (p_argcount>f->argument_count) {
+		r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+		r_error.argument=node->get_input_port_count();
+
+		return Variant();
+	}
+
+	//allocate variant stack
+	for(int i=0;i<f->max_stack;i++) {
+		memnew_placement(&variant_stack[i],Variant);
+	}
+
+	//allocate function arguments (must be copied for yield to work properly)
+	for(int i=0;i<p_argcount;i++) {
+		variant_stack[i]=*p_args[i];
+	}
+
+	return _call_internal(p_method,stack,total_stack_size,node,0,false,r_error);
+
+
+}
+
 void VisualScriptInstance::notification(int p_notification){
 void VisualScriptInstance::notification(int p_notification){
 
 
 	//do nothing as this is called using virtual
 	//do nothing as this is called using virtual
@@ -1977,7 +2057,129 @@ VisualScriptInstance::~VisualScriptInstance() {
 
 
 
 
 
 
+/////////////////////////////////////////////
+
 
 
+/////////////////////
+
+
+Variant VisualScriptFunctionState::_signal_callback(const Variant** p_args, int p_argcount, Variant::CallError& r_error) {
+
+	ERR_FAIL_COND_V(function==StringName(),Variant());
+
+#ifdef DEBUG_ENABLED
+	if (instance_id && !ObjectDB::get_instance(instance_id)) {
+		ERR_EXPLAIN("Resumed after yield, but class instance is gone");
+		ERR_FAIL_V(Variant());
+	}
+
+	if (script_id && !ObjectDB::get_instance(script_id)) {
+		ERR_EXPLAIN("Resumed after yield, but script is gone");
+		ERR_FAIL_V(Variant());
+	}
+#endif
+
+	r_error.error=Variant::CallError::CALL_OK;
+
+	Array args;
+
+	if (p_argcount==0) {
+		r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+		r_error.argument=1;
+		return Variant();
+	} else if (p_argcount==1) {
+		//noooneee, reserved for me, me and only me.
+	} else {
+
+		for(int i=0;i<p_argcount-1;i++) {
+			args.push_back(*p_args[i]);
+		}
+	}
+
+	Ref<VisualScriptFunctionState> self = *p_args[p_argcount-1]; //hi, I'm myself, needed this to remain alive.
+
+	if (self.is_null()) {
+		r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+		r_error.argument=p_argcount-1;
+		r_error.expected=Variant::OBJECT;
+		return Variant();
+	}
+
+	r_error.error=Variant::CallError::CALL_OK;
+
+	Variant *working_mem = ((Variant*)stack.ptr()) + working_mem_index;
+
+	*working_mem=args; //arguments go to working mem.
+
+	Variant ret = instance->_call_internal(function,stack.ptr(),stack.size(),node,flow_stack_pos,true,r_error);
+	function=StringName(); //invalidate
+	return ret;
+}
+
+void VisualScriptFunctionState::connect_to_signal(Object* p_obj, const String& p_signal, Array p_binds) {
+
+	Vector<Variant> binds;
+	for(int i=0;i<p_binds.size();i++) {
+		binds.push_back(p_binds[i]);
+	}
+	binds.push_back(Ref<VisualScriptFunctionState>(this)); //add myself on the back to avoid dying from unreferencing
+	p_obj->connect(p_signal,this,"_signal_callback",binds);
+}
+
+bool VisualScriptFunctionState::is_valid() const {
+
+	return function!=StringName();
+}
+
+Variant VisualScriptFunctionState::resume(Array p_args) {
+
+	ERR_FAIL_COND_V(function==StringName(),Variant());
+#ifdef DEBUG_ENABLED
+	if (instance_id && !ObjectDB::get_instance(instance_id)) {
+		ERR_EXPLAIN("Resumed after yield, but class instance is gone");
+		ERR_FAIL_V(Variant());
+	}
+
+	if (script_id && !ObjectDB::get_instance(script_id)) {
+		ERR_EXPLAIN("Resumed after yield, but script is gone");
+		ERR_FAIL_V(Variant());
+	}
+#endif
+
+	Variant::CallError r_error;
+	r_error.error=Variant::CallError::CALL_OK;
+
+	Variant *working_mem = ((Variant*)stack.ptr()) + working_mem_index;
+
+	*working_mem=p_args; //arguments go to working mem.
+
+	Variant ret= instance->_call_internal(function,stack.ptr(),stack.size(),node,flow_stack_pos,true,r_error);
+	function=StringName(); //invalidate
+	return ret;
+}
+
+
+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"));
+}
+
+VisualScriptFunctionState::VisualScriptFunctionState() {
+
+}
+
+VisualScriptFunctionState::~VisualScriptFunctionState() {
+
+	if (function!=StringName()) {
+		Variant *s = ((Variant*)stack.ptr());
+		for(int i=0;i<variant_stack_size;i++) {
+			s[i].~Variant();
+		}
+	}
+}
 
 
 
 
 
 

+ 41 - 2
modules/visual_script/visual_script.h

@@ -85,12 +85,20 @@ friend class VisualScriptLanguage; //for debugger
 
 
 public:
 public:
 
 
+	enum StartMode {
+		START_MODE_BEGIN_SEQUENCE,
+		START_MODE_CONTINUE_SEQUENCE,
+		START_MODE_RESUME_YIELD
+	};
+
 	enum {
 	enum {
 		STEP_SHIFT=1<<24,
 		STEP_SHIFT=1<<24,
 		STEP_MASK=STEP_SHIFT-1,
 		STEP_MASK=STEP_SHIFT-1,
 		STEP_FLAG_PUSH_STACK_BIT=STEP_SHIFT, //push bit to stack
 		STEP_FLAG_PUSH_STACK_BIT=STEP_SHIFT, //push bit to stack
 		STEP_FLAG_GO_BACK_BIT=STEP_SHIFT<<1, //go back to previous node
 		STEP_FLAG_GO_BACK_BIT=STEP_SHIFT<<1, //go back to previous node
-		STEP_EXIT_FUNCTION_BIT=STEP_SHIFT<<2, //return from function
+		STEP_NO_ADVANCE_BIT=STEP_SHIFT<<2, //do not advance past this node
+		STEP_EXIT_FUNCTION_BIT=STEP_SHIFT<<3, //return from function
+		STEP_YIELD_BIT=STEP_SHIFT<<4, //yield (will find VisualScriptFunctionState state in first working memory)
 
 
 		FLOW_STACK_PUSHED_BIT=1<<30, //in flow stack, means bit was pushed (must go back here if end of sequence)
 		FLOW_STACK_PUSHED_BIT=1<<30, //in flow stack, means bit was pushed (must go back here if end of sequence)
 		FLOW_STACK_MASK=FLOW_STACK_PUSHED_BIT-1
 		FLOW_STACK_MASK=FLOW_STACK_PUSHED_BIT-1
@@ -109,7 +117,7 @@ public:
 	virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 	virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str)=0; //do a step, return which sequence port to go out
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str)=0; //do a step, return which sequence port to go out
 
 
 	Ref<VisualScriptNode> get_base_node() { return Ref<VisualScriptNode>( base ); }
 	Ref<VisualScriptNode> get_base_node() { return Ref<VisualScriptNode>( base ); }
 
 
@@ -352,7 +360,11 @@ class VisualScriptInstance : public ScriptInstance {
 
 
 	StringName source;
 	StringName source;
 
 
+	Variant _call_internal(const StringName& p_method, void* p_stack,int p_stack_size, VisualScriptNodeInstance* p_node, int p_flow_stack_pos, bool p_resuming_yield,Variant::CallError &r_error);
+
+
 	//Map<StringName,Function> functions;
 	//Map<StringName,Function> functions;
+friend class VisualScriptFunctionState; //for yield
 friend class VisualScriptLanguage; //for debugger
 friend class VisualScriptLanguage; //for debugger
 public:
 public:
 	virtual bool set(const StringName& p_name, const Variant& p_value);
 	virtual bool set(const StringName& p_name, const Variant& p_value);
@@ -400,6 +412,33 @@ public:
 };
 };
 
 
 
 
+class VisualScriptFunctionState : public Reference {
+
+	OBJ_TYPE(VisualScriptFunctionState,Reference);
+friend class VisualScriptInstance;
+
+	ObjectID instance_id;
+	ObjectID script_id;
+	VisualScriptInstance *instance;
+	StringName function;
+	Vector<uint8_t> stack;
+	int working_mem_index;
+	int variant_stack_size;
+	VisualScriptNodeInstance *node;
+	int flow_stack_pos;
+
+	Variant _signal_callback(const Variant** p_args, int p_argcount, Variant::CallError& r_error);
+protected:
+	static void _bind_methods();
+public:
+
+	void connect_to_signal(Object* p_obj,const String& p_signal,Array p_binds);
+	bool is_valid() const;
+	Variant resume(Array p_args);
+	VisualScriptFunctionState();
+	~VisualScriptFunctionState();
+};
+
 
 
 typedef Ref<VisualScriptNode> (*VisualScriptNodeRegisterFunc)(const String& p_type);
 typedef Ref<VisualScriptNode> (*VisualScriptNodeRegisterFunc)(const String& p_type);
 
 

+ 1 - 1
modules/visual_script/visual_script_builtin_funcs.cpp

@@ -565,7 +565,7 @@ public:
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 		switch(func) {
 		switch(func) {
 			case VisualScriptBuiltinFunc::MATH_SIN: {
 			case VisualScriptBuiltinFunc::MATH_SIN: {

File diff suppressed because it is too large
+ 1079 - 8
modules/visual_script/visual_script_flow_control.cpp


+ 79 - 0
modules/visual_script/visual_script_flow_control.h

@@ -194,6 +194,85 @@ public:
 	VisualScriptSequence();
 	VisualScriptSequence();
 };
 };
 
 
+
+
+
+class VisualScriptInputSelector : public VisualScriptNode {
+
+	OBJ_TYPE(VisualScriptInputSelector,VisualScriptNode)
+
+
+
+protected:
+
+	static void _bind_methods();
+public:
+
+	virtual int get_output_sequence_port_count() const;
+	virtual bool has_input_sequence_port() const;
+
+
+	virtual String get_output_sequence_port_text(int p_port) const;
+
+
+	virtual int get_input_value_port_count() const;
+	virtual int get_output_value_port_count() const;
+
+
+	virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+	virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+	virtual String get_caption() const;
+	virtual String get_text() const;
+	virtual String get_category() const { return "flow_control"; }
+
+	virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
+
+
+	VisualScriptInputSelector();
+};
+
+
+
+
+class VisualScriptInputFilter : public VisualScriptNode {
+
+	OBJ_TYPE(VisualScriptInputFilter,VisualScriptNode)
+
+	Vector<InputEvent> filters;
+
+
+protected:
+	bool _set(const StringName& p_name, const Variant& p_value);
+	bool _get(const StringName& p_name,Variant &r_ret) const;
+	void _get_property_list( List<PropertyInfo> *p_list) const;
+
+public:
+
+	virtual int get_output_sequence_port_count() const;
+	virtual bool has_input_sequence_port() const;
+
+
+	virtual String get_output_sequence_port_text(int p_port) const;
+
+
+	virtual int get_input_value_port_count() const;
+	virtual int get_output_value_port_count() const;
+
+
+	virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+	virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+	virtual String get_caption() const;
+	virtual String get_text() const;
+	virtual String get_category() const { return "flow_control"; }
+
+	virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
+
+
+	VisualScriptInputFilter();
+};
+
 void register_visual_script_flow_control_nodes();
 void register_visual_script_flow_control_nodes();
 
 
 
 

+ 147 - 31
modules/visual_script/visual_script_func_nodes.cpp

@@ -504,7 +504,7 @@ public:
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 
 
 		switch(call_mode) {
 		switch(call_mode) {
@@ -546,7 +546,7 @@ public:
 			case VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE: {
 			case VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE: {
 
 
 				Variant v = *p_inputs[0];
 				Variant v = *p_inputs[0];
-				print_line("inputs: "+String(v));
+
 				if (returns) {
 				if (returns) {
 					*p_outputs[0] = v.call(function,p_inputs+1,input_args,r_error);
 					*p_outputs[0] = v.call(function,p_inputs+1,input_args,r_error);
 				} else {
 				} else {
@@ -598,6 +598,19 @@ static Ref<VisualScriptNode> create_function_call_node(const String& p_name) {
 ////////////////SET//////////////////////
 ////////////////SET//////////////////////
 //////////////////////////////////////////
 //////////////////////////////////////////
 
 
+static const char* event_type_names[InputEvent::TYPE_MAX]={
+	"None",
+	"Key",
+	"MouseMotion",
+	"MouseButton",
+	"JoystickMotion",
+	"JoystickButton",
+	"ScreenTouch",
+	"ScreenDrag",
+	"Action"
+};
+
+
 int VisualScriptPropertySet::get_output_sequence_port_count() const {
 int VisualScriptPropertySet::get_output_sequence_port_count() const {
 
 
 	return 1;
 	return 1;
@@ -671,7 +684,7 @@ int VisualScriptPropertySet::get_input_value_port_count() const{
 }
 }
 int VisualScriptPropertySet::get_output_value_port_count() const{
 int VisualScriptPropertySet::get_output_value_port_count() const{
 
 
-	return 0;
+	return call_mode==CALL_MODE_BASIC_TYPE? 1 : 0;
 }
 }
 
 
 String VisualScriptPropertySet::get_output_sequence_port_text(int p_port) const {
 String VisualScriptPropertySet::get_output_sequence_port_text(int p_port) const {
@@ -702,9 +715,17 @@ PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const
 	if (call_mode==CALL_MODE_BASIC_TYPE) {
 	if (call_mode==CALL_MODE_BASIC_TYPE) {
 
 
 
 
-		Variant::CallError ce;
-		Variant v = Variant::construct(basic_type,NULL,0,ce);
+		Variant v;
+		if (basic_type==Variant::INPUT_EVENT) {
+			InputEvent ev;
+			ev.type=event_type;
+			v=ev;
+		} else {
+			Variant::CallError ce;
+			v = Variant::construct(basic_type,NULL,0,ce);
+		}
 		v.get_property_list(&pinfo);
 		v.get_property_list(&pinfo);
+
 	} else if (call_mode==CALL_MODE_NODE_PATH) {
 	} else if (call_mode==CALL_MODE_NODE_PATH) {
 
 
 			Node *n = _get_base_node();
 			Node *n = _get_base_node();
@@ -736,8 +757,11 @@ PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const
 }
 }
 
 
 PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) const{
 PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) const{
-
-	return PropertyInfo();
+	if (call_mode==CALL_MODE_BASIC_TYPE) {
+		return PropertyInfo(basic_type,"out");
+	} else {
+		return PropertyInfo();
+	}
 
 
 }
 }
 
 
@@ -810,6 +834,21 @@ Variant::Type VisualScriptPropertySet::get_basic_type() const{
 	return basic_type;
 	return basic_type;
 }
 }
 
 
+void VisualScriptPropertySet::set_event_type(InputEvent::Type p_type) {
+
+	if (event_type==p_type)
+		return;
+	event_type=p_type;
+	_change_notify();
+	_update_base_type();
+	ports_changed_notify();
+}
+
+InputEvent::Type VisualScriptPropertySet::get_event_type() const{
+
+	return event_type;
+}
+
 
 
 void VisualScriptPropertySet::set_base_type(const StringName& p_type) {
 void VisualScriptPropertySet::set_base_type(const StringName& p_type) {
 
 
@@ -918,6 +957,12 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo& property) const {
 		}
 		}
 	}
 	}
 
 
+	if (property.name=="property/event_type") {
+		if (call_mode!=CALL_MODE_BASIC_TYPE || basic_type!=Variant::INPUT_EVENT) {
+			property.usage=0;
+		}
+	}
+
 	if (property.name=="property/node_path") {
 	if (property.name=="property/node_path") {
 		if (call_mode!=CALL_MODE_NODE_PATH) {
 		if (call_mode!=CALL_MODE_NODE_PATH) {
 			property.usage=0;
 			property.usage=0;
@@ -941,7 +986,14 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo& property) const {
 
 
 		if (call_mode==CALL_MODE_BASIC_TYPE) {
 		if (call_mode==CALL_MODE_BASIC_TYPE) {
 			Variant::CallError ce;
 			Variant::CallError ce;
-			Variant v = Variant::construct(basic_type,NULL,0,ce);
+			Variant v;
+			if (basic_type==Variant::INPUT_EVENT) {
+				InputEvent ev;
+				ev.type=event_type;
+				v=ev;
+			} else {
+				v = Variant::construct(basic_type,NULL,0,ce);
+			}
 			v.get_property_list(&pinfo);
 			v.get_property_list(&pinfo);
 
 
 		} else if (call_mode==CALL_MODE_NODE_PATH) {
 		} else if (call_mode==CALL_MODE_NODE_PATH) {
@@ -1030,6 +1082,8 @@ void VisualScriptPropertySet::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptPropertySet::set_basic_type);
 	ObjectTypeDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptPropertySet::set_basic_type);
 	ObjectTypeDB::bind_method(_MD("get_basic_type"),&VisualScriptPropertySet::get_basic_type);
 	ObjectTypeDB::bind_method(_MD("get_basic_type"),&VisualScriptPropertySet::get_basic_type);
 
 
+	ObjectTypeDB::bind_method(_MD("set_event_type","event_type"),&VisualScriptPropertySet::set_event_type);
+	ObjectTypeDB::bind_method(_MD("get_event_type"),&VisualScriptPropertySet::get_event_type);
 
 
 	ObjectTypeDB::bind_method(_MD("set_property","property"),&VisualScriptPropertySet::set_property);
 	ObjectTypeDB::bind_method(_MD("set_property","property"),&VisualScriptPropertySet::set_property);
 	ObjectTypeDB::bind_method(_MD("get_property"),&VisualScriptPropertySet::get_property);
 	ObjectTypeDB::bind_method(_MD("get_property"),&VisualScriptPropertySet::get_property);
@@ -1054,9 +1108,19 @@ void VisualScriptPropertySet::_bind_methods() {
 		bt+=Variant::get_type_name(Variant::Type(i));
 		bt+=Variant::get_type_name(Variant::Type(i));
 	}
 	}
 
 
+	String et;
+	for(int i=0;i<InputEvent::TYPE_MAX;i++) {
+		if (i>0)
+			et+=",";
+
+		et+=event_type_names[i];
+	}
+
+
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type",PROPERTY_USAGE_NOEDITOR),_SCS("set_call_mode"),_SCS("get_call_mode"));
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type",PROPERTY_USAGE_NOEDITOR),_SCS("set_call_mode"),_SCS("get_call_mode"));
 	ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
 	ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"property/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_type"));
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"property/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_type"));
+	ADD_PROPERTY(PropertyInfo(Variant::INT,"property/event_type",PROPERTY_HINT_ENUM,et),_SCS("set_event_type"),_SCS("get_event_type"));
 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
 	ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/property"),_SCS("set_property"),_SCS("get_property"));
 	ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/property"),_SCS("set_property"),_SCS("get_property"));
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"value/use_builtin"),_SCS("set_use_builtin_value"),_SCS("is_using_builtin_value"));
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"value/use_builtin"),_SCS("set_use_builtin_value"),_SCS("is_using_builtin_value"));
@@ -1087,7 +1151,7 @@ public:
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 
 
 		switch(call_mode) {
 		switch(call_mode) {
@@ -1157,6 +1221,10 @@ public:
 					r_error_str="Invalid index property name.";
 					r_error_str="Invalid index property name.";
 				}
 				}
 
 
+				if (call_mode==VisualScriptPropertySet::CALL_MODE_BASIC_TYPE) {
+					*p_outputs[0]=v;
+				}
+
 			} break;
 			} break;
 
 
 		}
 		}
@@ -1185,6 +1253,7 @@ VisualScriptPropertySet::VisualScriptPropertySet() {
 	call_mode=CALL_MODE_INSTANCE;
 	call_mode=CALL_MODE_INSTANCE;
 	base_type="Object";
 	base_type="Object";
 	basic_type=Variant::NIL;
 	basic_type=Variant::NIL;
+	event_type=InputEvent::NONE;
 
 
 }
 }
 
 
@@ -1324,8 +1393,15 @@ PropertyInfo VisualScriptPropertyGet::get_output_value_port_info(int p_idx) cons
 	if (call_mode==CALL_MODE_BASIC_TYPE) {
 	if (call_mode==CALL_MODE_BASIC_TYPE) {
 
 
 
 
-		Variant::CallError ce;
-		Variant v = Variant::construct(basic_type,NULL,0,ce);
+		Variant v;
+		if (basic_type==Variant::INPUT_EVENT) {
+			InputEvent ev;
+			ev.type=event_type;
+			v=ev;
+		} else {
+			Variant::CallError ce;
+			v = Variant::construct(basic_type,NULL,0,ce);
+		}
 		v.get_property_list(&pinfo);
 		v.get_property_list(&pinfo);
 	} else if (call_mode==CALL_MODE_NODE_PATH) {
 	} else if (call_mode==CALL_MODE_NODE_PATH) {
 
 
@@ -1460,6 +1536,21 @@ Variant::Type VisualScriptPropertyGet::get_basic_type() const{
 }
 }
 
 
 
 
+void VisualScriptPropertyGet::set_event_type(InputEvent::Type p_type) {
+
+	if (event_type==p_type)
+		return;
+	event_type=p_type;
+	_change_notify();
+	_update_base_type();
+	ports_changed_notify();
+}
+
+InputEvent::Type VisualScriptPropertyGet::get_event_type() const{
+
+	return event_type;
+}
+
 void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const {
 void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const {
 
 
 	if (property.name=="property/base_type") {
 	if (property.name=="property/base_type") {
@@ -1474,6 +1565,11 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const {
 			property.usage=0;
 			property.usage=0;
 		}
 		}
 	}
 	}
+	if (property.name=="property/event_type") {
+		if (call_mode!=CALL_MODE_BASIC_TYPE || basic_type!=Variant::INPUT_EVENT) {
+			property.usage=0;
+		}
+	}
 
 
 	if (property.name=="property/node_path") {
 	if (property.name=="property/node_path") {
 		if (call_mode!=CALL_MODE_NODE_PATH) {
 		if (call_mode!=CALL_MODE_NODE_PATH) {
@@ -1497,7 +1593,14 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const {
 
 
 		if (call_mode==CALL_MODE_BASIC_TYPE) {
 		if (call_mode==CALL_MODE_BASIC_TYPE) {
 			Variant::CallError ce;
 			Variant::CallError ce;
-			Variant v = Variant::construct(basic_type,NULL,0,ce);
+			Variant v;
+			if (basic_type==Variant::INPUT_EVENT) {
+				InputEvent ev;
+				ev.type=event_type;
+				v=ev;
+			} else {
+				v = Variant::construct(basic_type,NULL,0,ce);
+			}
 			v.get_property_list(&pinfo);
 			v.get_property_list(&pinfo);
 
 
 		} else if (call_mode==CALL_MODE_NODE_PATH) {
 		} else if (call_mode==CALL_MODE_NODE_PATH) {
@@ -1547,6 +1650,9 @@ void VisualScriptPropertyGet::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptPropertyGet::set_basic_type);
 	ObjectTypeDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptPropertyGet::set_basic_type);
 	ObjectTypeDB::bind_method(_MD("get_basic_type"),&VisualScriptPropertyGet::get_basic_type);
 	ObjectTypeDB::bind_method(_MD("get_basic_type"),&VisualScriptPropertyGet::get_basic_type);
 
 
+	ObjectTypeDB::bind_method(_MD("set_event_type","event_type"),&VisualScriptPropertyGet::set_event_type);
+	ObjectTypeDB::bind_method(_MD("get_event_type"),&VisualScriptPropertyGet::get_event_type);
+
 
 
 	ObjectTypeDB::bind_method(_MD("set_property","property"),&VisualScriptPropertyGet::set_property);
 	ObjectTypeDB::bind_method(_MD("set_property","property"),&VisualScriptPropertyGet::set_property);
 	ObjectTypeDB::bind_method(_MD("get_property"),&VisualScriptPropertyGet::get_property);
 	ObjectTypeDB::bind_method(_MD("get_property"),&VisualScriptPropertyGet::get_property);
@@ -1565,10 +1671,19 @@ void VisualScriptPropertyGet::_bind_methods() {
 		bt+=Variant::get_type_name(Variant::Type(i));
 		bt+=Variant::get_type_name(Variant::Type(i));
 	}
 	}
 
 
+	String et;
+	for(int i=0;i<InputEvent::TYPE_MAX;i++) {
+		if (i>0)
+			et+=",";
+
+		et+=event_type_names[i];
+	}
+
 
 
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance",PROPERTY_USAGE_NOEDITOR),_SCS("set_call_mode"),_SCS("get_call_mode"));
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance",PROPERTY_USAGE_NOEDITOR),_SCS("set_call_mode"),_SCS("get_call_mode"));
 	ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
 	ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"property/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_type"));
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"property/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_type"));
+	ADD_PROPERTY(PropertyInfo(Variant::INT,"property/event_type",PROPERTY_HINT_ENUM,et),_SCS("set_event_type"),_SCS("get_event_type"));
 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
 	ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/property"),_SCS("set_property"),_SCS("get_property"));
 	ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/property"),_SCS("set_property"),_SCS("get_property"));
 
 
@@ -1645,7 +1760,7 @@ public:
 
 
 	}
 	}
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 
 
 		bool valid;
 		bool valid;
@@ -1685,6 +1800,7 @@ VisualScriptPropertyGet::VisualScriptPropertyGet() {
 	call_mode=CALL_MODE_INSTANCE;
 	call_mode=CALL_MODE_INSTANCE;
 	base_type="Object";
 	base_type="Object";
 	basic_type=Variant::NIL;
 	basic_type=Variant::NIL;
+	event_type=InputEvent::NONE;
 
 
 }
 }
 
 
@@ -2084,7 +2200,7 @@ public:
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 
 
 		switch(call_mode) {
 		switch(call_mode) {
@@ -2297,7 +2413,7 @@ public:
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 
 
 		Object *obj = instance->get_owner_ptr();
 		Object *obj = instance->get_owner_ptr();
@@ -2359,24 +2475,24 @@ static Ref<VisualScriptNode> create_basic_type_call_node(const String& p_name) {
 
 
 void register_visual_script_func_nodes() {
 void register_visual_script_func_nodes() {
 
 
-	VisualScriptLanguage::singleton->add_register_func("functions/call_method/instance_call",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_INSTANCE>);
-	VisualScriptLanguage::singleton->add_register_func("functions/call_method/basic_type_call",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE>);
-	VisualScriptLanguage::singleton->add_register_func("functions/call_method/self_call",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_SELF>);
-	VisualScriptLanguage::singleton->add_register_func("functions/call_method/node_call",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_NODE_PATH>);
+	VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_instance",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_INSTANCE>);
+	VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_basic_type",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE>);
+	VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_self",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_SELF>);
+	VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_node",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_NODE_PATH>);
 
 
-	VisualScriptLanguage::singleton->add_register_func("functions/set_property/instace_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_INSTANCE>);
-	VisualScriptLanguage::singleton->add_register_func("functions/set_property/basic_type_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_BASIC_TYPE>);
-	VisualScriptLanguage::singleton->add_register_func("functions/set_property/self_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_SELF>);
-	VisualScriptLanguage::singleton->add_register_func("functions/set_property/node_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_NODE_PATH>);
+	VisualScriptLanguage::singleton->add_register_func("functions/property_set/instace_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_INSTANCE>);
+	VisualScriptLanguage::singleton->add_register_func("functions/property_set/basic_type_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_BASIC_TYPE>);
+	VisualScriptLanguage::singleton->add_register_func("functions/property_set/self_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_SELF>);
+	VisualScriptLanguage::singleton->add_register_func("functions/property_set/node_set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_NODE_PATH>);
 
 
-	VisualScriptLanguage::singleton->add_register_func("functions/get_property/instance_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_INSTANCE>);
-	VisualScriptLanguage::singleton->add_register_func("functions/get_property/basic_type_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_BASIC_TYPE>);
-	VisualScriptLanguage::singleton->add_register_func("functions/get_property/self_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_SELF>);
-	VisualScriptLanguage::singleton->add_register_func("functions/get_property/node_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_NODE_PATH>);
+	VisualScriptLanguage::singleton->add_register_func("functions/property_get/instance_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_INSTANCE>);
+	VisualScriptLanguage::singleton->add_register_func("functions/property_get/basic_type_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_BASIC_TYPE>);
+	VisualScriptLanguage::singleton->add_register_func("functions/property_get/self_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_SELF>);
+	VisualScriptLanguage::singleton->add_register_func("functions/property_get/node_get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_NODE_PATH>);
 
 
-	VisualScriptLanguage::singleton->add_register_func("functions/script/script_call",create_script_call_node<VisualScriptScriptCall::CALL_MODE_SELF>);
-	VisualScriptLanguage::singleton->add_register_func("functions/script/script_call_in_node",create_script_call_node<VisualScriptScriptCall::CALL_MODE_NODE_PATH>);
-	VisualScriptLanguage::singleton->add_register_func("functions/script/emit_signal",create_node_generic<VisualScriptEmitSignal>);
+	VisualScriptLanguage::singleton->add_register_func("functions/call_script/call_self",create_script_call_node<VisualScriptScriptCall::CALL_MODE_SELF>);
+	VisualScriptLanguage::singleton->add_register_func("functions/call_script/call_node",create_script_call_node<VisualScriptScriptCall::CALL_MODE_NODE_PATH>);
+	VisualScriptLanguage::singleton->add_register_func("functions/call_script/emit_signal",create_node_generic<VisualScriptEmitSignal>);
 
 
 
 
 	for(int i=0;i<Variant::VARIANT_MAX;i++) {
 	for(int i=0;i<Variant::VARIANT_MAX;i++) {
@@ -2389,7 +2505,7 @@ void register_visual_script_func_nodes() {
 		vt.get_method_list(&ml);
 		vt.get_method_list(&ml);
 
 
 		for (List<MethodInfo>::Element *E=ml.front();E;E=E->next()) {
 		for (List<MethodInfo>::Element *E=ml.front();E;E=E->next()) {
-			VisualScriptLanguage::singleton->add_register_func("functions/basic_types/"+type_name+"/"+E->get().name,create_basic_type_call_node);
+			VisualScriptLanguage::singleton->add_register_func("functions/by_type/"+type_name+"/"+E->get().name,create_basic_type_call_node);
 		}
 		}
 	}
 	}
 }
 }

+ 9 - 1
modules/visual_script/visual_script_func_nodes.h

@@ -93,12 +93,13 @@ public:
 private:
 private:
 
 
 	CallMode call_mode;
 	CallMode call_mode;
-	Variant::Type basic_type;
+	Variant::Type basic_type;	
 	StringName base_type;
 	StringName base_type;
 	NodePath base_path;
 	NodePath base_path;
 	StringName property;
 	StringName property;
 	bool use_builtin_value;
 	bool use_builtin_value;
 	Variant builtin_value;
 	Variant builtin_value;
+	InputEvent::Type event_type;
 
 
 	Node *_get_base_node() const;
 	Node *_get_base_node() const;
 	StringName _get_base_type() const;
 	StringName _get_base_type() const;
@@ -136,6 +137,9 @@ public:
 	void set_basic_type(Variant::Type p_type);
 	void set_basic_type(Variant::Type p_type);
 	Variant::Type get_basic_type() const;
 	Variant::Type get_basic_type() const;
 
 
+	void set_event_type(InputEvent::Type p_type);
+	InputEvent::Type get_event_type() const;
+
 	void set_property(const StringName& p_type);
 	void set_property(const StringName& p_type);
 	StringName get_property() const;
 	StringName get_property() const;
 
 
@@ -177,6 +181,7 @@ private:
 	StringName base_type;
 	StringName base_type;
 	NodePath base_path;
 	NodePath base_path;
 	StringName property;
 	StringName property;
+	InputEvent::Type event_type;
 
 
 	void _update_base_type();
 	void _update_base_type();
 	Node *_get_base_node() const;
 	Node *_get_base_node() const;
@@ -214,6 +219,9 @@ public:
 	void set_basic_type(Variant::Type p_type);
 	void set_basic_type(Variant::Type p_type);
 	Variant::Type get_basic_type() const;
 	Variant::Type get_basic_type() const;
 
 
+	void set_event_type(InputEvent::Type p_type);
+	InputEvent::Type get_event_type() const;
+
 	void set_property(const StringName& p_type);
 	void set_property(const StringName& p_type);
 	StringName get_property() const;
 	StringName get_property() const;
 
 

+ 15 - 15
modules/visual_script/visual_script_nodes.cpp

@@ -234,7 +234,7 @@ public:
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 		int ac = node->get_argument_count();
 		int ac = node->get_argument_count();
 
 
@@ -518,7 +518,7 @@ public:
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 		bool valid;
 		bool valid;
 		if (unary) {
 		if (unary) {
@@ -691,7 +691,7 @@ public:
 		 }
 		 }
 	}
 	}
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 		return 0;
 		return 0;
 	}
 	}
@@ -825,7 +825,7 @@ public:
 	virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
 	virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
 	virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 		if (instance->set_variable(variable,*p_inputs[0])==false) {
 		if (instance->set_variable(variable,*p_inputs[0])==false) {
 			r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD			;
 			r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD			;
@@ -980,7 +980,7 @@ public:
 
 
 	}
 	}
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 		return 0;
 		return 0;
 	}
 	}
@@ -1066,7 +1066,7 @@ public:
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 		bool valid;
 		bool valid;
 		*p_outputs[0] = p_inputs[0]->get(*p_inputs[1],&valid);
 		*p_outputs[0] = p_inputs[0]->get(*p_inputs[1],&valid);
@@ -1158,7 +1158,7 @@ public:
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
 	//virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
 	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 		bool valid;
 		bool valid;
 		*p_outputs[0]=*p_inputs[0];
 		*p_outputs[0]=*p_inputs[0];
@@ -1260,7 +1260,7 @@ public:
 
 
 	}
 	}
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 
 
 		return 0;
 		return 0;
@@ -1392,7 +1392,7 @@ public:
 
 
 	}
 	}
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 
 
 		return 0;
 		return 0;
@@ -1508,7 +1508,7 @@ public:
 		return true;
 		return true;
 	}
 	}
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 
 
 		return 0;
 		return 0;
@@ -1644,7 +1644,7 @@ public:
 		return true;
 		return true;
 	}
 	}
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 		return 0;
 		return 0;
 	}
 	}
@@ -1809,7 +1809,7 @@ public:
 
 
 	}
 	}
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 
 
 		return 0;
 		return 0;
@@ -1913,7 +1913,7 @@ public:
 		return true;
 		return true;
 	}
 	}
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 		return 0;
 		return 0;
 	}
 	}
@@ -1946,7 +1946,7 @@ VisualScriptResourcePath::VisualScriptResourcePath() {
 
 
 
 
 //////////////////////////////////////////
 //////////////////////////////////////////
-////////////////RESPATH///////////
+////////////////SELF///////////
 //////////////////////////////////////////
 //////////////////////////////////////////
 
 
 int VisualScriptSelf::get_output_sequence_port_count() const {
 int VisualScriptSelf::get_output_sequence_port_count() const {
@@ -2011,7 +2011,7 @@ public:
 		return true;
 		return true;
 	}
 	}
 
 
-	virtual int step(const Variant** p_inputs,Variant** p_outputs,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
 
 		return 0;
 		return 0;
 	}
 	}

+ 1 - 2
modules/visual_script/visual_script_nodes.h

@@ -552,8 +552,6 @@ public:
 	virtual String get_text() const;
 	virtual String get_text() const;
 	virtual String get_category() const { return "data"; }
 	virtual String get_category() const { return "data"; }
 
 
-	void set_resource_path(const String &p_path);
-	String get_resource_path();
 
 
 	virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
 	virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
 
 
@@ -561,6 +559,7 @@ public:
 };
 };
 
 
 
 
+
 void register_visual_script_nodes();
 void register_visual_script_nodes();
 
 
 #endif // VISUAL_SCRIPT_NODES_H
 #endif // VISUAL_SCRIPT_NODES_H

+ 622 - 0
modules/visual_script/visual_script_yield_nodes.cpp

@@ -0,0 +1,622 @@
+#include "visual_script_yield_nodes.h"
+#include "scene/main/scene_main_loop.h"
+#include "os/os.h"
+#include "scene/main/node.h"
+#include "visual_script_nodes.h"
+
+//////////////////////////////////////////
+////////////////YIELD///////////
+//////////////////////////////////////////
+
+int VisualScriptYield::get_output_sequence_port_count() const {
+
+	return 1;
+}
+
+bool VisualScriptYield::has_input_sequence_port() const{
+
+	return true;
+}
+
+int VisualScriptYield::get_input_value_port_count() const{
+
+	return 0;
+}
+int VisualScriptYield::get_output_value_port_count() const{
+
+	return 0;
+}
+
+String VisualScriptYield::get_output_sequence_port_text(int p_port) const {
+
+	return String();
+}
+
+PropertyInfo VisualScriptYield::get_input_value_port_info(int p_idx) const{
+
+	return PropertyInfo();
+}
+
+PropertyInfo VisualScriptYield::get_output_value_port_info(int p_idx) const{
+
+	return PropertyInfo();
+}
+
+
+String VisualScriptYield::get_caption() const {
+
+	return "Wait";
+}
+
+String VisualScriptYield::get_text() const {
+
+	switch (yield_mode) {
+		case YIELD_FRAME: return "Next Frame"; break;
+		case YIELD_FIXED_FRAME:  return "Next Fixed Frame"; break;
+		case YIELD_WAIT:  return rtos(wait_time)+" sec(s)"; break;
+	}
+
+	return String();
+}
+
+
+class VisualScriptNodeInstanceYield : public VisualScriptNodeInstance {
+public:
+
+	VisualScriptYield::YieldMode mode;
+	float wait_time;
+
+	virtual int get_working_memory_size() const { return 1; } //yield needs at least 1
+	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
+
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+
+		if (p_start_mode==START_MODE_RESUME_YIELD) {
+			return 0; //resuming yield
+		} else {
+			//yield
+
+
+			SceneTree *tree = OS::get_singleton()->get_main_loop()->cast_to<SceneTree>();
+			if (!tree) {
+				r_error_str="Main Loop is not SceneTree";
+				r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+				return 0;
+			}
+
+			Ref<VisualScriptFunctionState> state;
+			state.instance();
+
+			switch(mode) {
+
+				case VisualScriptYield::YIELD_FRAME: state->connect_to_signal(tree,"idle_frame",Array()); break;
+				case VisualScriptYield::YIELD_FIXED_FRAME:  state->connect_to_signal(tree,"fixed_frame",Array()); break;
+				case VisualScriptYield::YIELD_WAIT:  state->connect_to_signal(tree->create_timer(wait_time).ptr(),"timeout",Array()); break;
+
+			}
+
+			*p_working_mem=state;
+
+			return STEP_YIELD_BIT;
+		}
+	}
+
+};
+
+VisualScriptNodeInstance* VisualScriptYield::instance(VisualScriptInstance* p_instance) {
+
+	VisualScriptNodeInstanceYield * instance = memnew(VisualScriptNodeInstanceYield );
+	//instance->instance=p_instance;
+	instance->mode=yield_mode;
+	instance->wait_time=wait_time;
+	return instance;
+}
+
+void VisualScriptYield::set_yield_mode(YieldMode p_mode) {
+
+	if (yield_mode==p_mode)
+		return;
+	yield_mode=p_mode;
+	ports_changed_notify();
+	_change_notify();
+}
+
+VisualScriptYield::YieldMode VisualScriptYield::get_yield_mode(){
+
+	return yield_mode;
+}
+
+void VisualScriptYield::set_wait_time(float p_time) {
+
+	if (wait_time==p_time)
+		return;
+	wait_time=p_time;
+	ports_changed_notify();
+
+}
+
+float VisualScriptYield::get_wait_time(){
+
+	return wait_time;
+}
+
+
+void VisualScriptYield::_validate_property(PropertyInfo& property) const {
+
+
+	if (property.name=="wait_time") {
+		if (yield_mode!=YIELD_WAIT) {
+			property.usage=0;
+		}
+	}
+}
+
+void VisualScriptYield::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("set_yield_mode","mode"),&VisualScriptYield::set_yield_mode);
+	ObjectTypeDB::bind_method(_MD("get_yield_mode"),&VisualScriptYield::get_yield_mode);
+
+	ObjectTypeDB::bind_method(_MD("set_wait_time","sec"),&VisualScriptYield::set_wait_time);
+	ObjectTypeDB::bind_method(_MD("get_wait_time"),&VisualScriptYield::get_wait_time);
+
+	ADD_PROPERTY(PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Frame,FixedFrame,Time",PROPERTY_USAGE_NOEDITOR),_SCS("set_yield_mode"),_SCS("get_yield_mode"));
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"wait_time"),_SCS("set_wait_time"),_SCS("get_wait_time"));
+
+
+	BIND_CONSTANT( YIELD_FRAME );
+	BIND_CONSTANT( YIELD_FIXED_FRAME );
+	BIND_CONSTANT( YIELD_WAIT );
+
+}
+
+VisualScriptYield::VisualScriptYield() {
+
+	yield_mode=YIELD_FRAME;
+	wait_time=1;
+
+}
+
+
+template<VisualScriptYield::YieldMode MODE>
+static Ref<VisualScriptNode> create_yield_node(const String& p_name) {
+
+	Ref<VisualScriptYield> node;
+	node.instance();
+	node->set_yield_mode(MODE);
+	return node;
+}
+
+///////////////////////////////////////////////////
+////////////////YIELD SIGNAL//////////////////////
+//////////////////////////////////////////////////
+
+int VisualScriptYieldSignal::get_output_sequence_port_count() const {
+
+	return 1;
+}
+
+bool VisualScriptYieldSignal::has_input_sequence_port() const{
+
+	return true;
+}
+#ifdef TOOLS_ENABLED
+
+static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) {
+
+	if (p_edited_scene!=p_current_node && p_current_node->get_owner()!=p_edited_scene)
+		return NULL;
+
+	Ref<Script> scr = p_current_node->get_script();
+
+	if (scr.is_valid() && scr==script)
+		return p_current_node;
+
+	for(int i=0;i<p_current_node->get_child_count();i++) {
+		Node *n = _find_script_node(p_edited_scene,p_current_node->get_child(i),script);
+		if (n)
+			return n;
+	}
+
+	return NULL;
+}
+
+#endif
+Node *VisualScriptYieldSignal::_get_base_node() const {
+
+#ifdef TOOLS_ENABLED
+	Ref<Script> script = get_visual_script();
+	if (!script.is_valid())
+		return NULL;
+
+	MainLoop * main_loop = OS::get_singleton()->get_main_loop();
+	if (!main_loop)
+		return NULL;
+
+	SceneTree *scene_tree = main_loop->cast_to<SceneTree>();
+
+	if (!scene_tree)
+		return NULL;
+
+	Node *edited_scene = scene_tree->get_edited_scene_root();
+
+	if (!edited_scene)
+		return NULL;
+
+	Node* script_node = _find_script_node(edited_scene,edited_scene,script);
+
+	if (!script_node)
+		return NULL;
+
+	if (!script_node->has_node(base_path))
+		return NULL;
+
+	Node *path_to = script_node->get_node(base_path);
+
+	return path_to;
+#else
+
+	return NULL;
+#endif
+}
+
+StringName VisualScriptYieldSignal::_get_base_type() const {
+
+	if (call_mode==CALL_MODE_SELF && get_visual_script().is_valid())
+		return get_visual_script()->get_instance_base_type();
+	else if (call_mode==CALL_MODE_NODE_PATH && get_visual_script().is_valid()) {
+		Node *path = _get_base_node();
+		if (path)
+			return path->get_type();
+
+	}
+
+	return base_type;
+}
+
+int VisualScriptYieldSignal::get_input_value_port_count() const{
+
+	if (call_mode==CALL_MODE_INSTANCE)
+		return 1;
+	else
+		return 0;
+
+}
+int VisualScriptYieldSignal::get_output_value_port_count() const{
+
+
+	MethodInfo sr;
+
+	if (!ObjectTypeDB::get_signal(_get_base_type(),signal,&sr))
+		return 0;
+
+	return sr.arguments.size();
+
+}
+
+String VisualScriptYieldSignal::get_output_sequence_port_text(int p_port) const {
+
+	return String();
+}
+
+PropertyInfo VisualScriptYieldSignal::get_input_value_port_info(int p_idx) const{
+
+	if (call_mode==CALL_MODE_INSTANCE)
+		return PropertyInfo(Variant::OBJECT,"instance");
+	else
+		return PropertyInfo();
+
+}
+
+PropertyInfo VisualScriptYieldSignal::get_output_value_port_info(int p_idx) const{
+
+	MethodInfo sr;
+
+	if (!ObjectTypeDB::get_signal(_get_base_type(),signal,&sr))
+		return PropertyInfo(); //no signal
+	ERR_FAIL_INDEX_V(p_idx,sr.arguments.size(),PropertyInfo());
+	return sr.arguments[p_idx];
+
+}
+
+
+String VisualScriptYieldSignal::get_caption() const {
+
+	static const char*cname[3]= {
+		"WaitSignal",
+		"WaitNodeSignal",
+		"WaitInstanceSigna;",
+	};
+
+	return cname[call_mode];
+}
+
+String VisualScriptYieldSignal::get_text() const {
+
+	if (call_mode==CALL_MODE_SELF)
+		return "  "+String(signal)+"()";
+	else
+		return "  "+_get_base_type()+"."+String(signal)+"()";
+
+}
+
+
+void VisualScriptYieldSignal::set_base_type(const StringName& p_type) {
+
+	if (base_type==p_type)
+		return;
+
+	base_type=p_type;
+
+	_change_notify();
+	ports_changed_notify();
+}
+
+StringName VisualScriptYieldSignal::get_base_type() const{
+
+	return base_type;
+}
+
+void VisualScriptYieldSignal::set_signal(const StringName& p_type){
+
+	if (signal==p_type)
+		return;
+
+	signal=p_type;
+
+	_change_notify();
+	ports_changed_notify();
+}
+StringName VisualScriptYieldSignal::get_signal() const {
+
+
+	return signal;
+}
+
+void VisualScriptYieldSignal::set_base_path(const NodePath& p_type) {
+
+	if (base_path==p_type)
+		return;
+
+	base_path=p_type;
+
+	_change_notify();
+	ports_changed_notify();
+}
+
+NodePath VisualScriptYieldSignal::get_base_path() const {
+
+	return base_path;
+}
+
+
+void VisualScriptYieldSignal::set_call_mode(CallMode p_mode) {
+
+	if (call_mode==p_mode)
+		return;
+
+	call_mode=p_mode;
+
+	_change_notify();
+	ports_changed_notify();
+
+}
+
+VisualScriptYieldSignal::CallMode VisualScriptYieldSignal::get_call_mode() const {
+
+	return call_mode;
+}
+
+
+void VisualScriptYieldSignal::_validate_property(PropertyInfo& property) const {
+
+	if (property.name=="signal/base_type") {
+		if (call_mode!=CALL_MODE_INSTANCE) {
+			property.usage=PROPERTY_USAGE_NOEDITOR;
+		}
+	}
+
+
+	if (property.name=="signal/node_path") {
+		if (call_mode!=CALL_MODE_NODE_PATH) {
+			property.usage=0;
+		} else {
+
+			Node *bnode = _get_base_node();
+			if (bnode) {
+				property.hint_string=bnode->get_path(); //convert to loong string
+			} else {
+
+			}
+		}
+	}
+
+	if (property.name=="signal/signal") {
+		property.hint=PROPERTY_HINT_ENUM;
+
+
+		List<MethodInfo> methods;
+
+		ObjectTypeDB::get_signal_list(_get_base_type(),&methods);
+
+		List<String> mstring;
+		for (List<MethodInfo>::Element *E=methods.front();E;E=E->next()) {
+			if (E->get().name.begins_with("_"))
+				continue;
+			mstring.push_back(E->get().name.get_slice(":",0));
+		}
+
+		mstring.sort();
+
+		String ml;
+		for (List<String>::Element *E=mstring.front();E;E=E->next()) {
+
+			if (ml!=String())
+				ml+=",";
+			ml+=E->get();
+		}
+
+		property.hint_string=ml;
+	}
+
+
+}
+
+
+void VisualScriptYieldSignal::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("set_base_type","base_type"),&VisualScriptYieldSignal::set_base_type);
+	ObjectTypeDB::bind_method(_MD("get_base_type"),&VisualScriptYieldSignal::get_base_type);
+
+	ObjectTypeDB::bind_method(_MD("set_signal","signal"),&VisualScriptYieldSignal::set_signal);
+	ObjectTypeDB::bind_method(_MD("get_signal"),&VisualScriptYieldSignal::get_signal);
+
+	ObjectTypeDB::bind_method(_MD("set_call_mode","mode"),&VisualScriptYieldSignal::set_call_mode);
+	ObjectTypeDB::bind_method(_MD("get_call_mode"),&VisualScriptYieldSignal::get_call_mode);
+
+	ObjectTypeDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptYieldSignal::set_base_path);
+	ObjectTypeDB::bind_method(_MD("get_base_path"),&VisualScriptYieldSignal::get_base_path);
+
+
+
+	String bt;
+	for(int i=0;i<Variant::VARIANT_MAX;i++) {
+		if (i>0)
+			bt+=",";
+
+		bt+=Variant::get_type_name(Variant::Type(i));
+	}
+
+	ADD_PROPERTY(PropertyInfo(Variant::INT,"signal/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance",PROPERTY_USAGE_NOEDITOR),_SCS("set_call_mode"),_SCS("get_call_mode"));
+	ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
+	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"signal/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
+	ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/signal"),_SCS("set_signal"),_SCS("get_signal"));
+
+
+	BIND_CONSTANT( CALL_MODE_SELF );
+	BIND_CONSTANT( CALL_MODE_NODE_PATH);
+	BIND_CONSTANT( CALL_MODE_INSTANCE);
+
+}
+
+class VisualScriptNodeInstanceYieldSignal : public VisualScriptNodeInstance {
+public:
+
+
+	VisualScriptYieldSignal::CallMode call_mode;
+	NodePath node_path;
+	int output_args;
+	StringName signal;
+
+	VisualScriptYieldSignal *node;
+	VisualScriptInstance *instance;
+
+
+
+	virtual int get_working_memory_size() const { return 1; }
+	//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
+	//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
+
+	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
+
+		if (p_start_mode==START_MODE_RESUME_YIELD) {
+			return 0; //resuming yield
+		} else {
+			//yield
+
+			Object * object;
+
+			switch(call_mode) {
+
+				case VisualScriptYieldSignal::CALL_MODE_SELF: {
+
+					object=instance->get_owner_ptr();
+
+				} break;
+				case VisualScriptYieldSignal::CALL_MODE_NODE_PATH: {
+
+					Node* node = instance->get_owner_ptr()->cast_to<Node>();
+					if (!node) {
+						r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+						r_error_str="Base object is not a Node!";
+						return 0;
+					}
+
+					Node* another = node->get_node(node_path);
+					if (!node) {
+						r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+						r_error_str="Path does not lead Node!";
+						return 0;
+					}
+
+					object=another;
+
+				} break;
+				case VisualScriptYieldSignal::CALL_MODE_INSTANCE: {
+
+					object = *p_inputs[0];
+					if (!object) {
+						r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+						r_error_str="Supplied instance input is null.";
+						return 0;
+
+					}
+
+				} break;
+
+			}
+
+			Ref<VisualScriptFunctionState> state;
+			state.instance();
+
+			state->connect_to_signal(object,signal,Array());
+
+			*p_working_mem=state;
+
+			return STEP_YIELD_BIT;
+		}
+
+
+	}
+
+
+};
+
+VisualScriptNodeInstance* VisualScriptYieldSignal::instance(VisualScriptInstance* p_instance) {
+
+	VisualScriptNodeInstanceYieldSignal * instance = memnew(VisualScriptNodeInstanceYieldSignal );
+	instance->node=this;
+	instance->instance=p_instance;
+	instance->signal=signal;
+	instance->call_mode=call_mode;
+	instance->node_path=base_path;
+	instance->output_args = get_output_value_port_count();
+	return instance;
+}
+VisualScriptYieldSignal::VisualScriptYieldSignal() {
+
+	call_mode=CALL_MODE_INSTANCE;
+	base_type="Object";
+
+}
+
+template<VisualScriptYieldSignal::CallMode cmode>
+static Ref<VisualScriptNode> create_yield_signal_node(const String& p_name) {
+
+	Ref<VisualScriptYieldSignal> node;
+	node.instance();
+	node->set_call_mode(cmode);
+	return node;
+}
+
+void register_visual_script_yield_nodes() {
+
+	VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_frame",create_yield_node<VisualScriptYield::YIELD_FRAME>);
+	VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_fixed_frame",create_yield_node<VisualScriptYield::YIELD_FIXED_FRAME>);
+	VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_time",create_yield_node<VisualScriptYield::YIELD_WAIT>);
+
+	VisualScriptLanguage::singleton->add_register_func("functions/yield/instance_signal",create_yield_signal_node<VisualScriptYieldSignal::CALL_MODE_INSTANCE>);
+	VisualScriptLanguage::singleton->add_register_func("functions/yield/self_signal",create_yield_signal_node<VisualScriptYieldSignal::CALL_MODE_SELF>);
+	VisualScriptLanguage::singleton->add_register_func("functions/yield/node_signal",create_yield_signal_node<VisualScriptYieldSignal::CALL_MODE_NODE_PATH>);
+
+}

+ 127 - 0
modules/visual_script/visual_script_yield_nodes.h

@@ -0,0 +1,127 @@
+#ifndef VISUAL_SCRIPT_YIELD_NODES_H
+#define VISUAL_SCRIPT_YIELD_NODES_H
+
+#include "visual_script.h"
+
+class VisualScriptYield : public VisualScriptNode {
+
+	OBJ_TYPE(VisualScriptYield,VisualScriptNode)
+public:
+
+	enum YieldMode {
+		YIELD_FRAME,
+		YIELD_FIXED_FRAME,
+		YIELD_WAIT
+
+	};
+private:
+
+	YieldMode yield_mode;
+	float wait_time;
+
+
+protected:
+
+	virtual void _validate_property(PropertyInfo& property) const;
+
+	static void _bind_methods();
+public:
+
+	virtual int get_output_sequence_port_count() const;
+	virtual bool has_input_sequence_port() const;
+
+
+	virtual String get_output_sequence_port_text(int p_port) const;
+
+
+	virtual int get_input_value_port_count() const;
+	virtual int get_output_value_port_count() const;
+
+
+	virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+	virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+	virtual String get_caption() const;
+	virtual String get_text() const;
+	virtual String get_category() const { return "functions"; }
+
+	void set_yield_mode(YieldMode p_mode);
+	YieldMode get_yield_mode();
+
+	void set_wait_time(float p_time);
+	float get_wait_time();
+
+	virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
+
+	VisualScriptYield();
+};
+VARIANT_ENUM_CAST( VisualScriptYield::YieldMode )
+
+class VisualScriptYieldSignal : public VisualScriptNode {
+
+	OBJ_TYPE(VisualScriptYieldSignal,VisualScriptNode)
+public:
+	enum CallMode {
+		CALL_MODE_SELF,
+		CALL_MODE_NODE_PATH,
+		CALL_MODE_INSTANCE,
+
+	};
+private:
+
+	CallMode call_mode;
+	StringName base_type;
+	NodePath base_path;
+	StringName signal;
+
+	Node *_get_base_node() const;
+	StringName _get_base_type() const;
+
+
+protected:
+	virtual void _validate_property(PropertyInfo& property) const;
+
+	static void _bind_methods();
+
+public:
+
+	virtual int get_output_sequence_port_count() const;
+	virtual bool has_input_sequence_port() const;
+
+
+	virtual String get_output_sequence_port_text(int p_port) const;
+
+
+	virtual int get_input_value_port_count() const;
+	virtual int get_output_value_port_count() const;
+
+
+	virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+	virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+	virtual String get_caption() const;
+	virtual String get_text() const;
+	virtual String get_category() const { return "functions"; }
+
+	void set_base_type(const StringName& p_type);
+	StringName get_base_type() const;
+
+	void set_signal(const StringName& p_type);
+	StringName get_signal() const;
+
+	void set_base_path(const NodePath& p_type);
+	NodePath get_base_path() const;
+
+	void set_call_mode(CallMode p_mode);
+	CallMode get_call_mode() const;
+
+	virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
+
+	VisualScriptYieldSignal();
+};
+
+VARIANT_ENUM_CAST(VisualScriptYieldSignal::CallMode );
+
+void register_visual_script_yield_nodes();
+
+#endif // VISUAL_SCRIPT_YIELD_NODES_H

+ 16 - 1
tools/editor/scene_tree_dock.cpp

@@ -683,6 +683,8 @@ void SceneTreeDock::_notification(int p_what) {
 			}
 			}
 			button_add->set_icon(get_icon("Add","EditorIcons"));
 			button_add->set_icon(get_icon("Add","EditorIcons"));
 			button_instance->set_icon(get_icon("Instance","EditorIcons"));
 			button_instance->set_icon(get_icon("Instance","EditorIcons"));
+			button_create_script->set_icon(get_icon("Script","EditorIcons"));
+
 
 
 			filter_icon->set_texture(get_icon("Zoom","EditorIcons"));
 			filter_icon->set_texture(get_icon("Zoom","EditorIcons"));
 
 
@@ -1302,11 +1304,18 @@ void SceneTreeDock::_delete_confirm() {
 
 
 void SceneTreeDock::_selection_changed() {
 void SceneTreeDock::_selection_changed() {
 
 
-	if (EditorNode::get_singleton()->get_editor_selection()->get_selection().size()>1) {
+	int selection_size = EditorNode::get_singleton()->get_editor_selection()->get_selection().size();
+	if (selection_size>1) {
 		//automatically turn on multi-edit
 		//automatically turn on multi-edit
 		_tool_selected(TOOL_MULTI_EDIT);
 		_tool_selected(TOOL_MULTI_EDIT);
 	}
 	}
 
 
+	if (selection_size==1 && EditorNode::get_singleton()->get_editor_selection()->get_selection().front()->key()->get_script().is_null()) {
+		button_create_script->show();
+	} else {
+		button_create_script->hide();
+	}
+
 	//tool_buttons[TOOL_MULTI_EDIT]->set_disabled(EditorNode::get_singleton()->get_editor_selection()->get_selection().size()<2);
 	//tool_buttons[TOOL_MULTI_EDIT]->set_disabled(EditorNode::get_singleton()->get_editor_selection()->get_selection().size()<2);
 
 
 }
 }
@@ -1899,6 +1908,12 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
 	filter->connect("text_changed",this,"_filter_changed");
 	filter->connect("text_changed",this,"_filter_changed");
 
 
 
 
+	tb = memnew( ToolButton );
+	tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_SCRIPT, false));
+	tb->set_tooltip(TTR("Create a new script for the selected node."));
+	tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/add_script"));
+	filter_hbc->add_child(tb);
+	button_create_script=tb;
 
 
 
 
 	scene_tree = memnew( SceneTreeEditor(false,true,true ));
 	scene_tree = memnew( SceneTreeEditor(false,true,true ));

+ 1 - 0
tools/editor/scene_tree_dock.h

@@ -78,6 +78,7 @@ class SceneTreeDock : public VBoxContainer {
 
 
 	ToolButton *button_add;
 	ToolButton *button_add;
 	ToolButton *button_instance;
 	ToolButton *button_instance;
+	ToolButton *button_create_script;
 
 
 	SceneTreeEditor *scene_tree;
 	SceneTreeEditor *scene_tree;
 
 

Some files were not shown because too many files changed in this diff