From b77200728e7f2b2dd446a9717c83a20c9aac0ce4 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 7 Aug 2016 19:22:33 -0300 Subject: -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. --- core/io/resource_format_binary.cpp | 24 +- core/method_bind.h | 1 + core/object_type_db.cpp | 17 + core/object_type_db.h | 1 + core/os/keyboard.cpp | 21 + core/os/keyboard.h | 3 + modules/visual_script/register_types.cpp | 8 + modules/visual_script/visual_script.cpp | 358 +++++-- modules/visual_script/visual_script.h | 43 +- .../visual_script/visual_script_builtin_funcs.cpp | 2 +- .../visual_script/visual_script_flow_control.cpp | 1091 +++++++++++++++++++- modules/visual_script/visual_script_flow_control.h | 79 ++ modules/visual_script/visual_script_func_nodes.cpp | 178 +++- modules/visual_script/visual_script_func_nodes.h | 10 +- modules/visual_script/visual_script_nodes.cpp | 30 +- modules/visual_script/visual_script_nodes.h | 3 +- .../visual_script/visual_script_yield_nodes.cpp | 622 +++++++++++ modules/visual_script/visual_script_yield_nodes.h | 127 +++ tools/editor/scene_tree_dock.cpp | 17 +- tools/editor/scene_tree_dock.h | 1 + 20 files changed, 2488 insertions(+), 148 deletions(-) create mode 100644 modules/visual_script/visual_script_yield_nodes.cpp create mode 100644 modules/visual_script/visual_script_yield_nodes.h diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 343a54e0d7..a620dc0fef 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -447,13 +447,17 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) { } break; case VARIANT_INPUT_EVENT: { + InputEvent ev; + ev.type=f->get_32(); //will only work for null though. + r_v=ev; + } break; case VARIANT_DICTIONARY: { - uint32_t len=f->get_32(); - Dictionary d(len&0x80000000); //last bit means shared - len&=0x7FFFFFFF; - for(uint32_t i=0;iget_32(); + Dictionary d(len&0x80000000); //last bit means shared + len&=0x7FFFFFFF; + for(uint32_t i=0;iget_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); - for(uint32_t i=0;istore_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; case Variant::DICTIONARY: { diff --git a/core/method_bind.h b/core/method_bind.h index 3d62e38daa..072953743c 100644 --- a/core/method_bind.h +++ b/core/method_bind.h @@ -156,6 +156,7 @@ VARIANT_ENUM_CAST( Orientation ); VARIANT_ENUM_CAST( HAlign ); VARIANT_ENUM_CAST( Variant::Type ); VARIANT_ENUM_CAST( Variant::Operator ); +VARIANT_ENUM_CAST( InputEvent::Type ); class MethodBind { diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index 4998263961..ba98797a89 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -549,6 +549,23 @@ bool ObjectTypeDB::has_signal(StringName p_type,StringName p_signal) { 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) { diff --git a/core/object_type_db.h b/core/object_type_db.h index 8313091acd..9f7463e58b 100644 --- a/core/object_type_db.h +++ b/core/object_type_db.h @@ -453,6 +453,7 @@ public: static void add_signal(StringName p_type,const MethodInfo& 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 *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); diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp index 4c0a074a07..26b481840a 100644 --- a/core/os/keyboard.cpp +++ b/core/os/keyboard.cpp @@ -429,6 +429,27 @@ static const _KeyCodeReplace _keycode_replace_neo[]={ {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) { diff --git a/core/os/keyboard.h b/core/os/keyboard.h index 80472acc09..fd52d331c8 100644 --- a/core/os/keyboard.h +++ b/core/os/keyboard.h @@ -328,6 +328,9 @@ enum KeyModifierMask { String keycode_get_string(uint32_t p_code); bool keycode_has_unicode(uint32_t p_unicode); 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); #endif diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index 08b0280ac4..916c7b7255 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -35,6 +35,7 @@ #include "visual_script_func_nodes.h" #include "visual_script_builtin_funcs.h" #include "visual_script_flow_control.h" +#include "visual_script_yield_nodes.h" VisualScriptLanguage *visual_script_language=NULL; @@ -44,6 +45,7 @@ void register_visual_script_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_virtual_type(); + ObjectTypeDB::register_virtual_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); @@ -70,6 +72,11 @@ void register_visual_script_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); + + ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); @@ -81,6 +88,7 @@ void register_visual_script_types() { register_visual_script_func_nodes(); register_visual_script_builtin_func_node(); register_visual_script_flow_control_nodes(); + register_visual_script_yield_nodes(); #ifdef TOOLS_ENABLED VisualScriptEditor::register_editor(); diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 9dc91d82f1..9074a08bf4 100644 --- a/modules/visual_script/visual_script.cpp +++ b/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); + } void VisualScript::add_node(const StringName& p_func,int p_id, const Ref& 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) -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::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(); - 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); 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;inode_count;i++) { - sequence_bits[i]=false; //all starts as false - } - - - Map::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_argcountargument_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;imax_stack;i++) { - memnew_placement(&variant_stack[i],Variant); - } - - //allocate function arguments (must be copied for yield to work properly) - for(int i=0;inode; Variant return_value; Variant *working_mem=NULL; + + int flow_stack_pos=p_flow_stack_pos; + #ifdef DEBUG_ENABLED if (ScriptDebugger::get_singleton()) { VisualScriptLanguage::singleton->enter_function(this,&p_method,variant_stack,&working_mem,¤t_node_id); @@ -1518,12 +1455,19 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_ //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)); - 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) { //use error from step @@ -1531,6 +1475,52 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_ 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 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 if (ScriptDebugger::get_singleton()) { // line @@ -1586,10 +1576,11 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_ } next = node->sequence_outputs[output]; - if (next) + if (next) { VSDEBUG("GOT NEXT NODE - "+itos(next->get_id())); - else + } else { VSDEBUG("GOT NEXT NODE - NULL"); + } } if (flow_stack) { @@ -1742,6 +1733,95 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_ 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::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;inode_count;i++) { + sequence_bits[i]=false; //all starts as false + } + + + Map::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_argcountargument_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;imax_stack;i++) { + memnew_placement(&variant_stack[i],Variant); + } + + //allocate function arguments (must be copied for yield to work properly) + for(int i=0;i 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 binds; + for(int i=0;i(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 get_base_node() { return Ref( base ); } @@ -352,7 +360,11 @@ class VisualScriptInstance : public ScriptInstance { 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 functions; +friend class VisualScriptFunctionState; //for yield friend class VisualScriptLanguage; //for debugger public: 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 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 (*VisualScriptNodeRegisterFunc)(const String& p_type); diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 247cbeb2c9..e813d9ea84 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/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 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) { case VisualScriptBuiltinFunc::MATH_SIN: { diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index 094cb4aa1c..cb0ff4086c 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -1,4 +1,6 @@ #include "visual_script_flow_control.h" +#include "os/keyboard.h" +#include "globals.h" ////////////////////////////////////////// ////////////////RETURN//////////////////// @@ -104,7 +106,7 @@ public: //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,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 (with_value) { *p_working_mem = *p_inputs[0]; @@ -213,7 +215,7 @@ public: //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,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 (p_inputs[0]->operator bool()) return 0; @@ -307,7 +309,7 @@ public: //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,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 keep_going = p_inputs[0]->operator bool(); @@ -404,9 +406,9 @@ public: //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,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 (p_start_sequence) { + if (p_start_mode==START_MODE_BEGIN_SEQUENCE) { p_working_mem[0]=*p_inputs[0]; bool valid; bool can_iter = p_inputs[0]->iter_init(p_working_mem[1],valid); @@ -430,7 +432,7 @@ public: } - } else { + } else { //continue sequence bool valid; bool can_iter = p_working_mem[0].iter_next(p_working_mem[1],valid); @@ -555,9 +557,9 @@ public: //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,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 (p_start_sequence) { + if (p_start_mode==START_MODE_BEGIN_SEQUENCE) { p_working_mem[0]=0; } @@ -591,6 +593,1075 @@ VisualScriptSequence::VisualScriptSequence() { steps=1; } + +////////////////////////////////////////// +////////////////EVENT TYPE FILTER/////////// +////////////////////////////////////////// + +static const char* event_type_names[InputEvent::TYPE_MAX]={ + "None", + "Key", + "MouseMotion", + "MouseButton", + "JoystickMotion", + "JoystickButton", + "ScreenTouch", + "ScreenDrag", + "Action" +}; + +int VisualScriptInputSelector::get_output_sequence_port_count() const { + + return InputEvent::TYPE_MAX; +} + +bool VisualScriptInputSelector::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptInputSelector::get_input_value_port_count() const{ + + + return 1; +} +int VisualScriptInputSelector::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptInputSelector::get_output_sequence_port_text(int p_port) const { + + return event_type_names[p_port]; +} + +PropertyInfo VisualScriptInputSelector::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(Variant::INPUT_EVENT,"event"); +} + +PropertyInfo VisualScriptInputSelector::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(Variant::INPUT_EVENT,""); +} + + +String VisualScriptInputSelector::get_caption() const { + + return "InputSelector"; +} + +String VisualScriptInputSelector::get_text() const { + + return ""; +} + + +class VisualScriptNodeInstanceInputSelector : public VisualScriptNodeInstance { +public: + + VisualScriptInstance* instance; + InputEvent::Type type; + + //virtual int get_working_memory_size() const { return 0; } + //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_inputs[0]->get_type()!=Variant::INPUT_EVENT) { + r_error_str="Input value not of type event"; + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + return 0; + } + + InputEvent event = *p_inputs[0]; + + *p_outputs[0] = event; + + return event.type; + } + + +}; + +VisualScriptNodeInstance* VisualScriptInputSelector::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceInputSelector * instance = memnew(VisualScriptNodeInstanceInputSelector ); + instance->instance=p_instance; + return instance; +} + + + +void VisualScriptInputSelector::_bind_methods() { + + +} + +VisualScriptInputSelector::VisualScriptInputSelector() { + + +} + +////////////////////////////////////////// +////////////////EVENT ACTION FILTER/////////// +////////////////////////////////////////// + + +int VisualScriptInputFilter::get_output_sequence_port_count() const { + + return filters.size(); +} + +bool VisualScriptInputFilter::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptInputFilter::get_input_value_port_count() const{ + + + return 1; +} +int VisualScriptInputFilter::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptInputFilter::get_output_sequence_port_text(int p_port) const { + + String text; + + switch(filters[p_port].type) { + case InputEvent::NONE: { + text="None"; + } break; + case InputEvent::KEY: { + + InputEventKey k = filters[p_port].key; + + if (k.scancode==0 && k.unicode==0) { + text="No Key"; + } else { + if (k.scancode!=0) { + text="KeyCode: "+keycode_get_string(k.scancode); + } else if (k.unicode!=0) { + text="Uniode: "+String::chr(k.unicode); + } + + if (k.pressed) + text+=", Pressed"; + else + text+=", Released"; + + if (k.echo) + text+=", Echo"; + if (k.mod.alt) + text="Alt+"+text; + if (k.mod.shift) + text="Shift+"+text; + if (k.mod.control) + text="Ctrl+"+text; + if (k.mod.meta) + text="Meta+"+text; + } + + } break; + case InputEvent::MOUSE_MOTION: { + InputEventMouseMotion mm = filters[p_port].mouse_motion; + text="Mouse Motion"; + + String b = "Left,Right,Middle,WheelUp,WheelDown,WheelLeft,WheelRight"; + + for(int i=0;i<7;i++) { + if (mm.button_mask&(1<>1); + if (jm.axis&1) + text+=" > "+rtos(jm.axis_value); + else + text+=" < "+rtos(-jm.axis_value); + + } break; + case InputEvent::JOYSTICK_BUTTON: { + InputEventJoystickButton jb = filters[p_port].joy_button; + + text="JoyButton "+itos(jb.button_index); + if (jb.pressed) + text+=", Pressed"; + else + text+=", Released"; + } break; + case InputEvent::SCREEN_TOUCH: { + InputEventScreenTouch sd = filters[p_port].screen_touch; + + text="Touch Finger "+itos(sd.index); + if (sd.pressed) + text+=", Pressed"; + else + text+=", Released"; + } break; + case InputEvent::SCREEN_DRAG: { + InputEventScreenDrag sd = filters[p_port].screen_drag; + text="Drag Finger "+itos(sd.index); + } break; + case InputEvent::ACTION: { + + + List pinfo; + Globals::get_singleton()->get_property_list(&pinfo); + int index=1; + + text="No Action"; + for(List::Element *E=pinfo.front();E;E=E->next()) { + const PropertyInfo &pi=E->get(); + + if (!pi.name.begins_with("input/")) + continue; + + + if (filters[p_port].action.action==index) { + text="Action "+pi.name.substr(pi.name.find("/")+1,pi.name.length()); + break; + } + index++; + } + + if (filters[p_port].action.pressed) + text+=", Pressed"; + else + text+=", Released"; + + + } break; + } + + + + return text+" - "+itos(p_port); +} + +PropertyInfo VisualScriptInputFilter::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(Variant::INPUT_EVENT,"event"); +} + +PropertyInfo VisualScriptInputFilter::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(Variant::INPUT_EVENT,""); +} + + +String VisualScriptInputFilter::get_caption() const { + + return "InputFilter"; +} + +String VisualScriptInputFilter::get_text() const { + + return ""; +} + + + +bool VisualScriptInputFilter::_set(const StringName& p_name, const Variant& p_value) { + + if (p_name=="filter_count") { + filters.resize(p_value); + _change_notify(); + ports_changed_notify(); + return true; + } + + + if (String(p_name).begins_with("filter_")) { + + int idx = String(p_name).replace_first("filters_","").get_slice("/",0).to_int(); + + ERR_FAIL_INDEX_V(idx,filters.size(),false); + + String what = String(p_name).get_slice("/",1); + + + if (what=="type") { + filters[idx]=InputEvent(); + filters[idx].type=InputEvent::Type(int(p_value)); + if (filters[idx].type==InputEvent::JOYSTICK_MOTION) { + filters[idx].joy_motion.axis_value=0.5; //for treshold + } else if (filters[idx].type==InputEvent::KEY) { + filters[idx].key.pressed=true; //put these as true to make it more user friendly + } else if (filters[idx].type==InputEvent::MOUSE_BUTTON) { + filters[idx].mouse_button.pressed=true; + } else if (filters[idx].type==InputEvent::JOYSTICK_BUTTON) { + filters[idx].joy_button.pressed=true; + } else if (filters[idx].type==InputEvent::SCREEN_TOUCH) { + filters[idx].screen_touch.pressed=true; + } else if (filters[idx].type==InputEvent::ACTION) { + filters[idx].action.pressed=true; + } + _change_notify(); + ports_changed_notify(); + + return true; + } + if (what=="device") { + filters[idx].device=p_value; + ports_changed_notify(); + return true; + } + + switch(filters[idx].type) { + + case InputEvent::KEY: { + + if (what=="scancode") { + String sc = p_value; + if (sc==String()) { + filters[idx].key.scancode=0; + } else { + filters[idx].key.scancode=find_keycode(p_value); + } + + } else if (what=="unicode") { + + String uc = p_value; + + if (uc==String()) { + filters[idx].key.unicode=0; + } else { + filters[idx].key.unicode=uc[0]; + } + + } else if (what=="pressed") { + + filters[idx].key.pressed=p_value; + } else if (what=="echo") { + + filters[idx].key.echo=p_value; + + } else if (what=="mod_alt") { + filters[idx].key.mod.alt=p_value; + + } else if (what=="mod_shift") { + filters[idx].key.mod.shift=p_value; + + } else if (what=="mod_ctrl") { + filters[idx].key.mod.control=p_value; + + } else if (what=="mod_meta") { + filters[idx].key.mod.meta=p_value; + } else { + return false; + } + ports_changed_notify(); + + return true; + } break; + case InputEvent::MOUSE_MOTION: { + + + if (what=="button_mask") { + filters[idx].mouse_motion.button_mask=p_value; + + } else if (what=="mod_alt") { + filters[idx].mouse_motion.mod.alt=p_value; + + } else if (what=="mod_shift") { + filters[idx].mouse_motion.mod.shift=p_value; + + } else if (what=="mod_ctrl") { + filters[idx].mouse_motion.mod.control=p_value; + + } else if (what=="mod_meta") { + filters[idx].mouse_motion.mod.meta=p_value; + } else { + return false; + } + + ports_changed_notify(); + return true; + + } break; + case InputEvent::MOUSE_BUTTON: { + + if (what=="button_index") { + filters[idx].mouse_button.button_index=p_value; + } else if (what=="pressed") { + filters[idx].mouse_button.pressed=p_value; + } else if (what=="doubleclicked") { + filters[idx].mouse_button.doubleclick=p_value; + + } else if (what=="mod_alt") { + filters[idx].mouse_button.mod.alt=p_value; + + } else if (what=="mod_shift") { + filters[idx].mouse_button.mod.shift=p_value; + + } else if (what=="mod_ctrl") { + filters[idx].mouse_button.mod.control=p_value; + + } else if (what=="mod_meta") { + filters[idx].mouse_button.mod.meta=p_value; + } else { + return false; + } + ports_changed_notify(); + return true; + + } break; + case InputEvent::JOYSTICK_MOTION: { + + if (what=="axis") { + filters[idx].joy_motion.axis=int(p_value)<<1|filters[idx].joy_motion.axis; + } else if (what=="mode") { + filters[idx].joy_motion.axis|=int(p_value); + } else if (what=="treshold") { + filters[idx].joy_motion.axis_value=p_value; + } else { + return false; + } + ports_changed_notify(); + return true; + + + } break; + case InputEvent::JOYSTICK_BUTTON: { + + if (what=="button_index") { + filters[idx].joy_button.button_index=p_value; + } else if (what=="pressed") { + filters[idx].joy_button.pressed=p_value; + } else { + return false; + } + ports_changed_notify(); + return true; + + } break; + case InputEvent::SCREEN_TOUCH: { + + if (what=="finger_index") { + filters[idx].screen_touch.index=p_value; + } else if (what=="pressed") { + filters[idx].screen_touch.pressed=p_value; + } else { + return false; + } + ports_changed_notify(); + return true; + } break; + case InputEvent::SCREEN_DRAG: { + if (what=="finger_index") { + filters[idx].screen_drag.index=p_value; + } else { + return false; + } + ports_changed_notify(); + return true; + } break; + case InputEvent::ACTION: { + + + if (what=="action_name") { + + List pinfo; + Globals::get_singleton()->get_property_list(&pinfo); + int index=1; + + for(List::Element *E=pinfo.front();E;E=E->next()) { + const PropertyInfo &pi=E->get(); + + if (!pi.name.begins_with("input/")) + continue; + + String name = pi.name.substr(pi.name.find("/")+1,pi.name.length()); + if (name==String(p_value)) { + + filters[idx].action.action=index; + ports_changed_notify(); + return true; + } + + index++; + } + + filters[idx].action.action=0; + ports_changed_notify(); + + return false; + + } else if (what=="pressed") { + + filters[idx].action.pressed=p_value; + ports_changed_notify(); + return true; + } + + + } break; + + } + } + return false; +} + +bool VisualScriptInputFilter::_get(const StringName& p_name,Variant &r_ret) const{ + + if (p_name=="filter_count") { + r_ret=filters.size(); + return true; + } + + + if (String(p_name).begins_with("filter_")) { + + int idx = String(p_name).replace_first("filters_","").get_slice("/",0).to_int(); + + ERR_FAIL_INDEX_V(idx,filters.size(),false); + + String what = String(p_name).get_slice("/",1); + + + if (what=="type") { + r_ret=filters[idx].type; + return true; + } + if (what=="device") { + r_ret=filters[idx].device; + return true; + } + + switch(filters[idx].type) { + + case InputEvent::KEY: { + + if (what=="scancode") { + if (filters[idx].key.scancode==0) + r_ret=String(); + else { + + r_ret=keycode_get_string(filters[idx].key.scancode); + } + + } else if (what=="unicode") { + + + if (filters[idx].key.unicode==0) { + r_ret=String(); + } else { + CharType str[2]={ (CharType)filters[idx].key.unicode, 0}; + r_ret=String(str); + } + + } else if (what=="pressed") { + + r_ret=filters[idx].key.pressed; + } else if (what=="echo") { + + r_ret=filters[idx].key.echo; + + } else if (what=="mod_alt") { + r_ret=filters[idx].key.mod.alt; + + } else if (what=="mod_shift") { + r_ret=filters[idx].key.mod.shift; + + } else if (what=="mod_ctrl") { + r_ret=filters[idx].key.mod.control; + + } else if (what=="mod_meta") { + r_ret=filters[idx].key.mod.meta; + } else { + return false; + } + + return true; + } break; + case InputEvent::MOUSE_MOTION: { + + + if (what=="button_mask") { + r_ret=filters[idx].mouse_motion.button_mask; + + } else if (what=="mod_alt") { + r_ret=filters[idx].mouse_motion.mod.alt; + + } else if (what=="mod_shift") { + r_ret=filters[idx].mouse_motion.mod.shift; + + } else if (what=="mod_ctrl") { + r_ret=filters[idx].mouse_motion.mod.control; + + } else if (what=="mod_meta") { + r_ret=filters[idx].mouse_motion.mod.meta; + } else { + return false; + } + + return true; + + } break; + case InputEvent::MOUSE_BUTTON: { + + if (what=="button_index") { + r_ret=filters[idx].mouse_button.button_index; + } else if (what=="pressed") { + r_ret=filters[idx].mouse_button.pressed; + } else if (what=="doubleclicked") { + r_ret=filters[idx].mouse_button.doubleclick; + + } else if (what=="mod_alt") { + r_ret=filters[idx].mouse_button.mod.alt; + + } else if (what=="mod_shift") { + r_ret=filters[idx].mouse_button.mod.shift; + + } else if (what=="mod_ctrl") { + r_ret=filters[idx].mouse_button.mod.control; + + } else if (what=="mod_meta") { + r_ret=filters[idx].mouse_button.mod.meta; + } else { + return false; + } + return true; + + } break; + case InputEvent::JOYSTICK_MOTION: { + + if (what=="axis_index") { + r_ret=filters[idx].joy_motion.axis>>1; + } else if (what=="mode") { + r_ret=filters[idx].joy_motion.axis&1; + } else if (what=="treshold") { + r_ret=filters[idx].joy_motion.axis_value; + } else { + return false; + } + return true; + + + } break; + case InputEvent::JOYSTICK_BUTTON: { + + if (what=="button_index") { + r_ret=filters[idx].joy_button.button_index; + } else if (what=="pressed") { + r_ret=filters[idx].joy_button.pressed; + } else { + return false; + } + return true; + + } break; + case InputEvent::SCREEN_TOUCH: { + + if (what=="finger_index") { + r_ret=filters[idx].screen_touch.index; + } else if (what=="pressed") { + r_ret=filters[idx].screen_touch.pressed; + } else { + return false; + } + return true; + } break; + case InputEvent::SCREEN_DRAG: { + if (what=="finger_index") { + r_ret=filters[idx].screen_drag.index; + } else { + return false; + } + return true; + } break; + case InputEvent::ACTION: { + + + if (what=="action_name") { + + List pinfo; + Globals::get_singleton()->get_property_list(&pinfo); + int index=1; + + for(List::Element *E=pinfo.front();E;E=E->next()) { + const PropertyInfo &pi=E->get(); + + if (!pi.name.begins_with("input/")) + continue; + + + if (filters[idx].action.action==index) { + r_ret=pi.name.substr(pi.name.find("/")+1,pi.name.length()); + return true; + } + index++; + } + + r_ret="None"; //no index + return false; + + } else if (what=="pressed") { + + r_ret=filters[idx].action.pressed; + return true; + } + + + } break; + + } + } + return false; +} +void VisualScriptInputFilter::_get_property_list( List *p_list) const { + + p_list->push_back(PropertyInfo(Variant::INT,"filter_count",PROPERTY_HINT_RANGE,"0,64")); + + String et; + for(int i=0;i0) + et+=","; + + et+=event_type_names[i]; + } + + String kc; + String actions; + + + + for(int i=0;ipush_back(PropertyInfo(Variant::INT,base+"type",PROPERTY_HINT_ENUM,et)); + p_list->push_back(PropertyInfo(Variant::INT,base+"device")); + switch(filters[i].type) { + + case InputEvent::NONE: { + + } break; + case InputEvent::KEY: { + if (kc==String()) { + int kcc = keycode_get_count(); + kc="None"; + for(int i=0;ipush_back(PropertyInfo(Variant::STRING,base+"scancode",PROPERTY_HINT_ENUM,kc)); + p_list->push_back(PropertyInfo(Variant::STRING,base+"unicode")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"pressed")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"echo")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_alt")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_shift")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_ctrl")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_meta")); + + + } break; + case InputEvent::MOUSE_MOTION: { + p_list->push_back(PropertyInfo(Variant::INT,base+"button_mask",PROPERTY_HINT_FLAGS,"Left,Right,Middle,WheelUp,WheelDown,WheelLeft,WheelRight")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_alt")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_shift")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_ctrl")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_meta")); + + } break; + case InputEvent::MOUSE_BUTTON: { + p_list->push_back(PropertyInfo(Variant::INT,base+"button_index",PROPERTY_HINT_ENUM,"Any,Left,Right,Middle,WheelUp,WheelDown,WheelLeft,WheelRight")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"pressed")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"doubleclicked")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_alt")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_shift")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_ctrl")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"mod_meta")); + + } break; + case InputEvent::JOYSTICK_MOTION: { + + p_list->push_back(PropertyInfo(Variant::INT,base+"axis_index")); + p_list->push_back(PropertyInfo(Variant::INT,base+"mode",PROPERTY_HINT_ENUM,"Min,Max")); + p_list->push_back(PropertyInfo(Variant::REAL,base+"treshold",PROPERTY_HINT_RANGE,"0,1,0.01")); + } break; + case InputEvent::JOYSTICK_BUTTON: { + p_list->push_back(PropertyInfo(Variant::INT,base+"button_index")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"pressed")); + + } break; + case InputEvent::SCREEN_TOUCH: { + p_list->push_back(PropertyInfo(Variant::INT,base+"finger_index")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"pressed")); + + } break; + case InputEvent::SCREEN_DRAG: { + p_list->push_back(PropertyInfo(Variant::INT,base+"finger_index")); + } break; + case InputEvent::ACTION: { + + + + if (actions==String()) { + + actions="None"; + + List pinfo; + Globals::get_singleton()->get_property_list(&pinfo); + Vector al; + + for(List::Element *E=pinfo.front();E;E=E->next()) { + const PropertyInfo &pi=E->get(); + + if (!pi.name.begins_with("input/")) + continue; + + String name = pi.name.substr(pi.name.find("/")+1,pi.name.length()); + + + al.push_back(name); + } + + for(int i=0;ipush_back(PropertyInfo(Variant::STRING,base+"action_name",PROPERTY_HINT_ENUM,actions)); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"pressed")); + + } break; + + } + } +} + +class VisualScriptNodeInstanceInputFilter : public VisualScriptNodeInstance { +public: + + VisualScriptInstance* instance; + Vector filters; + + //virtual int get_working_memory_size() const { return 0; } + //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_inputs[0]->get_type()!=Variant::INPUT_EVENT) { + r_error_str="Input value not of type event"; + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + return 0; + } + + InputEvent event = *p_inputs[0]; + + + for(int i=0;i>1; + + if (axis==jm2.axis) { + + if (jm.axis&1) { + //greater + if (jm2.axis_value > jm.axis_value) { + match=true; + } + } else { + //less + if (jm2.axis_value < -jm.axis_value) { + match=true; + } + } + } + + + } break; + case InputEvent::JOYSTICK_BUTTON: { + InputEventJoystickButton jb = ie.joy_button; + InputEventJoystickButton jb2 = event.joy_button; + + if ( jb.button_index==jb2.button_index && + jb.pressed == jb2.pressed + ) { + match=true; + } + } break; + case InputEvent::SCREEN_TOUCH: { + InputEventScreenTouch st = ie.screen_touch; + InputEventScreenTouch st2 = event.screen_touch; + + if ( st.index==st2.index && + st.pressed==st2.pressed) { + match=true; + } + + } break; + case InputEvent::SCREEN_DRAG: { + InputEventScreenDrag sd = ie.screen_drag; + InputEventScreenDrag sd2 = event.screen_drag; + + if (sd.index==sd2.index) { + match=true; + } + } break; + case InputEvent::ACTION: { + + InputEventAction ia = ie.action; + InputEventAction ia2 = event.action; + + if ( ia.action==ia2.action && + ia.pressed==ia2.pressed) { + match=true; + } + } break; + + } + + *p_outputs[0] = event; + + if (match) + return i; //go through match output + + } + + return STEP_NO_ADVANCE_BIT; //none found, don't advance + + + } + + +}; + + +VisualScriptNodeInstance* VisualScriptInputFilter::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceInputFilter * instance = memnew(VisualScriptNodeInstanceInputFilter ); + instance->instance=p_instance; + instance->filters=filters; + return instance; +} + + + + +VisualScriptInputFilter::VisualScriptInputFilter() { + + +} + + + + void register_visual_script_flow_control_nodes() { VisualScriptLanguage::singleton->add_register_func("flow_control/return",create_return_node); @@ -599,5 +1670,9 @@ void register_visual_script_flow_control_nodes() { VisualScriptLanguage::singleton->add_register_func("flow_control/while",create_node_generic); VisualScriptLanguage::singleton->add_register_func("flow_control/iterator",create_node_generic); VisualScriptLanguage::singleton->add_register_func("flow_control/sequence",create_node_generic); + VisualScriptLanguage::singleton->add_register_func("flow_control/input_select",create_node_generic); + VisualScriptLanguage::singleton->add_register_func("flow_control/input_filter",create_node_generic); + + } diff --git a/modules/visual_script/visual_script_flow_control.h b/modules/visual_script/visual_script_flow_control.h index 49179fd934..ed0e328629 100644 --- a/modules/visual_script/visual_script_flow_control.h +++ b/modules/visual_script/visual_script_flow_control.h @@ -194,6 +194,85 @@ public: 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 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 *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(); diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index c7598c0eb0..4006dab4a5 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/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 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) { @@ -546,7 +546,7 @@ public: case VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE: { Variant v = *p_inputs[0]; - print_line("inputs: "+String(v)); + if (returns) { *p_outputs[0] = v.call(function,p_inputs+1,input_args,r_error); } else { @@ -598,6 +598,19 @@ static Ref create_function_call_node(const String& p_name) { ////////////////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 { return 1; @@ -671,7 +684,7 @@ int VisualScriptPropertySet::get_input_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 { @@ -702,9 +715,17 @@ PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const 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); + } else if (call_mode==CALL_MODE_NODE_PATH) { 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{ - - 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; } +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) { @@ -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 (call_mode!=CALL_MODE_NODE_PATH) { property.usage=0; @@ -941,7 +986,14 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo& property) const { 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 { + v = Variant::construct(basic_type,NULL,0,ce); + } v.get_property_list(&pinfo); } 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("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("get_property"),&VisualScriptPropertySet::get_property); @@ -1054,9 +1108,19 @@ void VisualScriptPropertySet::_bind_methods() { bt+=Variant::get_type_name(Variant::Type(i)); } + String et; + for(int i=0;i0) + 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::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/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::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")); @@ -1087,7 +1151,7 @@ public: //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,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) { @@ -1157,6 +1221,10 @@ public: r_error_str="Invalid index property name."; } + if (call_mode==VisualScriptPropertySet::CALL_MODE_BASIC_TYPE) { + *p_outputs[0]=v; + } + } break; } @@ -1185,6 +1253,7 @@ VisualScriptPropertySet::VisualScriptPropertySet() { call_mode=CALL_MODE_INSTANCE; base_type="Object"; 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) { - 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); } 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 { if (property.name=="property/base_type") { @@ -1474,6 +1565,11 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const { 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 (call_mode!=CALL_MODE_NODE_PATH) { @@ -1497,7 +1593,14 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const { 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 { + v = Variant::construct(basic_type,NULL,0,ce); + } v.get_property_list(&pinfo); } 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("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("get_property"),&VisualScriptPropertyGet::get_property); @@ -1565,10 +1671,19 @@ void VisualScriptPropertyGet::_bind_methods() { bt+=Variant::get_type_name(Variant::Type(i)); } + String et; + for(int i=0;i0) + 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::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/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::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; @@ -1685,6 +1800,7 @@ VisualScriptPropertyGet::VisualScriptPropertyGet() { call_mode=CALL_MODE_INSTANCE; base_type="Object"; 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 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) { @@ -2297,7 +2413,7 @@ public: //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,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(); @@ -2359,24 +2475,24 @@ static Ref create_basic_type_call_node(const String& p_name) { void register_visual_script_func_nodes() { - VisualScriptLanguage::singleton->add_register_func("functions/call_method/instance_call",create_function_call_node); - VisualScriptLanguage::singleton->add_register_func("functions/call_method/basic_type_call",create_function_call_node); - VisualScriptLanguage::singleton->add_register_func("functions/call_method/self_call",create_function_call_node); - VisualScriptLanguage::singleton->add_register_func("functions/call_method/node_call",create_function_call_node); + VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_instance",create_function_call_node); + VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_basic_type",create_function_call_node); + VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_self",create_function_call_node); + VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_node",create_function_call_node); - VisualScriptLanguage::singleton->add_register_func("functions/set_property/instace_set",create_property_set_node); - VisualScriptLanguage::singleton->add_register_func("functions/set_property/basic_type_set",create_property_set_node); - VisualScriptLanguage::singleton->add_register_func("functions/set_property/self_set",create_property_set_node); - VisualScriptLanguage::singleton->add_register_func("functions/set_property/node_set",create_property_set_node); + VisualScriptLanguage::singleton->add_register_func("functions/property_set/instace_set",create_property_set_node); + VisualScriptLanguage::singleton->add_register_func("functions/property_set/basic_type_set",create_property_set_node); + VisualScriptLanguage::singleton->add_register_func("functions/property_set/self_set",create_property_set_node); + VisualScriptLanguage::singleton->add_register_func("functions/property_set/node_set",create_property_set_node); - VisualScriptLanguage::singleton->add_register_func("functions/get_property/instance_get",create_property_get_node); - VisualScriptLanguage::singleton->add_register_func("functions/get_property/basic_type_get",create_property_get_node); - VisualScriptLanguage::singleton->add_register_func("functions/get_property/self_get",create_property_get_node); - VisualScriptLanguage::singleton->add_register_func("functions/get_property/node_get",create_property_get_node); + VisualScriptLanguage::singleton->add_register_func("functions/property_get/instance_get",create_property_get_node); + VisualScriptLanguage::singleton->add_register_func("functions/property_get/basic_type_get",create_property_get_node); + VisualScriptLanguage::singleton->add_register_func("functions/property_get/self_get",create_property_get_node); + VisualScriptLanguage::singleton->add_register_func("functions/property_get/node_get",create_property_get_node); - VisualScriptLanguage::singleton->add_register_func("functions/script/script_call",create_script_call_node); - VisualScriptLanguage::singleton->add_register_func("functions/script/script_call_in_node",create_script_call_node); - VisualScriptLanguage::singleton->add_register_func("functions/script/emit_signal",create_node_generic); + VisualScriptLanguage::singleton->add_register_func("functions/call_script/call_self",create_script_call_node); + VisualScriptLanguage::singleton->add_register_func("functions/call_script/call_node",create_script_call_node); + VisualScriptLanguage::singleton->add_register_func("functions/call_script/emit_signal",create_node_generic); for(int i=0;i::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); } } } diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h index 7ba573564c..2ccc61242a 100644 --- a/modules/visual_script/visual_script_func_nodes.h +++ b/modules/visual_script/visual_script_func_nodes.h @@ -93,12 +93,13 @@ public: private: CallMode call_mode; - Variant::Type basic_type; + Variant::Type basic_type; StringName base_type; NodePath base_path; StringName property; bool use_builtin_value; Variant builtin_value; + InputEvent::Type event_type; Node *_get_base_node() const; StringName _get_base_type() const; @@ -136,6 +137,9 @@ public: void set_basic_type(Variant::Type p_type); 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); StringName get_property() const; @@ -177,6 +181,7 @@ private: StringName base_type; NodePath base_path; StringName property; + InputEvent::Type event_type; void _update_base_type(); Node *_get_base_node() const; @@ -214,6 +219,9 @@ public: void set_basic_type(Variant::Type p_type); 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); StringName get_property() const; diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 8362cdd671..07be47c96f 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/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 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(); @@ -518,7 +518,7 @@ public: //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,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; 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; } @@ -825,7 +825,7 @@ public: 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,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) { 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; } @@ -1066,7 +1066,7 @@ public: //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 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; *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 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; *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; @@ -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; @@ -1508,7 +1508,7 @@ public: 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; @@ -1644,7 +1644,7 @@ public: 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; } @@ -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; @@ -1913,7 +1913,7 @@ public: 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; } @@ -1946,7 +1946,7 @@ VisualScriptResourcePath::VisualScriptResourcePath() { ////////////////////////////////////////// -////////////////RESPATH/////////// +////////////////SELF/////////// ////////////////////////////////////////// int VisualScriptSelf::get_output_sequence_port_count() const { @@ -2011,7 +2011,7 @@ public: 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; } diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index fe0092fd04..6630dbb04c 100644 --- a/modules/visual_script/visual_script_nodes.h +++ b/modules/visual_script/visual_script_nodes.h @@ -552,8 +552,6 @@ public: virtual String get_text() const; 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); @@ -561,6 +559,7 @@ public: }; + void register_visual_script_nodes(); #endif // VISUAL_SCRIPT_NODES_H diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp new file mode 100644 index 0000000000..a6f84a97d9 --- /dev/null +++ b/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(); + if (!tree) { + r_error_str="Main Loop is not SceneTree"; + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + return 0; + } + + Ref 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 +static Ref create_yield_node(const String& p_name) { + + Ref 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