diff options
author | Juan Linietsky <reduzio@gmail.com> | 2016-08-05 22:46:45 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2016-08-05 22:48:00 -0300 |
commit | 259418f8275371fc2f0bab6892caa4ef66b84240 (patch) | |
tree | 721e21ff566212918bf837f45c7687ce32213032 | |
parent | 6d5d23fa8de8673f4a2b312c05588fd4e7195543 (diff) |
VisualScript can now execute visual scripts, but there is no debugger or profiler yet.
27 files changed, 3324 insertions, 212 deletions
diff --git a/core/script_language.h b/core/script_language.h index 499dbe14a7..d1f82eff06 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -178,7 +178,7 @@ public: virtual void get_reserved_words(List<String> *p_words) const=0; virtual void get_comment_delimiters(List<String> *p_delimiters) const=0; virtual void get_string_delimiters(List<String> *p_delimiters) const=0; - virtual String get_template(const String& p_class_name, const String& p_base_class_name) const=0; + virtual Ref<Script> get_template(const String& p_class_name, const String& p_base_class_name) const=0; virtual bool validate(const String& p_script, int &r_line_error,int &r_col_error,String& r_test_error, const String& p_path="",List<String> *r_functions=NULL) const=0; virtual Script *create_script() const=0; virtual bool has_named_classes() const=0; diff --git a/methods.py b/methods.py index 74c282b8cf..e29fd760ba 100755 --- a/methods.py +++ b/methods.py @@ -1213,7 +1213,9 @@ def detect_modules(): register_cpp="" unregister_cpp="" - for x in glob.glob("modules/*"): + files = glob.glob("modules/*") + files.sort() #so register_module_types does not change that often, and also plugins are registered in alphabetic order + for x in files: if (not os.path.isdir(x)): continue x=x.replace("modules/","") # rest of world diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index b02e55cf9d..b3ab75b07c 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -44,7 +44,7 @@ void GDScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const { } -String GDScriptLanguage::get_template(const String& p_class_name, const String& p_base_class_name) const { +Ref<Script> GDScriptLanguage::get_template(const String& p_class_name, const String& p_base_class_name) const { String _template = String()+ "\nextends %BASE%\n\n"+ @@ -58,7 +58,14 @@ String GDScriptLanguage::get_template(const String& p_class_name, const String& "\n"+ "\n"; - return _template.replace("%BASE%",p_base_class_name); + _template = _template.replace("%BASE%",p_base_class_name); + + Ref<GDScript> script; + script.instance(); + script->set_source_code(_template); + + return script; + } diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h index 41c5c32e49..3634eb796e 100644 --- a/modules/gdscript/gd_script.h +++ b/modules/gdscript/gd_script.h @@ -375,7 +375,7 @@ public: virtual void get_reserved_words(List<String> *p_words) const; virtual void get_comment_delimiters(List<String> *p_delimiters) const; virtual void get_string_delimiters(List<String> *p_delimiters) const; - virtual String get_template(const String& p_class_name, const String& p_base_class_name) const; + virtual Ref<Script> get_template(const String& p_class_name, const String& p_base_class_name) const; virtual bool validate(const String& p_script,int &r_line_error,int &r_col_error,String& r_test_error, const String& p_path="",List<String> *r_functions=NULL) const; virtual Script *create_script() const; virtual bool has_named_classes() const; diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index da767c8447..08b0280ac4 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -46,7 +46,8 @@ void register_visual_script_types() { ObjectTypeDB::register_virtual_type<VisualScriptNode>(); ObjectTypeDB::register_type<VisualScriptFunction>(); ObjectTypeDB::register_type<VisualScriptOperator>(); - ObjectTypeDB::register_type<VisualScriptVariable>(); + ObjectTypeDB::register_type<VisualScriptVariableSet>(); + ObjectTypeDB::register_type<VisualScriptVariableGet>(); ObjectTypeDB::register_type<VisualScriptConstant>(); ObjectTypeDB::register_type<VisualScriptIndexGet>(); ObjectTypeDB::register_type<VisualScriptIndexSet>(); @@ -56,6 +57,7 @@ void register_visual_script_types() { ObjectTypeDB::register_type<VisualScriptSceneNode>(); ObjectTypeDB::register_type<VisualScriptSceneTree>(); ObjectTypeDB::register_type<VisualScriptResourcePath>(); + ObjectTypeDB::register_type<VisualScriptSelf>(); ObjectTypeDB::register_type<VisualScriptFunctionCall>(); ObjectTypeDB::register_type<VisualScriptPropertySet>(); diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 6f18bcfaee..5fc5e8a9fc 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -1,6 +1,7 @@ #include "visual_script.h" #include "visual_script_nodes.h" +#define SCRIPT_VARIABLES_PREFIX "script_variables/" void VisualScriptNode::_notification(int p_what) { @@ -99,12 +100,31 @@ Ref<VisualScript> VisualScriptNode::get_visual_script() const { ///////////////////// +VisualScriptNodeInstance::VisualScriptNodeInstance() { + + sequence_outputs=NULL; + input_ports=NULL; +} + VisualScriptNodeInstance::~VisualScriptNodeInstance() { + if (sequence_outputs) { + memdelete(sequence_outputs); + } + + if (input_ports) { + memdelete(input_ports); + } + + if (output_ports) { + memdelete(output_ports); + } + } void VisualScript::add_function(const StringName& p_name) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!String(p_name).is_valid_identifier()); ERR_FAIL_COND(functions.has(p_name)); @@ -118,6 +138,7 @@ bool VisualScript::has_function(const StringName& p_name) const { } void VisualScript::remove_function(const StringName& p_name) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!functions.has(p_name)); for (Map<int,Function::NodeData>::Element *E=functions[p_name].nodes.front();E;E=E->next()) { @@ -132,6 +153,7 @@ void VisualScript::remove_function(const StringName& p_name) { void VisualScript::rename_function(const StringName& p_name,const StringName& p_new_name) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!functions.has(p_name)); if (p_new_name==p_name) return; @@ -231,6 +253,7 @@ void VisualScript::_node_ports_changed(int p_id) { void VisualScript::add_node(const StringName& p_func,int p_id, const Ref<VisualScriptNode>& p_node, const Point2 &p_pos) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!functions.has(p_func)); @@ -265,6 +288,7 @@ void VisualScript::add_node(const StringName& p_func,int p_id, const Ref<VisualS void VisualScript::remove_node(const StringName& p_func,int p_id){ + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!functions.has(p_func)); Function &func = functions[p_func]; @@ -327,6 +351,7 @@ Ref<VisualScriptNode> VisualScript::get_node(const StringName& p_func,int p_id) void VisualScript::set_node_pos(const StringName& p_func,int p_id,const Point2& p_pos) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!functions.has(p_func)); Function &func = functions[p_func]; @@ -358,6 +383,7 @@ void VisualScript::get_node_list(const StringName& p_func,List<int> *r_nodes) co void VisualScript::sequence_connect(const StringName& p_func,int p_from_node,int p_from_output,int p_to_node){ + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!functions.has(p_func)); Function &func = functions[p_func]; @@ -413,6 +439,7 @@ void VisualScript::get_sequence_connection_list(const StringName& p_func,List<Se void VisualScript::data_connect(const StringName& p_func,int p_from_node,int p_from_port,int p_to_node,int p_to_port) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!functions.has(p_func)); Function &func = functions[p_func]; @@ -484,6 +511,7 @@ void VisualScript::get_data_connection_list(const StringName& p_func,List<DataCo void VisualScript::add_variable(const StringName& p_name,const Variant& p_default_value) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!String(p_name).is_valid_identifier()); ERR_FAIL_COND(variables.has(p_name)); @@ -494,6 +522,12 @@ void VisualScript::add_variable(const StringName& p_name,const Variant& p_defaul v.info.hint=PROPERTY_HINT_NONE; variables[p_name]=v; + script_variable_remap[SCRIPT_VARIABLES_PREFIX+String(p_name)]=p_name; + + +#ifdef TOOLS_ENABLED + _update_placeholders(); +#endif } @@ -506,6 +540,11 @@ void VisualScript::remove_variable(const StringName& p_name) { ERR_FAIL_COND(!variables.has(p_name)); variables.erase(p_name); + script_variable_remap.erase(SCRIPT_VARIABLES_PREFIX+String(p_name)); + +#ifdef TOOLS_ENABLED + _update_placeholders(); +#endif } void VisualScript::set_variable_default_value(const StringName& p_name,const Variant& p_value){ @@ -514,6 +553,10 @@ void VisualScript::set_variable_default_value(const StringName& p_name,const Var variables[p_name].default_value=p_value; +#ifdef TOOLS_ENABLED + _update_placeholders(); +#endif + } Variant VisualScript::get_variable_default_value(const StringName& p_name) const{ @@ -523,10 +566,15 @@ Variant VisualScript::get_variable_default_value(const StringName& p_name) const } void VisualScript::set_variable_info(const StringName& p_name,const PropertyInfo& p_info){ + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!variables.has(p_name)); variables[p_name].info=p_info; variables[p_name].info.name=p_name; +#ifdef TOOLS_ENABLED + _update_placeholders(); +#endif + } PropertyInfo VisualScript::get_variable_info(const StringName& p_name) const{ @@ -578,12 +626,14 @@ void VisualScript::get_variable_list(List<StringName> *r_variables){ void VisualScript::set_instance_base_type(const StringName& p_type) { + ERR_FAIL_COND( instances.size() ); base_type=p_type; } void VisualScript::rename_variable(const StringName& p_name,const StringName& p_new_name) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!variables.has(p_name)); if (p_new_name==p_name) return; @@ -601,6 +651,7 @@ void VisualScript::rename_variable(const StringName& p_name,const StringName& p_ void VisualScript::add_custom_signal(const StringName& p_name) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!String(p_name).is_valid_identifier()); ERR_FAIL_COND(custom_signals.has(p_name)); @@ -614,6 +665,7 @@ bool VisualScript::has_custom_signal(const StringName& p_name) const { } void VisualScript::custom_signal_add_argument(const StringName& p_func,Variant::Type p_type,const String& p_name,int p_index) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!custom_signals.has(p_func)); Argument arg; arg.type=p_type; @@ -626,6 +678,7 @@ void VisualScript::custom_signal_add_argument(const StringName& p_func,Variant:: } void VisualScript::custom_signal_set_argument_type(const StringName& p_func,int p_argidx,Variant::Type p_type) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!custom_signals.has(p_func)); ERR_FAIL_INDEX(p_argidx,custom_signals[p_func].size()); custom_signals[p_func][p_argidx].type=p_type; @@ -637,6 +690,7 @@ Variant::Type VisualScript::custom_signal_get_argument_type(const StringName& p_ return custom_signals[p_func][p_argidx].type; } void VisualScript::custom_signal_set_argument_name(const StringName& p_func,int p_argidx,const String& p_name) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!custom_signals.has(p_func)); ERR_FAIL_INDEX(p_argidx,custom_signals[p_func].size()); custom_signals[p_func][p_argidx].name=p_name; @@ -651,6 +705,7 @@ String VisualScript::custom_signal_get_argument_name(const StringName& p_func,in } void VisualScript::custom_signal_remove_argument(const StringName& p_func,int p_argidx) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!custom_signals.has(p_func)); ERR_FAIL_INDEX(p_argidx,custom_signals[p_func].size()); custom_signals[p_func].remove(p_argidx); @@ -665,6 +720,7 @@ int VisualScript::custom_signal_get_argument_count(const StringName& p_func) con } void VisualScript::custom_signal_swap_argument(const StringName& p_func,int p_argidx,int p_with_argidx) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!custom_signals.has(p_func)); ERR_FAIL_INDEX(p_argidx,custom_signals[p_func].size()); ERR_FAIL_INDEX(p_with_argidx,custom_signals[p_func].size()); @@ -674,6 +730,7 @@ void VisualScript::custom_signal_swap_argument(const StringName& p_func,int p_ar } void VisualScript::remove_custom_signal(const StringName& p_name) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!custom_signals.has(p_name)); custom_signals.erase(p_name); @@ -681,6 +738,7 @@ void VisualScript::remove_custom_signal(const StringName& p_name) { void VisualScript::rename_custom_signal(const StringName& p_name,const StringName& p_new_name) { + ERR_FAIL_COND( instances.size() ); ERR_FAIL_COND(!custom_signals.has(p_name)); if (p_new_name==p_name) return; @@ -725,7 +783,7 @@ int VisualScript::get_available_id() const { bool VisualScript::can_instance() const { - return ScriptServer::is_scripting_enabled(); + return true;//ScriptServer::is_scripting_enabled(); } @@ -735,14 +793,88 @@ StringName VisualScript::get_instance_base_type() const { return base_type; } + +#ifdef TOOLS_ENABLED +void VisualScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) { + + + placeholders.erase(p_placeholder); +} + + +void VisualScript::_update_placeholders() { + + if (placeholders.size()==0) + return; //no bother if no placeholders + List<PropertyInfo> pinfo; + Map<StringName,Variant> values; + + for (Map<StringName,Variable>::Element *E=variables.front();E;E=E->next()) { + + PropertyInfo p = E->get().info; + p.name=SCRIPT_VARIABLES_PREFIX+String(E->key()); + pinfo.push_back(p); + values[p.name]=E->get().default_value; + } + + for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) { + + E->get()->update(pinfo,values); + } + +} + +#endif + + ScriptInstance* VisualScript::instance_create(Object *p_this) { - return NULL; + + +#ifdef TOOLS_ENABLED + + if (!ScriptServer::is_scripting_enabled()) { + + + PlaceHolderScriptInstance *sins = memnew( PlaceHolderScriptInstance(VisualScriptLanguage::singleton,Ref<Script>((Script*)this),p_this)); + placeholders.insert(sins); + + List<PropertyInfo> pinfo; + Map<StringName,Variant> values; + + for (Map<StringName,Variable>::Element *E=variables.front();E;E=E->next()) { + + PropertyInfo p = E->get().info; + p.name=SCRIPT_VARIABLES_PREFIX+String(E->key()); + pinfo.push_back(p); + values[p.name]=E->get().default_value; + } + + sins->update(pinfo,values); + + return sins; + } +#endif + + + VisualScriptInstance *instance=memnew( VisualScriptInstance ); + instance->create(Ref<VisualScript>(this),p_this); + + + if (VisualScriptLanguage::singleton->lock) + VisualScriptLanguage::singleton->lock->lock(); + + instances[p_this]=instance; + + if (VisualScriptLanguage::singleton->lock) + VisualScriptLanguage::singleton->lock->unlock(); + + return instance; } bool VisualScript::instance_has(const Object *p_this) const { - return false; + return instances.has((Object*)p_this); } bool VisualScript::has_source_code() const { @@ -785,17 +917,37 @@ ScriptLanguage *VisualScript::get_language() const { bool VisualScript::has_script_signal(const StringName& p_signal) const { - return false; + return custom_signals.has(p_signal); } void VisualScript::get_script_signal_list(List<MethodInfo> *r_signals) const { + for (const Map<StringName,Vector<Argument> >::Element *E=custom_signals.front();E;E=E->next()) { + + MethodInfo mi; + mi.name=E->key(); + for(int i=0;i<E->get().size();i++) { + PropertyInfo arg; + arg.type=E->get()[i].type; + arg.name=E->get()[i].name; + mi.arguments.push_back(arg); + } + + + r_signals->push_back(mi); + } + + } bool VisualScript::get_property_default_value(const StringName& p_property,Variant& r_value) const { - return false; + if (!script_variable_remap.has(p_property)) + return false; + + r_value=variables[ script_variable_remap[p_property] ].default_value; + return true; } void VisualScript::get_method_list(List<MethodInfo> *p_list) const { @@ -832,8 +984,11 @@ void VisualScript::_set_data(const Dictionary& p_data) { for (int i=0;i<vars.size();i++) { Dictionary v=vars[i]; - add_variable(v["name"],v["default_value"]); - _set_variable_info(v["name"],v); + StringName name = v["name"]; + add_variable(name); + _set_variable_info(name,v); + set_variable_default_value(name,v["default_value"]); + } @@ -1058,6 +1213,690 @@ VisualScript::~VisualScript() { //////////////////////////////////////////// + +bool VisualScriptInstance::set(const StringName& p_name, const Variant& p_value) { + + const Map<StringName,StringName>::Element *remap = script->script_variable_remap.find(p_name); + if (!remap) + return false; + + Map<StringName,Variant>::Element *E=variables.find(remap->get()); + ERR_FAIL_COND_V(!E,false); + + E->get()=p_value; + + return true; +} + + +bool VisualScriptInstance::get(const StringName& p_name, Variant &r_ret) const { + + const Map<StringName,StringName>::Element *remap = script->script_variable_remap.find(p_name); + if (!remap) + return false; + + const Map<StringName,Variant>::Element *E=variables.find(remap->get()); + ERR_FAIL_COND_V(!E,false); + + return E->get(); +} +void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const{ + + for (const Map<StringName,VisualScript::Variable>::Element *E=script->variables.front();E;E=E->next()) { + + PropertyInfo p = E->get().info; + p.name=SCRIPT_VARIABLES_PREFIX+String(E->key()); + p_properties->push_back(p); + + } +} +Variant::Type VisualScriptInstance::get_property_type(const StringName& p_name,bool *r_is_valid) const{ + + const Map<StringName,StringName>::Element *remap = script->script_variable_remap.find(p_name); + if (!remap) { + if (r_is_valid) + *r_is_valid=false; + return Variant::NIL; + } + + const Map<StringName,VisualScript::Variable>::Element *E=script->variables.find(remap->get()); + if (!E) { + if (r_is_valid) + *r_is_valid=false; + ERR_FAIL_V(Variant::NIL); + } + + if (r_is_valid) + *r_is_valid=true; + + return E->get().info.type; + +} + +void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const{ + + for (const Map<StringName,VisualScript::Function>::Element *E=script->functions.front();E;E=E->next()) { + + MethodInfo mi; + mi.name=E->key(); + if (E->get().function_id>=0 && E->get().nodes.has(E->get().function_id)) { + + Ref<VisualScriptFunction> vsf = E->get().nodes[E->get().function_id].node; + if (vsf.is_valid()) { + + for(int i=0;i<vsf->get_argument_count();i++) { + PropertyInfo arg; + arg.name=vsf->get_argument_name(i); + arg.type=vsf->get_argument_type(i); + + mi.arguments.push_back(arg); + } + + //vsf->Get_ for now at least it does not return.. + } + } + + p_list->push_back(mi); + } + +} +bool VisualScriptInstance::has_method(const StringName& p_method) const{ + + return script->functions.has(p_method); +} + + +//#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 + + 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(); + + 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; + + bool error=false; + int current_node_id; + Variant return_value; + + + while(true) { + + current_node_id=node->get_id(); + + VSDEBUG("==========AT NODE: "+itos(current_node_id)+" base: "+node->get_base_node()->get_type()); + VSDEBUG("AT STACK POS: "+itos(flow_stack_pos)); + + + //setup working mem + Variant *working_mem=node->working_mem_idx>=0 ? &variant_stack[node->working_mem_idx] : (Variant*)NULL; + + VSDEBUG("WORKING MEM: "+itos(node->working_mem_idx)); + + if (current_node_id==f->node) { + //if function node, set up function arguments from begining of stack + + for(int i=0;i<f->argument_count;i++) { + input_args[i]=&variant_stack[i]; + } + } else { + //setup input pointers normally + VSDEBUG("INPUT PORTS: "+itos(node->input_port_count)); + + for(int i=0 ; i<node->input_port_count ; i++) { + + + int index = node->input_ports[i] & VisualScriptNodeInstance::INPUT_MASK; + + if (node->input_ports[i] & VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT) { + //is a default value (unassigned input port) + input_args[i]=&default_values[index]; + VSDEBUG("\tPORT "+itos(i)+" DEFAULT VAL"); + } else if (node->input_ports[i] & VisualScriptNodeInstance::INPUT_UNSEQUENCED_READ_BIT) { + //from a node that requires read + Function::UnsequencedGet *ug = &f->unsequenced_gets[index]; + + bool ok = ug->from->get_output_port_unsequenced(i,&variant_stack[ug->to_stack],working_mem,error_str); + if (!ok) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + current_node_id=ug->from->get_id(); + error=true; + break; + } + + VSDEBUG("\tPORT "+itos(i)+" UNSEQ READ TO STACK: " + itos(ug->to_stack)); + input_args[i]=&variant_stack[ug->to_stack]; + } else { + //regular temporary in stack + input_args[i]=&variant_stack[index]; + VSDEBUG("PORT "+itos(i)+" AT STACK "+itos(index)); + + } + } + } + + if (error) + break; + + //setup output pointers + + VSDEBUG("OUTPUT PORTS: "+itos(node->output_port_count)); + for(int i=0 ; i<node->output_port_count ; i++) { + output_args[i] = &variant_stack[ node->output_ports[i] ]; + VSDEBUG("PORT "+itos(i)+" AT STACK "+itos(node->output_ports[i])); + } + + //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 + + VSDEBUG("STEP - STARTSEQ: "+itos(start_sequence)); + + int ret = node->step(input_args,output_args,start_sequence,working_mem,r_error,error_str); + + if (r_error.error!=Variant::CallError::CALL_OK) { + //use error from step + error=true; + break; + } + + int output = ret & VisualScriptNodeInstance::STEP_MASK; + + VSDEBUG("STEP RETURN: "+itos(ret)); + + if (ret & VisualScriptNodeInstance::STEP_EXIT_FUNCTION_BIT) { + if (node->get_working_memory_size()==0) { + + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + error_str=RTR("Return value must be assigned to first element of node working memory! Fix your node please."); + error=true; + } else { + //assign from working memory, first element + return_value=*working_mem; + } + + VSDEBUG("EXITING FUNCTION - VALUE "+String(return_value)); + break; //exit function requested, bye + } + + VisualScriptNodeInstance *next=NULL; //next node + + if ( (ret==output || ret&VisualScriptNodeInstance::STEP_FLAG_PUSH_STACK_BIT) && node->sequence_output_count) { + //if no exit bit was set, and has sequence outputs, guess next node + if (output<0 || output>=node->sequence_output_count) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + error_str=RTR("Node returned an invalid sequence output: ")+itos(output); + error=true; + break; + } + + next = node->sequence_outputs[output]; + if (next) + VSDEBUG("GOT NEXT NODE - "+itos(next->get_id())); + else + VSDEBUG("GOT NEXT NODE - NULL"); + } + + if (flow_stack) { + + //update flow stack pos (may have changed) + flow_stack[flow_stack_pos] = current_node_id; + + //add stack push bit if requested + if (ret & VisualScriptNodeInstance::STEP_FLAG_PUSH_STACK_BIT) { + + flow_stack[flow_stack_pos] |= VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT; + sequence_bits[ node ->sequence_index ]=true; //remember sequence bit + VSDEBUG("NEXT SEQ - FLAG BIT"); + } else { + sequence_bits[ node ->sequence_index ]=false; //forget sequence bit + VSDEBUG("NEXT SEQ - NORMAL"); + } + + + if (ret & VisualScriptNodeInstance::STEP_FLAG_GO_BACK_BIT) { + //go back request + + if (flow_stack_pos>0) { + flow_stack_pos--; + node = instances[ flow_stack[flow_stack_pos] & VisualScriptNodeInstance::FLOW_STACK_MASK ]; + VSDEBUG("NEXT IS GO BACK"); + } else { + VSDEBUG("NEXT IS GO BACK, BUT NO NEXT SO EXIT"); + break; //simply exit without value or error + } + } else if (next) { + + + if (sequence_bits[next->sequence_index]) { + // what happened here is that we are entering a node that is in the middle of doing a sequence (pushed stack) from the front + // because each node has a working memory, we can't really do a sub-sequence + // as a result, the sequence will be restarted and the stack will roll back to find where this node + // started the sequence + + bool found = false; + + for(int i=flow_stack_pos;i>=0;i--) { + + + if ( (flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_MASK ) == next->get_id() ) { + flow_stack_pos=i; //roll back and remove bit + flow_stack[i]=next->get_id(); + sequence_bits[next->sequence_index]=false; + found=true; + } + } + + if (!found) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + error_str=RTR("Found sequence bit but not the node in the stack, report bug!"); + error=true; + break; + } + + VSDEBUG("RE-ENTERED A LOOP, RETURNED STACK POS TO - "+itos(flow_stack_pos)); + + } else { + // check for stack overflow + if (flow_stack_pos+1 >= flow_max) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + error_str=RTR("Stack overflow with stack depth: ")+itos(output); + error=true; + break; + } + + node = next; + + flow_stack_pos++; + flow_stack[flow_stack_pos]=node->get_id(); + + VSDEBUG("INCREASE FLOW STACK"); + + } + + } else { + //no next node, try to go back in stack to pushed bit + + bool found = false; + + for(int i=flow_stack_pos;i>=0;i--) { + + VSDEBUG("FS "+itos(i)+" - "+itos(flow_stack[i])); + if (flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT) { + + node = instances[ flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_MASK ]; + flow_stack_pos=i; + found=true; + } + } + + if (!found) { + VSDEBUG("NO NEXT NODE, NO GO BACK, EXITING"); + break; //done, couldn't find a push stack bit + } + + VSDEBUG("NO NEXT NODE, GO BACK TO: "+itos(flow_stack_pos)); + + } + } else { + + node=next; //stackless mode, simply assign next node + } + + } + + + + if (error) { + + //error + // function, file, line, error, explanation + String err_file = script->get_path(); + String err_func = p_method; + int err_line=current_node_id; //not a line but it works as one + + + //if (!GDScriptLanguage::get_singleton()->debug_break(err_text,false)) { + // debugger break did not happen + + VSDEBUG("ERRSTR: "+error_str); + _err_print_error(err_func.utf8().get_data(),err_file.utf8().get_data(),err_line,error_str.utf8().get_data(),ERR_HANDLER_SCRIPT); + + //} + } else { + + + //return_value= + } + + + //clean up variant stack + for(int i=0;i<f->max_stack;i++) { + variant_stack[i].~Variant(); + } + + + return return_value; +} + +void VisualScriptInstance::notification(int p_notification){ + + //do nothing as this is called using virtual + + Variant what=p_notification; + const Variant*whatp=&what; + Variant::CallError ce; + call(VisualScriptLanguage::singleton->notification,&whatp,1,ce); //do as call + +} + +Ref<Script> VisualScriptInstance::get_script() const{ + + return script; +} + + +void VisualScriptInstance::create(const Ref<VisualScript>& p_script,Object *p_owner) { + + script=p_script; + owner=p_owner; + + max_input_args = 0; + max_output_args = 0; + + for(const Map<StringName,VisualScript::Variable>::Element *E=script->variables.front();E;E=E->next()) { + variables[E->key()]=E->get().default_value; + } + + + for(const Map<StringName,VisualScript::Function>::Element *E=script->functions.front();E;E=E->next()) { + + Function function; + function.node=E->get().function_id; + function.max_stack=0; + function.flow_stack_size=0; + function.node_count=0; + + if (function.node<0) { + //@todo break debugger + + ERR_CONTINUE( function.node < 0 ); + } + + { + Ref<VisualScriptFunction> func_node = script->get_node(E->key(),E->get().function_id); + + //@todo break debugger + ERR_CONTINUE( !func_node.is_valid() ); + + function.argument_count=func_node->get_argument_count(); + function.max_stack+=function.argument_count; + function.flow_stack_size= func_node->is_stack_less() ? 0 : func_node->get_stack_size(); + + } + + //multiple passes are required to set up this complex thing.. + + + + + //first create the nodes + for (const Map<int,VisualScript::Function::NodeData>::Element *F=E->get().nodes.front();F;F=F->next()) { + + Ref<VisualScriptNode> node = F->get().node; + VisualScriptNodeInstance *instance = node->instance(this); //create instance + ERR_FAIL_COND(!instance); + + instance->base=node.ptr(); + + instance->id=F->key(); + instance->input_port_count = node->get_input_value_port_count(); + instance->output_port_count = node->get_output_value_port_count(); + instance->sequence_output_count = node->get_output_sequence_port_count(); + instance->sequence_index=function.node_count++; + + if (instance->input_port_count) { + instance->input_ports = memnew_arr(int,instance->input_port_count); + for(int i=0;i<instance->input_port_count;i++) { + instance->input_ports[i]=-1; //if not assigned, will become default value + } + } + + if (instance->output_port_count) { + instance->output_ports = memnew_arr(int,instance->output_port_count); + for(int i=0;i<instance->output_port_count;i++) { + instance->output_ports[i]=-1; //if not assigned, will output to trash + } + } + + if (instance->sequence_output_count) { + instance->sequence_outputs = memnew_arr(VisualScriptNodeInstance*,instance->sequence_output_count); + for(int i=0;i<instance->sequence_output_count;i++) { + instance->sequence_outputs[i]=NULL; //if it remains null, flow ends here + } + } + + if (instance->get_working_memory_size()) { + instance->working_mem_idx = function.max_stack; + function.max_stack+=instance->get_working_memory_size(); + } else { + instance->working_mem_idx=-1; //no working mem + } + + max_input_args = MAX( max_input_args, instance->input_port_count ); + max_output_args = MAX( max_output_args, instance->output_port_count ); + + instances[F->key()]=instance; + + + } + + function.trash_pos = function.max_stack++; //create pos for trash + + //second pass, do data connections + + for(const Set<VisualScript::DataConnection>::Element *F=E->get().data_connections.front();F;F=F->next()) { + + VisualScript::DataConnection dc = F->get(); + ERR_CONTINUE(!instances.has(dc.from_node)); + VisualScriptNodeInstance *from = instances[dc.from_node]; + ERR_CONTINUE(!instances.has(dc.to_node)); + VisualScriptNodeInstance *to = instances[dc.to_node]; + ERR_CONTINUE(dc.from_port >= from->output_port_count); + ERR_CONTINUE(dc.to_port >= to->input_port_count); + + if (from->output_ports[dc.from_port]==-1) { + + int stack_pos = function.max_stack++; + from->output_ports[dc.from_port] = stack_pos; + } + + + if (from->is_output_port_unsequenced(dc.from_node)) { + + //prepare an unsequenced read (must actually get the value from the output) + int stack_pos = function.max_stack++; + + Function::UnsequencedGet uget; + uget.from=from; + uget.from_port=dc.from_port; + uget.to_stack=stack_pos; + + to->input_ports[dc.to_port] = function.unsequenced_gets.size() | VisualScriptNodeInstance::INPUT_UNSEQUENCED_READ_BIT; + function.unsequenced_gets.push_back(uget); + + } else { + + to->input_ports[dc.to_port] = from->output_ports[dc.from_port]; //read from wherever the stack is + } + + } + + //third pass, do sequence connections + + for(const Set<VisualScript::SequenceConnection>::Element *F=E->get().sequence_connections.front();F;F=F->next()) { + + VisualScript::SequenceConnection sc = F->get(); + ERR_CONTINUE(!instances.has(sc.from_node)); + VisualScriptNodeInstance *from = instances[sc.from_node]; + ERR_CONTINUE(!instances.has(sc.to_node)); + VisualScriptNodeInstance *to = instances[sc.to_node]; + ERR_CONTINUE(sc.from_output >= from->sequence_output_count); + + from->sequence_outputs[sc.from_output]=to; + + } + + //fourth pass: + // 1) unassigned input ports to default values + // 2) connect unassigned output ports to trash + + + for (const Map<int,VisualScript::Function::NodeData>::Element *F=E->get().nodes.front();F;F=F->next()) { + + ERR_CONTINUE(!instances.has(F->key())); + + Ref<VisualScriptNode> node = F->get().node; + VisualScriptNodeInstance *instance = instances[F->key()]; + + // conect to default values + for(int i=0;i<instance->input_port_count;i++) { + if (instance->input_ports[i]==-1) { + + //unassigned, connect to default val + instance->input_ports[i] = default_values.size() | VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT; + default_values.push_back( node->get_default_input_value(i) ); + } + } + + // conect to trash + for(int i=0;i<instance->output_port_count;i++) { + if (instance->output_ports[i]==-1) { + instance->output_ports[i] = function.trash_pos; //trash is same for all + } + } + } + + + functions[E->key()]=function; + } +} + +ScriptLanguage *VisualScriptInstance::get_language(){ + + return VisualScriptLanguage::singleton; +} + + +VisualScriptInstance::VisualScriptInstance() { + + +} + +VisualScriptInstance::~VisualScriptInstance() { + + if (VisualScriptLanguage::singleton->lock) + VisualScriptLanguage::singleton->lock->lock(); + + script->instances.erase(owner); + + if (VisualScriptLanguage::singleton->lock) + VisualScriptLanguage::singleton->lock->unlock(); + + for (Map<int,VisualScriptNodeInstance*>::Element *E=instances.front();E;E=E->next()) { + memdelete(E->get()); + } +} + + + + + + + + + +/////////////////////////////////////////////// + String VisualScriptLanguage::get_name() const { return "VisualScript"; @@ -1098,9 +1937,12 @@ void VisualScriptLanguage::get_string_delimiters(List<String> *p_delimiters) con } -String VisualScriptLanguage::get_template(const String& p_class_name, const String& p_base_class_name) const { +Ref<Script> VisualScriptLanguage::get_template(const String& p_class_name, const String& p_base_class_name) const { - return String(); + Ref<VisualScript> script; + script.instance(); + script->set_instance_base_type(p_base_class_name); + return script; } bool VisualScriptLanguage::validate(const String& p_script, int &r_line_error,int &r_col_error,String& r_test_error, const String& p_path,List<String> *r_functions) const { @@ -1243,5 +2085,15 @@ void VisualScriptLanguage::get_registered_node_names(List<String> *r_names) { VisualScriptLanguage::VisualScriptLanguage() { + notification="_notification"; singleton=this; +#ifndef NO_THREADS + lock = Mutex::create(); +#endif +} + +VisualScriptLanguage::~VisualScriptLanguage() { + + if (lock) + memdelete(lock); } diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index 26daddbba6..c606604649 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -4,7 +4,7 @@ #include "script_language.h" -class VScriptInstance; +class VisualScriptInstance; class VisualScriptNodeInstance; class VisualScript; @@ -45,22 +45,69 @@ public: virtual String get_caption() const=0; virtual String get_text() const=0; + virtual String get_category() const=0; - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance)=0; + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance)=0; }; class VisualScriptNodeInstance { +friend class VisualScriptInstance; + + + + enum { //input argument addressing + INPUT_SHIFT=1<<24, + INPUT_MASK=INPUT_SHIFT-1, + INPUT_DEFAULT_VALUE_BIT=INPUT_SHIFT, // from unassigned input port, using default value (edited by user) + INPUT_UNSEQUENCED_READ_BIT=INPUT_SHIFT<<1, //from unsequenced read (requires calling a function, used for constants, variales, etc). + }; + + + int id; + int sequence_index; + VisualScriptNodeInstance **sequence_outputs; + int sequence_output_count; + int *input_ports; + int input_port_count; + int *output_ports; + int output_port_count; + int working_mem_idx; + + VisualScriptNode *base; + public: - virtual int step()=0; //do a step, return which sequence port to go out + enum { + STEP_SHIFT=1<<24, + STEP_MASK=STEP_SHIFT-1, + 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_EXIT_FUNCTION_BIT=STEP_SHIFT<<2, //return from function + + 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 + + }; + + _FORCE_INLINE_ int get_input_port_count() const { return input_port_count; } + _FORCE_INLINE_ int get_output_port_count() const { return output_port_count; } + _FORCE_INLINE_ int get_sequence_output_count() const { return sequence_output_count; } + + _FORCE_INLINE_ int get_id() const { return id; } + + virtual int get_working_memory_size() const { return 0; } - virtual Variant get_input_value(int p_idx)=0; - virtual Variant get_output_value(int p_idx)=0; + //unsequenced ports are those that can return a value even if no sequence happened through them, used for constants, variables, etc. + 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 VisualScriptNode* get_node()=0; + 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 + Ref<VisualScriptNode> get_base_node() { return Ref<VisualScriptNode>( base ); } + + VisualScriptNodeInstance(); virtual ~VisualScriptNodeInstance(); }; @@ -112,6 +159,7 @@ public: private: +friend class VisualScriptInstance; StringName base_type; struct Argument { @@ -133,6 +181,7 @@ private: int function_id; + Function() { function_id=-1; } }; @@ -146,8 +195,18 @@ private: Map<StringName,Function> functions; Map<StringName,Variable> variables; + Map<StringName,StringName> script_variable_remap; Map<StringName,Vector<Argument> > custom_signals; + Map<Object*,VisualScriptInstance*> instances; + +#ifdef TOOLS_ENABLED + Set<PlaceHolderScriptInstance*> placeholders; + //void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); + virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder); + void _update_placeholders(); +#endif + void _set_variable_info(const StringName& p_name,const Dictionary& p_info); Dictionary _get_variable_info(const StringName& p_name) const; @@ -248,15 +307,103 @@ public: }; +class VisualScriptInstance : public ScriptInstance { + + Object *owner; + Ref<VisualScript> script; + + Map<StringName,Variant> variables; //using variable path, not script + Map<int,VisualScriptNodeInstance*> instances; + + struct Function { + int node; + int max_stack; + int trash_pos; + int return_pos; + int flow_stack_size; + int node_count; + int argument_count; + bool valid; + + struct UnsequencedGet { + VisualScriptNodeInstance* from; + int from_port; + int to_stack; + }; + + Vector<UnsequencedGet> unsequenced_gets; + + }; + + Map<StringName,Function> functions; + + Vector<Variant> default_values; + int max_input_args,max_output_args; + + + //Map<StringName,Function> functions; + +public: + virtual bool set(const StringName& p_name, const Variant& p_value); + virtual bool get(const StringName& p_name, Variant &r_ret) const; + virtual void get_property_list(List<PropertyInfo> *p_properties) const; + virtual Variant::Type get_property_type(const StringName& p_name,bool *r_is_valid=NULL) const; + + virtual void get_method_list(List<MethodInfo> *p_list) const; + virtual bool has_method(const StringName& p_method) const; + virtual Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error); + virtual void notification(int p_notification); + + bool set_variable(const StringName& p_variable,const Variant& p_value) { + + Map<StringName,Variant>::Element *E=variables.find(p_variable); + if (!E) + return false; + + E->get()=p_value; + return true; + } + + bool get_variable(const StringName& p_variable,Variant* r_variable) const { + + const Map<StringName,Variant>::Element *E=variables.find(p_variable); + if (!E) + return false; + + *r_variable=E->get(); + return true; + + } + + virtual Ref<Script> get_script() const; + + _FORCE_INLINE_ VisualScript *get_script_ptr() { return script.ptr(); } + _FORCE_INLINE_ Object *get_owner_ptr() { return owner; } + + void create(const Ref<VisualScript>& p_script,Object *p_owner); + + virtual ScriptLanguage *get_language(); + + VisualScriptInstance(); + ~VisualScriptInstance(); +}; + + + typedef Ref<VisualScriptNode> (*VisualScriptNodeRegisterFunc)(const String& p_type); class VisualScriptLanguage : public ScriptLanguage { Map<String,VisualScriptNodeRegisterFunc> register_funcs; + + public: + StringName notification; static VisualScriptLanguage* singleton; + Mutex *lock; + virtual String get_name() const; /* LANGUAGE FUNCTIONS */ @@ -270,7 +417,7 @@ public: virtual void get_reserved_words(List<String> *p_words) const; virtual void get_comment_delimiters(List<String> *p_delimiters) const; virtual void get_string_delimiters(List<String> *p_delimiters) const; - virtual String get_template(const String& p_class_name, const String& p_base_class_name) const; + virtual Ref<Script> get_template(const String& p_class_name, const String& p_base_class_name) const; virtual bool validate(const String& p_script, int &r_line_error,int &r_col_error,String& r_test_error, const String& p_path="",List<String> *r_functions=NULL) const; virtual Script *create_script() const; virtual bool has_named_classes() const; @@ -313,6 +460,7 @@ public: VisualScriptLanguage(); + ~VisualScriptLanguage(); }; diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 58edafd963..247cbeb2c9 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -1,5 +1,11 @@ #include "visual_script_builtin_funcs.h" - +#include "math_funcs.h" +#include "object_type_db.h" +#include "reference.h" +#include "func_ref.h" +#include "os/os.h" +#include "variant_parser.h" +#include "io/marshalls.h" const char* VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX]={ "sin", @@ -538,12 +544,550 @@ VisualScriptBuiltinFunc::BuiltinFunc VisualScriptBuiltinFunc::get_func() { } +#define VALIDATE_ARG_NUM(m_arg) \ + if (!p_inputs[m_arg]->is_num()) {\ + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;\ + r_error.argument=m_arg;\ + r_error.expected=Variant::REAL;\ + return 0;\ + } + +class VisualScriptNodeInstanceBuiltinFunc : public VisualScriptNodeInstance { +public: + + VisualScriptBuiltinFunc *node; + VisualScriptInstance *instance; + + VisualScriptBuiltinFunc::BuiltinFunc func; + + + //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 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) { + + switch(func) { + case VisualScriptBuiltinFunc::MATH_SIN: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::sin(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_COS: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::cos(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_TAN: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::tan(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_SINH: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::sinh(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_COSH: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::cosh(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_TANH: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::tanh(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ASIN: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::asin(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ACOS: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::acos(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ATAN: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::atan(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ATAN2: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *p_outputs[0]=Math::atan2(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_SQRT: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::sqrt(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_FMOD: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *p_outputs[0]=Math::fmod(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_FPOSMOD: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *p_outputs[0]=Math::fposmod(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_FLOOR: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::floor(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_CEIL: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::ceil(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ROUND: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::round(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ABS: { + + if (p_inputs[0]->get_type()==Variant::INT) { + + int64_t i = *p_inputs[0]; + *p_outputs[0]=ABS(i); + } else if (p_inputs[0]->get_type()==Variant::REAL) { + + real_t r = *p_inputs[0]; + *p_outputs[0]=Math::abs(r); + } else { + + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::REAL; + + } + } break; + case VisualScriptBuiltinFunc::MATH_SIGN: { + + if (p_inputs[0]->get_type()==Variant::INT) { + + int64_t i = *p_inputs[0]; + *p_outputs[0]= i < 0 ? -1 : ( i > 0 ? +1 : 0); + } else if (p_inputs[0]->get_type()==Variant::REAL) { + + real_t r = *p_inputs[0]; + *p_outputs[0]= r < 0.0 ? -1.0 : ( r > 0.0 ? +1.0 : 0.0); + } else { + + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::REAL; + + } + } break; + case VisualScriptBuiltinFunc::MATH_POW: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *p_outputs[0]=Math::pow(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_LOG: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::log(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_EXP: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::exp(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ISNAN: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::is_nan(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ISINF: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::is_inf(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_EASE: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *p_outputs[0]=Math::ease(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_DECIMALS: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::step_decimals(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_STEPIFY: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *p_outputs[0]=Math::stepify(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_LERP: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + *p_outputs[0]=Math::lerp(*p_inputs[0],*p_inputs[1],*p_inputs[2]); + } break; + case VisualScriptBuiltinFunc::MATH_DECTIME: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + *p_outputs[0]=Math::dectime(*p_inputs[0],*p_inputs[1],*p_inputs[2]); + } break; + case VisualScriptBuiltinFunc::MATH_RANDOMIZE: { + Math::randomize(); + + } break; + case VisualScriptBuiltinFunc::MATH_RAND: { + *p_outputs[0]=Math::rand(); + } break; + case VisualScriptBuiltinFunc::MATH_RANDF: { + *p_outputs[0]=Math::randf(); + } break; + case VisualScriptBuiltinFunc::MATH_RANDOM: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *p_outputs[0]=Math::random(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_SEED: { + + VALIDATE_ARG_NUM(0); + uint32_t seed=*p_inputs[0]; + Math::seed(seed); + + } break; + case VisualScriptBuiltinFunc::MATH_RANDSEED: { + + VALIDATE_ARG_NUM(0); + uint32_t seed=*p_inputs[0]; + int ret = Math::rand_from_seed(&seed); + Array reta; + reta.push_back(ret); + reta.push_back(seed); + *p_outputs[0]=reta; + + } break; + case VisualScriptBuiltinFunc::MATH_DEG2RAD: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::deg2rad(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_RAD2DEG: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::rad2deg(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_LINEAR2DB: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::linear2db(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_DB2LINEAR: { + + VALIDATE_ARG_NUM(0); + *p_outputs[0]=Math::db2linear(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::LOGIC_MAX: { + + if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT) { + + int64_t a = *p_inputs[0]; + int64_t b = *p_inputs[1]; + *p_outputs[0]=MAX(a,b); + } else { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + + real_t a = *p_inputs[0]; + real_t b = *p_inputs[1]; + + *p_outputs[0]=MAX(a,b); + } + + } break; + case VisualScriptBuiltinFunc::LOGIC_MIN: { + + if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT) { + + int64_t a = *p_inputs[0]; + int64_t b = *p_inputs[1]; + *p_outputs[0]=MIN(a,b); + } else { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + + real_t a = *p_inputs[0]; + real_t b = *p_inputs[1]; + + *p_outputs[0]=MIN(a,b); + } + } break; + case VisualScriptBuiltinFunc::LOGIC_CLAMP: { + + if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT && p_inputs[2]->get_type()==Variant::INT) { + + int64_t a = *p_inputs[0]; + int64_t b = *p_inputs[1]; + int64_t c = *p_inputs[2]; + *p_outputs[0]=CLAMP(a,b,c); + } else { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + + real_t a = *p_inputs[0]; + real_t b = *p_inputs[1]; + real_t c = *p_inputs[2]; + + *p_outputs[0]=CLAMP(a,b,c); + } + } break; + case VisualScriptBuiltinFunc::LOGIC_NEAREST_PO2: { + + VALIDATE_ARG_NUM(0); + int64_t num = *p_inputs[0]; + *p_outputs[0] = nearest_power_of_2(num); + } break; + case VisualScriptBuiltinFunc::OBJ_WEAKREF: { + + if (p_inputs[0]->get_type()!=Variant::OBJECT) { + + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::OBJECT; + + return 0; + + } + + if (p_inputs[0]->is_ref()) { + + REF r = *p_inputs[0]; + if (!r.is_valid()) { + + return 0; + } + + Ref<WeakRef> wref = memnew( WeakRef ); + wref->set_ref(r); + *p_outputs[0]=wref; + } else { + Object *obj = *p_inputs[0]; + if (!obj) { + + return 0; + } + Ref<WeakRef> wref = memnew( WeakRef ); + wref->set_obj(obj); + *p_outputs[0]=wref; + } + + + + + } break; + case VisualScriptBuiltinFunc::FUNC_FUNCREF: { + + if (p_inputs[0]->get_type()!=Variant::OBJECT) { + + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::OBJECT; + + return 0; + + } + if (p_inputs[1]->get_type()!=Variant::STRING && p_inputs[1]->get_type()!=Variant::NODE_PATH) { + + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=1; + r_error.expected=Variant::STRING; + + return 0; + + } + + Ref<FuncRef> fr = memnew( FuncRef); + + fr->set_instance(*p_inputs[0]); + fr->set_function(*p_inputs[1]); + + *p_outputs[0]=fr; + + } break; + case VisualScriptBuiltinFunc::TYPE_CONVERT: { + + VALIDATE_ARG_NUM(1); + int type=*p_inputs[1]; + if (type<0 || type>=Variant::VARIANT_MAX) { + + *p_outputs[0]=RTR("Invalid type argument to convert(), use TYPE_* constants."); + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::INT; + return 0; + + } else { + + + *p_outputs[0]=Variant::construct(Variant::Type(type),p_inputs,1,r_error); + } + } break; + case VisualScriptBuiltinFunc::TYPE_OF: { -VisualScriptNodeInstance* VisualScriptBuiltinFunc::instance(VScriptInstance* p_instance) { - return NULL; + *p_outputs[0] = p_inputs[0]->get_type(); + + } break; + case VisualScriptBuiltinFunc::TYPE_EXISTS: { + + + *p_outputs[0] = ObjectTypeDB::type_exists(*p_inputs[0]); + + } break; + case VisualScriptBuiltinFunc::TEXT_STR: { + + String str = *p_inputs[0]; + + *p_outputs[0]=str; + + } break; + case VisualScriptBuiltinFunc::TEXT_PRINT: { + + String str = *p_inputs[0]; + print_line(str); + + + } break; + + case VisualScriptBuiltinFunc::TEXT_PRINTERR: { + + String str = *p_inputs[0]; + + //str+="\n"; + OS::get_singleton()->printerr("%s\n",str.utf8().get_data()); + + + } break; + case VisualScriptBuiltinFunc::TEXT_PRINTRAW: { + String str = *p_inputs[0]; + + //str+="\n"; + OS::get_singleton()->print("%s",str.utf8().get_data()); + + + } break; + case VisualScriptBuiltinFunc::VAR_TO_STR: { + + String vars; + VariantWriter::write_to_string(*p_inputs[0],vars); + *p_outputs[0]=vars; + } break; + case VisualScriptBuiltinFunc::STR_TO_VAR: { + + if (p_inputs[0]->get_type()!=Variant::STRING) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::STRING; + + return 0; + } + + VariantParser::StreamString ss; + ss.s=*p_inputs[0]; + + String errs; + int line; + Error err = VariantParser::parse(&ss,*p_outputs[0],errs,line); + + if (err!=OK) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::STRING; + *p_outputs[0]="Parse error at line "+itos(line)+": "+errs; + return 0; + } + + } break; + case VisualScriptBuiltinFunc::VAR_TO_BYTES: { + + + ByteArray barr; + int len; + Error err = encode_variant(*p_inputs[0],NULL,len); + if (err) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::NIL; + *p_outputs[0]="Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."; + return 0; + } + + barr.resize(len); + { + ByteArray::Write w = barr.write(); + encode_variant(*p_inputs[0],w.ptr(),len); + + } + *p_outputs[0]=barr; + } break; + case VisualScriptBuiltinFunc::BYTES_TO_VAR: { + + if (p_inputs[0]->get_type()!=Variant::RAW_ARRAY) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::RAW_ARRAY; + + return 0; + } + + ByteArray varr=*p_inputs[0]; + Variant ret; + { + ByteArray::Read r=varr.read(); + Error err = decode_variant(ret,r.ptr(),varr.size(),NULL); + if (err!=OK) { + *p_outputs[0]=RTR("Not enough bytes for decoding bytes, or invalid format."); + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::RAW_ARRAY; + return 0; + } + + } + + *p_outputs[0]=ret; + + } break; + default: {} + } + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptBuiltinFunc::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceBuiltinFunc * instance = memnew(VisualScriptNodeInstanceBuiltinFunc ); + instance->node=this; + instance->instance=p_instance; + instance->func=func; + return instance; } + void VisualScriptBuiltinFunc::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_func","which"),&VisualScriptBuiltinFunc::set_func); @@ -577,66 +1121,66 @@ static Ref<VisualScriptNode> create_builtin_func_node(const String& p_name) { void register_visual_script_builtin_func_node() { - VisualScriptLanguage::singleton->add_register_func("functions/builtin/sin",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SIN>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/cos",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_COS>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/tan",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_TAN>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/sinh",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SINH>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/cosh",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_COSH>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/tanh",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_TANH>); - - VisualScriptLanguage::singleton->add_register_func("functions/builtin/asin",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ASIN>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/acos",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ACOS>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/atan",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ATAN>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/atan2",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ATAN2>); - - VisualScriptLanguage::singleton->add_register_func("functions/builtin/sqrt",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SQRT>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/fmod",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FMOD>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/fposmod",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FPOSMOD>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/floor",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FLOOR>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/ceil",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_CEIL>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/round",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ROUND>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/abs",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ABS>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/sign",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SIGN>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/pow",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_POW>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/log",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LOG>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/exp",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_EXP>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/isnan",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ISNAN>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/isinf",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ISINF>); - - VisualScriptLanguage::singleton->add_register_func("functions/builtin/ease",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_EASE>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/decimals",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECIMALS>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/stepify",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_STEPIFY>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/lerp",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LERP>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/dectime",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECTIME>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/randomize",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOMIZE>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/rand",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAND>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/randf",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDF>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/random",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOM>); - - VisualScriptLanguage::singleton->add_register_func("functions/builtin/seed",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SEED>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/randseed",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDSEED>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/deg2rad",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DEG2RAD>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/rad2deg",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAD2DEG>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/linear2db",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LINEAR2DB>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/db2linear",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DB2LINEAR>); - - VisualScriptLanguage::singleton->add_register_func("functions/builtin/max",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MAX>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/min",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MIN>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/clamp",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_CLAMP>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/nearest_po2",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_NEAREST_PO2>); - - VisualScriptLanguage::singleton->add_register_func("functions/builtin/weakref",create_builtin_func_node<VisualScriptBuiltinFunc::OBJ_WEAKREF>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/funcref",create_builtin_func_node<VisualScriptBuiltinFunc::FUNC_FUNCREF>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/convert",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_CONVERT>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/typeof",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_OF>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/type_exists",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_EXISTS>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/str",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_STR>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/print",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINT>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/printerr",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINTERR>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/printraw",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINTRAW>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/var2str",create_builtin_func_node<VisualScriptBuiltinFunc::VAR_TO_STR>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/str2var",create_builtin_func_node<VisualScriptBuiltinFunc::STR_TO_VAR>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/var2bytes",create_builtin_func_node<VisualScriptBuiltinFunc::VAR_TO_BYTES>); - VisualScriptLanguage::singleton->add_register_func("functions/builtin/bytes2var",create_builtin_func_node<VisualScriptBuiltinFunc::BYTES_TO_VAR>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/sin",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SIN>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/cos",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_COS>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/tan",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_TAN>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/sinh",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SINH>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/cosh",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_COSH>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/tanh",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_TANH>); + + VisualScriptLanguage::singleton->add_register_func("functions/built_in/asin",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ASIN>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/acos",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ACOS>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/atan",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ATAN>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/atan2",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ATAN2>); + + VisualScriptLanguage::singleton->add_register_func("functions/built_in/sqrt",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SQRT>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/fmod",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FMOD>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/fposmod",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FPOSMOD>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/floor",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FLOOR>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/ceil",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_CEIL>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/round",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ROUND>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/abs",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ABS>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/sign",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SIGN>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/pow",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_POW>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/log",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LOG>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/exp",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_EXP>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/isnan",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ISNAN>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/isinf",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ISINF>); + + VisualScriptLanguage::singleton->add_register_func("functions/built_in/ease",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_EASE>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/decimals",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECIMALS>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/stepify",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_STEPIFY>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/lerp",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LERP>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/dectime",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECTIME>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/randomize",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOMIZE>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/rand",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAND>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/randf",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDF>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/random",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOM>); + + VisualScriptLanguage::singleton->add_register_func("functions/built_in/seed",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SEED>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/randseed",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDSEED>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/deg2rad",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DEG2RAD>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/rad2deg",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAD2DEG>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/linear2db",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LINEAR2DB>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/db2linear",create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DB2LINEAR>); + + VisualScriptLanguage::singleton->add_register_func("functions/built_in/max",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MAX>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/min",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MIN>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/clamp",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_CLAMP>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/nearest_po2",create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_NEAREST_PO2>); + + VisualScriptLanguage::singleton->add_register_func("functions/built_in/weakref",create_builtin_func_node<VisualScriptBuiltinFunc::OBJ_WEAKREF>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/funcref",create_builtin_func_node<VisualScriptBuiltinFunc::FUNC_FUNCREF>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/convert",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_CONVERT>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/typeof",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_OF>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/type_exists",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_EXISTS>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/str",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_STR>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/print",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINT>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/printerr",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINTERR>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/printraw",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINTRAW>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/var2str",create_builtin_func_node<VisualScriptBuiltinFunc::VAR_TO_STR>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/str2var",create_builtin_func_node<VisualScriptBuiltinFunc::STR_TO_VAR>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/var2bytes",create_builtin_func_node<VisualScriptBuiltinFunc::VAR_TO_BYTES>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/bytes2var",create_builtin_func_node<VisualScriptBuiltinFunc::BYTES_TO_VAR>); } diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h index b4dbd4db39..ebf227a192 100644 --- a/modules/visual_script/visual_script_builtin_funcs.h +++ b/modules/visual_script/visual_script_builtin_funcs.h @@ -91,11 +91,12 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "functions"; } void set_func(BuiltinFunc p_which); BuiltinFunc get_func(); - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptBuiltinFunc(); }; diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index ad4f2be34c..b9eb76862e 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -425,6 +425,10 @@ void VisualScriptEditor::_update_graph(int p_only_id) { GraphNode *gnode = memnew( GraphNode ); gnode->set_title(node->get_caption()); + if (EditorSettings::get_singleton()->has("visual_script/color_"+node->get_category())) { + gnode->set_modulate(EditorSettings::get_singleton()->get("visual_script/color_"+node->get_category())); + } + gnode->set_meta("__vnode",node); gnode->set_name(itos(E->get())); gnode->connect("dragged",this,"_node_moved",varray(E->get())); @@ -1377,6 +1381,16 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2& p_point,const Variant& p const_cast<VisualScriptEditor*>(this)->_show_hint("Hold Ctrl to drop a Setter, Shift+Ctrl to drop a Setter and copy the value."); #endif } + + if (String(d["type"])=="visual_script_variable_drag") { + +#ifdef OSX_ENABLED + const_cast<VisualScriptEditor*>(this)->_show_hint("Hold Meta to drop a Variable Setter."); +#else + const_cast<VisualScriptEditor*>(this)->_show_hint("Hold Ctrl to drop a Variable Setter."); +#endif + } + return true; } @@ -1448,6 +1462,11 @@ void VisualScriptEditor::drop_data_fw(const Point2& p_point,const Variant& p_dat if (d.has("type") && String(d["type"])=="visual_script_variable_drag") { +#ifdef OSX_ENABLED + bool use_set = Input::get_singleton()->is_key_pressed(KEY_META); +#else + bool use_set = Input::get_singleton()->is_key_pressed(KEY_CONTROL); +#endif Vector2 ofs = graph->get_scroll_ofs() + p_point; if (graph->is_using_snap()) { int snap = graph->get_snap(); @@ -1456,9 +1475,19 @@ void VisualScriptEditor::drop_data_fw(const Point2& p_point,const Variant& p_dat ofs/=EDSCALE; - Ref<VisualScriptVariable> vnode; - vnode.instance(); - vnode->set_variable(d["variable"]); + Ref<VisualScriptNode> vnode; + if (use_set) { + Ref<VisualScriptVariableSet> vnodes; + vnodes.instance(); + vnodes->set_variable(d["variable"]); + vnode=vnodes; + } else { + + Ref<VisualScriptVariableGet> vnodeg; + vnodeg.instance(); + vnodeg->set_variable(d["variable"]); + vnode=vnodeg; + } int new_id = script->get_available_id(); diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index 83d975fbca..094cb4aa1c 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -93,9 +93,38 @@ void VisualScriptReturn::_bind_methods() { } -VisualScriptNodeInstance* VisualScriptReturn::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceReturn : public VisualScriptNodeInstance { +public: - return NULL; + VisualScriptReturn *node; + VisualScriptInstance *instance; + bool with_value; + + 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,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) { + + if (with_value) { + *p_working_mem = *p_inputs[0]; + } else { + *p_working_mem = Variant(); + } + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptReturn::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceReturn * instance = memnew(VisualScriptNodeInstanceReturn ); + instance->node=this; + instance->instance=p_instance; + instance->with_value=with_value; + return instance; } VisualScriptReturn::VisualScriptReturn() { @@ -174,9 +203,33 @@ void VisualScriptCondition::_bind_methods() { } -VisualScriptNodeInstance* VisualScriptCondition::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceCondition : public VisualScriptNodeInstance { +public: + + VisualScriptCondition *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,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) { + + if (p_inputs[0]->operator bool()) + return 0; + else + return 1; + } + + +}; - return NULL; +VisualScriptNodeInstance* VisualScriptCondition::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceCondition * instance = memnew(VisualScriptNodeInstanceCondition ); + instance->node=this; + instance->instance=p_instance; + return instance; } VisualScriptCondition::VisualScriptCondition() { @@ -244,11 +297,36 @@ void VisualScriptWhile::_bind_methods() { } -VisualScriptNodeInstance* VisualScriptWhile::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceWhile : public VisualScriptNodeInstance { +public: + + VisualScriptWhile *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,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) { + + bool keep_going = p_inputs[0]->operator bool(); + + if (keep_going) + return 0|STEP_FLAG_PUSH_STACK_BIT; + else + return 1; + } - return NULL; -} +}; + +VisualScriptNodeInstance* VisualScriptWhile::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceWhile * instance = memnew(VisualScriptNodeInstanceWhile ); + instance->node=this; + instance->instance=p_instance; + return instance; +} VisualScriptWhile::VisualScriptWhile() { } @@ -316,9 +394,79 @@ void VisualScriptIterator::_bind_methods() { } -VisualScriptNodeInstance* VisualScriptIterator::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceIterator : public VisualScriptNodeInstance { +public: + + VisualScriptIterator *node; + VisualScriptInstance *instance; + + virtual int get_working_memory_size() const { return 2; } + //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) { + + if (p_start_sequence) { + p_working_mem[0]=*p_inputs[0]; + bool valid; + bool can_iter = p_inputs[0]->iter_init(p_working_mem[1],valid); + + if (!valid) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str=RTR("Input type not iterable: ")+Variant::get_type_name(p_inputs[0]->get_type()); + return 0; + } - return NULL; + if (!can_iter) + return 1; //nothing to iterate + + + *p_outputs[0]=p_working_mem[0].iter_get( p_working_mem[1],valid); + + if (!valid) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str=RTR("Iterator became invalid"); + return 0; + } + + + } else { + + bool valid; + bool can_iter = p_working_mem[0].iter_next(p_working_mem[1],valid); + + if (!valid) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str=RTR("Iterator became invalid: ")+Variant::get_type_name(p_inputs[0]->get_type()); + return 0; + } + + if (!can_iter) + return 1; //nothing to iterate + + + *p_outputs[0]=p_working_mem[0].iter_get( p_working_mem[1],valid); + + if (!valid) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str=RTR("Iterator became invalid"); + return 0; + } + + } + + return 0|STEP_FLAG_PUSH_STACK_BIT; //go around + } + + +}; + +VisualScriptNodeInstance* VisualScriptIterator::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceIterator * instance = memnew(VisualScriptNodeInstanceIterator ); + instance->node=this; + instance->instance=p_instance; + return instance; } VisualScriptIterator::VisualScriptIterator() { @@ -396,11 +544,48 @@ void VisualScriptSequence::_bind_methods() { } -VisualScriptNodeInstance* VisualScriptSequence::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceSequence : public VisualScriptNodeInstance { +public: - return NULL; -} + VisualScriptSequence *node; + VisualScriptInstance *instance; + int steps; + + 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,bool p_start_sequence,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) { + + if (p_start_sequence) { + + p_working_mem[0]=0; + } + + int step = p_working_mem[0]; + *p_outputs[0]=step; + + if (step+1==steps) + return step; + else { + p_working_mem[0]=step+1; + return step|STEP_FLAG_PUSH_STACK_BIT; + } + + } + + +}; + +VisualScriptNodeInstance* VisualScriptSequence::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceSequence * instance = memnew(VisualScriptNodeInstanceSequence ); + instance->node=this; + instance->instance=p_instance; + instance->steps=steps; + return instance; +} VisualScriptSequence::VisualScriptSequence() { steps=1; diff --git a/modules/visual_script/visual_script_flow_control.h b/modules/visual_script/visual_script_flow_control.h index 557654b080..49179fd934 100644 --- a/modules/visual_script/visual_script_flow_control.h +++ b/modules/visual_script/visual_script_flow_control.h @@ -31,6 +31,7 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "flow_control"; } void set_return_type(Variant::Type); Variant::Type get_return_type() const; @@ -39,7 +40,7 @@ public: bool is_return_value_enabled() const; - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptReturn(); }; @@ -72,9 +73,10 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "flow_control"; } - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptCondition(); }; @@ -107,9 +109,10 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "flow_control"; } - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptWhile(); }; @@ -143,9 +146,10 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "flow_control"; } - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptIterator(); }; @@ -180,11 +184,12 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "flow_control"; } void set_steps(int p_steps); int get_steps() const; - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptSequence(); }; diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 750ad00a56..c7598c0eb0 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -485,11 +485,96 @@ void VisualScriptFunctionCall::_bind_methods() { BIND_CONSTANT( CALL_MODE_BASIC_TYPE ); } -VisualScriptNodeInstance* VisualScriptFunctionCall::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceFunctionCall : public VisualScriptNodeInstance { +public: - return NULL; -} + VisualScriptFunctionCall::CallMode call_mode; + NodePath node_path; + int input_args; + bool returns; + StringName function; + + VisualScriptFunctionCall *node; + VisualScriptInstance *instance; + + + + //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 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) { + + + switch(call_mode) { + + case VisualScriptFunctionCall::CALL_MODE_SELF: { + + Object *object=instance->get_owner_ptr(); + + if (returns) { + *p_outputs[0] = object->call(function,p_inputs,input_args,r_error); + } else { + object->call(function,p_inputs,input_args,r_error); + } + } break; + case VisualScriptFunctionCall::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; + } + + if (returns) { + *p_outputs[0] = another->call(function,p_inputs,input_args,r_error); + } else { + another->call(function,p_inputs,input_args,r_error); + } + + } break; + case VisualScriptFunctionCall::CALL_MODE_INSTANCE: + 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 { + v.call(function,p_inputs+1,input_args,r_error); + } + + } break; + + } + return 0; + + } + + +}; + +VisualScriptNodeInstance* VisualScriptFunctionCall::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceFunctionCall * instance = memnew(VisualScriptNodeInstanceFunctionCall ); + instance->node=this; + instance->instance=p_instance; + instance->function=function; + instance->call_mode=call_mode; + instance->returns=get_output_value_port_count(); + instance->node_path=base_path; + instance->input_args = get_input_value_port_count() - ( (call_mode==CALL_MODE_BASIC_TYPE || call_mode==CALL_MODE_INSTANCE) ? 1: 0 ); + return instance; +} VisualScriptFunctionCall::VisualScriptFunctionCall() { call_mode=CALL_MODE_INSTANCE; @@ -983,9 +1068,116 @@ void VisualScriptPropertySet::_bind_methods() { } -VisualScriptNodeInstance* VisualScriptPropertySet::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstancePropertySet : public VisualScriptNodeInstance { +public: - return NULL; + + VisualScriptPropertySet::CallMode call_mode; + NodePath node_path; + StringName property; + bool use_builtin; + Variant builtin_val; + + VisualScriptPropertySet *node; + VisualScriptInstance *instance; + + + + //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 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) { + + + switch(call_mode) { + + case VisualScriptPropertySet::CALL_MODE_SELF: { + + Object *object=instance->get_owner_ptr(); + + bool valid; + + if (use_builtin) { + object->set(property,builtin_val,&valid); + } else { + object->set(property,*p_inputs[0],&valid); + } + + if (!valid) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str="Invalid index property name."; + } + } break; + case VisualScriptPropertySet::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; + } + + bool valid; + + if (use_builtin) { + another->set(property,builtin_val,&valid); + } else { + another->set(property,*p_inputs[0],&valid); + } + + if (!valid) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str="Invalid index property name."; + } + + } break; + case VisualScriptPropertySet::CALL_MODE_INSTANCE: + case VisualScriptPropertySet::CALL_MODE_BASIC_TYPE: { + + Variant v = *p_inputs[0]; + + bool valid; + + if (use_builtin) { + v.set(property,builtin_val,&valid); + } else { + v.set(property,p_inputs[1],&valid); + } + + if (!valid) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str="Invalid index property name."; + } + + } break; + + } + return 0; + + } + + +}; + +VisualScriptNodeInstance* VisualScriptPropertySet::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstancePropertySet * instance = memnew(VisualScriptNodeInstancePropertySet ); + instance->node=this; + instance->instance=p_instance; + instance->property=property; + instance->call_mode=call_mode; + instance->node_path=base_path; + instance->use_builtin=use_builtin_value; + instance->builtin_val=builtin_value; + return instance; } VisualScriptPropertySet::VisualScriptPropertySet() { @@ -1012,12 +1204,12 @@ static Ref<VisualScriptNode> create_property_set_node(const String& p_name) { int VisualScriptPropertyGet::get_output_sequence_port_count() const { - return 1; + return (call_mode==CALL_MODE_SELF || call_mode==CALL_MODE_NODE_PATH)?0:1; } bool VisualScriptPropertyGet::has_input_sequence_port() const{ - return true; + return (call_mode==CALL_MODE_SELF || call_mode==CALL_MODE_NODE_PATH)?false:true; } void VisualScriptPropertyGet::_update_base_type() { //cache it because this information may not be available on load @@ -1385,9 +1577,107 @@ void VisualScriptPropertyGet::_bind_methods() { BIND_CONSTANT( CALL_MODE_INSTANCE); } -VisualScriptNodeInstance* VisualScriptPropertyGet::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstancePropertyGet : public VisualScriptNodeInstance { +public: - return NULL; + + VisualScriptPropertyGet::CallMode call_mode; + NodePath node_path; + StringName property; + + VisualScriptPropertyGet *node; + VisualScriptInstance *instance; + + + + //virtual int get_working_memory_size() const { return 0; } + virtual bool is_output_port_unsequenced(int p_idx) const { return (call_mode==VisualScriptPropertyGet::CALL_MODE_SELF || call_mode==VisualScriptPropertyGet::CALL_MODE_NODE_PATH); } + virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { + + //these two modes can be get directly, so they use unsequenced mode + switch(call_mode) { + + case VisualScriptPropertyGet::CALL_MODE_SELF: { + + Object *object=instance->get_owner_ptr(); + + bool valid; + + *r_value = object->get(property,&valid); + + if (!valid) { + //r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error=RTR("Invalid index property name."); + return false; + } + } break; + case VisualScriptPropertyGet::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=RTR("Base object is not a Node!"); + return false; + } + + Node* another = node->get_node(node_path); + if (!node) { + //r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error=RTR("Path does not lead Node!"); + return false; + } + + bool valid; + + + *r_value = another->get(property,&valid); + + if (!valid) { + //r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error=vformat(RTR("Invalid index property name '%s' in node %s."),String(property),another->get_name()); + return false; + } + + } break; + default: {}; + } + 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) { + + + bool valid; + Variant v = *p_inputs[0]; + + *p_outputs[0] = v.get(property,&valid); + + if (!valid) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str=RTR("Invalid index property name."); + + } + + + return 0; + } + + + + +}; + +VisualScriptNodeInstance* VisualScriptPropertyGet::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstancePropertyGet * instance = memnew(VisualScriptNodeInstancePropertyGet ); + instance->node=this; + instance->instance=p_instance; + instance->property=property; + instance->call_mode=call_mode; + instance->node_path=base_path; + + return instance; } VisualScriptPropertyGet::VisualScriptPropertyGet() { @@ -1463,7 +1753,9 @@ Node *VisualScriptScriptCall::_get_base_node() const { int VisualScriptScriptCall::get_input_value_port_count() const{ - +#if 1 + return argument_count; +#else if (call_mode==CALL_MODE_SELF) { Ref<VisualScript> vs = get_visual_script(); @@ -1501,6 +1793,7 @@ int VisualScriptScriptCall::get_input_value_port_count() const{ return 0; +#endif } int VisualScriptScriptCall::get_output_value_port_count() const{ @@ -1573,6 +1866,48 @@ String VisualScriptScriptCall::get_text() const { return " "+String(function)+"()"; } +void VisualScriptScriptCall::_update_argument_count() { + + //try to remember the amount of arguments in the function, because if loaded from scratch + //this information will not be available + + if (call_mode==CALL_MODE_SELF) { + + Ref<VisualScript> vs = get_visual_script(); + if (vs.is_valid()) { + + if (!vs->has_function(function)) + return ; + + int id = vs->get_function_node_id(function); + if (id<0) + return; + + Ref<VisualScriptFunction> func = vs->get_node(function,id); + + argument_count=func->get_argument_count(); + } + } else { + + Node*base = _get_base_node(); + if (!base) + return; + + Ref<Script> script = base->get_script(); + if (!script.is_valid()) + return ; + + List<MethodInfo> functions; + script->get_method_list(&functions); + for (List<MethodInfo>::Element *E=functions.front();E;E=E->next()) { + if (E->get().name==function) { + argument_count=E->get().arguments.size(); + return; + } + } + + } +} void VisualScriptScriptCall::set_function(const StringName& p_type){ @@ -1581,7 +1916,7 @@ void VisualScriptScriptCall::set_function(const StringName& p_type){ return; function=p_type; - + _update_argument_count(); _change_notify(); ports_changed_notify(); } @@ -1597,7 +1932,7 @@ void VisualScriptScriptCall::set_base_path(const NodePath& p_type) { return; base_path=p_type; - + _update_argument_count(); _change_notify(); ports_changed_notify(); } @@ -1614,11 +1949,25 @@ void VisualScriptScriptCall::set_call_mode(CallMode p_mode) { return; call_mode=p_mode; + _update_argument_count(); + _change_notify(); + ports_changed_notify(); + +} + +void VisualScriptScriptCall::set_argument_count(int p_count) { + argument_count=p_count; _change_notify(); ports_changed_notify(); } + +int VisualScriptScriptCall::get_argument_count() const { + + return argument_count; +} + VisualScriptScriptCall::CallMode VisualScriptScriptCall::get_call_mode() const { return call_mode; @@ -1703,24 +2052,95 @@ void VisualScriptScriptCall::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptScriptCall::set_base_path); ObjectTypeDB::bind_method(_MD("get_base_path"),&VisualScriptScriptCall::get_base_path); + ObjectTypeDB::bind_method(_MD("set_argument_count","argument_count"),&VisualScriptScriptCall::set_argument_count); + ObjectTypeDB::bind_method(_MD("get_argument_count"),&VisualScriptScriptCall::get_argument_count); ADD_PROPERTY(PropertyInfo(Variant::INT,"function/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path"),_SCS("set_call_mode"),_SCS("get_call_mode")); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"function/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path")); ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/function"),_SCS("set_function"),_SCS("get_function")); + ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/argument_count"),_SCS("set_argument_count"),_SCS("get_argument_count")); BIND_CONSTANT( CALL_MODE_SELF ); BIND_CONSTANT( CALL_MODE_NODE_PATH); } -VisualScriptNodeInstance* VisualScriptScriptCall::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceScriptCall : public VisualScriptNodeInstance { +public: - return NULL; + + VisualScriptScriptCall::CallMode call_mode; + NodePath node_path; + int input_args; + bool returns; + StringName function; + + VisualScriptScriptCall *node; + VisualScriptInstance *instance; + + + + //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 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) { + + + switch(call_mode) { + + case VisualScriptScriptCall::CALL_MODE_SELF: { + + Object *object=instance->get_owner_ptr(); + + *p_outputs[0] = object->call(function,p_inputs,input_args,r_error); + + } break; + case VisualScriptScriptCall::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; + } + + + *p_outputs[0] = another->call(function,p_inputs,input_args,r_error); + + } break; + + } + return 0; + + } + + +}; + +VisualScriptNodeInstance* VisualScriptScriptCall::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceScriptCall * instance = memnew(VisualScriptNodeInstanceScriptCall ); + instance->node=this; + instance->instance=p_instance; + instance->function=function; + instance->call_mode=call_mode; + instance->node_path=base_path; + instance->input_args = argument_count; + return instance; } VisualScriptScriptCall::VisualScriptScriptCall() { call_mode=CALL_MODE_SELF; + argument_count=0; } @@ -1736,7 +2156,7 @@ static Ref<VisualScriptNode> create_script_call_node(const String& p_name) { ////////////////////////////////////////// -////////////////SCRIPT CALL////////////////////// +////////////////EMIT////////////////////// ////////////////////////////////////////// int VisualScriptEmitSignal::get_output_sequence_port_count() const { @@ -1865,14 +2285,78 @@ void VisualScriptEmitSignal::_bind_methods() { } -VisualScriptNodeInstance* VisualScriptEmitSignal::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceEmitSignal : public VisualScriptNodeInstance { +public: - return NULL; + VisualScriptEmitSignal *node; + VisualScriptInstance *instance; + int argcount; + StringName name; + + //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 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) { + + + Object *obj = instance->get_owner_ptr(); + + obj->emit_signal(name,p_inputs,argcount); + + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptEmitSignal::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceEmitSignal * instance = memnew(VisualScriptNodeInstanceEmitSignal ); + instance->node=this; + instance->instance=p_instance; + instance->name=name; + instance->argcount=get_input_value_port_count(); + return instance; } VisualScriptEmitSignal::VisualScriptEmitSignal() { } + + +static Ref<VisualScriptNode> create_basic_type_call_node(const String& p_name) { + + Vector<String> path = p_name.split("/"); + ERR_FAIL_COND_V(path.size()<4,Ref<VisualScriptNode>()); + String base_type = path[2]; + String method = path[3]; + + Ref<VisualScriptFunctionCall> node; + node.instance(); + + Variant::Type type=Variant::VARIANT_MAX; + + for(int i=0;i<Variant::VARIANT_MAX;i++) { + + if (Variant::get_type_name(Variant::Type(i))==base_type) { + type=Variant::Type(i); + break; + } + } + + ERR_FAIL_COND_V(type==Variant::VARIANT_MAX,Ref<VisualScriptNode>()); + + + node->set_call_mode(VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE); + node->set_basic_type(type); + node->set_function(method); + + return node; +} + + void register_visual_script_func_nodes() { VisualScriptLanguage::singleton->add_register_func("functions/call_method/instance_call",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_INSTANCE>); @@ -1895,4 +2379,17 @@ void register_visual_script_func_nodes() { VisualScriptLanguage::singleton->add_register_func("functions/script/emit_signal",create_node_generic<VisualScriptEmitSignal>); + for(int i=0;i<Variant::VARIANT_MAX;i++) { + + Variant::Type t = Variant::Type(i); + String type_name = Variant::get_type_name(t); + Variant::CallError ce; + Variant vt = Variant::construct(t,NULL,0,ce); + List<MethodInfo> ml; + vt.get_method_list(&ml); + + 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); + } + } } diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h index 940a133d63..7ba573564c 100644 --- a/modules/visual_script/visual_script_func_nodes.h +++ b/modules/visual_script/visual_script_func_nodes.h @@ -50,6 +50,7 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "functions"; } void set_basic_type(Variant::Type p_type); Variant::Type get_basic_type() const; @@ -69,7 +70,7 @@ public: void set_use_default_args(int p_amount); int get_use_default_args() const; - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptFunctionCall(); }; @@ -127,6 +128,7 @@ public: 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; @@ -149,7 +151,7 @@ public: void set_builtin_value(const Variant &p_value); Variant get_builtin_value() const; - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptPropertySet(); }; @@ -204,6 +206,7 @@ public: 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; @@ -220,7 +223,7 @@ public: void set_call_mode(CallMode p_mode); CallMode get_call_mode() const; - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptPropertyGet(); }; @@ -246,11 +249,13 @@ private: CallMode call_mode; NodePath base_path; StringName function; + int argument_count; Node *_get_base_node() const; + void _update_argument_count(); protected: virtual void _validate_property(PropertyInfo& property) const; @@ -274,6 +279,7 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "functions"; } void set_function(const StringName& p_type); StringName get_function() const; @@ -284,9 +290,11 @@ public: void set_call_mode(CallMode p_mode); CallMode get_call_mode() const; + void set_argument_count(int p_count); + int get_argument_count() const; - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptScriptCall(); }; @@ -328,11 +336,12 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "functions"; } void set_signal(const StringName& p_type); StringName get_signal() const; - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptEmitSignal(); }; diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 1e898675d3..ed7119e27a 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -53,7 +53,15 @@ bool VisualScriptFunction::_set(const StringName& p_name, const Variant& p_valu } + if (p_name=="stack/stackless") { + set_stack_less(p_value); + return true; + } + if (p_name=="stack/size") { + stack_size=p_value; + return true; + } return false; } @@ -81,6 +89,16 @@ bool VisualScriptFunction::_get(const StringName& p_name,Variant &r_ret) const } + if (p_name=="stack/stackless") { + r_ret=stack_less; + return true; + } + + if (p_name=="stack/size") { + r_ret=stack_size; + return true; + } + return false; } void VisualScriptFunction::_get_property_list( List<PropertyInfo> *p_list) const { @@ -96,6 +114,11 @@ void VisualScriptFunction::_get_property_list( List<PropertyInfo> *p_list) cons p_list->push_back(PropertyInfo(Variant::INT,"argument/"+itos(i+1)+"/type",PROPERTY_HINT_ENUM,argt)); p_list->push_back(PropertyInfo(Variant::STRING,"argument/"+itos(i+1)+"/name")); } + if (!stack_less) { + p_list->push_back(PropertyInfo(Variant::INT,"stack/size",PROPERTY_HINT_RANGE,"1,100000")); + } + p_list->push_back(PropertyInfo(Variant::BOOL,"stack/stackless")); + } @@ -201,15 +224,75 @@ int VisualScriptFunction::get_argument_count() const { return arguments.size(); } +class VisualScriptNodeInstanceFunction : public VisualScriptNodeInstance { +public: -VisualScriptNodeInstance* VisualScriptFunction::instance(VScriptInstance* p_instance) { + VisualScriptFunction *node; + VisualScriptInstance *instance; - return NULL; + //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 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) { + + int ac = node->get_argument_count(); + + for(int i=0;i<ac;i++) { +#ifdef DEBUG_ENABLED + Variant::Type expected = node->get_argument_type(i); + if (expected!=Variant::NIL) { + if (!Variant::can_convert_strict(p_inputs[i]->get_type(),expected)) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.expected=expected; + r_error.argument=i; + return 0; + } + } +#endif + + *p_outputs[i]=*p_inputs[i]; + } + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptFunction::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceFunction * instance = memnew(VisualScriptNodeInstanceFunction ); + instance->node=this; + instance->instance=p_instance; + return instance; } VisualScriptFunction::VisualScriptFunction() { + stack_size=256; + stack_less=false; +} + + +void VisualScriptFunction::set_stack_less(bool p_enable) { + stack_less=p_enable; + _change_notify(); +} + +bool VisualScriptFunction::is_stack_less() const { + return stack_less; +} + +void VisualScriptFunction::set_stack_size(int p_size) { + ERR_FAIL_COND(p_size <1 || p_size>100000); + stack_size=p_size; +} + +int VisualScriptFunction::get_stack_size() const { + + return stack_size; } @@ -425,9 +508,45 @@ void VisualScriptOperator::_bind_methods() { } -VisualScriptNodeInstance* VisualScriptOperator::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceOperator : public VisualScriptNodeInstance { +public: - return NULL; + bool unary; + Variant::Operator op; + + //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 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) { + + bool valid; + if (unary) { + + Variant::evaluate(op,*p_inputs[0],Variant(),*p_outputs[0],valid); + } else { + Variant::evaluate(op,*p_inputs[0],*p_inputs[1],*p_outputs[0],valid); + } + + if (!valid) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + if (p_outputs[0]->get_type()==Variant::STRING) { + r_error_str=*p_outputs[0]; + } + } + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptOperator::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceOperator * instance = memnew(VisualScriptNodeInstanceOperator ); + instance->unary=get_input_value_port_count()==1; + instance->op=op; + return instance; } VisualScriptOperator::VisualScriptOperator() { @@ -447,37 +566,42 @@ static Ref<VisualScriptNode> create_op_node(const String& p_name) { } ////////////////////////////////////////// -////////////////VARIABLE////////////////// +////////////////VARIABLE GET////////////////// ////////////////////////////////////////// -int VisualScriptVariable::get_output_sequence_port_count() const { +int VisualScriptVariableGet::get_output_sequence_port_count() const { - return 1; + return 0; } -bool VisualScriptVariable::has_input_sequence_port() const{ +bool VisualScriptVariableGet::has_input_sequence_port() const{ - return true; + return false; } -int VisualScriptVariable::get_input_value_port_count() const{ +int VisualScriptVariableGet::get_input_value_port_count() const{ - return 1; + return 0; } -int VisualScriptVariable::get_output_value_port_count() const{ +int VisualScriptVariableGet::get_output_value_port_count() const{ return 1; } -String VisualScriptVariable::get_output_sequence_port_text(int p_port) const { +String VisualScriptVariableGet::get_output_sequence_port_text(int p_port) const { return String(); } -PropertyInfo VisualScriptVariable::get_input_value_port_info(int p_idx) const{ +PropertyInfo VisualScriptVariableGet::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + +PropertyInfo VisualScriptVariableGet::get_output_value_port_info(int p_idx) const{ PropertyInfo pinfo; - pinfo.name="set"; + pinfo.name="value"; if (get_visual_script().is_valid() && get_visual_script()->has_variable(variable)) { PropertyInfo vinfo = get_visual_script()->get_variable_info(variable); pinfo.type=vinfo.type; @@ -487,10 +611,134 @@ PropertyInfo VisualScriptVariable::get_input_value_port_info(int p_idx) const{ return pinfo; } -PropertyInfo VisualScriptVariable::get_output_value_port_info(int p_idx) const{ + +String VisualScriptVariableGet::get_caption() const { + + return "Variable"; +} + +String VisualScriptVariableGet::get_text() const { + + return variable; +} + +void VisualScriptVariableGet::set_variable(StringName p_variable) { + + if (variable==p_variable) + return; + variable=p_variable; + ports_changed_notify(); + +} + +StringName VisualScriptVariableGet::get_variable() const{ + + return variable; +} + +void VisualScriptVariableGet::_validate_property(PropertyInfo& property) const { + + if (property.name=="variable/name" && get_visual_script().is_valid()) { + Ref<VisualScript> vs = get_visual_script(); + List<StringName> vars; + vs->get_variable_list(&vars); + + String vhint; + for (List<StringName>::Element *E=vars.front();E;E=E->next()) { + if (vhint!=String()) + vhint+=","; + + vhint+=E->get().operator String(); + } + + property.hint=PROPERTY_HINT_ENUM; + property.hint_string=vhint; + } +} + +void VisualScriptVariableGet::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_variable","name"),&VisualScriptVariableGet::set_variable); + ObjectTypeDB::bind_method(_MD("get_variable"),&VisualScriptVariableGet::get_variable); + + + ADD_PROPERTY(PropertyInfo(Variant::STRING,"variable/name"),_SCS("set_variable"),_SCS("get_variable")); + +} + +class VisualScriptNodeInstanceVariableGet : public VisualScriptNodeInstance { +public: + + VisualScriptVariableGet *node; + VisualScriptInstance *instance; + StringName variable; + + //virtual int get_working_memory_size() const { return 0; } + 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 { + + if (instance->get_variable(variable,r_value)==false) { + r_error=RTR("VariableGet not found in script: ")+"'"+String(variable)+"'"; + return false; + } else { + 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) { + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptVariableGet::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceVariableGet * instance = memnew(VisualScriptNodeInstanceVariableGet ); + instance->node=this; + instance->instance=p_instance; + instance->variable=variable; + return instance; +} +VisualScriptVariableGet::VisualScriptVariableGet() { + + +} + + +////////////////////////////////////////// +////////////////VARIABLE GET////////////////// +////////////////////////////////////////// + +int VisualScriptVariableSet::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptVariableSet::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptVariableSet::get_input_value_port_count() const{ + + return 1; +} +int VisualScriptVariableSet::get_output_value_port_count() const{ + + return 0; +} + +String VisualScriptVariableSet::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptVariableSet::get_input_value_port_info(int p_idx) const{ PropertyInfo pinfo; - pinfo.name="get"; + pinfo.name="set"; if (get_visual_script().is_valid() && get_visual_script()->has_variable(variable)) { PropertyInfo vinfo = get_visual_script()->get_variable_info(variable); pinfo.type=vinfo.type; @@ -500,18 +748,23 @@ PropertyInfo VisualScriptVariable::get_output_value_port_info(int p_idx) const{ return pinfo; } +PropertyInfo VisualScriptVariableSet::get_output_value_port_info(int p_idx) const{ -String VisualScriptVariable::get_caption() const { + return PropertyInfo(); +} - return "Variable"; + +String VisualScriptVariableSet::get_caption() const { + + return "VariableSet"; } -String VisualScriptVariable::get_text() const { +String VisualScriptVariableSet::get_text() const { return variable; } -void VisualScriptVariable::set_variable(StringName p_variable) { +void VisualScriptVariableSet::set_variable(StringName p_variable) { if (variable==p_variable) return; @@ -520,12 +773,12 @@ void VisualScriptVariable::set_variable(StringName p_variable) { } -StringName VisualScriptVariable::get_variable() const{ +StringName VisualScriptVariableSet::get_variable() const{ return variable; } -void VisualScriptVariable::_validate_property(PropertyInfo& property) const { +void VisualScriptVariableSet::_validate_property(PropertyInfo& property) const { if (property.name=="variable/name" && get_visual_script().is_valid()) { Ref<VisualScript> vs = get_visual_script(); @@ -545,22 +798,50 @@ void VisualScriptVariable::_validate_property(PropertyInfo& property) const { } } -void VisualScriptVariable::_bind_methods() { +void VisualScriptVariableSet::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_variable","name"),&VisualScriptVariable::set_variable); - ObjectTypeDB::bind_method(_MD("get_variable"),&VisualScriptVariable::get_variable); + ObjectTypeDB::bind_method(_MD("set_variable","name"),&VisualScriptVariableSet::set_variable); + ObjectTypeDB::bind_method(_MD("get_variable"),&VisualScriptVariableSet::get_variable); ADD_PROPERTY(PropertyInfo(Variant::STRING,"variable/name"),_SCS("set_variable"),_SCS("get_variable")); } -VisualScriptNodeInstance* VisualScriptVariable::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceVariableSet : public VisualScriptNodeInstance { +public: - return NULL; -} + VisualScriptVariableSet *node; + VisualScriptInstance *instance; + StringName variable; + + //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,bool p_start_sequence,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 ; + r_error_str=RTR("VariableSet not found in script: ")+"'"+String(variable)+"'"; + } -VisualScriptVariable::VisualScriptVariable() { + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptVariableSet::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceVariableSet * instance = memnew(VisualScriptNodeInstanceVariableSet ); + instance->node=this; + instance->instance=p_instance; + instance->variable=variable; + return instance; +} +VisualScriptVariableSet::VisualScriptVariableSet() { } @@ -679,9 +960,33 @@ void VisualScriptConstant::_bind_methods() { } -VisualScriptNodeInstance* VisualScriptConstant::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceConstant : public VisualScriptNodeInstance { +public: - return NULL; + Variant constant; + //virtual int get_working_memory_size() const { return 0; } + 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 { + + *r_value=constant; + + 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) { + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptConstant::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceConstant * instance = memnew(VisualScriptNodeInstanceConstant ); + instance->constant=value; + return instance; } VisualScriptConstant::VisualScriptConstant() { @@ -747,11 +1052,34 @@ String VisualScriptIndexGet::get_text() const { } -VisualScriptNodeInstance* VisualScriptIndexGet::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceIndexGet : public VisualScriptNodeInstance { +public: - return NULL; -} + //virtual int get_working_memory_size() const { return 0; } + //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) { + + bool valid; + *p_outputs[0] = p_inputs[0]->get(*p_inputs[1],&valid); + + if (!valid) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str="Invalid get: "+p_inputs[0]->get_construct_string(); + } + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptIndexGet::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceIndexGet * instance = memnew(VisualScriptNodeInstanceIndexGet ); + return instance; +} VisualScriptIndexGet::VisualScriptIndexGet() { @@ -816,11 +1144,35 @@ String VisualScriptIndexSet::get_text() const { } -VisualScriptNodeInstance* VisualScriptIndexSet::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceIndexSet : public VisualScriptNodeInstance { +public: - return NULL; -} + //virtual int get_working_memory_size() const { return 0; } + //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) { + + bool valid; + *p_outputs[0]=*p_inputs[0]; + p_outputs[0]->set(*p_inputs[1],*p_inputs[2],&valid); + + if (!valid) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str="Invalid set: "+p_inputs[1]->get_construct_string(); + } + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptIndexSet::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceIndexSet * instance = memnew(VisualScriptNodeInstanceIndexSet ); + return instance; +} VisualScriptIndexSet::VisualScriptIndexSet() { @@ -889,10 +1241,33 @@ int VisualScriptGlobalConstant::get_global_constant() { } +class VisualScriptNodeInstanceGlobalConstant : public VisualScriptNodeInstance { +public: -VisualScriptNodeInstance* VisualScriptGlobalConstant::instance(VScriptInstance* p_instance) { + int index; + //virtual int get_working_memory_size() const { return 0; } + 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 NULL; + *r_value = GlobalConstants::get_global_constant_value(index); + 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) { + + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptGlobalConstant::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceGlobalConstant * instance = memnew(VisualScriptNodeInstanceGlobalConstant ); + instance->index=index; + return instance; } void VisualScriptGlobalConstant::_bind_methods() { @@ -931,6 +1306,17 @@ const char* VisualScriptMathConstant::const_name[MATH_CONSTANT_MAX]={ "E", "Sqrt2", }; + +double VisualScriptMathConstant::const_value[MATH_CONSTANT_MAX]={ + 1.0, + Math_PI, + Math_PI*2, + Math_PI*0.5, + 2.71828182845904523536, + Math::sqrt(2.0) +}; + + int VisualScriptMathConstant::get_output_sequence_port_count() const { return 0; @@ -962,7 +1348,7 @@ PropertyInfo VisualScriptMathConstant::get_input_value_port_info(int p_idx) cons PropertyInfo VisualScriptMathConstant::get_output_value_port_info(int p_idx) const{ - return PropertyInfo(Variant::INT,"value"); + return PropertyInfo(Variant::REAL,"value"); } @@ -987,13 +1373,36 @@ VisualScriptMathConstant::MathConstant VisualScriptMathConstant::get_math_consta return constant; } +class VisualScriptNodeInstanceMathConstant : public VisualScriptNodeInstance { +public: + float value; + //virtual int get_working_memory_size() const { return 0; } + 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 { -VisualScriptNodeInstance* VisualScriptMathConstant::instance(VScriptInstance* p_instance) { + *r_value = value; + return true; - return NULL; + } + + 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) { + + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptMathConstant::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceMathConstant * instance = memnew(VisualScriptNodeInstanceMathConstant ); + instance->value=const_value[constant]; + return instance; } + void VisualScriptMathConstant::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_math_constant","which"),&VisualScriptMathConstant::set_math_constant); @@ -1080,11 +1489,35 @@ String VisualScriptEngineSingleton::get_singleton() { -VisualScriptNodeInstance* VisualScriptEngineSingleton::instance(VScriptInstance* p_instance) { +class VisualScriptNodeInstanceEngineSingleton : public VisualScriptNodeInstance { +public: - return NULL; + Object* singleton; + + //virtual int get_working_memory_size() const { return 0; } + 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 { + + *r_value=singleton; + 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) { + + + return 0; + } + +}; + +VisualScriptNodeInstance* VisualScriptEngineSingleton::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceEngineSingleton * instance = memnew(VisualScriptNodeInstanceEngineSingleton ); + instance->singleton=Globals::get_singleton()->get_singleton_object(singleton); + return instance; } + void VisualScriptEngineSingleton::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_singleton","name"),&VisualScriptEngineSingleton::set_singleton); @@ -1176,12 +1609,53 @@ NodePath VisualScriptSceneNode::get_node_path() { } +class VisualScriptNodeInstanceSceneNode : public VisualScriptNodeInstance { +public: -VisualScriptNodeInstance* VisualScriptSceneNode::instance(VScriptInstance* p_instance) { + VisualScriptSceneNode *node; + VisualScriptInstance *instance; + NodePath path; - return NULL; + //virtual int get_working_memory_size() const { return 0; } + 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 { + + Node* node = instance->get_owner_ptr()->cast_to<Node>(); + if (!node) { + r_error="Base object is not a Node!"; + return false; + } + + + + Node* another = node->get_node(path); + if (!node) { + r_error="Path does not lead Node!"; + return false; + } + + *r_value=another; + 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) { + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptSceneNode::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceSceneNode * instance = memnew(VisualScriptNodeInstanceSceneNode ); + instance->node=this; + instance->instance=p_instance; + instance->path=path; + return instance; } + #ifdef TOOLS_ENABLED static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) { @@ -1302,12 +1776,51 @@ String VisualScriptSceneTree::get_text() const { } +class VisualScriptNodeInstanceSceneTree : public VisualScriptNodeInstance { +public: -VisualScriptNodeInstance* VisualScriptSceneTree::instance(VScriptInstance* p_instance) { + VisualScriptSceneTree *node; + VisualScriptInstance *instance; - return NULL; + //virtual int get_working_memory_size() const { return 0; } + 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 { + + Node* node = instance->get_owner_ptr()->cast_to<Node>(); + if (!node) { + r_error="Base object is not a Node!"; + return false; + } + + SceneTree* tree = node->get_tree(); + if (!tree) { + r_error="Attempt to get SceneTree while node is not in the active tree."; + return false; + } + + *r_value=tree; + 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) { + + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptSceneTree::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceSceneTree * instance = memnew(VisualScriptNodeInstanceSceneTree ); + instance->node=this; + instance->instance=p_instance; + return instance; } + void VisualScriptSceneTree::_validate_property(PropertyInfo& property) const { } @@ -1382,10 +1895,31 @@ String VisualScriptResourcePath::get_resource_path() { } +class VisualScriptNodeInstanceResourcePath : public VisualScriptNodeInstance { +public: -VisualScriptNodeInstance* VisualScriptResourcePath::instance(VScriptInstance* p_instance) { + String path; - return NULL; + //virtual int get_working_memory_size() const { return 0; } + 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 { + *r_value = path; + 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) { + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptResourcePath::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceResourcePath * instance = memnew(VisualScriptNodeInstanceResourcePath ); + instance->path=path; + return instance; } @@ -1404,9 +1938,104 @@ VisualScriptResourcePath::VisualScriptResourcePath() { } + +////////////////////////////////////////// +////////////////RESPATH/////////// +////////////////////////////////////////// + +int VisualScriptSelf::get_output_sequence_port_count() const { + + return 0; +} + +bool VisualScriptSelf::has_input_sequence_port() const{ + + return false; +} + +int VisualScriptSelf::get_input_value_port_count() const{ + + return 0; +} +int VisualScriptSelf::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptSelf::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptSelf::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + +PropertyInfo VisualScriptSelf::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(Variant::OBJECT,"instance"); +} + + +String VisualScriptSelf::get_caption() const { + + return "Self"; +} + +String VisualScriptSelf::get_text() const { + + if (get_visual_script().is_valid()) + return get_visual_script()->get_instance_base_type(); + else + return ""; +} + + +class VisualScriptNodeInstanceSelf : public VisualScriptNodeInstance { +public: + + VisualScriptInstance* instance; + + //virtual int get_working_memory_size() const { return 0; } + 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 { + + *r_value = instance->get_owner_ptr(); + 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) { + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptSelf::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceSelf * instance = memnew(VisualScriptNodeInstanceSelf ); + instance->instance=p_instance; + return instance; +} + + + +void VisualScriptSelf::_bind_methods() { + +} + +VisualScriptSelf::VisualScriptSelf() { + + +} + + void register_visual_script_nodes() { - VisualScriptLanguage::singleton->add_register_func("data/variable",create_node_generic<VisualScriptVariable>); + VisualScriptLanguage::singleton->add_register_func("data/set_variable",create_node_generic<VisualScriptVariableGet>); + VisualScriptLanguage::singleton->add_register_func("data/get_variable",create_node_generic<VisualScriptVariableSet>); VisualScriptLanguage::singleton->add_register_func("data/constant",create_node_generic<VisualScriptConstant>); VisualScriptLanguage::singleton->add_register_func("data/global_constant",create_node_generic<VisualScriptGlobalConstant>); VisualScriptLanguage::singleton->add_register_func("data/math_constant",create_node_generic<VisualScriptMathConstant>); @@ -1414,6 +2043,7 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("data/scene_node",create_node_generic<VisualScriptSceneNode>); VisualScriptLanguage::singleton->add_register_func("data/scene_tree",create_node_generic<VisualScriptSceneTree>); VisualScriptLanguage::singleton->add_register_func("data/resource_path",create_node_generic<VisualScriptResourcePath>); + VisualScriptLanguage::singleton->add_register_func("data/self",create_node_generic<VisualScriptSelf>); VisualScriptLanguage::singleton->add_register_func("index/get_index",create_node_generic<VisualScriptIndexGet>); diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index 6080050d78..fe0092fd04 100644 --- a/modules/visual_script/visual_script_nodes.h +++ b/modules/visual_script/visual_script_nodes.h @@ -14,6 +14,10 @@ class VisualScriptFunction : public VisualScriptNode { }; Vector<Argument> arguments; + + bool stack_less; + int stack_size; + protected: bool _set(const StringName& p_name, const Variant& p_value); @@ -38,6 +42,7 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "flow_control"; } void add_argument(Variant::Type p_type,const String& p_name,int p_index=-1); void set_argument_type(int p_argidx,Variant::Type p_type); @@ -47,7 +52,14 @@ public: void remove_argument(int p_argidx); int get_argument_count() const; - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + void set_stack_less(bool p_enable); + bool is_stack_less() const; + + void set_stack_size(int p_size); + int get_stack_size() const; + + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptFunction(); }; @@ -80,19 +92,59 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "operators"; } void set_operator(Variant::Operator p_op); Variant::Operator get_operator() const; - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptOperator(); }; -class VisualScriptVariable : public VisualScriptNode { +class VisualScriptVariableGet : public VisualScriptNode { + + OBJ_TYPE(VisualScriptVariableGet,VisualScriptNode) + + + StringName variable; +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 "data"; } + + void set_variable(StringName p_var); + StringName get_variable() const; + + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + + VisualScriptVariableGet(); +}; + + +class VisualScriptVariableSet : public VisualScriptNode { - OBJ_TYPE(VisualScriptVariable,VisualScriptNode) + OBJ_TYPE(VisualScriptVariableSet,VisualScriptNode) StringName variable; @@ -118,15 +170,17 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "data"; } void set_variable(StringName p_var); StringName get_variable() const; - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); - VisualScriptVariable(); + VisualScriptVariableSet(); }; + class VisualScriptConstant : public VisualScriptNode { OBJ_TYPE(VisualScriptConstant,VisualScriptNode) @@ -156,6 +210,7 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "data"; } void set_constant_type(Variant::Type p_type); Variant::Type get_constant_type() const; @@ -163,7 +218,7 @@ public: void set_constant_value(Variant p_value); Variant get_constant_value() const; - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptConstant(); }; @@ -192,8 +247,9 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "operators"; } - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptIndexGet(); }; @@ -222,8 +278,9 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "operators"; } - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptIndexSet(); }; @@ -255,11 +312,12 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "data"; } void set_global_constant(int p_which); int get_global_constant(); - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptGlobalConstant(); }; @@ -283,6 +341,7 @@ public: private: static const char* const_name[MATH_CONSTANT_MAX]; + static double const_value[MATH_CONSTANT_MAX]; MathConstant constant; protected: static void _bind_methods(); @@ -304,11 +363,12 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "data"; } void set_math_constant(MathConstant p_which); MathConstant get_math_constant(); - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptMathConstant(); }; @@ -340,11 +400,12 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "data"; } void set_singleton(const String &p_string); String get_singleton(); - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptEngineSingleton(); }; @@ -378,11 +439,12 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "data"; } void set_node_path(const NodePath &p_path); NodePath get_node_path(); - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptSceneNode(); }; @@ -416,8 +478,9 @@ public: virtual String get_caption() const; virtual String get_text() const; + virtual String get_category() const { return "data"; } - virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptSceneTree(); }; @@ -450,16 +513,54 @@ public: virtual String get_caption() const; 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(VScriptInstance* p_instance); + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptResourcePath(); }; +class VisualScriptSelf : public VisualScriptNode { + + OBJ_TYPE(VisualScriptSelf,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 "data"; } + + void set_resource_path(const String &p_path); + String get_resource_path(); + + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + + VisualScriptSelf(); +}; + + void register_visual_script_nodes(); #endif // VISUAL_SCRIPT_NODES_H diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 920c6bf1e6..feaf516f42 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -41,6 +41,8 @@ void Container::_child_minsize_changed() { void Container::add_child_notify(Node *p_child) { + Control::add_child_notify(p_child); + Control *control = p_child->cast_to<Control>(); if (!control) return; @@ -50,18 +52,24 @@ void Container::add_child_notify(Node *p_child) { control->connect("visibility_changed",this,"_child_minsize_changed"); queue_sort(); + } void Container::move_child_notify(Node *p_child) { + Control::move_child_notify(p_child); + if (!p_child->cast_to<Control>()) return; queue_sort(); + + } void Container::remove_child_notify(Node *p_child) { + Control::remove_child_notify(p_child); Control *control = p_child->cast_to<Control>(); if (!control) diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index c08e10b9ff..71ec508c81 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -422,6 +422,32 @@ void Control::_resize(const Size2& p_size) { _size_changed(); } +//moved theme configuration here, so controls can set up even if still not inside active scene + +void Control::add_child_notify(Node *p_child) { + + Control *child_c=p_child->cast_to<Control>(); + if (!child_c) + return; + + if (child_c->data.theme.is_null() && data.theme_owner) { + child_c->data.theme_owner=data.theme_owner; + child_c->notification(NOTIFICATION_THEME_CHANGED); + } +} + +void Control::remove_child_notify(Node *p_child) { + + Control *child_c=p_child->cast_to<Control>(); + if (!child_c) + return; + + if (child_c->data.theme_owner && child_c->data.theme.is_null()) { + child_c->data.theme_owner=NULL; + //notification(NOTIFICATION_THEME_CHANGED); + } + +} void Control::_notification(int p_notification) { @@ -512,10 +538,10 @@ void Control::_notification(int p_notification) { } - if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) { - data.theme_owner=data.parent->data.theme_owner; - notification(NOTIFICATION_THEME_CHANGED); - } + //if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) { + // data.theme_owner=data.parent->data.theme_owner; + // notification(NOTIFICATION_THEME_CHANGED); + //} } break; case NOTIFICATION_EXIT_CANVAS: { @@ -547,10 +573,10 @@ void Control::_notification(int p_notification) { data.parent=NULL; data.parent_canvas_item=NULL; - if (data.theme_owner && data.theme.is_null()) { - data.theme_owner=NULL; + //if (data.theme_owner && data.theme.is_null()) { + // data.theme_owner=NULL; //notification(NOTIFICATION_THEME_CHANGED); - } + //} } break; case NOTIFICATION_MOVED_IN_PARENT: { diff --git a/scene/gui/control.h b/scene/gui/control.h index 1337cbc4b9..b9ac53067a 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -194,12 +194,16 @@ private: void _font_changed(); + friend class Viewport; void _modal_stack_remove(); void _modal_set_prev_focus_owner(ObjectID p_prev); protected: + virtual void add_child_notify(Node *p_child); + virtual void remove_child_notify(Node *p_child); + //virtual void _window_input_event(InputEvent p_event); bool _set(const StringName& p_name, const Variant& p_value); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index c488dd0d16..888e884d87 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -196,6 +196,8 @@ void GraphEdit::_graph_node_moved(Node *p_gn) { void GraphEdit::add_child_notify(Node *p_child) { + Control::add_child_notify(p_child); + top_layer->call_deferred("raise"); //top layer always on top! GraphNode *gn = p_child->cast_to<GraphNode>(); if (gn) { @@ -205,10 +207,14 @@ void GraphEdit::add_child_notify(Node *p_child) { _graph_node_moved(gn); gn->set_stop_mouse(false); } + + } void GraphEdit::remove_child_notify(Node *p_child) { + Control::remove_child_notify(p_child); + top_layer->call_deferred("raise"); //top layer always on top! GraphNode *gn = p_child->cast_to<GraphNode>(); if (gn) { diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 1efc9a1ceb..a4776aebde 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -189,6 +189,8 @@ void GraphNode::_notification(int p_what) { if (p_what==NOTIFICATION_DRAW) { Ref<StyleBox> sb=get_stylebox(selected ? "selectedframe" : "frame"); + sb=sb->duplicate(); + sb->call("set_modulate",modulate); Ref<Texture> port =get_icon("port"); Ref<Texture> close =get_icon("close"); int close_offset = get_constant("close_offset"); @@ -198,6 +200,9 @@ void GraphNode::_notification(int p_what) { Point2i icofs = -port->get_size()*0.5; int edgeofs=get_constant("port_offset"); icofs.y+=sb->get_margin(MARGIN_TOP); + + + draw_style_box(sb,Rect2(Point2(),get_size())); int w = get_size().width-sb->get_minimum_size().x; @@ -590,6 +595,16 @@ void GraphNode::_input_event(const InputEvent& p_ev) { } +void GraphNode::set_modulate(const Color &p_color) { + + modulate=p_color; + update(); +} + +Color GraphNode::get_modulate() const{ + + return modulate; +} void GraphNode::_bind_methods() { @@ -620,6 +635,8 @@ void GraphNode::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_connection_input_type","idx"),&GraphNode::get_connection_input_type); ObjectTypeDB::bind_method(_MD("get_connection_input_color","idx"),&GraphNode::get_connection_input_color); + ObjectTypeDB::bind_method(_MD("set_modulate","color"),&GraphNode::set_modulate); + ObjectTypeDB::bind_method(_MD("get_modulate"),&GraphNode::get_modulate); ObjectTypeDB::bind_method(_MD("set_show_close_button","show"),&GraphNode::set_show_close_button); ObjectTypeDB::bind_method(_MD("is_close_button_visible"),&GraphNode::is_close_button_visible); @@ -637,4 +654,5 @@ GraphNode::GraphNode() { show_close=false; connpos_dirty=true; set_stop_mouse(false); + modulate=Color(1,1,1,1); } diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index f308f30b81..3e1729440e 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -77,6 +77,8 @@ class GraphNode : public Container { Vector2 drag_from; bool selected; + + Color modulate; protected: @@ -128,6 +130,9 @@ public: Color get_connection_output_color(int p_idx); + void set_modulate(const Color& p_color); + Color get_modulate() const; + virtual Size2 get_minimum_size() const; GraphNode(); diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 0e0339c488..8557500488 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -400,6 +400,7 @@ void TabContainer::_child_renamed_callback() { void TabContainer::add_child_notify(Node *p_child) { + Control::add_child_notify(p_child); Control *c = p_child->cast_to<Control>(); if (!c) @@ -532,6 +533,8 @@ Control* TabContainer::get_current_tab_control() const { void TabContainer::remove_child_notify(Node *p_child) { + Control::remove_child_notify(p_child); + int tc = get_tab_count(); if (current==tc-1) { current--; diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index 8580ffdc5a..59246dfabe 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -141,7 +141,7 @@ void StyleBoxTexture::draw(RID p_canvas_item,const Rect2& p_rect) const { r.pos.y-=expand_margin[MARGIN_TOP]; r.size.x+=expand_margin[MARGIN_LEFT]+expand_margin[MARGIN_RIGHT]; r.size.y+=expand_margin[MARGIN_TOP]+expand_margin[MARGIN_BOTTOM]; - VisualServer::get_singleton()->canvas_item_add_style_box( p_canvas_item,r,region_rect,texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center); + VisualServer::get_singleton()->canvas_item_add_style_box( p_canvas_item,r,region_rect,texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center,modulate); } void StyleBoxTexture::set_draw_center(bool p_draw) { @@ -193,6 +193,19 @@ Rect2 StyleBoxTexture::get_region_rect() const { } +void StyleBoxTexture::set_modulate(const Color& p_modulate) { + if (modulate==p_modulate) + return; + modulate=p_modulate; + emit_changed(); +} + +Color StyleBoxTexture::get_modulate() const { + + return modulate; +} + + void StyleBoxTexture::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_texture","texture:Texture"),&StyleBoxTexture::set_texture); @@ -210,6 +223,10 @@ void StyleBoxTexture::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_draw_center","enable"),&StyleBoxTexture::set_draw_center); ObjectTypeDB::bind_method(_MD("get_draw_center"),&StyleBoxTexture::get_draw_center); + ObjectTypeDB::bind_method(_MD("set_modulate","color"),&StyleBoxTexture::set_modulate); + ObjectTypeDB::bind_method(_MD("get_modulate"),&StyleBoxTexture::get_modulate); + + ADD_SIGNAL(MethodInfo("texture_changed")); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), _SCS("set_texture"),_SCS("get_texture") ); @@ -222,6 +239,7 @@ void StyleBoxTexture::_bind_methods() { ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin/right", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_RIGHT ); ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin/top", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_TOP ); ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin/bottom", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_BOTTOM ); + ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate/color" ), _SCS("set_modulate"),_SCS("get_modulate")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "draw_center" ) , _SCS("set_draw_center"),_SCS("get_draw_center")); } @@ -234,6 +252,7 @@ StyleBoxTexture::StyleBoxTexture() { expand_margin[i]=0; } draw_center=true; + modulate=Color(1,1,1,1); } StyleBoxTexture::~StyleBoxTexture() { diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h index 98aaee754b..f667318e24 100644 --- a/scene/resources/style_box.h +++ b/scene/resources/style_box.h @@ -84,6 +84,7 @@ class StyleBoxTexture : public StyleBox { Rect2 region_rect; Ref<Texture> texture; bool draw_center; + Color modulate; protected: @@ -109,6 +110,9 @@ public: bool get_draw_center() const; virtual Size2 get_center_size() const; + void set_modulate(const Color& p_modulate); + Color get_modulate() const; + virtual void draw(RID p_canvas_item,const Rect2& p_rect) const; diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index 9dcf71e256..11402c64e9 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -647,6 +647,11 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { set("import/automatic_reimport_on_sources_changed",true); + set("visual_script/color_functions",Color(1,0.9,0.9)); + set("visual_script/color_data",Color(0.9,1.0,0.9)); + set("visual_script/color_operators",Color(0.9,0.9,1.0)); + set("visual_script/color_flow_control",Color(1.0,1.0,0.8)); + if (p_extra_config.is_valid()) { if (p_extra_config->has_section("init_projects") && p_extra_config->has_section_key("init_projects", "list")) { @@ -945,6 +950,8 @@ bool EditorSettings::_save_text_editor_theme(String p_file) { cf->set_value(theme_section, "word_highlighted_color", ((Color)get("text_editor/word_highlighted_color")).to_html()); cf->set_value(theme_section, "search_result_color", ((Color)get("text_editor/search_result_color")).to_html()); cf->set_value(theme_section, "search_result_border_color", ((Color)get("text_editor/search_result_border_color")).to_html()); + + Error err = cf->save(p_file); if (err == OK) { diff --git a/tools/editor/script_create_dialog.cpp b/tools/editor/script_create_dialog.cpp index e93a40efbc..749198314a 100644 --- a/tools/editor/script_create_dialog.cpp +++ b/tools/editor/script_create_dialog.cpp @@ -117,20 +117,20 @@ void ScriptCreateDialog::ok_pressed() { - String text = ScriptServer::get_language( language_menu->get_selected() )->get_template(cname,parent_name->get_text()); - Script *script = ScriptServer::get_language( language_menu->get_selected() )->create_script(); - script->set_source_code(text); - if (cname!="") - script->set_name(cname); + Ref<Script> scr = ScriptServer::get_language( language_menu->get_selected() )->get_template(cname,parent_name->get_text()); + //scr->set_source_code(text); + + + if (cname!="") + scr->set_name(cname); - Ref<Script> scr(script); if (!internal->is_pressed()) { String lpath = Globals::get_singleton()->localize_path(file_path->get_text()); - script->set_path(lpath); + scr->set_path(lpath); if (!path_valid) { alert->set_text(TTR("Invalid path!")); @@ -145,7 +145,7 @@ void ScriptCreateDialog::ok_pressed() { alert->popup_centered_minsize(); return; } - scr->set_path(lpath); + //scr->set_path(lpath); //EditorFileSystem::get_singleton()->update_file(lpath,scr->get_type()); |