diff options
Diffstat (limited to 'modules/visual_script')
-rw-r--r-- | modules/visual_script/SCsub | 5 | ||||
-rw-r--r-- | modules/visual_script/config.py | 11 | ||||
-rw-r--r-- | modules/visual_script/register_types.cpp | 96 | ||||
-rw-r--r-- | modules/visual_script/register_types.h | 30 | ||||
-rw-r--r-- | modules/visual_script/visual_script.cpp | 1156 | ||||
-rw-r--r-- | modules/visual_script/visual_script.h | 318 | ||||
-rw-r--r-- | modules/visual_script/visual_script_builtin_funcs.cpp | 641 | ||||
-rw-r--r-- | modules/visual_script/visual_script_builtin_funcs.h | 109 | ||||
-rw-r--r-- | modules/visual_script/visual_script_editor.cpp | 1956 | ||||
-rw-r--r-- | modules/visual_script/visual_script_editor.h | 147 | ||||
-rw-r--r-- | modules/visual_script/visual_script_flow_control.cpp | 418 | ||||
-rw-r--r-- | modules/visual_script/visual_script_flow_control.h | 196 | ||||
-rw-r--r-- | modules/visual_script/visual_script_func_nodes.cpp | 1584 | ||||
-rw-r--r-- | modules/visual_script/visual_script_func_nodes.h | 325 | ||||
-rw-r--r-- | modules/visual_script/visual_script_nodes.cpp | 1297 | ||||
-rw-r--r-- | modules/visual_script/visual_script_nodes.h | 394 |
16 files changed, 8683 insertions, 0 deletions
diff --git a/modules/visual_script/SCsub b/modules/visual_script/SCsub new file mode 100644 index 0000000000..403fe68f66 --- /dev/null +++ b/modules/visual_script/SCsub @@ -0,0 +1,5 @@ +Import('env') + +env.add_source_files(env.modules_sources,"*.cpp") + +Export('env') diff --git a/modules/visual_script/config.py b/modules/visual_script/config.py new file mode 100644 index 0000000000..ea7e83378a --- /dev/null +++ b/modules/visual_script/config.py @@ -0,0 +1,11 @@ + + +def can_build(platform): + return True + + +def configure(env): + pass + + + diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp new file mode 100644 index 0000000000..2cd84203e8 --- /dev/null +++ b/modules/visual_script/register_types.cpp @@ -0,0 +1,96 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "visual_script.h" +#include "visual_script_editor.h" +#include "io/resource_loader.h" +#include "visual_script_nodes.h" +#include "visual_script_func_nodes.h" +#include "visual_script_builtin_funcs.h" +#include "visual_script_flow_control.h" + + +VisualScriptLanguage *visual_script_language=NULL; + + +void register_visual_script_types() { + + ObjectTypeDB::register_type<VisualScript>(); + ObjectTypeDB::register_virtual_type<VisualScriptNode>(); + ObjectTypeDB::register_type<VisualScriptFunction>(); + ObjectTypeDB::register_type<VisualScriptOperator>(); + ObjectTypeDB::register_type<VisualScriptVariable>(); + ObjectTypeDB::register_type<VisualScriptConstant>(); + ObjectTypeDB::register_type<VisualScriptIndexGet>(); + ObjectTypeDB::register_type<VisualScriptIndexSet>(); + ObjectTypeDB::register_type<VisualScriptGlobalConstant>(); + ObjectTypeDB::register_type<VisualScriptMathConstant>(); + ObjectTypeDB::register_type<VisualScriptSingleton>(); + ObjectTypeDB::register_type<VisualScriptSceneNode>(); + + ObjectTypeDB::register_type<VisualScriptFunctionCall>(); + ObjectTypeDB::register_type<VisualScriptPropertySet>(); + ObjectTypeDB::register_type<VisualScriptPropertyGet>(); + ObjectTypeDB::register_type<VisualScriptScriptCall>(); + ObjectTypeDB::register_type<VisualScriptEmitSignal>(); + + ObjectTypeDB::register_type<VisualScriptReturn>(); + ObjectTypeDB::register_type<VisualScriptCondition>(); + ObjectTypeDB::register_type<VisualScriptWhile>(); + ObjectTypeDB::register_type<VisualScriptIterator>(); + ObjectTypeDB::register_type<VisualScriptSequence>(); + + ObjectTypeDB::register_type<VisualScriptBuiltinFunc>(); + + visual_script_language=memnew( VisualScriptLanguage ); + //script_language_gd->init(); + ScriptServer::register_language(visual_script_language); + + register_visual_script_nodes(); + register_visual_script_func_nodes(); + register_visual_script_builtin_func_node(); + register_visual_script_flow_control_nodes(); + +#ifdef TOOLS_ENABLED + VisualScriptEditor::register_editor(); +#endif + + +} + +void unregister_visual_script_types() { + + + ScriptServer::unregister_language(visual_script_language); + + if (visual_script_language) + memdelete( visual_script_language ); + +} diff --git a/modules/visual_script/register_types.h b/modules/visual_script/register_types.h new file mode 100644 index 0000000000..0a5805eb0b --- /dev/null +++ b/modules/visual_script/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_visual_script_types(); +void unregister_visual_script_types(); diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp new file mode 100644 index 0000000000..6541ac6b86 --- /dev/null +++ b/modules/visual_script/visual_script.cpp @@ -0,0 +1,1156 @@ +#include "visual_script.h" +#include "visual_script_nodes.h" + +void VisualScriptNode::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("get_visual_script:VisualScript"),&VisualScriptNode::get_visual_script); + ADD_SIGNAL(MethodInfo("ports_changed")); +} + + +Ref<VisualScript> VisualScriptNode::get_visual_script() const { + + if (scripts_used.size()) + return Ref<VisualScript>(scripts_used.front()->get()); + + return Ref<VisualScript>(); + +} + +//////////////// + +///////////////////// + +VisualScriptNodeInstance::~VisualScriptNodeInstance() { + +} + +void VisualScript::add_function(const StringName& p_name) { + + ERR_FAIL_COND(!String(p_name).is_valid_identifier()); + ERR_FAIL_COND(functions.has(p_name)); + + functions[p_name]=Function(); +} + +bool VisualScript::has_function(const StringName& p_name) const { + + return functions.has(p_name); + +} +void VisualScript::remove_function(const StringName& p_name) { + + ERR_FAIL_COND(!functions.has(p_name)); + + for (Map<int,Function::NodeData>::Element *E=functions[p_name].nodes.front();E;E=E->next()) { + + E->get().node->disconnect("ports_changed",this,"_node_ports_changed"); + E->get().node->scripts_used.erase(this); + } + + functions.erase(p_name); + +} + +void VisualScript::rename_function(const StringName& p_name,const StringName& p_new_name) { + + ERR_FAIL_COND(!functions.has(p_name)); + if (p_new_name==p_name) + return; + + ERR_FAIL_COND(!String(p_new_name).is_valid_identifier()); + + ERR_FAIL_COND(functions.has(p_new_name)); + ERR_FAIL_COND(variables.has(p_new_name)); + ERR_FAIL_COND(custom_signals.has(p_new_name)); + + functions[p_new_name]=functions[p_name]; + functions.erase(p_name); + +} + +void VisualScript::get_function_list(List<StringName> *r_functions) const { + + for (const Map<StringName,Function>::Element *E=functions.front();E;E=E->next()) { + r_functions->push_back(E->key()); + } + + r_functions->sort_custom<StringName::AlphCompare>(); + +} + +int VisualScript::get_function_node_id(const StringName& p_name) const { + + ERR_FAIL_COND_V(!functions.has(p_name),-1); + + return functions[p_name].function_id; + +} + + +void VisualScript::_node_ports_changed(int p_id) { + + + StringName function; + + for (Map<StringName,Function>::Element *E=functions.front();E;E=E->next()) { + + if (E->get().nodes.has(p_id)) { + function=E->key(); + break; + } + } + + ERR_FAIL_COND(function==StringName()); + + Function &func = functions[function]; + Ref<VisualScriptNode> vsn = func.nodes[p_id].node; + + //must revalidate all the functions + + { + List<SequenceConnection> to_remove; + + for (Set<SequenceConnection>::Element *E=func.sequence_connections.front();E;E=E->next()) { + if (E->get().from_node==p_id && E->get().from_output>=vsn->get_output_sequence_port_count()) { + + to_remove.push_back(E->get()); + } + if (E->get().to_node==p_id && !vsn->has_input_sequence_port()) { + + to_remove.push_back(E->get()); + } + } + + while(to_remove.size()) { + func.sequence_connections.erase(to_remove.front()->get()); + to_remove.pop_front(); + } + } + + { + + List<DataConnection> to_remove; + + + for (Set<DataConnection>::Element *E=func.data_connections.front();E;E=E->next()) { + if (E->get().from_node==p_id && E->get().from_port>=vsn->get_output_value_port_count()) { + to_remove.push_back(E->get()); + } + if (E->get().to_node==p_id && E->get().to_port>=vsn->get_input_value_port_count()) { + to_remove.push_back(E->get()); + } + } + + while(to_remove.size()) { + func.data_connections.erase(to_remove.front()->get()); + to_remove.pop_front(); + } + } + + emit_signal("node_ports_changed",function,p_id); +} + +void VisualScript::add_node(const StringName& p_func,int p_id, const Ref<VisualScriptNode>& p_node, const Point2 &p_pos) { + + ERR_FAIL_COND(!functions.has(p_func)); + + + for (Map<StringName,Function>::Element *E=functions.front();E;E=E->next()) { + + ERR_FAIL_COND(E->get().nodes.has(p_id)); //id can exist only one in script, even for different functions + } + + Function &func = functions[p_func]; + + + if (p_node->cast_to<VisualScriptFunction>()) { + //the function indeed + ERR_EXPLAIN("A function node already has been set here."); + ERR_FAIL_COND(func.function_id>=0); + + func.function_id=p_id; + } + + Function::NodeData nd; + nd.node=p_node; + nd.pos=p_pos; + + Ref<VisualScriptNode> vsn = p_node; + vsn->connect("ports_changed",this,"_node_ports_changed",varray(p_id)); + vsn->scripts_used.insert(this); + + + + func.nodes[p_id]=nd; +} + +void VisualScript::remove_node(const StringName& p_func,int p_id){ + + ERR_FAIL_COND(!functions.has(p_func)); + Function &func = functions[p_func]; + + ERR_FAIL_COND(!func.nodes.has(p_id)); + { + List<SequenceConnection> to_remove; + + for (Set<SequenceConnection>::Element *E=func.sequence_connections.front();E;E=E->next()) { + if (E->get().from_node==p_id || E->get().to_node==p_id) { + to_remove.push_back(E->get()); + } + } + + while(to_remove.size()) { + func.sequence_connections.erase(to_remove.front()->get()); + to_remove.pop_front(); + } + } + + { + + List<DataConnection> to_remove; + + + for (Set<DataConnection>::Element *E=func.data_connections.front();E;E=E->next()) { + if (E->get().from_node==p_id || E->get().to_node==p_id) { + to_remove.push_back(E->get()); + } + } + + while(to_remove.size()) { + func.data_connections.erase(to_remove.front()->get()); + to_remove.pop_front(); + } + } + + if (func.nodes[p_id].node->cast_to<VisualScriptFunction>()) { + func.function_id=-1; //revert to invalid + } + + func.nodes[p_id].node->disconnect("ports_changed",this,"_node_ports_changed"); + func.nodes[p_id].node->scripts_used.erase(this); + + func.nodes.erase(p_id); + + +} + + + +Ref<VisualScriptNode> VisualScript::get_node(const StringName& p_func,int p_id) const{ + + ERR_FAIL_COND_V(!functions.has(p_func),Ref<VisualScriptNode>()); + const Function &func = functions[p_func]; + + ERR_FAIL_COND_V(!func.nodes.has(p_id),Ref<VisualScriptNode>()); + + return func.nodes[p_id].node; +} + +void VisualScript::set_node_pos(const StringName& p_func,int p_id,const Point2& p_pos) { + + ERR_FAIL_COND(!functions.has(p_func)); + Function &func = functions[p_func]; + + ERR_FAIL_COND(!func.nodes.has(p_id)); + func.nodes[p_id].pos=p_pos; +} + +Point2 VisualScript::get_node_pos(const StringName& p_func,int p_id) const{ + + ERR_FAIL_COND_V(!functions.has(p_func),Point2()); + const Function &func = functions[p_func]; + + ERR_FAIL_COND_V(!func.nodes.has(p_id),Point2()); + return func.nodes[p_id].pos; +} + + +void VisualScript::get_node_list(const StringName& p_func,List<int> *r_nodes) const{ + + ERR_FAIL_COND(!functions.has(p_func)); + const Function &func = functions[p_func]; + + for (const Map<int,Function::NodeData>::Element *E=func.nodes.front();E;E=E->next()) { + r_nodes->push_back(E->key()); + } + +} + + +void VisualScript::sequence_connect(const StringName& p_func,int p_from_node,int p_from_output,int p_to_node){ + + ERR_FAIL_COND(!functions.has(p_func)); + Function &func = functions[p_func]; + + + SequenceConnection sc; + sc.from_node=p_from_node; + sc.from_output=p_from_output; + sc.to_node=p_to_node; + ERR_FAIL_COND(func.sequence_connections.has(sc)); + + func.sequence_connections.insert(sc); + +} + +void VisualScript::sequence_disconnect(const StringName& p_func,int p_from_node,int p_from_output,int p_to_node){ + + ERR_FAIL_COND(!functions.has(p_func)); + Function &func = functions[p_func]; + + SequenceConnection sc; + sc.from_node=p_from_node; + sc.from_output=p_from_output; + sc.to_node=p_to_node; + ERR_FAIL_COND(!func.sequence_connections.has(sc)); + + func.sequence_connections.erase(sc); + +} + +bool VisualScript::has_sequence_connection(const StringName& p_func,int p_from_node,int p_from_output,int p_to_node) const{ + + ERR_FAIL_COND_V(!functions.has(p_func),false); + const Function &func = functions[p_func]; + + SequenceConnection sc; + sc.from_node=p_from_node; + sc.from_output=p_from_output; + sc.to_node=p_to_node; + + return func.sequence_connections.has(sc); +} + +void VisualScript::get_sequence_connection_list(const StringName& p_func,List<SequenceConnection> *r_connection) const { + + ERR_FAIL_COND(!functions.has(p_func)); + const Function &func = functions[p_func]; + + for (const Set<SequenceConnection>::Element *E=func.sequence_connections.front();E;E=E->next()) { + r_connection->push_back(E->get()); + } +} + + +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(!functions.has(p_func)); + Function &func = functions[p_func]; + + DataConnection dc; + dc.from_node=p_from_node; + dc.from_port=p_from_port; + dc.to_node=p_to_node; + dc.to_port=p_to_port; + + ERR_FAIL_COND( func.data_connections.has(dc)); + + func.data_connections.insert(dc); +} + +void VisualScript::data_disconnect(const StringName& p_func,int p_from_node,int p_from_port,int p_to_node,int p_to_port) { + + ERR_FAIL_COND(!functions.has(p_func)); + Function &func = functions[p_func]; + + DataConnection dc; + dc.from_node=p_from_node; + dc.from_port=p_from_port; + dc.to_node=p_to_node; + dc.to_port=p_to_port; + + ERR_FAIL_COND( !func.data_connections.has(dc)); + + func.data_connections.erase(dc); + +} + +bool VisualScript::has_data_connection(const StringName& p_func,int p_from_node,int p_from_port,int p_to_node,int p_to_port) const { + + ERR_FAIL_COND_V(!functions.has(p_func),false); + const Function &func = functions[p_func]; + + DataConnection dc; + dc.from_node=p_from_node; + dc.from_port=p_from_port; + dc.to_node=p_to_node; + dc.to_port=p_to_port; + + return func.data_connections.has(dc); + +} + +void VisualScript::get_data_connection_list(const StringName& p_func,List<DataConnection> *r_connection) const { + + ERR_FAIL_COND(!functions.has(p_func)); + const Function &func = functions[p_func]; + + for (const Set<DataConnection>::Element *E=func.data_connections.front();E;E=E->next()) { + r_connection->push_back(E->get()); + } +} + +void VisualScript::add_variable(const StringName& p_name,const Variant& p_default_value) { + + ERR_FAIL_COND(!String(p_name).is_valid_identifier()); + ERR_FAIL_COND(variables.has(p_name)); + + Variable v; + v.default_value=p_default_value; + v.info.type=p_default_value.get_type(); + v.info.name=p_name; + v.info.hint=PROPERTY_HINT_NONE; + + variables[p_name]=v; + +} + +bool VisualScript::has_variable(const StringName& p_name) const { + + return variables.has(p_name); +} + +void VisualScript::remove_variable(const StringName& p_name) { + + ERR_FAIL_COND(!variables.has(p_name)); + variables.erase(p_name); +} + +void VisualScript::set_variable_default_value(const StringName& p_name,const Variant& p_value){ + + ERR_FAIL_COND(!variables.has(p_name)); + + variables[p_name].default_value=p_value; + +} +Variant VisualScript::get_variable_default_value(const StringName& p_name) const{ + + ERR_FAIL_COND_V(!variables.has(p_name),Variant()); + return variables[p_name].default_value; + +} +void VisualScript::set_variable_info(const StringName& p_name,const PropertyInfo& p_info){ + + ERR_FAIL_COND(!variables.has(p_name)); + variables[p_name].info=p_info; + variables[p_name].info.name=p_name; + + +} +PropertyInfo VisualScript::get_variable_info(const StringName& p_name) const{ + + ERR_FAIL_COND_V(!variables.has(p_name),PropertyInfo()); + return variables[p_name].info; +} + +void VisualScript::_set_variable_info(const StringName& p_name,const Dictionary& p_info) { + + PropertyInfo pinfo; + if (p_info.has("type")) + pinfo.type=Variant::Type(int(p_info["type"])); + if (p_info.has("name")) + pinfo.name=p_info["name"]; + if (p_info.has("hint")) + pinfo.hint=PropertyHint(int(p_info["hint"])); + if (p_info.has("hint_string")) + pinfo.hint_string=p_info["hint_string"]; + if (p_info.has("usage")) + pinfo.usage=p_info["usage"]; + + set_variable_info(p_name,pinfo); +} + +Dictionary VisualScript::_get_variable_info(const StringName& p_name) const{ + + PropertyInfo pinfo=get_variable_info(p_name); + Dictionary d; + d["type"]=pinfo.type; + d["name"]=pinfo.name; + d["hint"]=pinfo.hint; + d["hint_string"]=pinfo.hint_string; + d["usage"]=pinfo.usage; + + return d; +} + +void VisualScript::get_variable_list(List<StringName> *r_variables){ + + + for (Map<StringName,Variable>::Element *E=variables.front();E;E=E->next()) { + r_variables->push_back(E->key()); + } + + r_variables->sort_custom<StringName::AlphCompare>(); +} + + +void VisualScript::set_instance_base_type(const StringName& p_type) { + + base_type=p_type; +} + + +void VisualScript::rename_variable(const StringName& p_name,const StringName& p_new_name) { + + ERR_FAIL_COND(!variables.has(p_name)); + if (p_new_name==p_name) + return; + + ERR_FAIL_COND(!String(p_new_name).is_valid_identifier()); + + ERR_FAIL_COND(functions.has(p_new_name)); + ERR_FAIL_COND(variables.has(p_new_name)); + ERR_FAIL_COND(custom_signals.has(p_new_name)); + + variables[p_new_name]=variables[p_name]; + variables.erase(p_name); + +} + +void VisualScript::add_custom_signal(const StringName& p_name) { + + ERR_FAIL_COND(!String(p_name).is_valid_identifier()); + ERR_FAIL_COND(custom_signals.has(p_name)); + + custom_signals[p_name]=Vector<Argument>(); +} + +bool VisualScript::has_custom_signal(const StringName& p_name) const { + + return custom_signals.has(p_name); + +} +void VisualScript::custom_signal_add_argument(const StringName& p_func,Variant::Type p_type,const String& p_name,int p_index) { + + ERR_FAIL_COND(!custom_signals.has(p_func)); + Argument arg; + arg.type=p_type; + arg.name=p_name; + if (p_index<0) + custom_signals[p_func].push_back(arg); + else + custom_signals[p_func].insert(0,arg); + +} +void VisualScript::custom_signal_set_argument_type(const StringName& p_func,int p_argidx,Variant::Type p_type) { + + 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; +} +Variant::Type VisualScript::custom_signal_get_argument_type(const StringName& p_func,int p_argidx) const { + + ERR_FAIL_COND_V(!custom_signals.has(p_func),Variant::NIL); + ERR_FAIL_INDEX_V(p_argidx,custom_signals[p_func].size(),Variant::NIL); + 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(!custom_signals.has(p_func)); + ERR_FAIL_INDEX(p_argidx,custom_signals[p_func].size()); + custom_signals[p_func][p_argidx].name=p_name; + +} +String VisualScript::custom_signal_get_argument_name(const StringName& p_func,int p_argidx) const { + + ERR_FAIL_COND_V(!custom_signals.has(p_func),String()); + ERR_FAIL_INDEX_V(p_argidx,custom_signals[p_func].size(),String()); + return custom_signals[p_func][p_argidx].name; + +} +void VisualScript::custom_signal_remove_argument(const StringName& p_func,int p_argidx) { + + 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); + +} + +int VisualScript::custom_signal_get_argument_count(const StringName& p_func) const { + + ERR_FAIL_COND_V(!custom_signals.has(p_func),0); + return custom_signals[p_func].size(); + +} +void VisualScript::custom_signal_swap_argument(const StringName& p_func,int p_argidx,int p_with_argidx) { + + 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()); + + SWAP( custom_signals[p_func][p_argidx], custom_signals[p_func][p_with_argidx] ); + +} +void VisualScript::remove_custom_signal(const StringName& p_name) { + + ERR_FAIL_COND(!custom_signals.has(p_name)); + custom_signals.erase(p_name); + +} + +void VisualScript::rename_custom_signal(const StringName& p_name,const StringName& p_new_name) { + + ERR_FAIL_COND(!custom_signals.has(p_name)); + if (p_new_name==p_name) + return; + + ERR_FAIL_COND(!String(p_new_name).is_valid_identifier()); + + ERR_FAIL_COND(functions.has(p_new_name)); + ERR_FAIL_COND(variables.has(p_new_name)); + ERR_FAIL_COND(custom_signals.has(p_new_name)); + + custom_signals[p_new_name]=custom_signals[p_name]; + custom_signals.erase(p_name); + +} + +void VisualScript::get_custom_signal_list(List<StringName> *r_custom_signals) const { + + for (const Map<StringName,Vector<Argument> >::Element *E=custom_signals.front();E;E=E->next()) { + r_custom_signals->push_back(E->key()); + } + + r_custom_signals->sort_custom<StringName::AlphCompare>(); + +} + +int VisualScript::get_available_id() const { + + int max_id=0; + for (Map<StringName,Function>::Element *E=functions.front();E;E=E->next()) { + if (E->get().nodes.empty()) + continue; + + int last_id = E->get().nodes.back()->key(); + max_id=MAX(max_id,last_id+1); + } + + return max_id; +} + +///////////////////////////////// + + +bool VisualScript::can_instance() const { + + return ScriptServer::is_scripting_enabled(); + +} + + +StringName VisualScript::get_instance_base_type() const { + + return base_type; +} + +ScriptInstance* VisualScript::instance_create(Object *p_this) { + + return NULL; +} + +bool VisualScript::instance_has(const Object *p_this) const { + + return false; +} + +bool VisualScript::has_source_code() const { + + return false; +} + +String VisualScript::get_source_code() const { + + return String(); +} + +void VisualScript::set_source_code(const String& p_code) { + +} + +Error VisualScript::reload(bool p_keep_state) { + + return OK; +} + + +bool VisualScript::is_tool() const { + + return false; +} + + +String VisualScript::get_node_type() const { + + return String(); +} + + +ScriptLanguage *VisualScript::get_language() const { + + return VisualScriptLanguage::singleton; +} + + +bool VisualScript::has_script_signal(const StringName& p_signal) const { + + return false; +} + +void VisualScript::get_script_signal_list(List<MethodInfo> *r_signals) const { + +} + + +bool VisualScript::get_property_default_value(const StringName& p_property,Variant& r_value) const { + + return false; +} +void VisualScript::get_method_list(List<MethodInfo> *p_list) const { + + for (Map<StringName,Function>::Element *E=functions.front();E;E=E->next()) { + + MethodInfo mi; + mi.name=E->key(); + if (E->get().function_id>=0) { + + Ref<VisualScriptFunction> func=E->get().nodes[E->get().function_id].node; + if (func.is_valid()) { + + for(int i=0;i<func->get_argument_count();i++) { + PropertyInfo arg; + arg.name=func->get_argument_name(i); + arg.type=func->get_argument_type(i); + mi.arguments.push_back(arg); + } + } + } + + p_list->push_back(mi); + } +} + +void VisualScript::_set_data(const Dictionary& p_data) { + + Dictionary d = p_data; + if (d.has("base_type")) + base_type=d["base_type"]; + + variables.clear(); + Array vars=d["variables"]; + 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); + } + + + custom_signals.clear(); + Array sigs=d["signals"]; + for (int i=0;i<sigs.size();i++) { + + Dictionary cs=sigs[i]; + add_custom_signal(cs["name"]); + + Array args=cs["arguments"]; + for(int j=0;j<args.size();j+=2) { + custom_signal_add_argument(cs["name"],Variant::Type(int(args[j+1])),args[j]); + } + } + + Array funcs=d["functions"]; + functions.clear(); + + for (int i=0;i<funcs.size();i++) { + + Dictionary func=funcs[i]; + + StringName name=func["name"]; + //int id=func["function_id"]; + add_function(name); + + Array nodes = func["nodes"]; + + for(int i=0;i<nodes.size();i+=3) { + + add_node(name,nodes[i],nodes[i+2],nodes[i+1]); + } + + + Array sequence_connections=func["sequence_connections"]; + + for (int j=0;j<sequence_connections.size();j+=3) { + + sequence_connect(name,sequence_connections[j+0],sequence_connections[j+1],sequence_connections[j+2]); + } + + + Array data_connections=func["data_connections"]; + + for (int j=0;j<data_connections.size();j+=4) { + + data_connect(name,data_connections[j+0],data_connections[j+1],data_connections[j+2],data_connections[j+3]); + + } + + + } + +} + +Dictionary VisualScript::_get_data() const{ + + Dictionary d; + d["base_type"]=base_type; + Array vars; + for (const Map<StringName,Variable>::Element *E=variables.front();E;E=E->next()) { + + Dictionary var = _get_variable_info(E->key()); + var["name"]=E->key(); //make sure it's the right one + var["default_value"]=E->get().default_value; + vars.push_back(var); + } + d["variables"]=vars; + + Array sigs; + for (const Map<StringName,Vector<Argument> >::Element *E=custom_signals.front();E;E=E->next()) { + + Dictionary cs; + cs["name"]=E->key(); + Array args; + for(int i=0;i<E->get().size();i++) { + args.push_back(E->get()[i].name); + args.push_back(E->get()[i].type); + } + cs["arguments"]=args; + + sigs.push_back(cs); + } + + d["signals"]=sigs; + + Array funcs; + + for (const Map<StringName,Function>::Element *E=functions.front();E;E=E->next()) { + + Dictionary func; + func["name"]=E->key(); + func["function_id"]=E->get().function_id; + + Array nodes; + + for (const Map<int,Function::NodeData>::Element *F=E->get().nodes.front();F;F=F->next()) { + + nodes.push_back(F->key()); + nodes.push_back(F->get().pos); + nodes.push_back(F->get().node); + + } + + func["nodes"]=nodes; + + Array sequence_connections; + + for (const Set<SequenceConnection>::Element *F=E->get().sequence_connections.front();F;F=F->next()) { + + sequence_connections.push_back(F->get().from_node); + sequence_connections.push_back(F->get().from_output); + sequence_connections.push_back(F->get().to_node); + + } + + + func["sequence_connections"]=sequence_connections; + + Array data_connections; + + for (const Set<DataConnection>::Element *F=E->get().data_connections.front();F;F=F->next()) { + + data_connections.push_back(F->get().from_node); + data_connections.push_back(F->get().from_port); + data_connections.push_back(F->get().to_node); + data_connections.push_back(F->get().to_port); + + } + + + func["data_connections"]=data_connections; + + funcs.push_back(func); + + } + + d["functions"]=funcs; + + + return d; + +} + +void VisualScript::_bind_methods() { + + + + ObjectTypeDB::bind_method(_MD("_node_ports_changed"),&VisualScript::_node_ports_changed); + + ObjectTypeDB::bind_method(_MD("add_function","name"),&VisualScript::add_function); + ObjectTypeDB::bind_method(_MD("has_function","name"),&VisualScript::has_function); + ObjectTypeDB::bind_method(_MD("remove_function","name"),&VisualScript::remove_function); + ObjectTypeDB::bind_method(_MD("rename_function","name","new_name"),&VisualScript::rename_function); + + ObjectTypeDB::bind_method(_MD("add_node","func","id","node","pos"),&VisualScript::add_node,DEFVAL(Point2())); + ObjectTypeDB::bind_method(_MD("remove_node","func","id"),&VisualScript::remove_node); + ObjectTypeDB::bind_method(_MD("get_function_node_id","name"),&VisualScript::get_function_node_id); + + ObjectTypeDB::bind_method(_MD("get_node","func","id"),&VisualScript::get_node); + ObjectTypeDB::bind_method(_MD("set_node_pos","func","id","pos"),&VisualScript::set_node_pos); + ObjectTypeDB::bind_method(_MD("get_node_pos","func","id"),&VisualScript::get_node_pos); + + ObjectTypeDB::bind_method(_MD("sequence_connect","func","from_node","from_output","to_node"),&VisualScript::sequence_connect); + ObjectTypeDB::bind_method(_MD("sequence_disconnect","func","from_node","from_output","to_node"),&VisualScript::sequence_disconnect); + ObjectTypeDB::bind_method(_MD("has_sequence_connection","func","from_node","from_output","to_node"),&VisualScript::has_sequence_connection); + + ObjectTypeDB::bind_method(_MD("data_connect","func","from_node","from_port","to_node","to_port"),&VisualScript::data_connect); + ObjectTypeDB::bind_method(_MD("data_disconnect","func","from_node","from_port","to_node","to_port"),&VisualScript::data_disconnect); + ObjectTypeDB::bind_method(_MD("has_data_connection","func","from_node","from_port","to_node","to_port"),&VisualScript::has_data_connection); + + ObjectTypeDB::bind_method(_MD("add_variable","name","default_value"),&VisualScript::add_variable,DEFVAL(Variant())); + ObjectTypeDB::bind_method(_MD("has_variable","name"),&VisualScript::has_variable); + ObjectTypeDB::bind_method(_MD("remove_variable","name"),&VisualScript::remove_variable); + ObjectTypeDB::bind_method(_MD("set_variable_default_value","name","value"),&VisualScript::set_variable_default_value); + ObjectTypeDB::bind_method(_MD("get_variable_default_value","name"),&VisualScript::get_variable_default_value); + ObjectTypeDB::bind_method(_MD("set_variable_info","name","value"),&VisualScript::_set_variable_info); + ObjectTypeDB::bind_method(_MD("get_variable_info","name"),&VisualScript::_get_variable_info); + ObjectTypeDB::bind_method(_MD("rename_variable","name","new_name"),&VisualScript::rename_variable); + + ObjectTypeDB::bind_method(_MD("add_custom_signal","name"),&VisualScript::add_custom_signal); + ObjectTypeDB::bind_method(_MD("has_custom_signal","name"),&VisualScript::has_custom_signal); + ObjectTypeDB::bind_method(_MD("custom_signal_add_argument","name","type","argname","index"),&VisualScript::custom_signal_add_argument,DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("custom_signal_set_argument_type","name","argidx","type"),&VisualScript::custom_signal_set_argument_type); + ObjectTypeDB::bind_method(_MD("custom_signal_get_argument_type","name","argidx"),&VisualScript::custom_signal_get_argument_type); + ObjectTypeDB::bind_method(_MD("custom_signal_set_argument_name","name","argidx","argname"),&VisualScript::custom_signal_set_argument_name); + ObjectTypeDB::bind_method(_MD("custom_signal_get_argument_name","name","argidx"),&VisualScript::custom_signal_get_argument_name); + ObjectTypeDB::bind_method(_MD("custom_signal_remove_argument","argidx"),&VisualScript::custom_signal_remove_argument); + ObjectTypeDB::bind_method(_MD("custom_signal_get_argument_count","name"),&VisualScript::custom_signal_get_argument_count); + ObjectTypeDB::bind_method(_MD("custom_signal_swap_argument","name","argidx","withidx"),&VisualScript::custom_signal_swap_argument); + ObjectTypeDB::bind_method(_MD("remove_custom_signal","name"),&VisualScript::remove_custom_signal); + ObjectTypeDB::bind_method(_MD("rename_custom_signal","name","new_name"),&VisualScript::rename_custom_signal); + + //ObjectTypeDB::bind_method(_MD("set_variable_info","name","info"),&VScript::set_variable_info); + //ObjectTypeDB::bind_method(_MD("get_variable_info","name"),&VScript::set_variable_info); + + ObjectTypeDB::bind_method(_MD("set_instance_base_type","type"),&VisualScript::set_instance_base_type); + + ObjectTypeDB::bind_method(_MD("_set_data","data"),&VisualScript::_set_data); + ObjectTypeDB::bind_method(_MD("_get_data"),&VisualScript::_get_data); + + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_data"),_SCS("_get_data")); + + ADD_SIGNAL(MethodInfo("node_ports_changed",PropertyInfo(Variant::STRING,"function"),PropertyInfo(Variant::INT,"id"))); +} + +VisualScript::VisualScript() { + + base_type="Object"; + +} + +VisualScript::~VisualScript() { + + while(!functions.empty()) { + remove_function(functions.front()->key()); + } + +} + +//////////////////////////////////////////// + + +String VisualScriptLanguage::get_name() const { + + return "VisualScript"; +} + +/* LANGUAGE FUNCTIONS */ +void VisualScriptLanguage::init() { + + +} +String VisualScriptLanguage::get_type() const { + + return "VisualScript"; +} +String VisualScriptLanguage::get_extension() const { + + return "vs"; +} +Error VisualScriptLanguage::execute_file(const String& p_path) { + + return OK; +} +void VisualScriptLanguage::finish() { + + +} + +/* EDITOR FUNCTIONS */ +void VisualScriptLanguage::get_reserved_words(List<String> *p_words) const { + + +} +void VisualScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const { + + +} +void VisualScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const { + + +} +String VisualScriptLanguage::get_template(const String& p_class_name, const String& p_base_class_name) const { + + return String(); +} +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 { + + return false; +} +Script *VisualScriptLanguage::create_script() const { + + return memnew( VisualScript ); +} +bool VisualScriptLanguage::has_named_classes() const { + + return false; +} +int VisualScriptLanguage::find_function(const String& p_function,const String& p_code) const { + + return -1; +} +String VisualScriptLanguage::make_function(const String& p_class,const String& p_name,const StringArray& p_args) const { + + return String(); +} + +void VisualScriptLanguage::auto_indent_code(String& p_code,int p_from_line,int p_to_line) const { + + +} +void VisualScriptLanguage::add_global_constant(const StringName& p_variable,const Variant& p_value) { + + +} + + +/* DEBUGGER FUNCTIONS */ + +String VisualScriptLanguage::debug_get_error() const { + + return String(); +} +int VisualScriptLanguage::debug_get_stack_level_count() const { + + return 0; +} +int VisualScriptLanguage::debug_get_stack_level_line(int p_level) const { + + return 0; +} +String VisualScriptLanguage::debug_get_stack_level_function(int p_level) const { + + return String(); +} +String VisualScriptLanguage::debug_get_stack_level_source(int p_level) const { + + return String(); +} +void VisualScriptLanguage::debug_get_stack_level_locals(int p_level,List<String> *p_locals, List<Variant> *p_values, int p_max_subitems,int p_max_depth) { + + +} +void VisualScriptLanguage::debug_get_stack_level_members(int p_level,List<String> *p_members, List<Variant> *p_values, int p_max_subitems,int p_max_depth) { + + +} +void VisualScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems,int p_max_depth) { + + +} +String VisualScriptLanguage::debug_parse_stack_level_expression(int p_level,const String& p_expression,int p_max_subitems,int p_max_depth) { + + return String(); +} + + +void VisualScriptLanguage::reload_all_scripts() { + + +} +void VisualScriptLanguage::reload_tool_script(const Ref<Script>& p_script,bool p_soft_reload) { + + +} +/* LOADER FUNCTIONS */ + +void VisualScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const { + + p_extensions->push_back("vs"); + +} +void VisualScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const { + + +} +void VisualScriptLanguage::get_public_constants(List<Pair<String,Variant> > *p_constants) const { + + +} + +void VisualScriptLanguage::profiling_start() { + + +} +void VisualScriptLanguage::profiling_stop() { + + +} + +int VisualScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr,int p_info_max) { + + return 0; +} + +int VisualScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr,int p_info_max) { + + return 0; +} + + +VisualScriptLanguage* VisualScriptLanguage::singleton=NULL; + + +void VisualScriptLanguage::add_register_func(const String& p_name,VisualScriptNodeRegisterFunc p_func) { + + ERR_FAIL_COND(register_funcs.has(p_name)); + register_funcs[p_name]=p_func; +} + +Ref<VisualScriptNode> VisualScriptLanguage::create_node_from_name(const String& p_name) { + + ERR_FAIL_COND_V(!register_funcs.has(p_name),Ref<VisualScriptNode>()); + + return register_funcs[p_name](p_name); +} + +void VisualScriptLanguage::get_registered_node_names(List<String> *r_names) { + + for (Map<String,VisualScriptNodeRegisterFunc>::Element *E=register_funcs.front();E;E=E->next()) { + r_names->push_back(E->key()); + } +} + + +VisualScriptLanguage::VisualScriptLanguage() { + + singleton=this; +} diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h new file mode 100644 index 0000000000..5ea466c579 --- /dev/null +++ b/modules/visual_script/visual_script.h @@ -0,0 +1,318 @@ +#ifndef VSCRIPT_H +#define VSCRIPT_H + +#include "script_language.h" + + +class VScriptInstance; +class VisualScriptNodeInstance; +class VisualScript; + +class VisualScriptNode : public Resource { + OBJ_TYPE(VisualScriptNode,Resource) + +friend class VisualScript; + + Set<VisualScript*> scripts_used; +protected: + static void _bind_methods(); +public: + + Ref<VisualScript> get_visual_script() const; + + virtual int get_output_sequence_port_count() const=0; + virtual bool has_input_sequence_port() const=0; + + virtual String get_output_sequence_port_text(int p_port) const=0; + + virtual int get_input_value_port_count() const=0; + virtual int get_output_value_port_count() const=0; + + + virtual PropertyInfo get_input_value_port_info(int p_idx) const=0; + virtual PropertyInfo get_output_value_port_info(int p_idx) const=0; + + virtual String get_caption() const=0; + virtual String get_text() const=0; + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance)=0; + +}; + + +class VisualScriptNodeInstance { +public: + + virtual int step()=0; //do a step, return which sequence port to go out + + virtual Variant get_input_value(int p_idx)=0; + virtual Variant get_output_value(int p_idx)=0; + + virtual VisualScriptNode* get_node()=0; + + virtual ~VisualScriptNodeInstance(); +}; + + +class VisualScript : public Script { + + OBJ_TYPE( VisualScript, Script ) + + RES_BASE_EXTENSION("vs"); + +public: + + struct SequenceConnection { + + union { + + struct { + uint64_t from_node : 24; + uint64_t from_output : 16; + uint64_t to_node : 24; + }; + uint64_t id; + }; + + bool operator<(const SequenceConnection& p_connection) const { + + return id<p_connection.id; + } + }; + + struct DataConnection { + + union { + + struct { + uint64_t from_node : 24; + uint64_t from_port : 8; + uint64_t to_node : 24; + uint64_t to_port : 8; + }; + uint64_t id; + }; + + bool operator<(const DataConnection& p_connection) const { + + return id<p_connection.id; + } + }; + + +private: + + StringName base_type; + struct Argument { + String name; + Variant::Type type; + }; + + struct Function { + struct NodeData { + Point2 pos; + Ref<VisualScriptNode> node; + }; + + Map<int,NodeData> nodes; + + Set<SequenceConnection> sequence_connections; + + Set<DataConnection> data_connections; + + int function_id; + + Function() { function_id=-1; } + + }; + + struct Variable { + PropertyInfo info; + Variant default_value; + }; + + + + Map<StringName,Function> functions; + Map<StringName,Variable> variables; + Map<StringName,Vector<Argument> > custom_signals; + + void _set_variable_info(const StringName& p_name,const Dictionary& p_info); + Dictionary _get_variable_info(const StringName& p_name) const; + + + void _set_data(const Dictionary& p_data); + Dictionary _get_data() const; + +protected: + + void _node_ports_changed(int p_id); + static void _bind_methods(); +public: + + + void add_function(const StringName& p_name); + bool has_function(const StringName& p_name) const; + void remove_function(const StringName& p_name); + void rename_function(const StringName& p_name,const StringName& p_new_name); + void get_function_list(List<StringName> *r_functions) const; + int get_function_node_id(const StringName& p_name) const; + + + void add_node(const StringName& p_func,int p_id,const Ref<VisualScriptNode>& p_node,const Point2& p_pos=Point2()); + void remove_node(const StringName& p_func,int p_id); + Ref<VisualScriptNode> get_node(const StringName& p_func,int p_id) const; + void set_node_pos(const StringName& p_func,int p_id,const Point2& p_pos); + Point2 get_node_pos(const StringName& p_func,int p_id) const; + void get_node_list(const StringName& p_func,List<int> *r_nodes) const; + + void sequence_connect(const StringName& p_func,int p_from_node,int p_from_output,int p_to_node); + void sequence_disconnect(const StringName& p_func,int p_from_node,int p_from_output,int p_to_node); + bool has_sequence_connection(const StringName& p_func,int p_from_node,int p_from_output,int p_to_node) const; + void get_sequence_connection_list(const StringName& p_func,List<SequenceConnection> *r_connection) const; + + void data_connect(const StringName& p_func,int p_from_node,int p_from_port,int p_to_node,int p_to_port); + void data_disconnect(const StringName& p_func,int p_from_node,int p_from_port,int p_to_node,int p_to_port); + bool has_data_connection(const StringName& p_func,int p_from_node,int p_from_port,int p_to_node,int p_to_port) const; + void get_data_connection_list(const StringName& p_func,List<DataConnection> *r_connection) const; + + void add_variable(const StringName& p_name,const Variant& p_default_value=Variant()); + bool has_variable(const StringName& p_name) const; + void remove_variable(const StringName& p_name); + void set_variable_default_value(const StringName& p_name,const Variant& p_value); + Variant get_variable_default_value(const StringName& p_name) const; + void set_variable_info(const StringName& p_name,const PropertyInfo& p_info); + PropertyInfo get_variable_info(const StringName& p_name) const; + void get_variable_list(List<StringName> *r_variables); + void rename_variable(const StringName& p_name,const StringName& p_new_name); + + + void add_custom_signal(const StringName& p_name); + bool has_custom_signal(const StringName& p_name) const; + void custom_signal_add_argument(const StringName& p_func,Variant::Type p_type,const String& p_name,int p_index=-1); + void custom_signal_set_argument_type(const StringName& p_func,int p_argidx,Variant::Type p_type); + Variant::Type custom_signal_get_argument_type(const StringName& p_func,int p_argidx) const; + void custom_signal_set_argument_name(const StringName& p_func,int p_argidx,const String& p_name); + String custom_signal_get_argument_name(const StringName& p_func,int p_argidx) const; + void custom_signal_remove_argument(const StringName& p_func,int p_argidx); + int custom_signal_get_argument_count(const StringName& p_func) const; + void custom_signal_swap_argument(const StringName& p_func,int p_argidx,int p_with_argidx); + void remove_custom_signal(const StringName& p_name); + void rename_custom_signal(const StringName& p_name,const StringName& p_new_name); + + void get_custom_signal_list(List<StringName> *r_custom_signals) const; + + int get_available_id() const; + + void set_instance_base_type(const StringName& p_type); + + virtual bool can_instance() const; + + virtual StringName get_instance_base_type() const; + virtual ScriptInstance* instance_create(Object *p_this); + virtual bool instance_has(const Object *p_this) const; + + + virtual bool has_source_code() const; + virtual String get_source_code() const; + virtual void set_source_code(const String& p_code); + virtual Error reload(bool p_keep_state=false); + + virtual bool is_tool() const; + + virtual String get_node_type() const; + + virtual ScriptLanguage *get_language() const; + + virtual bool has_script_signal(const StringName& p_signal) const; + virtual void get_script_signal_list(List<MethodInfo> *r_signals) const; + + virtual bool get_property_default_value(const StringName& p_property,Variant& r_value) const; + virtual void get_method_list(List<MethodInfo> *p_list) const; + + + VisualScript(); + ~VisualScript(); +}; + + +typedef Ref<VisualScriptNode> (*VisualScriptNodeRegisterFunc)(const String& p_type); + +class VisualScriptLanguage : public ScriptLanguage { + + Map<String,VisualScriptNodeRegisterFunc> register_funcs; +public: + + static VisualScriptLanguage* singleton; + + virtual String get_name() const; + + /* LANGUAGE FUNCTIONS */ + virtual void init(); + virtual String get_type() const; + virtual String get_extension() const; + virtual Error execute_file(const String& p_path) ; + virtual void finish(); + + /* EDITOR FUNCTIONS */ + 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 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; + virtual int find_function(const String& p_function,const String& p_code) const; + virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const; + virtual void auto_indent_code(String& p_code,int p_from_line,int p_to_line) const; + virtual void add_global_constant(const StringName& p_variable,const Variant& p_value); + + + /* DEBUGGER FUNCTIONS */ + + virtual String debug_get_error() const; + virtual int debug_get_stack_level_count() const; + virtual int debug_get_stack_level_line(int p_level) const; + virtual String debug_get_stack_level_function(int p_level) const; + virtual String debug_get_stack_level_source(int p_level) const; + virtual void debug_get_stack_level_locals(int p_level,List<String> *p_locals, List<Variant> *p_values, int p_max_subitems=-1,int p_max_depth=-1); + virtual void debug_get_stack_level_members(int p_level,List<String> *p_members, List<Variant> *p_values, int p_max_subitems=-1,int p_max_depth=-1); + virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems=-1,int p_max_depth=-1); + virtual String debug_parse_stack_level_expression(int p_level,const String& p_expression,int p_max_subitems=-1,int p_max_depth=-1); + + + virtual void reload_all_scripts(); + virtual void reload_tool_script(const Ref<Script>& p_script,bool p_soft_reload); + /* LOADER FUNCTIONS */ + + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual void get_public_functions(List<MethodInfo> *p_functions) const; + virtual void get_public_constants(List<Pair<String,Variant> > *p_constants) const; + + virtual void profiling_start(); + virtual void profiling_stop(); + + virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr,int p_info_max); + virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr,int p_info_max); + + void add_register_func(const String& p_name,VisualScriptNodeRegisterFunc p_func); + Ref<VisualScriptNode> create_node_from_name(const String& p_name); + void get_registered_node_names(List<String> *r_names); + + + VisualScriptLanguage(); + +}; + +//aid for registering +template<class T> +static Ref<VisualScriptNode> create_node_generic(const String& p_name) { + + Ref<T> node; + node.instance(); + return node; +} + + + +#endif // VSCRIPT_H diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp new file mode 100644 index 0000000000..80468ca77b --- /dev/null +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -0,0 +1,641 @@ +#include "visual_script_builtin_funcs.h" + + +const char* VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX]={ + "sin", + "cos", + "tan", + "sinh", + "cosh", + "tanh", + "asin", + "acos", + "atan", + "atan2", + "sqrt", + "fmod", + "fposmod", + "floor", + "ceil", + "round", + "abs", + "sign", + "pow", + "log", + "exp", + "is_nan", + "is_inf", + "ease", + "decimals", + "stepify", + "lerp", + "dectime", + "randomize", + "randi", + "randf", + "rand_range", + "seed", + "rand_seed", + "deg2rad", + "rad2deg", + "linear2db", + "db2linear", + "max", + "min", + "clamp", + "nearest_po2", + "weakref", + "funcref", + "convert", + "typeof", + "type_exists", + "str", + "print", + "printerr", + "printraw", + "var2str", + "str2var", + "var2bytes", + "bytes2var", +}; + + + +int VisualScriptBuiltinFunc::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptBuiltinFunc::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptBuiltinFunc::get_input_value_port_count() const{ + + + switch(func) { + + case MATH_RANDOMIZE: + case MATH_RAND: + case MATH_RANDF: + return 0; + case MATH_SIN: + case MATH_COS: + case MATH_TAN: + case MATH_SINH: + case MATH_COSH: + case MATH_TANH: + case MATH_ASIN: + case MATH_ACOS: + case MATH_ATAN: + case MATH_SQRT: + case MATH_FLOOR: + case MATH_CEIL: + case MATH_ROUND: + case MATH_ABS: + case MATH_SIGN: + case MATH_LOG: + case MATH_EXP: + case MATH_ISNAN: + case MATH_ISINF: + case MATH_DECIMALS: + case MATH_SEED: + case MATH_RANDSEED: + case MATH_DEG2RAD: + case MATH_RAD2DEG: + case MATH_LINEAR2DB: + case MATH_DB2LINEAR: + case LOGIC_NEAREST_PO2: + case OBJ_WEAKREF: + case TYPE_OF: + case TEXT_STR: + case TEXT_PRINT: + case TEXT_PRINTERR: + case TEXT_PRINTRAW: + case VAR_TO_STR: + case STR_TO_VAR: + case VAR_TO_BYTES: + case BYTES_TO_VAR: + case TYPE_EXISTS: + return 1; + case MATH_ATAN2: + case MATH_FMOD: + case MATH_FPOSMOD: + case MATH_POW: + case MATH_EASE: + case MATH_STEPIFY: + case MATH_RANDOM: + case LOGIC_MAX: + case LOGIC_MIN: + case FUNC_FUNCREF: + case TYPE_CONVERT: + return 2; + case MATH_LERP: + case MATH_DECTIME: + case LOGIC_CLAMP: + return 3; + case FUNC_MAX:{} + + } + return 0; +} +int VisualScriptBuiltinFunc::get_output_value_port_count() const{ + + switch(func) { + case MATH_RANDOMIZE: + case TEXT_PRINT: + case TEXT_PRINTERR: + case TEXT_PRINTRAW: + case MATH_SEED: + return 0; + case MATH_RANDSEED: + return 2; + default: + return 1; + } + + return 1; +} + +String VisualScriptBuiltinFunc::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const{ + + switch(func) { + + case MATH_SIN: + case MATH_COS: + case MATH_TAN: + case MATH_SINH: + case MATH_COSH: + case MATH_TANH: + case MATH_ASIN: + case MATH_ACOS: + case MATH_ATAN: + case MATH_ATAN2: + case MATH_SQRT: { + return PropertyInfo(Variant::REAL,"num"); + } break; + case MATH_FMOD: + case MATH_FPOSMOD: { + if (p_idx==0) + return PropertyInfo(Variant::REAL,"x"); + else + return PropertyInfo(Variant::REAL,"y"); + } break; + case MATH_FLOOR: + case MATH_CEIL: + case MATH_ROUND: + case MATH_ABS: + case MATH_SIGN: { + return PropertyInfo(Variant::REAL,"num"); + + } break; + + case MATH_POW: { + if (p_idx==0) + return PropertyInfo(Variant::REAL,"x"); + else + return PropertyInfo(Variant::REAL,"y"); + } break; + case MATH_LOG: + case MATH_EXP: + case MATH_ISNAN: + case MATH_ISINF: { + return PropertyInfo(Variant::REAL,"num"); + } break; + case MATH_EASE: { + if (p_idx==0) + return PropertyInfo(Variant::REAL,"s"); + else + return PropertyInfo(Variant::REAL,"curve"); + } break; + case MATH_DECIMALS: { + return PropertyInfo(Variant::REAL,"step"); + } break; + case MATH_STEPIFY: { + if (p_idx==0) + return PropertyInfo(Variant::REAL,"s"); + else + return PropertyInfo(Variant::REAL,"steps"); + } break; + case MATH_LERP: { + if (p_idx==0) + return PropertyInfo(Variant::REAL,"from"); + else if (p_idx==1) + return PropertyInfo(Variant::REAL,"to"); + else + return PropertyInfo(Variant::REAL,"weight"); + + } break; + case MATH_DECTIME: { + if (p_idx==0) + return PropertyInfo(Variant::REAL,"value"); + else if (p_idx==1) + return PropertyInfo(Variant::REAL,"amount"); + else + return PropertyInfo(Variant::REAL,"step"); + } break; + case MATH_RANDOMIZE: { + + } break; + case MATH_RAND: { + + } break; + case MATH_RANDF: { + + } break; + case MATH_RANDOM: { + if (p_idx==0) + return PropertyInfo(Variant::REAL,"from"); + else + return PropertyInfo(Variant::REAL,"to"); + } break; + case MATH_SEED: { + return PropertyInfo(Variant::INT,"seed"); + } break; + case MATH_RANDSEED: { + return PropertyInfo(Variant::INT,"seed"); + } break; + case MATH_DEG2RAD: { + return PropertyInfo(Variant::REAL,"deg"); + } break; + case MATH_RAD2DEG: { + return PropertyInfo(Variant::REAL,"rad"); + } break; + case MATH_LINEAR2DB: { + return PropertyInfo(Variant::REAL,"nrg"); + } break; + case MATH_DB2LINEAR: { + return PropertyInfo(Variant::REAL,"db"); + } break; + case LOGIC_MAX: { + if (p_idx==0) + return PropertyInfo(Variant::REAL,"a"); + else + return PropertyInfo(Variant::REAL,"b"); + } break; + case LOGIC_MIN: { + if (p_idx==0) + return PropertyInfo(Variant::REAL,"a"); + else + return PropertyInfo(Variant::REAL,"b"); + } break; + case LOGIC_CLAMP: { + if (p_idx==0) + return PropertyInfo(Variant::REAL,"a"); + else if (p_idx==0) + return PropertyInfo(Variant::REAL,"min"); + else + return PropertyInfo(Variant::REAL,"max"); + } break; + case LOGIC_NEAREST_PO2: { + return PropertyInfo(Variant::INT,"num"); + } break; + case OBJ_WEAKREF: { + + return PropertyInfo(Variant::OBJECT,"source"); + + } break; + case FUNC_FUNCREF: { + + if (p_idx==0) + return PropertyInfo(Variant::OBJECT,"instance"); + else + return PropertyInfo(Variant::STRING,"funcname"); + + } break; + case TYPE_CONVERT: { + + if (p_idx==0) + return PropertyInfo(Variant::NIL,"what"); + else + return PropertyInfo(Variant::STRING,"type"); + } break; + case TYPE_OF: { + return PropertyInfo(Variant::NIL,"what"); + + } break; + case TYPE_EXISTS: { + + return PropertyInfo(Variant::STRING,"type"); + + } break; + case TEXT_STR: { + + return PropertyInfo(Variant::NIL,"value"); + + + } break; + case TEXT_PRINT: { + + return PropertyInfo(Variant::NIL,"value"); + + } break; + case TEXT_PRINTERR: { + return PropertyInfo(Variant::NIL,"value"); + + } break; + case TEXT_PRINTRAW: { + + return PropertyInfo(Variant::NIL,"value"); + + } break; + case VAR_TO_STR: { + return PropertyInfo(Variant::NIL,"var"); + + } break; + case STR_TO_VAR: { + + return PropertyInfo(Variant::STRING,"string"); + } break; + case VAR_TO_BYTES: { + return PropertyInfo(Variant::NIL,"var"); + + } break; + case BYTES_TO_VAR: { + + return PropertyInfo(Variant::RAW_ARRAY,"bytes"); + } break; + case FUNC_MAX:{} + } + + return PropertyInfo(); +} + +PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) const{ + + Variant::Type t=Variant::NIL; + switch(func) { + + case MATH_SIN: + case MATH_COS: + case MATH_TAN: + case MATH_SINH: + case MATH_COSH: + case MATH_TANH: + case MATH_ASIN: + case MATH_ACOS: + case MATH_ATAN: + case MATH_ATAN2: + case MATH_SQRT: + case MATH_FMOD: + case MATH_FPOSMOD: + case MATH_FLOOR: + case MATH_CEIL: + t=Variant::REAL; + case MATH_ROUND: { + t=Variant::INT; + } break; + case MATH_ABS: { + t=Variant::NIL; + } break; + case MATH_SIGN: { + t=Variant::NIL; + } break; + case MATH_POW: + case MATH_LOG: + case MATH_EXP: { + t=Variant::REAL; + } break; + case MATH_ISNAN: + case MATH_ISINF: { + t=Variant::BOOL; + } break; + case MATH_EASE: { + t=Variant::REAL; + } break; + case MATH_DECIMALS: { + t=Variant::INT; + } break; + case MATH_STEPIFY: + case MATH_LERP: + case MATH_DECTIME: { + t=Variant::REAL; + + } break; + case MATH_RANDOMIZE: { + + } break; + case MATH_RAND: { + + t=Variant::INT; + } break; + case MATH_RANDF: + case MATH_RANDOM: { + t=Variant::REAL; + } break; + case MATH_SEED: { + + } break; + case MATH_RANDSEED: { + + if (p_idx==0) + return PropertyInfo(Variant::INT,"rnd"); + else + return PropertyInfo(Variant::INT,"seed"); + } break; + case MATH_DEG2RAD: + case MATH_RAD2DEG: + case MATH_LINEAR2DB: + case MATH_DB2LINEAR: { + t=Variant::REAL; + } break; + case LOGIC_MAX: + case LOGIC_MIN: + case LOGIC_CLAMP: { + + + } break; + + case LOGIC_NEAREST_PO2: { + t=Variant::NIL; + } break; + case OBJ_WEAKREF: { + + t=Variant::OBJECT; + + } break; + case FUNC_FUNCREF: { + + t=Variant::OBJECT; + + } break; + case TYPE_CONVERT: { + + + + } break; + case TYPE_OF: { + t=Variant::INT; + + } break; + case TYPE_EXISTS: { + + t=Variant::BOOL; + + } break; + case TEXT_STR: { + + t=Variant::STRING; + + } break; + case TEXT_PRINT: { + + + } break; + case TEXT_PRINTERR: { + + } break; + case TEXT_PRINTRAW: { + + } break; + case VAR_TO_STR: { + t=Variant::STRING; + } break; + case STR_TO_VAR: { + + } break; + case VAR_TO_BYTES: { + t=Variant::RAW_ARRAY; + + } break; + case BYTES_TO_VAR: { + + + } break; + case FUNC_MAX:{} + } + + return PropertyInfo(t,""); +} + +String VisualScriptBuiltinFunc::get_caption() const { + + return "BuiltinFunc"; +} + +String VisualScriptBuiltinFunc::get_text() const { + + return func_name[func]; +} + +void VisualScriptBuiltinFunc::set_func(BuiltinFunc p_which) { + + ERR_FAIL_INDEX(p_which,FUNC_MAX); + func=p_which; + _change_notify(); + emit_signal("ports_changed"); +} + +VisualScriptBuiltinFunc::BuiltinFunc VisualScriptBuiltinFunc::get_func() { + return func; +} + + + +VisualScriptNodeInstance* VisualScriptBuiltinFunc::instance(VScriptInstance* p_instance) { + + return NULL; +} + +void VisualScriptBuiltinFunc::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_func","which"),&VisualScriptBuiltinFunc::set_func); + ObjectTypeDB::bind_method(_MD("get_func"),&VisualScriptBuiltinFunc::get_func); + + String cc; + + for(int i=0;i<FUNC_MAX;i++) { + + if (i>0) + cc+=","; + cc+=func_name[i]; + } + ADD_PROPERTY(PropertyInfo(Variant::INT,"function",PROPERTY_HINT_ENUM,cc),_SCS("set_func"),_SCS("get_func")); +} + +VisualScriptBuiltinFunc::VisualScriptBuiltinFunc() { + + func=MATH_SIN; +} + +template<VisualScriptBuiltinFunc::BuiltinFunc func> +static Ref<VisualScriptNode> create_builtin_func_node(const String& p_name) { + + Ref<VisualScriptBuiltinFunc> node; + node.instance(); + node->set_func(func); + return node; +} + +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>); + +} diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h new file mode 100644 index 0000000000..b4dbd4db39 --- /dev/null +++ b/modules/visual_script/visual_script_builtin_funcs.h @@ -0,0 +1,109 @@ +#ifndef VISUAL_SCRIPT_BUILTIN_FUNCS_H +#define VISUAL_SCRIPT_BUILTIN_FUNCS_H + +#include "visual_script.h" + + +class VisualScriptBuiltinFunc : public VisualScriptNode { + + OBJ_TYPE(VisualScriptBuiltinFunc,VisualScriptNode) +public: + + enum BuiltinFunc { + MATH_SIN, + MATH_COS, + MATH_TAN, + MATH_SINH, + MATH_COSH, + MATH_TANH, + MATH_ASIN, + MATH_ACOS, + MATH_ATAN, + MATH_ATAN2, + MATH_SQRT, + MATH_FMOD, + MATH_FPOSMOD, + MATH_FLOOR, + MATH_CEIL, + MATH_ROUND, + MATH_ABS, + MATH_SIGN, + MATH_POW, + MATH_LOG, + MATH_EXP, + MATH_ISNAN, + MATH_ISINF, + MATH_EASE, + MATH_DECIMALS, + MATH_STEPIFY, + MATH_LERP, + MATH_DECTIME, + MATH_RANDOMIZE, + MATH_RAND, + MATH_RANDF, + MATH_RANDOM, + MATH_SEED, + MATH_RANDSEED, + MATH_DEG2RAD, + MATH_RAD2DEG, + MATH_LINEAR2DB, + MATH_DB2LINEAR, + LOGIC_MAX, + LOGIC_MIN, + LOGIC_CLAMP, + LOGIC_NEAREST_PO2, + OBJ_WEAKREF, + FUNC_FUNCREF, + TYPE_CONVERT, + TYPE_OF, + TYPE_EXISTS, + TEXT_STR, + TEXT_PRINT, + TEXT_PRINTERR, + TEXT_PRINTRAW, + VAR_TO_STR, + STR_TO_VAR, + VAR_TO_BYTES, + BYTES_TO_VAR, + FUNC_MAX + }; + +private: + static const char* func_name[FUNC_MAX]; + BuiltinFunc func; +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; + + void set_func(BuiltinFunc p_which); + BuiltinFunc get_func(); + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptBuiltinFunc(); +}; + +VARIANT_ENUM_CAST(VisualScriptBuiltinFunc::BuiltinFunc) + + +void register_visual_script_builtin_func_node(); + + +#endif // VISUAL_SCRIPT_BUILTIN_FUNCS_H diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp new file mode 100644 index 0000000000..3b40d71ff6 --- /dev/null +++ b/modules/visual_script/visual_script_editor.cpp @@ -0,0 +1,1956 @@ +#include "visual_script_editor.h" +#include "tools/editor/editor_node.h" +#include "visual_script_nodes.h" +#include "visual_script_flow_control.h" +#include "visual_script_func_nodes.h" + +class VisualScriptEditorSignalEdit : public Object { + + OBJ_TYPE(VisualScriptEditorSignalEdit,Object) + + StringName sig; +public: + UndoRedo *undo_redo; + Ref<VisualScript> script; + + +protected: + + static void _bind_methods() { + ObjectTypeDB::bind_method("_sig_changed",&VisualScriptEditorSignalEdit::_sig_changed); + } + + void _sig_changed() { + + _change_notify(); + } + + bool _set(const StringName& p_name, const Variant& p_value) { + + if (sig==StringName()) + return false; + + if (p_name=="argument_count") { + + int new_argc=p_value; + int argc = script->custom_signal_get_argument_count(sig); + if (argc==new_argc) + return true; + + undo_redo->create_action("Change Signal Arguments"); + + + + if (new_argc < argc) { + for(int i=new_argc;i<argc;i++) { + undo_redo->add_do_method(script.ptr(),"custom_signal_remove_argument",sig,new_argc); + undo_redo->add_undo_method(script.ptr(),"custom_signal_add_argument",sig,script->custom_signal_get_argument_name(sig,i),script->custom_signal_get_argument_type(sig,i),-1); + } + } else if (new_argc>argc) { + + for(int i=argc;i<new_argc;i++) { + + undo_redo->add_do_method(script.ptr(),"custom_signal_add_argument",sig,Variant::NIL,"arg"+itos(i+1),-1); + undo_redo->add_undo_method(script.ptr(),"custom_signal_remove_argument",sig,argc); + } + } + + undo_redo->add_do_method(this,"_sig_changed"); + undo_redo->add_undo_method(this,"_sig_changed"); + + undo_redo->commit_action(); + + return true; + } + if (String(p_name).begins_with("argument/")) { + int idx = String(p_name).get_slice("/",1).to_int()-1; + ERR_FAIL_INDEX_V(idx,script->custom_signal_get_argument_count(sig),false); + String what = String(p_name).get_slice("/",2); + if (what=="type") { + + int old_type = script->custom_signal_get_argument_type(sig,idx); + int new_type=p_value; + undo_redo->create_action("Change Argument Type"); + undo_redo->add_do_method(script.ptr(),"custom_signal_set_argument_type",sig,idx,new_type); + undo_redo->add_undo_method(script.ptr(),"custom_signal_set_argument_type",sig,idx,old_type); + undo_redo->commit_action(); + + return true; + } + + if (what=="name") { + + String old_name = script->custom_signal_get_argument_name(sig,idx); + String new_name=p_value; + undo_redo->create_action("Change Argument name"); + undo_redo->add_do_method(script.ptr(),"custom_signal_set_argument_name",sig,idx,new_name); + undo_redo->add_undo_method(script.ptr(),"custom_signal_set_argument_name",sig,idx,old_name); + undo_redo->commit_action(); + return true; + } + + + } + + + return false; + } + + bool _get(const StringName& p_name,Variant &r_ret) const { + + if (sig==StringName()) + return false; + + if (p_name=="argument_count") { + r_ret = script->custom_signal_get_argument_count(sig); + return true; + } + if (String(p_name).begins_with("argument/")) { + int idx = String(p_name).get_slice("/",1).to_int()-1; + ERR_FAIL_INDEX_V(idx,script->custom_signal_get_argument_count(sig),false); + String what = String(p_name).get_slice("/",2); + if (what=="type") { + r_ret = script->custom_signal_get_argument_type(sig,idx); + return true; + } + if (what=="name") { + r_ret = script->custom_signal_get_argument_name(sig,idx); + return true; + } + + + + } + + return false; + } + void _get_property_list( List<PropertyInfo> *p_list) const { + + if (sig==StringName()) + return; + + p_list->push_back(PropertyInfo(Variant::INT,"argument_count",PROPERTY_HINT_RANGE,"0,256")); + String argt="Variant"; + for(int i=1;i<Variant::VARIANT_MAX;i++) { + argt+=","+Variant::get_type_name(Variant::Type(i)); + } + + for(int i=0;i<script->custom_signal_get_argument_count(sig);i++) { + 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")); + } + } + +public: + + + void edit(const StringName& p_sig) { + + sig=p_sig; + _change_notify(); + } + + VisualScriptEditorSignalEdit() { undo_redo=NULL; } +}; + +class VisualScriptEditorVariableEdit : public Object { + + OBJ_TYPE(VisualScriptEditorVariableEdit,Object) + + StringName var; +public: + UndoRedo *undo_redo; + Ref<VisualScript> script; + + +protected: + + static void _bind_methods() { + ObjectTypeDB::bind_method("_var_changed",&VisualScriptEditorVariableEdit::_var_changed); + ObjectTypeDB::bind_method("_var_value_changed",&VisualScriptEditorVariableEdit::_var_value_changed); + } + + void _var_changed() { + + _change_notify(); + } + void _var_value_changed() { + + _change_notify("value"); //so the whole tree is not redrawn, makes editing smoother in general + } + + bool _set(const StringName& p_name, const Variant& p_value) { + + if (var==StringName()) + return false; + + + + if (String(p_name)=="value") { + undo_redo->create_action("Set Variable Default Value"); + Variant current=script->get_variable_default_value(var); + undo_redo->add_do_method(script.ptr(),"set_variable_default_value",var,p_value); + undo_redo->add_undo_method(script.ptr(),"set_variable_default_value",var,current); + undo_redo->add_do_method(this,"_var_value_changed"); + undo_redo->add_undo_method(this,"_var_value_changed"); + undo_redo->commit_action(); + return true; + } + + Dictionary d = script->call("get_variable_info",var); + + if (String(p_name)=="type") { + + Dictionary dc=d.copy(); + dc["type"]=p_value; + undo_redo->create_action("Set Variable Type"); + undo_redo->add_do_method(script.ptr(),"set_variable_info",var,dc); + undo_redo->add_undo_method(script.ptr(),"set_variable_info",var,d); + undo_redo->add_do_method(this,"_var_changed"); + undo_redo->add_undo_method(this,"_var_changed"); + undo_redo->commit_action(); + return true; + } + + if (String(p_name)=="hint") { + + Dictionary dc=d.copy(); + dc["hint"]=p_value; + undo_redo->create_action("Set Variable Type"); + undo_redo->add_do_method(script.ptr(),"set_variable_info",var,dc); + undo_redo->add_undo_method(script.ptr(),"set_variable_info",var,d); + undo_redo->add_do_method(this,"_var_changed"); + undo_redo->add_undo_method(this,"_var_changed"); + undo_redo->commit_action(); + return true; + } + + if (String(p_name)=="hint_string") { + + Dictionary dc=d.copy(); + dc["hint_string"]=p_value; + undo_redo->create_action("Set Variable Type"); + undo_redo->add_do_method(script.ptr(),"set_variable_info",var,dc); + undo_redo->add_undo_method(script.ptr(),"set_variable_info",var,d); + undo_redo->add_do_method(this,"_var_changed"); + undo_redo->add_undo_method(this,"_var_changed"); + undo_redo->commit_action(); + return true; + } + + + return false; + } + + bool _get(const StringName& p_name,Variant &r_ret) const { + + if (var==StringName()) + return false; + + if (String(p_name)=="value") { + r_ret=script->get_variable_default_value(var); + return true; + } + + PropertyInfo pinfo = script->get_variable_info(var); + + if (String(p_name)=="type") { + r_ret=pinfo.type; + return true; + } + if (String(p_name)=="hint") { + r_ret=pinfo.hint; + return true; + } + if (String(p_name)=="hint_string") { + r_ret=pinfo.hint_string; + return true; + } + + return false; + } + void _get_property_list( List<PropertyInfo> *p_list) const { + + if (var==StringName()) + return; + + String argt="Variant"; + for(int i=1;i<Variant::VARIANT_MAX;i++) { + argt+=","+Variant::get_type_name(Variant::Type(i)); + } + p_list->push_back(PropertyInfo(Variant::INT,"type",PROPERTY_HINT_ENUM,argt)); + p_list->push_back(PropertyInfo(script->get_variable_info(var).type,"value",script->get_variable_info(var).hint,script->get_variable_info(var).hint_string,PROPERTY_USAGE_DEFAULT)); + p_list->push_back(PropertyInfo(Variant::INT,"hint",PROPERTY_HINT_ENUM,"None,Range,ExpRange,Enum,ExpEasing,Length,SpriteFrame,KeyAccel,BitFlags,AllFlags,File,Dir,GlobalFile,GlobalDir,ResourceType,MultilineText")); + p_list->push_back(PropertyInfo(Variant::STRING,"hint_string")); + + } + +public: + + + void edit(const StringName& p_var) { + + var=p_var; + _change_notify(); + } + + VisualScriptEditorVariableEdit() { undo_redo=NULL; } +}; + +static Color _color_from_type(Variant::Type p_type) { + + Color color; + color.set_hsv(p_type/float(Variant::VARIANT_MAX),0.7,0.7); + return color; +} + + + +void VisualScriptEditor::_update_graph_connections() { + + graph->clear_connections(); + + List<VisualScript::SequenceConnection> sequence_conns; + script->get_sequence_connection_list(edited_func,&sequence_conns); + + + for (List<VisualScript::SequenceConnection>::Element *E=sequence_conns.front();E;E=E->next()) { + + graph->connect_node(itos(E->get().from_node),E->get().from_output,itos(E->get().to_node),0); + } + + List<VisualScript::DataConnection> data_conns; + script->get_data_connection_list(edited_func,&data_conns); + + for (List<VisualScript::DataConnection>::Element *E=data_conns.front();E;E=E->next()) { + + VisualScript::DataConnection dc=E->get(); + + + Ref<VisualScriptNode> from_node = script->get_node(edited_func,E->get().from_node); + Ref<VisualScriptNode> to_node = script->get_node(edited_func,E->get().to_node); + + if (to_node->has_input_sequence_port()) { + dc.to_port++; + } + + dc.from_port+=from_node->get_output_sequence_port_count(); + + graph->connect_node(itos(E->get().from_node),dc.from_port,itos(E->get().to_node),dc.to_port); + } + +} + + +void VisualScriptEditor::_update_graph(int p_only_id) { + + + //byebye all nodes + if (p_only_id>=0) { + if (graph->has_node(itos(p_only_id))) { + Node* gid = graph->get_node(itos(p_only_id)); + if (gid) + memdelete(gid); + } + } else { + + for(int i=0;i<graph->get_child_count();i++) { + + if (graph->get_child(i)->cast_to<GraphNode>()) { + memdelete(graph->get_child(i)); + i--; + } + } + } + + if (!script->has_function(edited_func)) + return; + + Ref<Texture> type_icons[Variant::VARIANT_MAX]={ + Control::get_icon("MiniVariant","EditorIcons"), + Control::get_icon("MiniBoolean","EditorIcons"), + Control::get_icon("MiniInteger","EditorIcons"), + Control::get_icon("MiniFloat","EditorIcons"), + Control::get_icon("MiniString","EditorIcons"), + Control::get_icon("MiniVector2","EditorIcons"), + Control::get_icon("MiniRect2","EditorIcons"), + Control::get_icon("MiniVector3","EditorIcons"), + Control::get_icon("MiniMatrix2","EditorIcons"), + Control::get_icon("MiniPlane","EditorIcons"), + Control::get_icon("MiniQuat","EditorIcons"), + Control::get_icon("MiniAabb","EditorIcons"), + Control::get_icon("MiniMatrix3","EditorIcons"), + Control::get_icon("MiniTransform","EditorIcons"), + Control::get_icon("MiniColor","EditorIcons"), + Control::get_icon("MiniImage","EditorIcons"), + Control::get_icon("MiniPath","EditorIcons"), + Control::get_icon("MiniRid","EditorIcons"), + Control::get_icon("MiniObject","EditorIcons"), + Control::get_icon("MiniInput","EditorIcons"), + Control::get_icon("MiniDictionary","EditorIcons"), + Control::get_icon("MiniArray","EditorIcons"), + Control::get_icon("MiniRawArray","EditorIcons"), + Control::get_icon("MiniIntArray","EditorIcons"), + Control::get_icon("MiniFloatArray","EditorIcons"), + Control::get_icon("MiniStringArray","EditorIcons"), + Control::get_icon("MiniVector2Array","EditorIcons"), + Control::get_icon("MiniVector3Array","EditorIcons"), + Control::get_icon("MiniColorArray","EditorIcons") + }; + + + + Ref<Texture> seq_port = Control::get_icon("VisualShaderPort","EditorIcons"); + + List<int> ids; + script->get_node_list(edited_func,&ids); + StringName editor_icons="EditorIcons"; + + for(List<int>::Element *E=ids.front();E;E=E->next()) { + + if (p_only_id>=0 && p_only_id!=E->get()) + continue; + + Ref<VisualScriptNode> node = script->get_node(edited_func,E->get()); + Vector2 pos = script->get_node_pos(edited_func,E->get()); + + GraphNode *gnode = memnew( GraphNode ); + gnode->set_title(node->get_caption()); + + gnode->set_meta("__vnode",node); + gnode->set_name(itos(E->get())); + gnode->connect("dragged",this,"_node_moved",varray(E->get())); + gnode->connect("close_request",this,"_remove_node",varray(E->get()),CONNECT_DEFERRED); + + + if (E->get()!=script->get_function_node_id(edited_func)) { + //function can't be erased + gnode->set_show_close_button(true); + } + + Label *text = memnew( Label ); + text->set_text(node->get_text()); + gnode->add_child(text); + + int slot_idx=0; + + bool single_seq_output = node->get_output_sequence_port_count()==1 && node->get_output_sequence_port_text(0)==String(); + gnode->set_slot(0,node->has_input_sequence_port(),TYPE_SEQUENCE,Color(1,1,1,1),single_seq_output,TYPE_SEQUENCE,Color(1,1,1,1),seq_port,seq_port); + gnode->set_offset(pos*EDSCALE); + slot_idx++; + + if (!single_seq_output) { + for(int i=0;i<node->get_output_sequence_port_count();i++) { + + Label *text2 = memnew( Label ); + text2->set_text(node->get_output_sequence_port_text(i)); + text2->set_align(Label::ALIGN_RIGHT); + gnode->add_child(text2); + gnode->set_slot(slot_idx,false,0,Color(),true,TYPE_SEQUENCE,Color(1,1,1,1),seq_port,seq_port); + slot_idx++; + } + } + + for(int i=0;i<MAX(node->get_output_value_port_count(),node->get_input_value_port_count());i++) { + + bool left_ok=false; + Variant::Type left_type=Variant::NIL; + String left_name; + + if (i<node->get_input_value_port_count()) { + PropertyInfo pi = node->get_input_value_port_info(i); + left_ok=true; + left_type=pi.type; + left_name=pi.name; + } + + bool right_ok=false; + Variant::Type right_type=Variant::NIL; + String right_name; + + if (i<node->get_output_value_port_count()) { + PropertyInfo pi = node->get_output_value_port_info(i); + right_ok=true; + right_type=pi.type; + right_name=pi.name; + } + + HBoxContainer *hbc = memnew( HBoxContainer); + + if (left_ok) { + + Ref<Texture> t; + if (left_type>=0 && left_type<Variant::VARIANT_MAX) { + t=type_icons[left_type]; + } + if (t.is_valid()) { + TextureFrame *tf = memnew(TextureFrame); + tf->set_texture(t); + tf->set_stretch_mode(TextureFrame::STRETCH_KEEP_CENTERED); + hbc->add_child(tf); + } + + hbc->add_child(memnew(Label(left_name))); + } else { + Control *c = memnew(Control); + c->set_custom_minimum_size(Size2(10,0)*EDSCALE); + hbc->add_child(c); + } + + hbc->add_spacer(); + + if (right_ok) { + + hbc->add_child(memnew(Label(right_name))); + + Ref<Texture> t; + if (right_type>=0 && right_type<Variant::VARIANT_MAX) { + t=type_icons[right_type]; + } + if (t.is_valid()) { + TextureFrame *tf = memnew(TextureFrame); + tf->set_texture(t); + tf->set_stretch_mode(TextureFrame::STRETCH_KEEP_CENTERED); + hbc->add_child(tf); + } + + } + + gnode->add_child(hbc); + + gnode->set_slot(slot_idx,left_ok,left_type,_color_from_type(left_type),right_ok,right_type,_color_from_type(right_type)); + + slot_idx++; + } + + graph->add_child(gnode); + } + + _update_graph_connections(); + +} + +void VisualScriptEditor::_update_members() { + + + updating_members=true; + + members->clear(); + TreeItem *root = members->create_item(); + + TreeItem *functions = members->create_item(root); + functions->set_selectable(0,false); + functions->set_text(0,TTR("Functions:")); + functions->add_button(0,Control::get_icon("Override","EditorIcons"),1); + functions->add_button(0,Control::get_icon("Add","EditorIcons"),0); + functions->set_custom_bg_color(0,Control::get_color("prop_section","Editor")); + + List<StringName> func_names; + script->get_function_list(&func_names); + for (List<StringName>::Element *E=func_names.front();E;E=E->next()) { + TreeItem *ti = members->create_item(functions) ; + ti->set_text(0,E->get()); + ti->set_selectable(0,true); + ti->set_editable(0,true); + //ti->add_button(0,Control::get_icon("Edit","EditorIcons"),0); function arguments are in the node now + ti->add_button(0,Control::get_icon("Del","EditorIcons"),1); + ti->set_metadata(0,E->get()); + if (selected==E->get()) + ti->select(0); + } + + TreeItem *variables = members->create_item(root); + variables->set_selectable(0,false); + variables->set_text(0,TTR("Variables:")); + variables->add_button(0,Control::get_icon("Add","EditorIcons")); + variables->set_custom_bg_color(0,Control::get_color("prop_section","Editor")); + + + List<StringName> var_names; + script->get_variable_list(&var_names); + for (List<StringName>::Element *E=var_names.front();E;E=E->next()) { + TreeItem *ti = members->create_item(variables) ; + ti->set_text(0,E->get()); + ti->set_selectable(0,true); + ti->set_editable(0,true); + ti->add_button(0,Control::get_icon("Edit","EditorIcons"),0); + ti->add_button(0,Control::get_icon("Del","EditorIcons"),1); + ti->set_metadata(0,E->get()); + if (selected==E->get()) + ti->select(0); + } + + TreeItem *_signals = members->create_item(root); + _signals->set_selectable(0,false); + _signals->set_text(0,TTR("Signals:")); + _signals->add_button(0,Control::get_icon("Add","EditorIcons")); + _signals->set_custom_bg_color(0,Control::get_color("prop_section","Editor")); + + List<StringName> signal_names; + script->get_custom_signal_list(&signal_names); + for (List<StringName>::Element *E=signal_names.front();E;E=E->next()) { + TreeItem *ti = members->create_item(_signals) ; + ti->set_text(0,E->get()); + ti->set_selectable(0,true); + ti->set_editable(0,true); + ti->add_button(0,Control::get_icon("Edit","EditorIcons"),0); + ti->add_button(0,Control::get_icon("Del","EditorIcons"),1); + ti->set_metadata(0,E->get()); + if (selected==E->get()) + ti->select(0); + } + + String base_type=script->get_instance_base_type(); + String icon_type=base_type; + if (!Control::has_icon(base_type,"EditorIcons")) { + icon_type="Object"; + } + + base_type_select->set_text(base_type); + base_type_select->set_icon(Control::get_icon(icon_type,"EditorIcons")); + + updating_members=false; + +} + +void VisualScriptEditor::_member_selected() { + + if (updating_members) + return; + + TreeItem *ti=members->get_selected(); + ERR_FAIL_COND(!ti); + + + selected=ti->get_metadata(0); +// print_line("selected: "+String(selected)); + + + if (ti->get_parent()==members->get_root()->get_children()) { + + if (edited_func!=selected) { + + revert_on_drag=edited_func; + edited_func=selected; + _update_graph(); + } + + return; //or crash because it will become invalid + + } + + + +} + +void VisualScriptEditor::_member_edited() { + + if (updating_members) + return; + + TreeItem *ti=members->get_edited(); + ERR_FAIL_COND(!ti); + + String name = ti->get_metadata(0); + String new_name = ti->get_text(0); + + if (name==new_name) + return; + + if (!new_name.is_valid_identifier()) { + + EditorNode::get_singleton()->show_warning(TTR("Name is not a valid identifier: ")+new_name); + updating_members=true; + ti->set_text(0,name); + updating_members=false; + return; + + } + + if (script->has_function(new_name) || script->has_variable(new_name) || script->has_custom_signal(new_name)) { + + EditorNode::get_singleton()->show_warning(TTR("Name already in use by another func/var/signal: ")+new_name); + updating_members=true; + ti->set_text(0,name); + updating_members=false; + return; + } + + TreeItem *root=members->get_root(); + + if (ti->get_parent()==root->get_children()) { + + if (edited_func==selected) { + edited_func=new_name; + } + selected=new_name; + + + _update_graph(); + + undo_redo->create_action(TTR("Rename Function")); + undo_redo->add_do_method(script.ptr(),"rename_function",name,new_name); + undo_redo->add_undo_method(script.ptr(),"rename_function",new_name,name); + undo_redo->add_do_method(this,"_update_members"); + undo_redo->add_undo_method(this,"_update_members"); + undo_redo->commit_action(); + + return; //or crash because it will become invalid + + } + + if (ti->get_parent()==root->get_children()->get_next()) { + + selected=new_name; + undo_redo->create_action(TTR("Rename Variable")); + undo_redo->add_do_method(script.ptr(),"rename_variable",name,new_name); + undo_redo->add_undo_method(script.ptr(),"rename_variable",new_name,name); + undo_redo->add_do_method(this,"_update_members"); + undo_redo->add_undo_method(this,"_update_members"); + undo_redo->commit_action(); + + return; //or crash because it will become invalid + } + + if (ti->get_parent()==root->get_children()->get_next()->get_next()) { + + selected=new_name; + undo_redo->create_action(TTR("Rename Signal")); + undo_redo->add_do_method(script.ptr(),"rename_custom_signal",name,new_name); + undo_redo->add_undo_method(script.ptr(),"rename_custom_signal",new_name,name); + undo_redo->add_do_method(this,"_update_members"); + undo_redo->add_undo_method(this,"_update_members"); + undo_redo->commit_action(); + + return; //or crash because it will become invalid + } +} + +void VisualScriptEditor::_override_pressed(int p_id) { + + //override a virtual function or method from base type + + ERR_FAIL_COND(!virtuals_in_menu.has(p_id)); + + VirtualInMenu vim=virtuals_in_menu[p_id]; + + String name = _validate_name(vim.name); + selected=name; + edited_func=selected; + Ref<VisualScriptFunction> func_node; + func_node.instance(); + func_node->set_name(vim.name); + + undo_redo->create_action(TTR("Add Function")); + undo_redo->add_do_method(script.ptr(),"add_function",name); + for(int i=0;i<vim.args.size();i++) { + func_node->add_argument(vim.args[i].first,vim.args[i].second); + } + + + undo_redo->add_do_method(script.ptr(),"add_node",name,script->get_available_id(),func_node); + if (vim.ret!=Variant::NIL || vim.ret_variant) { + Ref<VisualScriptReturn> ret_node; + ret_node.instance(); + ret_node->set_return_type(vim.ret); + ret_node->set_enable_return_value(true); + ret_node->set_name(vim.name); + undo_redo->add_do_method(script.ptr(),"add_node",name,script->get_available_id()+1,ret_node,Vector2(500,0)); + + } + + undo_redo->add_undo_method(script.ptr(),"remove_function",name); + undo_redo->add_do_method(this,"_update_members"); + undo_redo->add_undo_method(this,"_update_members"); + undo_redo->commit_action(); + + + _update_graph(); +} + +void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_button) { + + TreeItem *ti=p_item->cast_to<TreeItem>(); + + TreeItem *root=members->get_root(); + + if (ti->get_parent()==root) { + //main buttons + if (ti==root->get_children()) { + //add function, this one uses menu + + if (p_button==1) { + new_function_menu->clear(); + new_function_menu->set_size(Size2(0,0)); + int idx=0; + + virtuals_in_menu.clear(); + + List<MethodInfo> mi; + ObjectTypeDB::get_method_list(script->get_instance_base_type(),&mi); + for (List<MethodInfo>::Element *E=mi.front();E;E=E->next()) { + MethodInfo mi=E->get(); + if (mi.flags&METHOD_FLAG_VIRTUAL) { + + VirtualInMenu vim; + vim.name=mi.name; + vim.ret=mi.return_val.type; + if (mi.return_val.name!=String()) + vim.ret_variant=true; + else + vim.ret_variant=false; + + String desc; + + if (mi.return_val.type==Variant::NIL) + desc="var"; + else + desc=Variant::get_type_name(mi.return_val.type); + desc+=" "+mi.name+" ( "; + + + for(int i=0;i<mi.arguments.size();i++) { + + if (i>0) + desc+=", "; + + if (mi.arguments[i].type==Variant::NIL) + desc+="var "; + else + desc+=Variant::get_type_name(mi.arguments[i].type)+" "; + + desc+=mi.arguments[i].name; + + Pair<Variant::Type,String> p; + p.first=mi.arguments[i].type; + p.second=mi.arguments[i].name; + vim.args.push_back( p ); + + } + + desc+=" )"; + + virtuals_in_menu[idx]=vim; + + new_function_menu->add_item(desc,idx); + idx++; + } + } + + Rect2 pos = members->get_item_rect(ti); + new_function_menu->set_pos(members->get_global_pos()+pos.pos+Vector2(0,pos.size.y)); + new_function_menu->popup(); + return; + } else if (p_button==0) { + + + String name = _validate_name("new_function"); + selected=name; + edited_func=selected; + + Ref<VisualScriptFunction> func_node; + func_node.instance(); + func_node->set_name(name); + + undo_redo->create_action(TTR("Add Function")); + undo_redo->add_do_method(script.ptr(),"add_function",name); + undo_redo->add_do_method(script.ptr(),"add_node",name,script->get_available_id(),func_node); + undo_redo->add_undo_method(script.ptr(),"remove_function",name); + undo_redo->add_do_method(this,"_update_members"); + undo_redo->add_undo_method(this,"_update_members"); + undo_redo->commit_action(); + + _update_graph(); + } + + return; //or crash because it will become invalid + + } + + if (ti==root->get_children()->get_next()) { + //add variable + String name = _validate_name("new_variable"); + selected=name; + + undo_redo->create_action(TTR("Add Variable")); + undo_redo->add_do_method(script.ptr(),"add_variable",name); + undo_redo->add_undo_method(script.ptr(),"remove_variable",name); + undo_redo->add_do_method(this,"_update_members"); + undo_redo->add_undo_method(this,"_update_members"); + undo_redo->commit_action(); + return; //or crash because it will become invalid + + } + + if (ti==root->get_children()->get_next()->get_next()) { + //add variable + String name = _validate_name("new_signal"); + selected=name; + + undo_redo->create_action(TTR("Add Signal")); + undo_redo->add_do_method(script.ptr(),"add_custom_signal",name); + undo_redo->add_undo_method(script.ptr(),"remove_custom_signal",name); + undo_redo->add_do_method(this,"_update_members"); + undo_redo->add_undo_method(this,"_update_members"); + undo_redo->commit_action(); + return; //or crash because it will become invalid + + } + + } else { + + if (ti->get_parent()==root->get_children()) { + //edit/remove function + String name = ti->get_metadata(0); + + if (p_button==1) { + //delete the function + undo_redo->create_action(TTR("Remove Function")); + undo_redo->add_do_method(script.ptr(),"remove_function",name); + undo_redo->add_undo_method(script.ptr(),"add_function",name); + List<int> nodes; + script->get_node_list(name,&nodes); + for (List<int>::Element *E=nodes.front();E;E=E->next()) { + undo_redo->add_undo_method(script.ptr(),"add_node",name,E->get(),script->get_node(name,E->get()),script->get_node_pos(name,E->get())); + } + + List<VisualScript::SequenceConnection> seq_connections; + + script->get_sequence_connection_list(name,&seq_connections); + + for (List<VisualScript::SequenceConnection>::Element *E=seq_connections.front();E;E=E->next()) { + undo_redo->add_undo_method(script.ptr(),"sequence_connect",name,E->get().from_node,E->get().from_output,E->get().to_node); + } + + List<VisualScript::DataConnection> data_connections; + + script->get_data_connection_list(name,&data_connections); + + for (List<VisualScript::DataConnection>::Element *E=data_connections.front();E;E=E->next()) { + undo_redo->add_undo_method(script.ptr(),"data_connect",name,E->get().from_node,E->get().from_port,E->get().to_node,E->get().to_port); + } + + //for(int i=0;i<script->function_get_argument_count(name);i++) { + //// undo_redo->add_undo_method(script.ptr(),"function_add_argument",name,script->function_get_argument_name(name,i),script->function_get_argument_type(name,i)); + //} + undo_redo->add_do_method(this,"_update_members"); + undo_redo->add_undo_method(this,"_update_members"); + undo_redo->commit_action(); + + } else if (p_button==0) { + + } + return; //or crash because it will become invalid + + } + + if (ti->get_parent()==root->get_children()->get_next()) { + //edit/remove variable + + String name = ti->get_metadata(0); + + if (p_button==1) { + + + undo_redo->create_action(TTR("Remove Variable")); + undo_redo->add_do_method(script.ptr(),"remove_variable",name); + undo_redo->add_undo_method(script.ptr(),"add_variable",name,script->get_variable_default_value(name)); + undo_redo->add_undo_method(script.ptr(),"set_variable_info",name,script->call("get_variable_info",name)); //return as dict + undo_redo->add_do_method(this,"_update_members"); + undo_redo->add_undo_method(this,"_update_members"); + undo_redo->commit_action(); + return; //or crash because it will become invalid + } else if (p_button==0) { + + variable_editor->edit(name); + edit_variable_dialog->set_title(TTR("Editing Variable: ")+name); + edit_variable_dialog->popup_centered_minsize(Size2(400,200)*EDSCALE); + } + + } + + if (ti->get_parent()==root->get_children()->get_next()->get_next()) { + //edit/remove variable + String name = ti->get_metadata(0); + + if (p_button==1) { + + undo_redo->create_action(TTR("Remove Signal")); + undo_redo->add_do_method(script.ptr(),"remove_custom_signal",name); + undo_redo->add_undo_method(script.ptr(),"add_custom_signal",name); + + for(int i=0;i<script->custom_signal_get_argument_count(name);i++) { + undo_redo->add_undo_method(script.ptr(),"custom_signal_add_argument",name,script->custom_signal_get_argument_name(name,i),script->custom_signal_get_argument_type(name,i)); + } + + undo_redo->add_do_method(this,"_update_members"); + undo_redo->add_undo_method(this,"_update_members"); + undo_redo->commit_action(); + } else if (p_button==0) { + + signal_editor->edit(name); + edit_signal_dialog->set_title(TTR("Editing Signal: ")+name); + edit_signal_dialog->popup_centered_minsize(Size2(400,300)*EDSCALE); + } + + return; //or crash because it will become invalid + + } + + + } +} + +void VisualScriptEditor::_available_node_doubleclicked() { + + TreeItem *item = nodes->get_selected(); + + if (!item) + return; + + String which = item->get_metadata(0); + if (which==String()) + return; + + Vector2 ofs = graph->get_scroll_ofs() + graph->get_size() * 0.5; + ofs/=EDSCALE; + + while(true) { + bool exists=false; + List<int> existing; + script->get_node_list(edited_func,&existing); + for (List<int>::Element *E=existing.front();E;E=E->next()) { + Point2 pos = script->get_node_pos(edited_func,E->get()); + if (pos.distance_to(ofs)<15) { + ofs+=Vector2(25,25); + exists=true; + break; + } + } + + if (exists) + continue; + break; + + } + + + Ref<VisualScriptNode> vnode = VisualScriptLanguage::singleton->create_node_from_name(which); + int new_id = script->get_available_id(); + + undo_redo->create_action(TTR("Add Node")); + undo_redo->add_do_method(script.ptr(),"add_node",edited_func,new_id,vnode,ofs); + undo_redo->add_undo_method(script.ptr(),"remove_node",edited_func,new_id); + undo_redo->add_do_method(this,"_update_graph"); + undo_redo->add_undo_method(this,"_update_graph"); + undo_redo->commit_action(); + + Node* node = graph->get_node(itos(new_id)); + if (node) { + graph->set_selected(node); + _node_selected(node); + } + +} + +void VisualScriptEditor::_update_available_nodes() { + + nodes->clear(); + + TreeItem *root = nodes->create_item(); + + Map<String,TreeItem*> path_cache; + + List<String> fnodes; + VisualScriptLanguage::singleton->get_registered_node_names(&fnodes); + + for (List<String>::Element *E=fnodes.front();E;E=E->next()) { + + Vector<String> path = E->get().split("/"); + String sp; + TreeItem* parent=root; + + for(int i=0;i<path.size()-1;i++) { + + if (i>0) + sp+=","; + sp+=path[i]; + if (!path_cache.has(sp)) { + TreeItem* pathn = nodes->create_item(parent); + pathn->set_selectable(0,false); + pathn->set_text(0,path[i].capitalize()); + path_cache[sp]=pathn; + parent=pathn; + pathn->set_collapsed(true); //should remember state + } else { + parent=path_cache[sp]; + } + } + + TreeItem *item = nodes->create_item(parent); + item->set_text(0,path[path.size()-1].capitalize()); + item->set_selectable(0,true); + item->set_metadata(0,E->get()); + } + +} + +String VisualScriptEditor::_validate_name(const String& p_name) const { + + String valid=p_name; + + int counter=1; + while(true) { + + bool exists = script->has_function(valid) || script->has_variable(valid) || script->has_custom_signal(valid); + + if (exists) { + counter++; + valid=p_name+"_"+itos(counter); + continue; + } + + break; + } + + return valid; +} + +void VisualScriptEditor::_on_nodes_delete() { + + + List<int> to_erase; + + for(int i=0;i<graph->get_child_count();i++) { + GraphNode *gn = graph->get_child(i)->cast_to<GraphNode>(); + if (gn) { + if (gn->is_selected() && gn->is_close_button_visible()) { + to_erase.push_back(gn->get_name().operator String().to_int()); + } + } + } + + if (to_erase.empty()) + return; + + undo_redo->create_action("Remove VisualScript Nodes"); + + for(List<int>::Element*F=to_erase.front();F;F=F->next()) { + + + undo_redo->add_do_method(script.ptr(),"remove_node",edited_func,F->get()); + undo_redo->add_undo_method(script.ptr(),"add_node",edited_func,F->get(),script->get_node(edited_func,F->get()),script->get_node_pos(edited_func,F->get())); + + + List<VisualScript::SequenceConnection> sequence_conns; + script->get_sequence_connection_list(edited_func,&sequence_conns); + + + for (List<VisualScript::SequenceConnection>::Element *E=sequence_conns.front();E;E=E->next()) { + + if (E->get().from_node==F->get() || E->get().to_node==F->get()) { + undo_redo->add_undo_method(script.ptr(),"sequence_connect",edited_func,E->get().from_node,E->get().from_output,E->get().to_node); + } + } + + List<VisualScript::DataConnection> data_conns; + script->get_data_connection_list(edited_func,&data_conns); + + for (List<VisualScript::DataConnection>::Element *E=data_conns.front();E;E=E->next()) { + + if (E->get().from_node==F->get() || E->get().to_node==F->get()) { + undo_redo->add_undo_method(script.ptr(),"data_connect",edited_func,E->get().from_node,E->get().from_port,E->get().to_node,E->get().to_port); + } + } + + } + undo_redo->add_do_method(this,"_update_graph"); + undo_redo->add_undo_method(this,"_update_graph"); + + undo_redo->commit_action(); +} + + +void VisualScriptEditor::_on_nodes_duplicate() { + + + List<int> to_duplicate; + + for(int i=0;i<graph->get_child_count();i++) { + GraphNode *gn = graph->get_child(i)->cast_to<GraphNode>(); + if (gn) { + if (gn->is_selected() && gn->is_close_button_visible()) { + to_duplicate.push_back(gn->get_name().operator String().to_int()); + } + } + } + + if (to_duplicate.empty()) + return; + + undo_redo->create_action("Duplicate VisualScript Nodes"); + int idc=script->get_available_id()+1; + + Set<int> to_select; + + for(List<int>::Element*F=to_duplicate.front();F;F=F->next()) { + + Ref<VisualScriptNode> node = script->get_node(edited_func,F->get()); + + Ref<VisualScriptNode> dupe = node->duplicate(); + + int new_id = idc++; + to_select.insert(new_id); + undo_redo->add_do_method(script.ptr(),"add_node",edited_func,new_id,dupe,script->get_node_pos(edited_func,F->get())+Vector2(20,20)); + undo_redo->add_undo_method(script.ptr(),"remove_node",edited_func,new_id); + + } + undo_redo->add_do_method(this,"_update_graph"); + undo_redo->add_undo_method(this,"_update_graph"); + + undo_redo->commit_action(); + + for(int i=0;i<graph->get_child_count();i++) { + GraphNode *gn = graph->get_child(i)->cast_to<GraphNode>(); + if (gn) { + int id = gn->get_name().operator String().to_int(); + gn->set_selected(to_select.has(id)); + + } + } + + if (to_select.size()) { + EditorNode::get_singleton()->push_item(script->get_node(edited_func,to_select.front()->get()).ptr()); + } + +} + +void VisualScriptEditor::_input(const InputEvent& p_event) { + + if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==BUTTON_LEFT) { + revert_on_drag=String(); //so we can still drag functions + } +} + +Variant VisualScriptEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) { + + + if (p_from==nodes) { + + TreeItem *it = nodes->get_item_at_pos(p_point); + if (!it) + return Variant(); + String type=it->get_metadata(0); + if (type==String()) + return Variant(); + + Dictionary dd; + dd["type"]="visual_script_node_drag"; + dd["node_type"]=type; + + Label *label = memnew(Label); + label->set_text(it->get_text(0)); + set_drag_preview(label); + return dd; + } + + if (p_from==members) { + + + TreeItem *it = members->get_item_at_pos(p_point); + if (!it) + return Variant(); + + String type=it->get_metadata(0); + + if (type==String()) + return Variant(); + + + Dictionary dd; + TreeItem *root=members->get_root(); + + if (it->get_parent()==root->get_children()) { + + dd["type"]="visual_script_function_drag"; + dd["function"]=type; + if (revert_on_drag!=String()) { + edited_func=revert_on_drag; //revert so function does not change + revert_on_drag=String(); + _update_graph(); + } + } else if (it->get_parent()==root->get_children()->get_next()) { + + dd["type"]="visual_script_variable_drag"; + dd["variable"]=type; + } else if (it->get_parent()==root->get_children()->get_next()->get_next()) { + + dd["type"]="visual_script_signal_drag"; + dd["signal"]=type; + + } else { + return Variant(); + } + + + + + + + Label *label = memnew(Label); + label->set_text(it->get_text(0)); + set_drag_preview(label); + return dd; + } + return Variant(); +} + +bool VisualScriptEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{ + + if (p_from==graph) { + + Dictionary d = p_data; + if (d.has("type") && + ( + String(d["type"])=="visual_script_node_drag" || + String(d["type"])=="visual_script_function_drag" || + String(d["type"])=="visual_script_variable_drag" || + String(d["type"])=="visual_script_signal_drag" + ) ) + return true; + } + + + return false; +} +void VisualScriptEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){ + + if (p_from==graph) { + + Dictionary d = p_data; + if (d.has("type") && String(d["type"])=="visual_script_node_drag") { + + Vector2 ofs = graph->get_scroll_ofs() + p_point; + + ofs/=EDSCALE; + + Ref<VisualScriptNode> vnode = VisualScriptLanguage::singleton->create_node_from_name(d["node_type"]); + int new_id = script->get_available_id(); + + undo_redo->create_action(TTR("Add Node")); + undo_redo->add_do_method(script.ptr(),"add_node",edited_func,new_id,vnode,ofs); + undo_redo->add_undo_method(script.ptr(),"remove_node",edited_func,new_id); + undo_redo->add_do_method(this,"_update_graph"); + undo_redo->add_undo_method(this,"_update_graph"); + undo_redo->commit_action(); + + Node* node = graph->get_node(itos(new_id)); + if (node) { + graph->set_selected(node); + _node_selected(node); + } + } + + if (d.has("type") && String(d["type"])=="visual_script_variable_drag") { + + Vector2 ofs = graph->get_scroll_ofs() + p_point; + + ofs/=EDSCALE; + + Ref<VisualScriptVariable> vnode; + vnode.instance(); + vnode->set_variable(d["variable"]); + + int new_id = script->get_available_id(); + + undo_redo->create_action(TTR("Add Node")); + undo_redo->add_do_method(script.ptr(),"add_node",edited_func,new_id,vnode,ofs); + undo_redo->add_undo_method(script.ptr(),"remove_node",edited_func,new_id); + undo_redo->add_do_method(this,"_update_graph"); + undo_redo->add_undo_method(this,"_update_graph"); + undo_redo->commit_action(); + + Node* node = graph->get_node(itos(new_id)); + if (node) { + graph->set_selected(node); + _node_selected(node); + } + } + + if (d.has("type") && String(d["type"])=="visual_script_function_drag") { + + Vector2 ofs = graph->get_scroll_ofs() + p_point; + + ofs/=EDSCALE; + + Ref<VisualScriptScriptCall> vnode; + vnode.instance(); + vnode->set_call_mode(VisualScriptScriptCall::CALL_MODE_SELF); + vnode->set_function(d["function"]); + + int new_id = script->get_available_id(); + + undo_redo->create_action(TTR("Add Node")); + undo_redo->add_do_method(script.ptr(),"add_node",edited_func,new_id,vnode,ofs); + undo_redo->add_undo_method(script.ptr(),"remove_node",edited_func,new_id); + undo_redo->add_do_method(this,"_update_graph"); + undo_redo->add_undo_method(this,"_update_graph"); + undo_redo->commit_action(); + + Node* node = graph->get_node(itos(new_id)); + if (node) { + graph->set_selected(node); + _node_selected(node); + } + } + + + if (d.has("type") && String(d["type"])=="visual_script_signal_drag") { + + Vector2 ofs = graph->get_scroll_ofs() + p_point; + + ofs/=EDSCALE; + + Ref<VisualScriptEmitSignal> vnode; + vnode.instance(); + vnode->set_signal(d["signal"]); + + int new_id = script->get_available_id(); + + undo_redo->create_action(TTR("Add Node")); + undo_redo->add_do_method(script.ptr(),"add_node",edited_func,new_id,vnode,ofs); + undo_redo->add_undo_method(script.ptr(),"remove_node",edited_func,new_id); + undo_redo->add_do_method(this,"_update_graph"); + undo_redo->add_undo_method(this,"_update_graph"); + undo_redo->commit_action(); + + Node* node = graph->get_node(itos(new_id)); + if (node) { + graph->set_selected(node); + _node_selected(node); + } + } + } + + +} + + +///////////////////////// + + + +void VisualScriptEditor::apply_code() { + + +} + +Ref<Script> VisualScriptEditor::get_edited_script() const{ + + return script; +} + +Vector<String> VisualScriptEditor::get_functions(){ + + return Vector<String>(); +} + +void VisualScriptEditor::set_edited_script(const Ref<Script>& p_script){ + + script=p_script; + signal_editor->script=p_script; + signal_editor->undo_redo=undo_redo; + variable_editor->script=p_script; + variable_editor->undo_redo=undo_redo; + + + script->connect("node_ports_changed",this,"_node_ports_changed"); + + _update_members(); + _update_available_nodes(); +} + +void VisualScriptEditor::reload_text(){ + + +} + +String VisualScriptEditor::get_name(){ + + String name; + + if (script->get_path().find("local://")==-1 && script->get_path().find("::")==-1) { + name=script->get_path().get_file(); + if (is_unsaved()) { + name+="(*)"; + } + } else if (script->get_name()!="") + name=script->get_name(); + else + name=script->get_type()+"("+itos(script->get_instance_ID())+")"; + + return name; + +} + +Ref<Texture> VisualScriptEditor::get_icon(){ + + return Control::get_icon("VisualScript","EditorIcons"); +} + +bool VisualScriptEditor::is_unsaved(){ + + return false; +} + +Variant VisualScriptEditor::get_edit_state(){ + + return Variant(); +} + +void VisualScriptEditor::set_edit_state(const Variant& p_state){ + + +} + +void VisualScriptEditor::goto_line(int p_line){ + + +} + +void VisualScriptEditor::trim_trailing_whitespace(){ + + +} + +void VisualScriptEditor::ensure_focus(){ + + +} + +void VisualScriptEditor::tag_saved_version(){ + + +} + +void VisualScriptEditor::reload(bool p_soft){ + + +} + +void VisualScriptEditor::get_breakpoints(List<int> *p_breakpoints){ + + +} + +bool VisualScriptEditor::goto_method(const String& p_method){ + + return false; +} + +void VisualScriptEditor::add_callback(const String& p_function,StringArray p_args){ + + +} + +void VisualScriptEditor::update_settings(){ + + +} + + +void VisualScriptEditor::set_tooltip_request_func(String p_method,Object* p_obj){ + + +} + +Control *VisualScriptEditor::get_edit_menu(){ + + return NULL; +} + +void VisualScriptEditor::_change_base_type() { + + select_base_type->popup(true); +} + +void VisualScriptEditor::_change_base_type_callback() { + + String bt = select_base_type->get_selected_type(); + + ERR_FAIL_COND(bt==String()); + undo_redo->create_action("Change Base Type"); + undo_redo->add_do_method(script.ptr(),"set_instance_base_type",bt); + undo_redo->add_undo_method(script.ptr(),"set_instance_base_type",script->get_instance_base_type()); + undo_redo->add_do_method(this,"_update_members"); + undo_redo->add_undo_method(this,"_update_members"); + undo_redo->commit_action(); + +} + +void VisualScriptEditor::_node_selected(Node* p_node) { + + Ref<VisualScriptNode> vnode = p_node->get_meta("__vnode"); + if (vnode.is_null()) + return; + + EditorNode::get_singleton()->push_item(vnode.ptr()); //edit node in inspector +} + +static bool _get_out_slot(const Ref<VisualScriptNode>& p_node,int p_slot,int& r_real_slot,bool& r_sequence) { + + if (p_slot<p_node->get_output_sequence_port_count()) { + r_sequence=true; + r_real_slot=p_slot; + + return true; + } + + r_real_slot=p_slot-p_node->get_output_sequence_port_count(); + r_sequence=false; + + return (r_real_slot<p_node->get_output_value_port_count()); + +} + +static bool _get_in_slot(const Ref<VisualScriptNode>& p_node,int p_slot,int& r_real_slot,bool& r_sequence) { + + if (p_slot==0 && p_node->has_input_sequence_port()) { + r_sequence=true; + r_real_slot=0; + return true; + } + + + r_real_slot=p_slot-(p_node->has_input_sequence_port()?1:0); + r_sequence=false; + + return r_real_slot<p_node->get_input_value_port_count(); + +} + + +void VisualScriptEditor::_begin_node_move() { + + undo_redo->create_action("Move Node(s)"); +} + +void VisualScriptEditor::_end_node_move() { + + undo_redo->commit_action(); +} + +void VisualScriptEditor::_move_node(String func,int p_id,const Vector2& p_to) { + + + + if (func==String(edited_func)) { + Node* node = graph->get_node(itos(p_id)); + if (node && node->cast_to<GraphNode>()) + node->cast_to<GraphNode>()->set_offset(p_to); + } + script->set_node_pos(edited_func,p_id,p_to/EDSCALE); +} + +void VisualScriptEditor::_node_moved(Vector2 p_from,Vector2 p_to, int p_id) { + + undo_redo->add_do_method(this,"_move_node",String(edited_func),p_id,p_to); + undo_redo->add_undo_method(this,"_move_node",String(edited_func),p_id,p_from); +} + +void VisualScriptEditor::_remove_node(int p_id) { + + + undo_redo->create_action("Remove VisualScript Node"); + + undo_redo->add_do_method(script.ptr(),"remove_node",edited_func,p_id); + undo_redo->add_undo_method(script.ptr(),"add_node",edited_func,p_id,script->get_node(edited_func,p_id),script->get_node_pos(edited_func,p_id)); + + + List<VisualScript::SequenceConnection> sequence_conns; + script->get_sequence_connection_list(edited_func,&sequence_conns); + + + for (List<VisualScript::SequenceConnection>::Element *E=sequence_conns.front();E;E=E->next()) { + + if (E->get().from_node==p_id || E->get().to_node==p_id) { + undo_redo->add_undo_method(script.ptr(),"sequence_connect",edited_func,E->get().from_node,E->get().from_output,E->get().to_node); + } + } + + List<VisualScript::DataConnection> data_conns; + script->get_data_connection_list(edited_func,&data_conns); + + for (List<VisualScript::DataConnection>::Element *E=data_conns.front();E;E=E->next()) { + + if (E->get().from_node==p_id || E->get().to_node==p_id) { + undo_redo->add_undo_method(script.ptr(),"data_connect",edited_func,E->get().from_node,E->get().from_port,E->get().to_node,E->get().to_port); + } + } + + undo_redo->add_do_method(this,"_update_graph"); + undo_redo->add_undo_method(this,"_update_graph"); + + undo_redo->commit_action(); +} + + +void VisualScriptEditor::_node_ports_changed(const String& p_func,int p_id) { + + if (p_func!=String(edited_func)) + return; + + _update_graph(p_id); +} + +void VisualScriptEditor::_graph_connected(const String& p_from,int p_from_slot,const String& p_to,int p_to_slot) { + + Ref<VisualScriptNode> from_node = script->get_node(edited_func,p_from.to_int()); + ERR_FAIL_COND(!from_node.is_valid()); + + bool from_seq; + int from_port; + + if (!_get_out_slot(from_node,p_from_slot,from_port,from_seq)) + return; //can't connect this, it' s invalid + + Ref<VisualScriptNode> to_node = script->get_node(edited_func,p_to.to_int()); + ERR_FAIL_COND(!to_node.is_valid()); + + bool to_seq; + int to_port; + + if (!_get_in_slot(to_node,p_to_slot,to_port,to_seq)) + return; //can't connect this, it' s invalid + + + ERR_FAIL_COND(from_seq!=to_seq); + + + undo_redo->create_action("Connect Nodes"); + + if (from_seq) { + undo_redo->add_do_method(script.ptr(),"sequence_connect",edited_func,p_from.to_int(),from_port,p_to.to_int()); + undo_redo->add_undo_method(script.ptr(),"sequence_disconnect",edited_func,p_from.to_int(),from_port,p_to.to_int()); + } else { + undo_redo->add_do_method(script.ptr(),"data_connect",edited_func,p_from.to_int(),from_port,p_to.to_int(),to_port); + undo_redo->add_undo_method(script.ptr(),"data_disconnect",edited_func,p_from.to_int(),from_port,p_to.to_int(),to_port); + } + + undo_redo->add_do_method(this,"_update_graph_connections"); + undo_redo->add_undo_method(this,"_update_graph_connections"); + + undo_redo->commit_action(); + +} + +void VisualScriptEditor::_graph_disconnected(const String& p_from,int p_from_slot,const String& p_to,int p_to_slot){ + + Ref<VisualScriptNode> from_node = script->get_node(edited_func,p_from.to_int()); + ERR_FAIL_COND(!from_node.is_valid()); + + bool from_seq; + int from_port; + + if (!_get_out_slot(from_node,p_from_slot,from_port,from_seq)) + return; //can't connect this, it' s invalid + + Ref<VisualScriptNode> to_node = script->get_node(edited_func,p_to.to_int()); + ERR_FAIL_COND(!to_node.is_valid()); + + bool to_seq; + int to_port; + + if (!_get_in_slot(to_node,p_to_slot,to_port,to_seq)) + return; //can't connect this, it' s invalid + + + ERR_FAIL_COND(from_seq!=to_seq); + + + undo_redo->create_action("Connect Nodes"); + + if (from_seq) { + undo_redo->add_do_method(script.ptr(),"sequence_disconnect",edited_func,p_from.to_int(),from_port,p_to.to_int()); + undo_redo->add_undo_method(script.ptr(),"sequence_connect",edited_func,p_from.to_int(),from_port,p_to.to_int()); + } else { + undo_redo->add_do_method(script.ptr(),"data_disconnect",edited_func,p_from.to_int(),from_port,p_to.to_int(),to_port); + undo_redo->add_undo_method(script.ptr(),"data_connect",edited_func,p_from.to_int(),from_port,p_to.to_int(),to_port); + } + + undo_redo->add_do_method(this,"_update_graph_connections"); + undo_redo->add_undo_method(this,"_update_graph_connections"); + + undo_redo->commit_action(); +} + + +void VisualScriptEditor::_bind_methods() { + + ObjectTypeDB::bind_method("_member_button",&VisualScriptEditor::_member_button); + ObjectTypeDB::bind_method("_member_edited",&VisualScriptEditor::_member_edited); + ObjectTypeDB::bind_method("_member_selected",&VisualScriptEditor::_member_selected); + ObjectTypeDB::bind_method("_update_members",&VisualScriptEditor::_update_members); + ObjectTypeDB::bind_method("_change_base_type",&VisualScriptEditor::_change_base_type); + ObjectTypeDB::bind_method("_change_base_type_callback",&VisualScriptEditor::_change_base_type_callback); + ObjectTypeDB::bind_method("_override_pressed",&VisualScriptEditor::_override_pressed); + ObjectTypeDB::bind_method("_node_selected",&VisualScriptEditor::_node_selected); + ObjectTypeDB::bind_method("_node_moved",&VisualScriptEditor::_node_moved); + ObjectTypeDB::bind_method("_move_node",&VisualScriptEditor::_move_node); + ObjectTypeDB::bind_method("_begin_node_move",&VisualScriptEditor::_begin_node_move); + ObjectTypeDB::bind_method("_end_node_move",&VisualScriptEditor::_end_node_move); + ObjectTypeDB::bind_method("_remove_node",&VisualScriptEditor::_remove_node); + ObjectTypeDB::bind_method("_update_graph",&VisualScriptEditor::_update_graph,DEFVAL(-1)); + ObjectTypeDB::bind_method("_node_ports_changed",&VisualScriptEditor::_node_ports_changed); + ObjectTypeDB::bind_method("_available_node_doubleclicked",&VisualScriptEditor::_available_node_doubleclicked); + + ObjectTypeDB::bind_method("get_drag_data_fw",&VisualScriptEditor::get_drag_data_fw); + ObjectTypeDB::bind_method("can_drop_data_fw",&VisualScriptEditor::can_drop_data_fw); + ObjectTypeDB::bind_method("drop_data_fw",&VisualScriptEditor::drop_data_fw); + + ObjectTypeDB::bind_method("_input",&VisualScriptEditor::_input); + ObjectTypeDB::bind_method("_on_nodes_delete",&VisualScriptEditor::_on_nodes_delete); + ObjectTypeDB::bind_method("_on_nodes_duplicate",&VisualScriptEditor::_on_nodes_duplicate); + + + ObjectTypeDB::bind_method("_graph_connected",&VisualScriptEditor::_graph_connected); + ObjectTypeDB::bind_method("_graph_disconnected",&VisualScriptEditor::_graph_disconnected); + ObjectTypeDB::bind_method("_update_graph_connections",&VisualScriptEditor::_update_graph_connections); + + +} + + + +VisualScriptEditor::VisualScriptEditor() { + + main_hsplit = memnew( HSplitContainer ); + add_child(main_hsplit); + main_hsplit->set_area_as_parent_rect(); + + left_vsplit = memnew( VSplitContainer ); + main_hsplit->add_child(left_vsplit); + + VBoxContainer *left_vb = memnew( VBoxContainer ); + left_vsplit->add_child(left_vb); + left_vb->set_v_size_flags(SIZE_EXPAND_FILL); + left_vb->set_custom_minimum_size(Size2(180,1)*EDSCALE); + + base_type_select = memnew( Button ); + left_vb->add_margin_child(TTR("Base Type:"),base_type_select); + base_type_select->connect("pressed",this,"_change_base_type"); + + members = memnew( Tree ); + left_vb->add_margin_child(TTR("Members:"),members,true); + members->set_hide_root(true); + members->connect("button_pressed",this,"_member_button"); + members->connect("item_edited",this,"_member_edited"); + members->connect("cell_selected",this,"_member_selected"); + members->set_single_select_cell_editing_only_when_already_selected(true); + members->set_hide_folding(true); + members->set_drag_forwarding(this); + + + VBoxContainer *left_vb2 = memnew( VBoxContainer ); + left_vsplit->add_child(left_vb2); + left_vb2->set_v_size_flags(SIZE_EXPAND_FILL); + + nodes = memnew( Tree ); + left_vb2->add_margin_child(TTR("Available Nodes:"),nodes,true); + nodes->set_hide_root(true); + nodes->connect("item_activated",this,"_available_node_doubleclicked"); + nodes->set_drag_forwarding(this); + + graph = memnew( GraphEdit ); + main_hsplit->add_child(graph); + graph->set_h_size_flags(SIZE_EXPAND_FILL); + graph->connect("node_selected",this,"_node_selected"); + graph->connect("_begin_node_move",this,"_begin_node_move"); + graph->connect("_end_node_move",this,"_end_node_move"); + graph->connect("delete_nodes_request",this,"_on_nodes_delete"); + graph->connect("duplicate_nodes_request",this,"_on_nodes_duplicate"); + graph->set_drag_forwarding(this); + + + + //allowed casts (connections) + for(int i=0;i<Variant::VARIANT_MAX;i++) { + graph->add_valid_connection_type(Variant::NIL,i); + graph->add_valid_connection_type(i,Variant::NIL); + for(int j=0;j<Variant::VARIANT_MAX;j++) { + if (Variant::can_convert(Variant::Type(i),Variant::Type(j))) { + graph->add_valid_connection_type(i,j); + } + } + + graph->add_valid_right_disconnect_type(i); + } + + graph->add_valid_left_disconnect_type(TYPE_SEQUENCE); + + graph->connect("connection_request",this,"_graph_connected"); + graph->connect("disconnection_request",this,"_graph_disconnected"); + + edit_signal_dialog = memnew( AcceptDialog ); + edit_signal_dialog->get_ok()->set_text(TTR("Close")); + add_child(edit_signal_dialog); + edit_signal_dialog->set_title(TTR("Edit Signal Arguments:")); + + signal_editor = memnew( VisualScriptEditorSignalEdit ); + edit_signal_edit = memnew( PropertyEditor ); + edit_signal_edit->hide_top_label(); + edit_signal_dialog->add_child(edit_signal_edit); + edit_signal_dialog->set_child_rect(edit_signal_edit); + edit_signal_edit->edit(signal_editor); + + edit_variable_dialog = memnew( AcceptDialog ); + edit_variable_dialog->get_ok()->set_text(TTR("Close")); + add_child(edit_variable_dialog); + edit_variable_dialog->set_title(TTR("Edit Variable:")); + + variable_editor = memnew( VisualScriptEditorVariableEdit ); + edit_variable_edit = memnew( PropertyEditor ); + edit_variable_edit->hide_top_label(); + edit_variable_dialog->add_child(edit_variable_edit); + edit_variable_dialog->set_child_rect(edit_variable_edit); + edit_variable_edit->edit(variable_editor); + + select_base_type=memnew(CreateDialog); + select_base_type->set_base_type("Object"); //anything goes + select_base_type->connect("create",this,"_change_base_type_callback"); + select_base_type->get_ok()->set_text(TTR("Change")); + add_child(select_base_type); + + undo_redo = EditorNode::get_singleton()->get_undo_redo(); + + new_function_menu = memnew( PopupMenu ); + new_function_menu->connect("item_pressed",this,"_override_pressed"); + add_child(new_function_menu); + updating_members=false; + + set_process_input(true); //for revert on drag + set_process_unhandled_input(true); //for revert on drag +} + +VisualScriptEditor::~VisualScriptEditor() { + + undo_redo->clear_history(); //avoid crashes + memdelete(signal_editor); + memdelete(variable_editor); +} + +static ScriptEditorBase * create_editor(const Ref<Script>& p_script) { + + if (p_script->cast_to<VisualScript>()) { + return memnew( VisualScriptEditor ); + } + + return NULL; +} + + +void VisualScriptEditor::register_editor() { + + ScriptEditor::register_create_script_editor_function(create_editor); +} + diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h new file mode 100644 index 0000000000..fcb31e50cc --- /dev/null +++ b/modules/visual_script/visual_script_editor.h @@ -0,0 +1,147 @@ +#ifndef VisualSCRIPT_EDITOR_H +#define VisualSCRIPT_EDITOR_H + +#include "tools/editor/plugins/script_editor_plugin.h" +#include "visual_script.h" +#include "tools/editor/property_editor.h" +#include "scene/gui/graph_edit.h" +#include "tools/editor/create_dialog.h" + +class VisualScriptEditorSignalEdit; +class VisualScriptEditorVariableEdit; + + + +class VisualScriptEditor : public ScriptEditorBase { + OBJ_TYPE(VisualScriptEditor,ScriptEditorBase) + + enum { + TYPE_SEQUENCE=1000, + INDEX_BASE_SEQUENCE=1024 + + + }; + + Ref<VisualScript> script; + + Button *base_type_select; + + HSplitContainer *main_hsplit; + VSplitContainer *left_vsplit; + + GraphEdit *graph; + + VisualScriptEditorSignalEdit *signal_editor; + + AcceptDialog *edit_signal_dialog; + PropertyEditor *edit_signal_edit; + + + VisualScriptEditorVariableEdit *variable_editor; + + AcceptDialog *edit_variable_dialog; + PropertyEditor *edit_variable_edit; + + UndoRedo *undo_redo; + + Tree *members; + Tree *nodes; + + CreateDialog *select_base_type; + + struct VirtualInMenu { + String name; + Variant::Type ret; + bool ret_variant; + Vector< Pair<Variant::Type,String> > args; + }; + + Map<int,VirtualInMenu> virtuals_in_menu; + + PopupMenu *new_function_menu; + + + StringName edited_func; + + void _update_graph_connections(); + void _update_graph(int p_only_id=-1); + + bool updating_members; + + void _update_members(); + + StringName selected; + + String _validate_name(const String& p_name) const; + + + void _node_selected(Node* p_node); + + void _change_base_type_callback(); + void _change_base_type(); + void _member_selected(); + void _member_edited(); + void _override_pressed(int p_id); + + void _begin_node_move(); + void _end_node_move(); + void _move_node(String func,int p_id,const Vector2& p_to); + + void _node_moved(Vector2 p_from,Vector2 p_to, int p_id); + void _remove_node(int p_id); + void _graph_connected(const String& p_from,int p_from_slot,const String& p_to,int p_to_slot); + void _graph_disconnected(const String& p_from,int p_from_slot,const String& p_to,int p_to_slot); + void _node_ports_changed(const String& p_func,int p_id); + void _available_node_doubleclicked(); + + void _update_available_nodes(); + + void _member_button(Object *p_item, int p_column, int p_button); + + + String revert_on_drag; + + void _input(const InputEvent& p_event); + void _on_nodes_delete(); + void _on_nodes_duplicate(); + + Variant get_drag_data_fw(const Point2& p_point,Control* p_from); + bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const; + void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from); + + +protected: + + static void _bind_methods(); +public: + + virtual void apply_code(); + virtual Ref<Script> get_edited_script() const; + virtual Vector<String> get_functions(); + virtual void set_edited_script(const Ref<Script>& p_script); + virtual void reload_text(); + virtual String get_name(); + virtual Ref<Texture> get_icon(); + virtual bool is_unsaved(); + virtual Variant get_edit_state(); + virtual void set_edit_state(const Variant& p_state); + virtual void goto_line(int p_line); + virtual void trim_trailing_whitespace(); + virtual void ensure_focus(); + virtual void tag_saved_version(); + virtual void reload(bool p_soft); + virtual void get_breakpoints(List<int> *p_breakpoints); + virtual bool goto_method(const String& p_method); + virtual void add_callback(const String& p_function,StringArray p_args); + virtual void update_settings(); + + virtual void set_tooltip_request_func(String p_method,Object* p_obj); + virtual Control *get_edit_menu(); + + static void register_editor(); + + VisualScriptEditor(); + ~VisualScriptEditor(); +}; + +#endif // VisualSCRIPT_EDITOR_H diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp new file mode 100644 index 0000000000..f735564b8b --- /dev/null +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -0,0 +1,418 @@ +#include "visual_script_flow_control.h" + +////////////////////////////////////////// +////////////////RETURN//////////////////// +////////////////////////////////////////// + +int VisualScriptReturn::get_output_sequence_port_count() const { + + return 0; +} + +bool VisualScriptReturn::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptReturn::get_input_value_port_count() const{ + + return with_value?1:0; +} +int VisualScriptReturn::get_output_value_port_count() const{ + + return 0; +} + +String VisualScriptReturn::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptReturn::get_input_value_port_info(int p_idx) const{ + + PropertyInfo pinfo; + pinfo.name="result"; + pinfo.type=type; + return pinfo; +} +PropertyInfo VisualScriptReturn::get_output_value_port_info(int p_idx) const{ + return PropertyInfo(); +} + +String VisualScriptReturn::get_caption() const { + + return "Return"; +} + +String VisualScriptReturn::get_text() const { + + return get_name(); +} + +void VisualScriptReturn::set_return_type(Variant::Type p_type) { + + if (type==p_type) + return; + type=p_type; + emit_signal("ports_changed"); + +} + +Variant::Type VisualScriptReturn::get_return_type() const{ + + return type; +} + +void VisualScriptReturn::set_enable_return_value(bool p_enable) { + if (with_value==p_enable) + return; + + with_value=p_enable; + emit_signal("ports_changed"); +} + +bool VisualScriptReturn::is_return_value_enabled() const { + + return with_value; +} + +void VisualScriptReturn::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_return_type","type"),&VisualScriptReturn::set_return_type); + ObjectTypeDB::bind_method(_MD("get_return_type"),&VisualScriptReturn::get_return_type); + ObjectTypeDB::bind_method(_MD("set_enable_return_value","enable"),&VisualScriptReturn::set_enable_return_value); + ObjectTypeDB::bind_method(_MD("is_return_value_enabled"),&VisualScriptReturn::is_return_value_enabled); + + String argt="Variant"; + for(int i=1;i<Variant::VARIANT_MAX;i++) { + argt+=","+Variant::get_type_name(Variant::Type(i)); + } + + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"return_value/enabled"),_SCS("set_enable_return_value"),_SCS("is_return_value_enabled")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"return_value/type",PROPERTY_HINT_ENUM,argt),_SCS("set_return_type"),_SCS("get_return_type")); + +} + +VisualScriptNodeInstance* VisualScriptReturn::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptReturn::VisualScriptReturn() { + + with_value=false; + type=Variant::NIL; +} + +template<bool with_value> +static Ref<VisualScriptNode> create_return_node(const String& p_name) { + + Ref<VisualScriptReturn> node; + node.instance(); + node->set_enable_return_value(with_value); + return node; +} + + + +////////////////////////////////////////// +////////////////CONDITION///////////////// +////////////////////////////////////////// + +int VisualScriptCondition::get_output_sequence_port_count() const { + + return 2; +} + +bool VisualScriptCondition::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptCondition::get_input_value_port_count() const{ + + return 1; +} +int VisualScriptCondition::get_output_value_port_count() const{ + + return 0; +} + +String VisualScriptCondition::get_output_sequence_port_text(int p_port) const { + + if (p_port==0) + return "true"; + else + return "false"; +} + +PropertyInfo VisualScriptCondition::get_input_value_port_info(int p_idx) const{ + + PropertyInfo pinfo; + pinfo.name="cond"; + pinfo.type=Variant::BOOL; + return pinfo; +} +PropertyInfo VisualScriptCondition::get_output_value_port_info(int p_idx) const{ + return PropertyInfo(); +} + +String VisualScriptCondition::get_caption() const { + + return "Condition"; +} + +String VisualScriptCondition::get_text() const { + + return "if (cond) is: "; +} + + +void VisualScriptCondition::_bind_methods() { + + + +} + +VisualScriptNodeInstance* VisualScriptCondition::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptCondition::VisualScriptCondition() { + +} + + + +////////////////////////////////////////// +////////////////WHILE///////////////// +////////////////////////////////////////// + +int VisualScriptWhile::get_output_sequence_port_count() const { + + return 2; +} + +bool VisualScriptWhile::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptWhile::get_input_value_port_count() const{ + + return 1; +} +int VisualScriptWhile::get_output_value_port_count() const{ + + return 0; +} + +String VisualScriptWhile::get_output_sequence_port_text(int p_port) const { + + if (p_port==0) + return "repeat"; + else + return "exit"; +} + +PropertyInfo VisualScriptWhile::get_input_value_port_info(int p_idx) const{ + + PropertyInfo pinfo; + pinfo.name="cond"; + pinfo.type=Variant::BOOL; + return pinfo; +} +PropertyInfo VisualScriptWhile::get_output_value_port_info(int p_idx) const{ + return PropertyInfo(); +} + +String VisualScriptWhile::get_caption() const { + + return "While"; +} + +String VisualScriptWhile::get_text() const { + + return "while (cond): "; +} + + +void VisualScriptWhile::_bind_methods() { + + + +} + +VisualScriptNodeInstance* VisualScriptWhile::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptWhile::VisualScriptWhile() { + +} + + + +////////////////////////////////////////// +////////////////ITERATOR///////////////// +////////////////////////////////////////// + +int VisualScriptIterator::get_output_sequence_port_count() const { + + return 2; +} + +bool VisualScriptIterator::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptIterator::get_input_value_port_count() const{ + + return 1; +} +int VisualScriptIterator::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptIterator::get_output_sequence_port_text(int p_port) const { + + if (p_port==0) + return "each"; + else + return "exit"; +} + +PropertyInfo VisualScriptIterator::get_input_value_port_info(int p_idx) const{ + + PropertyInfo pinfo; + pinfo.name="input"; + pinfo.type=Variant::NIL; + return pinfo; +} +PropertyInfo VisualScriptIterator::get_output_value_port_info(int p_idx) const{ + PropertyInfo pinfo; + pinfo.name="elem"; + pinfo.type=Variant::NIL; + return pinfo; +} +String VisualScriptIterator::get_caption() const { + + return "Iterator"; +} + +String VisualScriptIterator::get_text() const { + + return "for (elem) in (input): "; +} + + +void VisualScriptIterator::_bind_methods() { + + + +} + +VisualScriptNodeInstance* VisualScriptIterator::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptIterator::VisualScriptIterator() { + +} + + + +////////////////////////////////////////// +////////////////SEQUENCE///////////////// +////////////////////////////////////////// + +int VisualScriptSequence::get_output_sequence_port_count() const { + + return steps; +} + +bool VisualScriptSequence::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptSequence::get_input_value_port_count() const{ + + return 0; +} +int VisualScriptSequence::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptSequence::get_output_sequence_port_text(int p_port) const { + + return itos(p_port+1); +} + +PropertyInfo VisualScriptSequence::get_input_value_port_info(int p_idx) const{ + return PropertyInfo(); +} +PropertyInfo VisualScriptSequence::get_output_value_port_info(int p_idx) const{ + return PropertyInfo(Variant::INT,"current"); +} +String VisualScriptSequence::get_caption() const { + + return "Sequence"; +} + +String VisualScriptSequence::get_text() const { + + return "in order: "; +} + +void VisualScriptSequence::set_steps(int p_steps) { + + ERR_FAIL_COND(p_steps<1); + if (steps==p_steps) + return; + + steps=p_steps; + emit_signal("ports_changed"); + +} + +int VisualScriptSequence::get_steps() const { + + return steps; +} + +void VisualScriptSequence::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_steps","steps"),&VisualScriptSequence::set_steps); + ObjectTypeDB::bind_method(_MD("get_steps"),&VisualScriptSequence::get_steps); + + ADD_PROPERTY(PropertyInfo(Variant::INT,"steps",PROPERTY_HINT_RANGE,"1,64,1"),_SCS("set_steps"),_SCS("get_steps")); + +} + +VisualScriptNodeInstance* VisualScriptSequence::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptSequence::VisualScriptSequence() { + + steps=1; +} + +void register_visual_script_flow_control_nodes() { + + VisualScriptLanguage::singleton->add_register_func("flow_control/return",create_return_node<false>); + VisualScriptLanguage::singleton->add_register_func("flow_control/return_with_value",create_return_node<true>); + VisualScriptLanguage::singleton->add_register_func("flow_control/condition",create_node_generic<VisualScriptCondition>); + VisualScriptLanguage::singleton->add_register_func("flow_control/while",create_node_generic<VisualScriptWhile>); + VisualScriptLanguage::singleton->add_register_func("flow_control/iterator",create_node_generic<VisualScriptIterator>); + VisualScriptLanguage::singleton->add_register_func("flow_control/sequence",create_node_generic<VisualScriptSequence>); + +} diff --git a/modules/visual_script/visual_script_flow_control.h b/modules/visual_script/visual_script_flow_control.h new file mode 100644 index 0000000000..557654b080 --- /dev/null +++ b/modules/visual_script/visual_script_flow_control.h @@ -0,0 +1,196 @@ +#ifndef VISUAL_SCRIPT_FLOW_CONTROL_H +#define VISUAL_SCRIPT_FLOW_CONTROL_H + +#include "visual_script.h" + +class VisualScriptReturn : public VisualScriptNode { + + OBJ_TYPE(VisualScriptReturn,VisualScriptNode) + + + Variant::Type type; + bool with_value; +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; + + void set_return_type(Variant::Type); + Variant::Type get_return_type() const; + + void set_enable_return_value(bool p_enable); + bool is_return_value_enabled() const; + + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptReturn(); +}; + + +class VisualScriptCondition : public VisualScriptNode { + + OBJ_TYPE(VisualScriptCondition,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 VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptCondition(); +}; + + +class VisualScriptWhile : public VisualScriptNode { + + OBJ_TYPE(VisualScriptWhile,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 VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptWhile(); +}; + + + +class VisualScriptIterator : public VisualScriptNode { + + OBJ_TYPE(VisualScriptIterator,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 VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptIterator(); +}; + + + +class VisualScriptSequence : public VisualScriptNode { + + OBJ_TYPE(VisualScriptSequence,VisualScriptNode) + + + int steps; + +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; + + void set_steps(int p_steps); + int get_steps() const; + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptSequence(); +}; + +void register_visual_script_flow_control_nodes(); + + + +#endif // VISUAL_SCRIPT_FLOW_CONTROL_H diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp new file mode 100644 index 0000000000..6fb2b19585 --- /dev/null +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -0,0 +1,1584 @@ +#include "visual_script_func_nodes.h" +#include "scene/main/scene_main_loop.h" +#include "os/os.h" +#include "scene/main/node.h" +#include "visual_script_nodes.h" + +////////////////////////////////////////// +////////////////CALL////////////////////// +////////////////////////////////////////// + +int VisualScriptFunctionCall::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptFunctionCall::has_input_sequence_port() const{ + + return true; +} +#ifdef TOOLS_ENABLED + +static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) { + + if (p_edited_scene!=p_current_node && p_current_node->get_owner()!=p_edited_scene) + return NULL; + + Ref<Script> scr = p_current_node->get_script(); + + if (scr.is_valid() && scr==script) + return p_current_node; + + for(int i=0;i<p_current_node->get_child_count();i++) { + Node *n = _find_script_node(p_edited_scene,p_current_node->get_child(i),script); + if (n) + return n; + } + + return NULL; +} + +#endif +Node *VisualScriptFunctionCall::_get_base_node() const { + +#ifdef TOOLS_ENABLED + Ref<Script> script = get_visual_script(); + if (!script.is_valid()) + return NULL; + + MainLoop * main_loop = OS::get_singleton()->get_main_loop(); + if (!main_loop) + return NULL; + + SceneTree *scene_tree = main_loop->cast_to<SceneTree>(); + + if (!scene_tree) + return NULL; + + Node *edited_scene = scene_tree->get_edited_scene_root(); + + if (!edited_scene) + return NULL; + + Node* script_node = _find_script_node(edited_scene,edited_scene,script); + + if (!script_node) + return NULL; + + if (!script_node->has_node(base_path)) + return NULL; + + Node *path_to = script_node->get_node(base_path); + + return path_to; +#else + + return NULL; +#endif +} + +StringName VisualScriptFunctionCall::_get_base_type() const { + + if (call_mode==CALL_MODE_SELF && get_visual_script().is_valid()) + return get_visual_script()->get_instance_base_type(); + else if (call_mode==CALL_MODE_NODE_PATH && get_visual_script().is_valid()) { + Node *path = _get_base_node(); + if (path) + return path->get_type(); + + } + + return base_type; +} + +int VisualScriptFunctionCall::get_input_value_port_count() const{ + + MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); + if (!mb) + return 0; + + return mb->get_argument_count() + (call_mode==CALL_MODE_INSTANCE?1:0) - use_default_args; + +} +int VisualScriptFunctionCall::get_output_value_port_count() const{ + + MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); + if (!mb) + return 0; + + return mb->has_return() ? 1 : 0; +} + +String VisualScriptFunctionCall::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptFunctionCall::get_input_value_port_info(int p_idx) const{ + + if (call_mode==CALL_MODE_INSTANCE) { + if (p_idx==0) { + PropertyInfo pi; + pi.type=Variant::OBJECT; + pi.name="instance"; + return pi; + } else { + p_idx--; + } + } + +#ifdef DEBUG_METHODS_ENABLED + + + + MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); + if (!mb) + return PropertyInfo(); + + return mb->get_argument_info(p_idx); +#else + return PropertyInfo(); +#endif + +} + +PropertyInfo VisualScriptFunctionCall::get_output_value_port_info(int p_idx) const{ + + +#ifdef DEBUG_METHODS_ENABLED + + MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); + if (!mb) + return PropertyInfo(); + + PropertyInfo pi = mb->get_argument_info(-1); + pi.name=""; + return pi; +#else + return PropertyInfo(); +#endif +} + + +String VisualScriptFunctionCall::get_caption() const { + + return "Call"; +} + +String VisualScriptFunctionCall::get_text() const { + + if (call_mode==CALL_MODE_SELF) + return " "+String(function)+"()"; + else + return " "+base_type+"."+String(function)+"()"; + +} + +void VisualScriptFunctionCall::_update_defargs() { + + if (!get_visual_script().is_valid()) + return; //do not change if not valid yet + + MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); + if (!mb) + return; + + use_default_args=mb->get_default_argument_count(); + +} + +void VisualScriptFunctionCall::set_base_type(const StringName& p_type) { + + if (base_type==p_type) + return; + + base_type=p_type; + _update_defargs(); + _change_notify(); + emit_signal("ports_changed"); +} + +StringName VisualScriptFunctionCall::get_base_type() const{ + + return base_type; +} + +void VisualScriptFunctionCall::set_function(const StringName& p_type){ + + if (function==p_type) + return; + + function=p_type; + _update_defargs(); + _change_notify(); + emit_signal("ports_changed"); +} +StringName VisualScriptFunctionCall::get_function() const { + + + return function; +} + +void VisualScriptFunctionCall::set_base_path(const NodePath& p_type) { + + if (base_path==p_type) + return; + + base_path=p_type; + _update_defargs(); + _change_notify(); + emit_signal("ports_changed"); +} + +NodePath VisualScriptFunctionCall::get_base_path() const { + + return base_path; +} + + +void VisualScriptFunctionCall::set_call_mode(CallMode p_mode) { + + if (call_mode==p_mode) + return; + + call_mode=p_mode; + _update_defargs(); + _change_notify(); + emit_signal("ports_changed"); + +} +VisualScriptFunctionCall::CallMode VisualScriptFunctionCall::get_call_mode() const { + + return call_mode; +} + +void VisualScriptFunctionCall::set_use_default_args(int p_amount) { + + if (use_default_args==p_amount) + return; + + use_default_args=p_amount; + emit_signal("ports_changed"); + + +} + +int VisualScriptFunctionCall::get_use_default_args() const{ + + return use_default_args; +} +void VisualScriptFunctionCall::_validate_property(PropertyInfo& property) const { + + if (property.name=="function/base_type") { + if (call_mode!=CALL_MODE_INSTANCE) { + property.usage=0; + } + } + + + if (property.name=="function/node_path") { + if (call_mode!=CALL_MODE_NODE_PATH) { + property.usage=0; + } else { + + Node *bnode = _get_base_node(); + if (bnode) { + property.hint_string=bnode->get_path(); //convert to loong string + } else { + + } + } + } + + if (property.name=="function/function") { + property.hint=PROPERTY_HINT_ENUM; + + + List<MethodInfo> methods; + + StringName base = _get_base_type(); + ObjectTypeDB::get_method_list(base,&methods); + + + List<String> mstring; + for (List<MethodInfo>::Element *E=methods.front();E;E=E->next()) { + if (E->get().name.begins_with("_")) + continue; + mstring.push_back(E->get().name.get_slice(":",0)); + } + + mstring.sort(); + + String ml; + for (List<String>::Element *E=mstring.front();E;E=E->next()) { + + if (ml!=String()) + ml+=","; + ml+=E->get(); + } + + property.hint_string=ml; + } + + if (property.name=="function/use_default_args") { + property.hint=PROPERTY_HINT_RANGE; + + int mc=0; + + MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); + if (mb) { + + mc=mb->get_default_argument_count(); + } + + property.hint_string="0,"+itos(mc)+",1"; + } +} + + +void VisualScriptFunctionCall::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_base_type","base_type"),&VisualScriptFunctionCall::set_base_type); + ObjectTypeDB::bind_method(_MD("get_base_type"),&VisualScriptFunctionCall::get_base_type); + + ObjectTypeDB::bind_method(_MD("set_function","function"),&VisualScriptFunctionCall::set_function); + ObjectTypeDB::bind_method(_MD("get_function"),&VisualScriptFunctionCall::get_function); + + ObjectTypeDB::bind_method(_MD("set_call_mode","mode"),&VisualScriptFunctionCall::set_call_mode); + ObjectTypeDB::bind_method(_MD("get_call_mode"),&VisualScriptFunctionCall::get_call_mode); + + ObjectTypeDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptFunctionCall::set_base_path); + ObjectTypeDB::bind_method(_MD("get_base_path"),&VisualScriptFunctionCall::get_base_path); + + ObjectTypeDB::bind_method(_MD("set_use_default_args","amount"),&VisualScriptFunctionCall::set_use_default_args); + ObjectTypeDB::bind_method(_MD("get_use_default_args"),&VisualScriptFunctionCall::get_use_default_args); + + + ADD_PROPERTY(PropertyInfo(Variant::INT,"function/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance"),_SCS("set_call_mode"),_SCS("get_call_mode")); + ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type")); + 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::INT,"function/use_default_args"),_SCS("set_use_default_args"),_SCS("get_use_default_args")); + + BIND_CONSTANT( CALL_MODE_SELF ); + BIND_CONSTANT( CALL_MODE_NODE_PATH); + BIND_CONSTANT( CALL_MODE_INSTANCE); +} + +VisualScriptNodeInstance* VisualScriptFunctionCall::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptFunctionCall::VisualScriptFunctionCall() { + + call_mode=CALL_MODE_INSTANCE; + use_default_args=0; + base_type="Object"; + +} + +template<VisualScriptFunctionCall::CallMode cmode> +static Ref<VisualScriptNode> create_function_call_node(const String& p_name) { + + Ref<VisualScriptFunctionCall> node; + node.instance(); + node->set_call_mode(cmode); + return node; +} + + +////////////////////////////////////////// +////////////////SET////////////////////// +////////////////////////////////////////// + +int VisualScriptPropertySet::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptPropertySet::has_input_sequence_port() const{ + + return true; +} + +Node *VisualScriptPropertySet::_get_base_node() const { + +#ifdef TOOLS_ENABLED + Ref<Script> script = get_visual_script(); + if (!script.is_valid()) + return NULL; + + MainLoop * main_loop = OS::get_singleton()->get_main_loop(); + if (!main_loop) + return NULL; + + SceneTree *scene_tree = main_loop->cast_to<SceneTree>(); + + if (!scene_tree) + return NULL; + + Node *edited_scene = scene_tree->get_edited_scene_root(); + + if (!edited_scene) + return NULL; + + Node* script_node = _find_script_node(edited_scene,edited_scene,script); + + if (!script_node) + return NULL; + + if (!script_node->has_node(base_path)) + return NULL; + + Node *path_to = script_node->get_node(base_path); + + return path_to; +#else + + return NULL; +#endif +} + +StringName VisualScriptPropertySet::_get_base_type() const { + + if (call_mode==CALL_MODE_SELF && get_visual_script().is_valid()) + return get_visual_script()->get_instance_base_type(); + else if (call_mode==CALL_MODE_NODE_PATH && get_visual_script().is_valid()) { + Node *path = _get_base_node(); + if (path) + return path->get_type(); + + } + + return base_type; +} + +int VisualScriptPropertySet::get_input_value_port_count() const{ + + if (use_builtin_value) + return 0; + else + return 1; + + +} +int VisualScriptPropertySet::get_output_value_port_count() const{ + + return 0; +} + +String VisualScriptPropertySet::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const{ + + if (call_mode==CALL_MODE_INSTANCE) { + if (p_idx==0) { + PropertyInfo pi; + pi.type=Variant::OBJECT; + pi.name="instance"; + return pi; + } else { + p_idx--; + } + } + +#ifdef DEBUG_METHODS_ENABLED + + //not very efficient but.. + + + List<PropertyInfo> pinfo; + + if (call_mode==CALL_MODE_NODE_PATH) { + + Node *n = _get_base_node(); + if (n) { + n->get_property_list(&pinfo); + } else { + ObjectTypeDB::get_property_list(_get_base_type(),&pinfo); + } + } else { + ObjectTypeDB::get_property_list(_get_base_type(),&pinfo); + } + + for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) { + + if (E->get().name==property) { + + PropertyInfo info=E->get(); + info.name="value"; + return info; + } + } + + +#endif + + return PropertyInfo(Variant::NIL,"value"); + +} + +PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(); + +} + + +String VisualScriptPropertySet::get_caption() const { + + return "Set"; +} + +String VisualScriptPropertySet::get_text() const { + + return property; + +} + +void VisualScriptPropertySet::set_base_type(const StringName& p_type) { + + if (base_type==p_type) + return; + + base_type=p_type; + _change_notify(); + emit_signal("ports_changed"); +} + +StringName VisualScriptPropertySet::get_base_type() const{ + + return base_type; +} + +void VisualScriptPropertySet::set_property(const StringName& p_type){ + + if (property==p_type) + return; + + property=p_type; + _change_notify(); + emit_signal("ports_changed"); +} +StringName VisualScriptPropertySet::get_property() const { + + + return property; +} + +void VisualScriptPropertySet::set_base_path(const NodePath& p_type) { + + if (base_path==p_type) + return; + + base_path=p_type; + _change_notify(); + emit_signal("ports_changed"); +} + +NodePath VisualScriptPropertySet::get_base_path() const { + + return base_path; +} + + +void VisualScriptPropertySet::set_call_mode(CallMode p_mode) { + + if (call_mode==p_mode) + return; + + call_mode=p_mode; + _change_notify(); + emit_signal("ports_changed"); + +} +VisualScriptPropertySet::CallMode VisualScriptPropertySet::get_call_mode() const { + + return call_mode; +} + + +void VisualScriptPropertySet::set_use_builtin_value(bool p_use) { + + if (use_builtin_value==p_use) + return; + + use_builtin_value=p_use; + _change_notify(); + emit_signal("ports_changed"); + +} + +bool VisualScriptPropertySet::is_using_builtin_value() const{ + + return use_builtin_value; +} + +void VisualScriptPropertySet::set_builtin_value(const Variant& p_value){ + + if (builtin_value==p_value) + return; + + builtin_value=p_value; + +} +Variant VisualScriptPropertySet::get_builtin_value() const{ + + return builtin_value; +} +void VisualScriptPropertySet::_validate_property(PropertyInfo& property) const { + + if (property.name=="property/base_type") { + if (call_mode!=CALL_MODE_INSTANCE) { + property.usage=0; + } + } + + + if (property.name=="property/node_path") { + if (call_mode!=CALL_MODE_NODE_PATH) { + property.usage=0; + } else { + + Node *bnode = _get_base_node(); + if (bnode) { + property.hint_string=bnode->get_path(); //convert to loong string + } else { + + } + } + } + + if (property.name=="property/property") { + property.hint=PROPERTY_HINT_ENUM; + + + List<PropertyInfo> pinfo; + + if (call_mode==CALL_MODE_NODE_PATH) { + + Node *n = _get_base_node(); + if (n) { + n->get_property_list(&pinfo); + } else { + ObjectTypeDB::get_property_list(_get_base_type(),&pinfo); + } + } else { + ObjectTypeDB::get_property_list(_get_base_type(),&pinfo); + } + + List<String> mstring; + + for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) { + + if (E->get().usage&PROPERTY_USAGE_EDITOR) + mstring.push_back(E->get().name); + } + + String ml; + for (List<String>::Element *E=mstring.front();E;E=E->next()) { + + if (ml!=String()) + ml+=","; + ml+=E->get(); + } + + property.hint_string=ml; + } + + if (property.name=="value/builtin") { + + if (!use_builtin_value) { + property.usage=0; + } else { + List<PropertyInfo> pinfo; + + + if (call_mode==CALL_MODE_NODE_PATH) { + + Node *n = _get_base_node(); + if (n) { + n->get_property_list(&pinfo); + } else { + ObjectTypeDB::get_property_list(_get_base_type(),&pinfo); + } + } else { + ObjectTypeDB::get_property_list(_get_base_type(),&pinfo); + } + + for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) { + + if (E->get().name==this->property) { + + property.hint=E->get().hint; + property.type=E->get().type; + property.hint_string=E->get().hint_string; + } + } + } + + } +} + +void VisualScriptPropertySet::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_base_type","base_type"),&VisualScriptPropertySet::set_base_type); + ObjectTypeDB::bind_method(_MD("get_base_type"),&VisualScriptPropertySet::get_base_type); + + ObjectTypeDB::bind_method(_MD("set_property","property"),&VisualScriptPropertySet::set_property); + ObjectTypeDB::bind_method(_MD("get_property"),&VisualScriptPropertySet::get_property); + + ObjectTypeDB::bind_method(_MD("set_call_mode","mode"),&VisualScriptPropertySet::set_call_mode); + ObjectTypeDB::bind_method(_MD("get_call_mode"),&VisualScriptPropertySet::get_call_mode); + + ObjectTypeDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptPropertySet::set_base_path); + ObjectTypeDB::bind_method(_MD("get_base_path"),&VisualScriptPropertySet::get_base_path); + + ObjectTypeDB::bind_method(_MD("set_builtin_value","value"),&VisualScriptPropertySet::set_builtin_value); + ObjectTypeDB::bind_method(_MD("get_builtin_value"),&VisualScriptPropertySet::get_builtin_value); + + ObjectTypeDB::bind_method(_MD("set_use_builtin_value","enable"),&VisualScriptPropertySet::set_use_builtin_value); + ObjectTypeDB::bind_method(_MD("is_using_builtin_value"),&VisualScriptPropertySet::is_using_builtin_value); + + ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance"),_SCS("set_call_mode"),_SCS("get_call_mode")); + ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type")); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path")); + ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/property"),_SCS("set_property"),_SCS("get_property")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"value/use_builtin"),_SCS("set_use_builtin_value"),_SCS("is_using_builtin_value")); + ADD_PROPERTY(PropertyInfo(Variant::NIL,"value/builtin"),_SCS("set_builtin_value"),_SCS("get_builtin_value")); + + BIND_CONSTANT( CALL_MODE_SELF ); + BIND_CONSTANT( CALL_MODE_NODE_PATH); + BIND_CONSTANT( CALL_MODE_INSTANCE); +} + +VisualScriptNodeInstance* VisualScriptPropertySet::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptPropertySet::VisualScriptPropertySet() { + + call_mode=CALL_MODE_INSTANCE; + base_type="Object"; + +} + +template<VisualScriptPropertySet::CallMode cmode> +static Ref<VisualScriptNode> create_property_set_node(const String& p_name) { + + Ref<VisualScriptPropertySet> node; + node.instance(); + node->set_call_mode(cmode); + return node; +} + + +////////////////////////////////////////// +////////////////SET////////////////////// +////////////////////////////////////////// + +int VisualScriptPropertyGet::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptPropertyGet::has_input_sequence_port() const{ + + return true; +} + +Node *VisualScriptPropertyGet::_get_base_node() const { + +#ifdef TOOLS_ENABLED + Ref<Script> script = get_visual_script(); + if (!script.is_valid()) + return NULL; + + MainLoop * main_loop = OS::get_singleton()->get_main_loop(); + if (!main_loop) + return NULL; + + SceneTree *scene_tree = main_loop->cast_to<SceneTree>(); + + if (!scene_tree) + return NULL; + + Node *edited_scene = scene_tree->get_edited_scene_root(); + + if (!edited_scene) + return NULL; + + Node* script_node = _find_script_node(edited_scene,edited_scene,script); + + if (!script_node) + return NULL; + + if (!script_node->has_node(base_path)) + return NULL; + + Node *path_to = script_node->get_node(base_path); + + return path_to; +#else + + return NULL; +#endif +} + +StringName VisualScriptPropertyGet::_get_base_type() const { + + if (call_mode==CALL_MODE_SELF && get_visual_script().is_valid()) + return get_visual_script()->get_instance_base_type(); + else if (call_mode==CALL_MODE_NODE_PATH && get_visual_script().is_valid()) { + Node *path = _get_base_node(); + if (path) + return path->get_type(); + + } + + return base_type; +} + +int VisualScriptPropertyGet::get_input_value_port_count() const{ + + return 0; + +} +int VisualScriptPropertyGet::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptPropertyGet::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptPropertyGet::get_input_value_port_info(int p_idx) const{ + + if (call_mode==CALL_MODE_INSTANCE) { + if (p_idx==0) { + PropertyInfo pi; + pi.type=Variant::OBJECT; + pi.name="instance"; + return pi; + } else { + p_idx--; + } + } + return PropertyInfo(); + +} + +PropertyInfo VisualScriptPropertyGet::get_output_value_port_info(int p_idx) const{ + + + +#ifdef DEBUG_METHODS_ENABLED + + //not very efficient but.. + + + List<PropertyInfo> pinfo; + + if (call_mode==CALL_MODE_NODE_PATH) { + + Node *n = _get_base_node(); + if (n) { + n->get_property_list(&pinfo); + } else { + ObjectTypeDB::get_property_list(_get_base_type(),&pinfo); + } + } else { + ObjectTypeDB::get_property_list(_get_base_type(),&pinfo); + } + + for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) { + + if (E->get().name==property) { + + PropertyInfo info=E->get(); + info.name=""; + return info; + } + } + + +#endif + + return PropertyInfo(Variant::NIL,""); +} + + +String VisualScriptPropertyGet::get_caption() const { + + return "Get"; +} + +String VisualScriptPropertyGet::get_text() const { + + return property; + +} + +void VisualScriptPropertyGet::set_base_type(const StringName& p_type) { + + if (base_type==p_type) + return; + + base_type=p_type; + _change_notify(); + emit_signal("ports_changed"); +} + +StringName VisualScriptPropertyGet::get_base_type() const{ + + return base_type; +} + +void VisualScriptPropertyGet::set_property(const StringName& p_type){ + + if (property==p_type) + return; + + property=p_type; + _change_notify(); + emit_signal("ports_changed"); +} +StringName VisualScriptPropertyGet::get_property() const { + + + return property; +} + +void VisualScriptPropertyGet::set_base_path(const NodePath& p_type) { + + if (base_path==p_type) + return; + + base_path=p_type; + _change_notify(); + emit_signal("ports_changed"); +} + +NodePath VisualScriptPropertyGet::get_base_path() const { + + return base_path; +} + + +void VisualScriptPropertyGet::set_call_mode(CallMode p_mode) { + + if (call_mode==p_mode) + return; + + call_mode=p_mode; + _change_notify(); + emit_signal("ports_changed"); + +} +VisualScriptPropertyGet::CallMode VisualScriptPropertyGet::get_call_mode() const { + + return call_mode; +} + +void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const { + + if (property.name=="property/base_type") { + if (call_mode!=CALL_MODE_INSTANCE) { + property.usage=0; + } + } + + + if (property.name=="property/node_path") { + if (call_mode!=CALL_MODE_NODE_PATH) { + property.usage=0; + } else { + + Node *bnode = _get_base_node(); + if (bnode) { + property.hint_string=bnode->get_path(); //convert to loong string + } else { + + } + } + } + + if (property.name=="property/property") { + property.hint=PROPERTY_HINT_ENUM; + + + List<PropertyInfo> pinfo; + + if (call_mode==CALL_MODE_NODE_PATH) { + + Node *n = _get_base_node(); + if (n) { + n->get_property_list(&pinfo); + } else { + ObjectTypeDB::get_property_list(_get_base_type(),&pinfo); + } + } else { + ObjectTypeDB::get_property_list(_get_base_type(),&pinfo); + } + + List<String> mstring; + + for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) { + + if (E->get().usage&PROPERTY_USAGE_EDITOR) + mstring.push_back(E->get().name); + } + + String ml; + for (List<String>::Element *E=mstring.front();E;E=E->next()) { + + if (ml!=String()) + ml+=","; + ml+=E->get(); + } + + property.hint_string=ml; + } + +} + +void VisualScriptPropertyGet::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_base_type","base_type"),&VisualScriptPropertyGet::set_base_type); + ObjectTypeDB::bind_method(_MD("get_base_type"),&VisualScriptPropertyGet::get_base_type); + + ObjectTypeDB::bind_method(_MD("set_property","property"),&VisualScriptPropertyGet::set_property); + ObjectTypeDB::bind_method(_MD("get_property"),&VisualScriptPropertyGet::get_property); + + ObjectTypeDB::bind_method(_MD("set_call_mode","mode"),&VisualScriptPropertyGet::set_call_mode); + ObjectTypeDB::bind_method(_MD("get_call_mode"),&VisualScriptPropertyGet::get_call_mode); + + ObjectTypeDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptPropertyGet::set_base_path); + ObjectTypeDB::bind_method(_MD("get_base_path"),&VisualScriptPropertyGet::get_base_path); + + + + ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance"),_SCS("set_call_mode"),_SCS("get_call_mode")); + ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type")); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path")); + ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/property"),_SCS("set_property"),_SCS("get_property")); + + BIND_CONSTANT( CALL_MODE_SELF ); + BIND_CONSTANT( CALL_MODE_NODE_PATH); + BIND_CONSTANT( CALL_MODE_INSTANCE); +} + +VisualScriptNodeInstance* VisualScriptPropertyGet::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptPropertyGet::VisualScriptPropertyGet() { + + call_mode=CALL_MODE_INSTANCE; + base_type="Object"; + +} + +template<VisualScriptPropertyGet::CallMode cmode> +static Ref<VisualScriptNode> create_property_get_node(const String& p_name) { + + Ref<VisualScriptPropertyGet> node; + node.instance(); + node->set_call_mode(cmode); + return node; +} + + +////////////////////////////////////////// +////////////////SCRIPT CALL////////////////////// +////////////////////////////////////////// + +int VisualScriptScriptCall::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptScriptCall::has_input_sequence_port() const{ + + return true; +} + +Node *VisualScriptScriptCall::_get_base_node() const { + +#ifdef TOOLS_ENABLED + Ref<Script> script = get_visual_script(); + if (!script.is_valid()) + return NULL; + + MainLoop * main_loop = OS::get_singleton()->get_main_loop(); + if (!main_loop) + return NULL; + + SceneTree *scene_tree = main_loop->cast_to<SceneTree>(); + + if (!scene_tree) + return NULL; + + Node *edited_scene = scene_tree->get_edited_scene_root(); + + if (!edited_scene) + return NULL; + + Node* script_node = _find_script_node(edited_scene,edited_scene,script); + + if (!script_node) + return NULL; + + if (!script_node->has_node(base_path)) + return NULL; + + Node *path_to = script_node->get_node(base_path); + + return path_to; +#else + + return NULL; +#endif +} + + +int VisualScriptScriptCall::get_input_value_port_count() const{ + + + if (call_mode==CALL_MODE_SELF) { + + Ref<VisualScript> vs = get_visual_script(); + if (vs.is_valid()) { + + if (!vs->has_function(function)) + return 0; + + int id = vs->get_function_node_id(function); + if (id<0) + return 0; + + Ref<VisualScriptFunction> func = vs->get_node(function,id); + + return func->get_argument_count(); + } + } else { + + Node*base = _get_base_node(); + if (!base) + return 0; + Ref<Script> script = base->get_script(); + if (!script.is_valid()) + return 0; + + List<MethodInfo> functions; + script->get_method_list(&functions); + for (List<MethodInfo>::Element *E=functions.front();E;E=E->next()) { + if (E->get().name==function) { + return E->get().arguments.size(); + } + } + + } + + + return 0; + +} +int VisualScriptScriptCall::get_output_value_port_count() const{ + return 1; +} + +String VisualScriptScriptCall::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptScriptCall::get_input_value_port_info(int p_idx) const{ + + if (call_mode==CALL_MODE_SELF) { + + Ref<VisualScript> vs = get_visual_script(); + if (vs.is_valid()) { + + if (!vs->has_function(function)) + return PropertyInfo(); + + int id = vs->get_function_node_id(function); + if (id<0) + return PropertyInfo(); + + Ref<VisualScriptFunction> func = vs->get_node(function,id); + + if (p_idx>=func->get_argument_count()) + return PropertyInfo(); + return PropertyInfo(func->get_argument_type(p_idx),func->get_argument_name(p_idx)); + } + } else { + + Node*base = _get_base_node(); + if (!base) + return PropertyInfo(); + Ref<Script> script = base->get_script(); + if (!script.is_valid()) + return PropertyInfo(); + + List<MethodInfo> functions; + script->get_method_list(&functions); + for (List<MethodInfo>::Element *E=functions.front();E;E=E->next()) { + if (E->get().name==function) { + if (p_idx<0 || p_idx>=E->get().arguments.size()) + return PropertyInfo(); + return E->get().arguments[p_idx]; + } + } + + } + + return PropertyInfo(); + +} + +PropertyInfo VisualScriptScriptCall::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + + +String VisualScriptScriptCall::get_caption() const { + + return "ScriptCall"; +} + +String VisualScriptScriptCall::get_text() const { + + return " "+String(function)+"()"; +} + + + +void VisualScriptScriptCall::set_function(const StringName& p_type){ + + if (function==p_type) + return; + + function=p_type; + + _change_notify(); + emit_signal("ports_changed"); +} +StringName VisualScriptScriptCall::get_function() const { + + + return function; +} + +void VisualScriptScriptCall::set_base_path(const NodePath& p_type) { + + if (base_path==p_type) + return; + + base_path=p_type; + + _change_notify(); + emit_signal("ports_changed"); +} + +NodePath VisualScriptScriptCall::get_base_path() const { + + return base_path; +} + + +void VisualScriptScriptCall::set_call_mode(CallMode p_mode) { + + if (call_mode==p_mode) + return; + + call_mode=p_mode; + + _change_notify(); + emit_signal("ports_changed"); + +} +VisualScriptScriptCall::CallMode VisualScriptScriptCall::get_call_mode() const { + + return call_mode; +} + +void VisualScriptScriptCall::_validate_property(PropertyInfo& property) const { + + + + if (property.name=="function/node_path") { + if (call_mode!=CALL_MODE_NODE_PATH) { + property.usage=0; + } else { + + Node *bnode = _get_base_node(); + if (bnode) { + property.hint_string=bnode->get_path(); //convert to loong string + } else { + + } + } + } + + if (property.name=="function/function") { + property.hint=PROPERTY_HINT_ENUM; + + + List<MethodInfo> methods; + + if (call_mode==CALL_MODE_SELF) { + + Ref<VisualScript> vs = get_visual_script(); + if (vs.is_valid()) { + + vs->get_method_list(&methods); + + } + } else { + + Node*base = _get_base_node(); + if (!base) + return; + Ref<Script> script = base->get_script(); + if (!script.is_valid()) + return; + + script->get_method_list(&methods); + + } + + List<String> mstring; + for (List<MethodInfo>::Element *E=methods.front();E;E=E->next()) { + if (E->get().name.begins_with("_")) + continue; + mstring.push_back(E->get().name.get_slice(":",0)); + } + + mstring.sort(); + + String ml; + for (List<String>::Element *E=mstring.front();E;E=E->next()) { + + if (ml!=String()) + ml+=","; + ml+=E->get(); + } + + property.hint_string=ml; + } + +} + + +void VisualScriptScriptCall::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_function","function"),&VisualScriptScriptCall::set_function); + ObjectTypeDB::bind_method(_MD("get_function"),&VisualScriptScriptCall::get_function); + + ObjectTypeDB::bind_method(_MD("set_call_mode","mode"),&VisualScriptScriptCall::set_call_mode); + ObjectTypeDB::bind_method(_MD("get_call_mode"),&VisualScriptScriptCall::get_call_mode); + + ObjectTypeDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptScriptCall::set_base_path); + ObjectTypeDB::bind_method(_MD("get_base_path"),&VisualScriptScriptCall::get_base_path); + + + 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")); + + BIND_CONSTANT( CALL_MODE_SELF ); + BIND_CONSTANT( CALL_MODE_NODE_PATH); + +} + +VisualScriptNodeInstance* VisualScriptScriptCall::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptScriptCall::VisualScriptScriptCall() { + + call_mode=CALL_MODE_SELF; + + +} + +template<VisualScriptScriptCall::CallMode cmode> +static Ref<VisualScriptNode> create_script_call_node(const String& p_name) { + + Ref<VisualScriptScriptCall> node; + node.instance(); + node->set_call_mode(cmode); + return node; +} + + +////////////////////////////////////////// +////////////////SCRIPT CALL////////////////////// +////////////////////////////////////////// + +int VisualScriptEmitSignal::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptEmitSignal::has_input_sequence_port() const{ + + return true; +} + + +int VisualScriptEmitSignal::get_input_value_port_count() const{ + + Ref<VisualScript> vs = get_visual_script(); + if (vs.is_valid()) { + + if (!vs->has_custom_signal(name)) + return 0; + + return vs->custom_signal_get_argument_count(name); + } + + return 0; + +} +int VisualScriptEmitSignal::get_output_value_port_count() const{ + return 0; +} + +String VisualScriptEmitSignal::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptEmitSignal::get_input_value_port_info(int p_idx) const{ + + Ref<VisualScript> vs = get_visual_script(); + if (vs.is_valid()) { + + if (!vs->has_custom_signal(name)) + return PropertyInfo(); + + return PropertyInfo(vs->custom_signal_get_argument_type(name,p_idx),vs->custom_signal_get_argument_name(name,p_idx)); + } + + return PropertyInfo(); + +} + +PropertyInfo VisualScriptEmitSignal::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + + +String VisualScriptEmitSignal::get_caption() const { + + return "EmitSignal"; +} + +String VisualScriptEmitSignal::get_text() const { + + return "emit "+String(name); +} + + + +void VisualScriptEmitSignal::set_signal(const StringName& p_type){ + + if (name==p_type) + return; + + name=p_type; + + _change_notify(); + emit_signal("ports_changed"); +} +StringName VisualScriptEmitSignal::get_signal() const { + + + return name; +} + + +void VisualScriptEmitSignal::_validate_property(PropertyInfo& property) const { + + + + if (property.name=="signal/signal") { + property.hint=PROPERTY_HINT_ENUM; + + + List<StringName> sigs; + + Ref<VisualScript> vs = get_visual_script(); + if (vs.is_valid()) { + + vs->get_custom_signal_list(&sigs); + + } + + String ml; + for (List<StringName>::Element *E=sigs.front();E;E=E->next()) { + + if (ml!=String()) + ml+=","; + ml+=E->get(); + } + + property.hint_string=ml; + } + +} + + +void VisualScriptEmitSignal::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_signal","name"),&VisualScriptEmitSignal::set_signal); + ObjectTypeDB::bind_method(_MD("get_signal"),&VisualScriptEmitSignal::get_signal); + + + ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/signal"),_SCS("set_signal"),_SCS("get_signal")); + + +} + +VisualScriptNodeInstance* VisualScriptEmitSignal::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptEmitSignal::VisualScriptEmitSignal() { +} + +void register_visual_script_func_nodes() { + + VisualScriptLanguage::singleton->add_register_func("functions/call_method/call",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_INSTANCE>); + VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_in_self",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_SELF>); + VisualScriptLanguage::singleton->add_register_func("functions/call_method/call_in_node",create_function_call_node<VisualScriptFunctionCall::CALL_MODE_NODE_PATH>); + + VisualScriptLanguage::singleton->add_register_func("functions/set_property/set",create_property_set_node<VisualScriptPropertySet::CALL_MODE_INSTANCE>); + VisualScriptLanguage::singleton->add_register_func("functions/set_property/set_in_self",create_property_set_node<VisualScriptPropertySet::CALL_MODE_SELF>); + VisualScriptLanguage::singleton->add_register_func("functions/set_property/set_in_node",create_property_set_node<VisualScriptPropertySet::CALL_MODE_NODE_PATH>); + + VisualScriptLanguage::singleton->add_register_func("functions/get_property/get",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_INSTANCE>); + VisualScriptLanguage::singleton->add_register_func("functions/get_property/get_from_self",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_SELF>); + VisualScriptLanguage::singleton->add_register_func("functions/get_property/get_from_node",create_property_get_node<VisualScriptPropertyGet::CALL_MODE_NODE_PATH>); + + VisualScriptLanguage::singleton->add_register_func("functions/script/script_call",create_script_call_node<VisualScriptScriptCall::CALL_MODE_SELF>); + VisualScriptLanguage::singleton->add_register_func("functions/script/script_call_in_node",create_script_call_node<VisualScriptScriptCall::CALL_MODE_NODE_PATH>); + VisualScriptLanguage::singleton->add_register_func("functions/script/emit_signal",create_node_generic<VisualScriptEmitSignal>); + + +} diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h new file mode 100644 index 0000000000..d1201541b3 --- /dev/null +++ b/modules/visual_script/visual_script_func_nodes.h @@ -0,0 +1,325 @@ +#ifndef VISUAL_SCRIPT_FUNC_NODES_H +#define VISUAL_SCRIPT_FUNC_NODES_H + +#include "visual_script.h" + + +class VisualScriptFunctionCall : public VisualScriptNode { + + OBJ_TYPE(VisualScriptFunctionCall,VisualScriptNode) +public: + enum CallMode { + CALL_MODE_SELF, + CALL_MODE_NODE_PATH, + CALL_MODE_INSTANCE, + }; +private: + + CallMode call_mode; + StringName base_type; + NodePath base_path; + StringName function; + int use_default_args; + + Node *_get_base_node() const; + StringName _get_base_type() const; + + void _update_defargs(); +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; + + void set_base_type(const StringName& p_type); + StringName get_base_type() const; + + void set_function(const StringName& p_type); + StringName get_function() const; + + void set_base_path(const NodePath& p_type); + NodePath get_base_path() const; + + void set_call_mode(CallMode p_mode); + CallMode get_call_mode() const; + + void set_use_default_args(int p_amount); + int get_use_default_args() const; + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptFunctionCall(); +}; + +VARIANT_ENUM_CAST(VisualScriptFunctionCall::CallMode ); + + +class VisualScriptPropertySet : public VisualScriptNode { + + OBJ_TYPE(VisualScriptPropertySet,VisualScriptNode) +public: + enum CallMode { + CALL_MODE_SELF, + CALL_MODE_NODE_PATH, + CALL_MODE_INSTANCE, + }; +private: + + CallMode call_mode; + StringName base_type; + NodePath base_path; + StringName property; + bool use_builtin_value; + Variant builtin_value; + + Node *_get_base_node() const; + StringName _get_base_type() const; + + +protected: + virtual void _validate_property(PropertyInfo& property) const; + + static void _bind_methods(); + +public: + + virtual int get_output_sequence_port_count() const; + virtual bool has_input_sequence_port() const; + + + virtual String get_output_sequence_port_text(int p_port) const; + + + virtual int get_input_value_port_count() const; + virtual int get_output_value_port_count() const; + + + virtual PropertyInfo get_input_value_port_info(int p_idx) const; + virtual PropertyInfo get_output_value_port_info(int p_idx) const; + + virtual String get_caption() const; + virtual String get_text() const; + + void set_base_type(const StringName& p_type); + StringName get_base_type() const; + + void set_property(const StringName& p_type); + StringName get_property() const; + + void set_base_path(const NodePath& p_type); + NodePath get_base_path() const; + + void set_call_mode(CallMode p_mode); + CallMode get_call_mode() const; + + void set_use_builtin_value(bool p_use); + bool is_using_builtin_value() const; + + void set_builtin_value(const Variant &p_value); + Variant get_builtin_value() const; + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptPropertySet(); +}; + +VARIANT_ENUM_CAST(VisualScriptPropertySet::CallMode ); + + +class VisualScriptPropertyGet : public VisualScriptNode { + + OBJ_TYPE(VisualScriptPropertyGet,VisualScriptNode) +public: + enum CallMode { + CALL_MODE_SELF, + CALL_MODE_NODE_PATH, + CALL_MODE_INSTANCE, + }; +private: + + CallMode call_mode; + StringName base_type; + NodePath base_path; + StringName property; + + + Node *_get_base_node() const; + StringName _get_base_type() const; + + +protected: + virtual void _validate_property(PropertyInfo& property) const; + + static void _bind_methods(); + +public: + + virtual int get_output_sequence_port_count() const; + virtual bool has_input_sequence_port() const; + + + virtual String get_output_sequence_port_text(int p_port) const; + + + virtual int get_input_value_port_count() const; + virtual int get_output_value_port_count() const; + + + virtual PropertyInfo get_input_value_port_info(int p_idx) const; + virtual PropertyInfo get_output_value_port_info(int p_idx) const; + + virtual String get_caption() const; + virtual String get_text() const; + + void set_base_type(const StringName& p_type); + StringName get_base_type() const; + + void set_property(const StringName& p_type); + StringName get_property() const; + + void set_base_path(const NodePath& p_type); + NodePath get_base_path() const; + + void set_call_mode(CallMode p_mode); + CallMode get_call_mode() const; + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptPropertyGet(); +}; + + + + + +VARIANT_ENUM_CAST(VisualScriptPropertyGet::CallMode ); + + + +class VisualScriptScriptCall : public VisualScriptNode { + + OBJ_TYPE(VisualScriptScriptCall,VisualScriptNode) +public: + enum CallMode { + CALL_MODE_SELF, + CALL_MODE_NODE_PATH, + }; +private: + + CallMode call_mode; + NodePath base_path; + StringName function; + + + Node *_get_base_node() const; + + +protected: + virtual void _validate_property(PropertyInfo& property) const; + + static void _bind_methods(); + +public: + + virtual int get_output_sequence_port_count() const; + virtual bool has_input_sequence_port() const; + + + virtual String get_output_sequence_port_text(int p_port) const; + + + virtual int get_input_value_port_count() const; + virtual int get_output_value_port_count() const; + + + virtual PropertyInfo get_input_value_port_info(int p_idx) const; + virtual PropertyInfo get_output_value_port_info(int p_idx) const; + + virtual String get_caption() const; + virtual String get_text() const; + + void set_function(const StringName& p_type); + StringName get_function() const; + + void set_base_path(const NodePath& p_type); + NodePath get_base_path() const; + + void set_call_mode(CallMode p_mode); + CallMode get_call_mode() const; + + + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptScriptCall(); +}; + +VARIANT_ENUM_CAST(VisualScriptScriptCall::CallMode ); + + + + +class VisualScriptEmitSignal : public VisualScriptNode { + + OBJ_TYPE(VisualScriptEmitSignal,VisualScriptNode) + +private: + + StringName name; + + +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; + + void set_signal(const StringName& p_type); + StringName get_signal() const; + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptEmitSignal(); +}; + + + +void register_visual_script_func_nodes(); + +#endif // VISUAL_SCRIPT_FUNC_NODES_H diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp new file mode 100644 index 0000000000..f8d883c491 --- /dev/null +++ b/modules/visual_script/visual_script_nodes.cpp @@ -0,0 +1,1297 @@ +#include "visual_script_nodes.h" +#include "global_constants.h" +#include "globals.h" +#include "scene/main/scene_main_loop.h" +#include "os/os.h" +#include "scene/main/node.h" + +////////////////////////////////////////// +////////////////FUNCTION////////////////// +////////////////////////////////////////// + + +bool VisualScriptFunction::_set(const StringName& p_name, const Variant& p_value) { + + + if (p_name=="argument_count") { + + int new_argc=p_value; + int argc = arguments.size(); + if (argc==new_argc) + return true; + + arguments.resize(new_argc); + + for(int i=argc;i<new_argc;i++) { + arguments[i].name="arg"+itos(i+1); + arguments[i].type=Variant::NIL; + } + emit_signal("ports_changed"); + _change_notify(); + return true; + } + if (String(p_name).begins_with("argument/")) { + int idx = String(p_name).get_slice("/",1).to_int()-1; + ERR_FAIL_INDEX_V(idx,arguments.size(),false); + String what = String(p_name).get_slice("/",2); + if (what=="type") { + + Variant::Type new_type = Variant::Type(int(p_value)); + arguments[idx].type=new_type; + emit_signal("ports_changed"); + + return true; + } + + if (what=="name") { + + arguments[idx].name=p_value; + emit_signal("ports_changed"); + return true; + } + + + } + + + return false; +} + +bool VisualScriptFunction::_get(const StringName& p_name,Variant &r_ret) const { + + + if (p_name=="argument_count") { + r_ret = arguments.size(); + return true; + } + if (String(p_name).begins_with("argument/")) { + int idx = String(p_name).get_slice("/",1).to_int()-1; + ERR_FAIL_INDEX_V(idx,arguments.size(),false); + String what = String(p_name).get_slice("/",2); + if (what=="type") { + r_ret = arguments[idx].type; + return true; + } + if (what=="name") { + r_ret = arguments[idx].name; + return true; + } + + + + } + + return false; +} +void VisualScriptFunction::_get_property_list( List<PropertyInfo> *p_list) const { + + + p_list->push_back(PropertyInfo(Variant::INT,"argument_count",PROPERTY_HINT_RANGE,"0,256")); + String argt="Variant"; + for(int i=1;i<Variant::VARIANT_MAX;i++) { + argt+=","+Variant::get_type_name(Variant::Type(i)); + } + + for(int i=0;i<arguments.size();i++) { + 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")); + } +} + + +int VisualScriptFunction::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptFunction::has_input_sequence_port() const{ + + return false; +} + +int VisualScriptFunction::get_input_value_port_count() const{ + + return 0; +} +int VisualScriptFunction::get_output_value_port_count() const{ + + return arguments.size(); +} + +String VisualScriptFunction::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptFunction::get_input_value_port_info(int p_idx) const{ + + ERR_FAIL_V(PropertyInfo()); + return PropertyInfo(); +} +PropertyInfo VisualScriptFunction::get_output_value_port_info(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,arguments.size(),PropertyInfo()); + PropertyInfo out; + out.type=arguments[p_idx].type; + out.name=arguments[p_idx].name; + return out; +} + +String VisualScriptFunction::get_caption() const { + + return "Function"; +} + +String VisualScriptFunction::get_text() const { + + return get_name(); //use name as function name I guess +} + +void VisualScriptFunction::add_argument(Variant::Type p_type,const String& p_name,int p_index){ + + Argument arg; + arg.name=p_name; + arg.type=p_type; + if (p_index>=0) + arguments.insert(p_index,arg); + else + arguments.push_back(arg); + + emit_signal("ports_changed"); + +} +void VisualScriptFunction::set_argument_type(int p_argidx,Variant::Type p_type){ + + ERR_FAIL_INDEX(p_argidx,arguments.size()); + + arguments[p_argidx].type=p_type; + emit_signal("ports_changed"); +} +Variant::Type VisualScriptFunction::get_argument_type(int p_argidx) const { + + ERR_FAIL_INDEX_V(p_argidx,arguments.size(),Variant::NIL); + return arguments[p_argidx].type; + +} +void VisualScriptFunction::set_argument_name(int p_argidx,const String& p_name) { + + ERR_FAIL_INDEX(p_argidx,arguments.size()); + + arguments[p_argidx].name=p_name; + emit_signal("ports_changed"); + +} +String VisualScriptFunction::get_argument_name(int p_argidx) const { + + ERR_FAIL_INDEX_V(p_argidx,arguments.size(),String()); + return arguments[p_argidx].name; + +} +void VisualScriptFunction::remove_argument(int p_argidx) { + + ERR_FAIL_INDEX(p_argidx,arguments.size()); + + arguments.remove(p_argidx); + emit_signal("ports_changed"); + +} + +int VisualScriptFunction::get_argument_count() const { + + return arguments.size(); +} + + +VisualScriptNodeInstance* VisualScriptFunction::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptFunction::VisualScriptFunction() { + + +} + + +////////////////////////////////////////// +////////////////OPERATOR////////////////// +////////////////////////////////////////// + +int VisualScriptOperator::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptOperator::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptOperator::get_input_value_port_count() const{ + + return (op==Variant::OP_BIT_NEGATE || op==Variant::OP_NOT || op==Variant::OP_NEGATE) ? 1 : 2; +} +int VisualScriptOperator::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptOperator::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptOperator::get_input_value_port_info(int p_idx) const{ + + static const Variant::Type port_types[Variant::OP_MAX][2]={ + {Variant::NIL,Variant::NIL}, //OP_EQUAL, + {Variant::NIL,Variant::NIL}, //OP_NOT_EQUAL, + {Variant::NIL,Variant::NIL}, //OP_LESS, + {Variant::NIL,Variant::NIL}, //OP_LESS_EQUAL, + {Variant::NIL,Variant::NIL}, //OP_GREATER, + {Variant::NIL,Variant::NIL}, //OP_GREATER_EQUAL, + //mathematic + {Variant::NIL,Variant::NIL}, //OP_ADD, + {Variant::NIL,Variant::NIL}, //OP_SUBSTRACT, + {Variant::NIL,Variant::NIL}, //OP_MULTIPLY, + {Variant::NIL,Variant::NIL}, //OP_DIVIDE, + {Variant::NIL,Variant::NIL}, //OP_NEGATE, + {Variant::INT,Variant::INT}, //OP_MODULE, + {Variant::STRING,Variant::STRING}, //OP_STRING_CONCAT, + //bitwise + {Variant::INT,Variant::INT}, //OP_SHIFT_LEFT, + {Variant::INT,Variant::INT}, //OP_SHIFT_RIGHT, + {Variant::INT,Variant::INT}, //OP_BIT_AND, + {Variant::INT,Variant::INT}, //OP_BIT_OR, + {Variant::INT,Variant::INT}, //OP_BIT_XOR, + {Variant::INT,Variant::INT}, //OP_BIT_NEGATE, + //logic + {Variant::BOOL,Variant::BOOL}, //OP_AND, + {Variant::BOOL,Variant::BOOL}, //OP_OR, + {Variant::BOOL,Variant::BOOL}, //OP_XOR, + {Variant::BOOL,Variant::BOOL}, //OP_NOT, + //containment + {Variant::NIL,Variant::NIL} //OP_IN, + }; + + ERR_FAIL_INDEX_V(p_idx,Variant::OP_MAX,PropertyInfo()); + + PropertyInfo pinfo; + pinfo.name=p_idx==0?"A":"B"; + pinfo.type=port_types[op][p_idx]; + return pinfo; +} +PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const{ + static const Variant::Type port_types[Variant::OP_MAX]={ + //comparation + Variant::BOOL, //OP_EQUAL, + Variant::BOOL, //OP_NOT_EQUAL, + Variant::BOOL, //OP_LESS, + Variant::BOOL, //OP_LESS_EQUAL, + Variant::BOOL, //OP_GREATER, + Variant::BOOL, //OP_GREATER_EQUAL, + //mathematic + Variant::NIL, //OP_ADD, + Variant::NIL, //OP_SUBSTRACT, + Variant::NIL, //OP_MULTIPLY, + Variant::NIL, //OP_DIVIDE, + Variant::NIL, //OP_NEGATE, + Variant::INT, //OP_MODULE, + Variant::STRING, //OP_STRING_CONCAT, + //bitwise + Variant::INT, //OP_SHIFT_LEFT, + Variant::INT, //OP_SHIFT_RIGHT, + Variant::INT, //OP_BIT_AND, + Variant::INT, //OP_BIT_OR, + Variant::INT, //OP_BIT_XOR, + Variant::INT, //OP_BIT_NEGATE, + //logic + Variant::BOOL, //OP_AND, + Variant::BOOL, //OP_OR, + Variant::BOOL, //OP_XOR, + Variant::BOOL, //OP_NOT, + //containment + Variant::BOOL //OP_IN, + }; + + PropertyInfo pinfo; + pinfo.name=""; + pinfo.type=port_types[op]; + return pinfo; + +} + +static const char* op_names[]={ + //comparation + "Equal", //OP_EQUAL, + "NotEqual", //OP_NOT_EQUAL, + "Less", //OP_LESS, + "LessEqual", //OP_LESS_EQUAL, + "Greater", //OP_GREATER, + "GreaterEq", //OP_GREATER_EQUAL, + //mathematic + "Add", //OP_ADD, + "Subtract", //OP_SUBSTRACT, + "Multiply", //OP_MULTIPLY, + "Divide", //OP_DIVIDE, + "Negate", //OP_NEGATE, + "Remainder", //OP_MODULE, + "Concat", //OP_STRING_CONCAT, + //bitwise + "ShiftLeft", //OP_SHIFT_LEFT, + "ShiftRight", //OP_SHIFT_RIGHT, + "BitAnd", //OP_BIT_AND, + "BitOr", //OP_BIT_OR, + "BitXor", //OP_BIT_XOR, + "BitNeg", //OP_BIT_NEGATE, + //logic + "And", //OP_AND, + "Or", //OP_OR, + "Xor", //OP_XOR, + "Not", //OP_NOT, + //containment + "In", //OP_IN, +}; + +String VisualScriptOperator::get_caption() const { + + + + return op_names[op]; +} + +String VisualScriptOperator::get_text() const { + + static const wchar_t* op_names[]={ + //comparation + L"A = B", //OP_EQUAL, + L"A \u2260 B", //OP_NOT_EQUAL, + L"A < B", //OP_LESS, + L"A \u2264 B", //OP_LESS_EQUAL, + L"A > B", //OP_GREATER, + L"A \u2265 B", //OP_GREATER_EQUAL, + //mathematic + L"A + B", //OP_ADD, + L"A - B", //OP_SUBSTRACT, + L"A x B", //OP_MULTIPLY, + L"A \u00F7 B", //OP_DIVIDE, + L"\u00AC A", //OP_NEGATE, + L"A mod B", //OP_MODULE, + L"A .. B", //OP_STRING_CONCAT, + //bitwise + L"A << B", //OP_SHIFT_LEFT, + L"A >> B", //OP_SHIFT_RIGHT, + L"A & B", //OP_BIT_AND, + L"A | B", //OP_BIT_OR, + L"A ^ B", //OP_BIT_XOR, + L"~A", //OP_BIT_NEGATE, + //logic + L"A and B", //OP_AND, + L"A or B", //OP_OR, + L"A xor B", //OP_XOR, + L"not A", //OP_NOT, + + }; + return op_names[op]; +} + +void VisualScriptOperator::set_operator(Variant::Operator p_op) { + + if (op==p_op) + return; + op=p_op; + emit_signal("ports_changed"); + +} + +Variant::Operator VisualScriptOperator::get_operator() const{ + + return op; +} + + +void VisualScriptOperator::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_operator","op"),&VisualScriptOperator::set_operator); + ObjectTypeDB::bind_method(_MD("get_operator"),&VisualScriptOperator::get_operator); + + String types; + for(int i=0;i<Variant::OP_MAX;i++) { + if (i>0) + types+=","; + types+=op_names[i]; + } + ADD_PROPERTY(PropertyInfo(Variant::INT,"operator_value/type",PROPERTY_HINT_ENUM,types),_SCS("set_operator"),_SCS("get_operator")); + +} + +VisualScriptNodeInstance* VisualScriptOperator::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptOperator::VisualScriptOperator() { + + op=Variant::OP_ADD; +} + + + +template<Variant::Operator OP> +static Ref<VisualScriptNode> create_op_node(const String& p_name) { + + Ref<VisualScriptOperator> node; + node.instance(); + node->set_operator(OP); + return node; +} + +////////////////////////////////////////// +////////////////VARIABLE////////////////// +////////////////////////////////////////// + +int VisualScriptVariable::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptVariable::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptVariable::get_input_value_port_count() const{ + + return 1; +} +int VisualScriptVariable::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptVariable::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptVariable::get_input_value_port_info(int p_idx) const{ + + PropertyInfo pinfo; + 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; + pinfo.hint=vinfo.hint; + pinfo.hint_string=vinfo.hint_string; + } + return pinfo; +} + +PropertyInfo VisualScriptVariable::get_output_value_port_info(int p_idx) const{ + + PropertyInfo pinfo; + pinfo.name="get"; + 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; + pinfo.hint=vinfo.hint; + pinfo.hint_string=vinfo.hint_string; + } + return pinfo; +} + + +String VisualScriptVariable::get_caption() const { + + return "Variable"; +} + +String VisualScriptVariable::get_text() const { + + return variable; +} + +void VisualScriptVariable::set_variable(StringName p_variable) { + + if (variable==p_variable) + return; + variable=p_variable; + emit_signal("ports_changed"); + +} + +StringName VisualScriptVariable::get_variable() const{ + + return variable; +} + +void VisualScriptVariable::_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 VisualScriptVariable::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_variable","name"),&VisualScriptVariable::set_variable); + ObjectTypeDB::bind_method(_MD("get_variable"),&VisualScriptVariable::get_variable); + + + ADD_PROPERTY(PropertyInfo(Variant::STRING,"variable/name"),_SCS("set_variable"),_SCS("get_variable")); + +} + +VisualScriptNodeInstance* VisualScriptVariable::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptVariable::VisualScriptVariable() { + + +} + + + +////////////////////////////////////////// +////////////////CONSTANT////////////////// +////////////////////////////////////////// + +int VisualScriptConstant::get_output_sequence_port_count() const { + + return 0; +} + +bool VisualScriptConstant::has_input_sequence_port() const{ + + return false; +} + +int VisualScriptConstant::get_input_value_port_count() const{ + + return 0; +} +int VisualScriptConstant::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptConstant::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptConstant::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + +PropertyInfo VisualScriptConstant::get_output_value_port_info(int p_idx) const{ + + PropertyInfo pinfo; + pinfo.name="get"; + pinfo.type=type; + return pinfo; +} + + +String VisualScriptConstant::get_caption() const { + + return "Constant"; +} + +String VisualScriptConstant::get_text() const { + + return String(value); +} + +void VisualScriptConstant::set_constant_type(Variant::Type p_type) { + + if (type==p_type) + return; + + type=p_type; + emit_signal("ports_changed"); + Variant::CallError ce; + value=Variant::construct(type,NULL,0,ce); + _change_notify(); + +} + +Variant::Type VisualScriptConstant::get_constant_type() const{ + + return type; +} + +void VisualScriptConstant::set_constant_value(Variant p_value){ + + if (value==p_value) + return; + + value=p_value; + emit_signal("ports_changed"); +} +Variant VisualScriptConstant::get_constant_value() const{ + + return value; +} + +void VisualScriptConstant::_validate_property(PropertyInfo& property) const { + + + if (property.name=="constant/value") { + property.type=type; + if (type==Variant::NIL) + property.usage=0; //do not save if nil + } +} + +void VisualScriptConstant::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_constant_type","type"),&VisualScriptConstant::set_constant_type); + ObjectTypeDB::bind_method(_MD("get_constant_type"),&VisualScriptConstant::get_constant_type); + + ObjectTypeDB::bind_method(_MD("set_constant_value","value"),&VisualScriptConstant::set_constant_value); + ObjectTypeDB::bind_method(_MD("get_constant_value"),&VisualScriptConstant::get_constant_value); + + String argt="Null"; + for(int i=1;i<Variant::VARIANT_MAX;i++) { + argt+=","+Variant::get_type_name(Variant::Type(i)); + } + + + ADD_PROPERTY(PropertyInfo(Variant::INT,"constant/type",PROPERTY_HINT_ENUM,argt),_SCS("set_constant_type"),_SCS("get_constant_type")); + ADD_PROPERTY(PropertyInfo(Variant::NIL,"constant/value"),_SCS("set_constant_value"),_SCS("get_constant_value")); + +} + +VisualScriptNodeInstance* VisualScriptConstant::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptConstant::VisualScriptConstant() { + + type=Variant::NIL; + +} + + + +////////////////////////////////////////// +////////////////INDEX//////////////////// +////////////////////////////////////////// + +int VisualScriptIndexGet::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptIndexGet::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptIndexGet::get_input_value_port_count() const{ + + return 2; +} +int VisualScriptIndexGet::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptIndexGet::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptIndexGet::get_input_value_port_info(int p_idx) const{ + + if (p_idx==0) { + return PropertyInfo(Variant::NIL,"base"); + } else { + return PropertyInfo(Variant::NIL,"index"); + + } +} + +PropertyInfo VisualScriptIndexGet::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + + +String VisualScriptIndexGet::get_caption() const { + + return "IndexGet"; +} + +String VisualScriptIndexGet::get_text() const { + + return String("get"); +} + + +VisualScriptNodeInstance* VisualScriptIndexGet::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptIndexGet::VisualScriptIndexGet() { + + + +} + +////////////////////////////////////////// +////////////////INDEXSET////////////////// +////////////////////////////////////////// + +int VisualScriptIndexSet::get_output_sequence_port_count() const { + + return 1; +} + +bool VisualScriptIndexSet::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptIndexSet::get_input_value_port_count() const{ + + return 3; +} +int VisualScriptIndexSet::get_output_value_port_count() const{ + + return 0; +} + +String VisualScriptIndexSet::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptIndexSet::get_input_value_port_info(int p_idx) const{ + + if (p_idx==0) { + return PropertyInfo(Variant::NIL,"base"); + } else if (p_idx==1){ + return PropertyInfo(Variant::NIL,"index"); + + } else { + return PropertyInfo(Variant::NIL,"value"); + + } +} + +PropertyInfo VisualScriptIndexSet::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + + +String VisualScriptIndexSet::get_caption() const { + + return "IndexSet"; +} + +String VisualScriptIndexSet::get_text() const { + + return String("set"); +} + + +VisualScriptNodeInstance* VisualScriptIndexSet::instance(VScriptInstance* p_instance) { + + return NULL; +} + +VisualScriptIndexSet::VisualScriptIndexSet() { + + + +} + + +////////////////////////////////////////// +////////////////GLOBALCONSTANT/////////// +////////////////////////////////////////// + +int VisualScriptGlobalConstant::get_output_sequence_port_count() const { + + return 0; +} + +bool VisualScriptGlobalConstant::has_input_sequence_port() const{ + + return false; +} + +int VisualScriptGlobalConstant::get_input_value_port_count() const{ + + return 0; +} +int VisualScriptGlobalConstant::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptGlobalConstant::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptGlobalConstant::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + +PropertyInfo VisualScriptGlobalConstant::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(Variant::INT,"value"); +} + + +String VisualScriptGlobalConstant::get_caption() const { + + return "GlobalConst"; +} + +String VisualScriptGlobalConstant::get_text() const { + + return GlobalConstants::get_global_constant_name(index); +} + +void VisualScriptGlobalConstant::set_global_constant(int p_which) { + + index=p_which; + _change_notify(); + emit_signal("ports_changed"); +} + +int VisualScriptGlobalConstant::get_global_constant() { + return index; +} + + + +VisualScriptNodeInstance* VisualScriptGlobalConstant::instance(VScriptInstance* p_instance) { + + return NULL; +} + +void VisualScriptGlobalConstant::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_global_constant","index"),&VisualScriptGlobalConstant::set_global_constant); + ObjectTypeDB::bind_method(_MD("get_global_constant"),&VisualScriptGlobalConstant::get_global_constant); + + String cc; + + for(int i=0;i<GlobalConstants::get_global_constant_count();i++) { + + if (i>0) + cc+=","; + cc+=GlobalConstants::get_global_constant_name(i); + } + ADD_PROPERTY(PropertyInfo(Variant::INT,"constant",PROPERTY_HINT_ENUM,cc),_SCS("set_global_constant"),_SCS("get_global_constant")); +} + +VisualScriptGlobalConstant::VisualScriptGlobalConstant() { + + index=0; +} + + + +////////////////////////////////////////// +////////////////MATHCONSTANT/////////// +////////////////////////////////////////// + + +const char* VisualScriptMathConstant::const_name[MATH_CONSTANT_MAX]={ + "One", + "PI", + "PIx2", + "PI/2", + "E", + "Sqrt2", +}; +int VisualScriptMathConstant::get_output_sequence_port_count() const { + + return 0; +} + +bool VisualScriptMathConstant::has_input_sequence_port() const{ + + return false; +} + +int VisualScriptMathConstant::get_input_value_port_count() const{ + + return 0; +} +int VisualScriptMathConstant::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptMathConstant::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptMathConstant::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + +PropertyInfo VisualScriptMathConstant::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(Variant::INT,"value"); +} + + +String VisualScriptMathConstant::get_caption() const { + + return "MathConst"; +} + +String VisualScriptMathConstant::get_text() const { + + return const_name[constant]; +} + +void VisualScriptMathConstant::set_math_constant(MathConstant p_which) { + + constant=p_which; + _change_notify(); + emit_signal("ports_changed"); +} + +VisualScriptMathConstant::MathConstant VisualScriptMathConstant::get_math_constant() { + return constant; +} + + + +VisualScriptNodeInstance* VisualScriptMathConstant::instance(VScriptInstance* p_instance) { + + return NULL; +} + +void VisualScriptMathConstant::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_math_constant","which"),&VisualScriptMathConstant::set_math_constant); + ObjectTypeDB::bind_method(_MD("get_math_constant"),&VisualScriptMathConstant::get_math_constant); + + String cc; + + for(int i=0;i<MATH_CONSTANT_MAX;i++) { + + if (i>0) + cc+=","; + cc+=const_name[i]; + } + ADD_PROPERTY(PropertyInfo(Variant::INT,"constant",PROPERTY_HINT_ENUM,cc),_SCS("set_math_constant"),_SCS("get_math_constant")); +} + +VisualScriptMathConstant::VisualScriptMathConstant() { + + constant=MATH_CONSTANT_ONE; +} + + + +////////////////////////////////////////// +////////////////GLOBALSINGLETON/////////// +////////////////////////////////////////// + +int VisualScriptSingleton::get_output_sequence_port_count() const { + + return 0; +} + +bool VisualScriptSingleton::has_input_sequence_port() const{ + + return false; +} + +int VisualScriptSingleton::get_input_value_port_count() const{ + + return 0; +} +int VisualScriptSingleton::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptSingleton::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptSingleton::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + +PropertyInfo VisualScriptSingleton::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(Variant::OBJECT,"instance"); +} + + +String VisualScriptSingleton::get_caption() const { + + return "Singleton"; +} + +String VisualScriptSingleton::get_text() const { + + return singleton; +} + +void VisualScriptSingleton::set_singleton(const String& p_string) { + + singleton=p_string; + + _change_notify(); + emit_signal("ports_changed"); +} + +String VisualScriptSingleton::get_singleton() { + return singleton; +} + + + +VisualScriptNodeInstance* VisualScriptSingleton::instance(VScriptInstance* p_instance) { + + return NULL; +} + +void VisualScriptSingleton::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_singleton","name"),&VisualScriptSingleton::set_singleton); + ObjectTypeDB::bind_method(_MD("get_singleton"),&VisualScriptSingleton::get_singleton); + + String cc; + + List<Globals::Singleton> singletons; + + Globals::get_singleton()->get_singletons(&singletons); + + for (List<Globals::Singleton>::Element *E=singletons.front();E;E=E->next()) { + if (E->get().name=="VS" || E->get().name=="PS" || E->get().name=="PS2D" || E->get().name=="AS" || E->get().name=="TS" || E->get().name=="SS" || E->get().name=="SS2D") + continue; //skip these, too simple named + + if (cc!=String()) + cc+=","; + cc+=E->get().name; + } + + ADD_PROPERTY(PropertyInfo(Variant::STRING,"constant",PROPERTY_HINT_ENUM,cc),_SCS("set_singleton"),_SCS("get_singleton")); +} + +VisualScriptSingleton::VisualScriptSingleton() { + + singleton=String(); +} + + + +////////////////////////////////////////// +////////////////GETNODE/////////// +////////////////////////////////////////// + +int VisualScriptSceneNode::get_output_sequence_port_count() const { + + return 0; +} + +bool VisualScriptSceneNode::has_input_sequence_port() const{ + + return false; +} + +int VisualScriptSceneNode::get_input_value_port_count() const{ + + return 0; +} +int VisualScriptSceneNode::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptSceneNode::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptSceneNode::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + +PropertyInfo VisualScriptSceneNode::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(Variant::OBJECT,"node"); +} + + +String VisualScriptSceneNode::get_caption() const { + + return "SceneNode"; +} + +String VisualScriptSceneNode::get_text() const { + + return path.simplified(); +} + +void VisualScriptSceneNode::set_node_path(const NodePath& p_path) { + + path=p_path; + _change_notify(); + emit_signal("ports_changed"); +} + +NodePath VisualScriptSceneNode::get_node_path() { + return path; +} + + + +VisualScriptNodeInstance* VisualScriptSceneNode::instance(VScriptInstance* p_instance) { + + return NULL; +} + +#ifdef TOOLS_ENABLED + +static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) { + + if (p_edited_scene!=p_current_node && p_current_node->get_owner()!=p_edited_scene) + return NULL; + + Ref<Script> scr = p_current_node->get_script(); + + if (scr.is_valid() && scr==script) + return p_current_node; + + for(int i=0;i<p_current_node->get_child_count();i++) { + Node *n = _find_script_node(p_edited_scene,p_current_node->get_child(i),script); + if (n) + return n; + } + + return NULL; +} + +#endif + +void VisualScriptSceneNode::_validate_property(PropertyInfo& property) const { + +#ifdef TOOLS_ENABLED + if (property.name=="node_path") { + + Ref<Script> script = get_visual_script(); + if (!script.is_valid()) + return; + + MainLoop * main_loop = OS::get_singleton()->get_main_loop(); + if (!main_loop) + return; + + SceneTree *scene_tree = main_loop->cast_to<SceneTree>(); + + if (!scene_tree) + return; + + Node *edited_scene = scene_tree->get_edited_scene_root(); + + if (!edited_scene) + return; + + Node* script_node = _find_script_node(edited_scene,edited_scene,script); + + if (!script_node) + return; + + property.hint_string=script_node->get_path(); + } +#endif +} + +void VisualScriptSceneNode::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_node_path","path"),&VisualScriptSceneNode::set_node_path); + ObjectTypeDB::bind_method(_MD("get_node_path"),&VisualScriptSceneNode::get_node_path); + + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_node_path"),_SCS("get_node_path")); +} + +VisualScriptSceneNode::VisualScriptSceneNode() { + + path=String("."); +} + + +void register_visual_script_nodes() { + + VisualScriptLanguage::singleton->add_register_func("data/variable",create_node_generic<VisualScriptVariable>); + 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>); + VisualScriptLanguage::singleton->add_register_func("data/singleton",create_node_generic<VisualScriptSingleton>); + VisualScriptLanguage::singleton->add_register_func("data/scene_node",create_node_generic<VisualScriptSceneNode>); + + + VisualScriptLanguage::singleton->add_register_func("index/get",create_node_generic<VisualScriptIndexGet>); + VisualScriptLanguage::singleton->add_register_func("index/set",create_node_generic<VisualScriptIndexSet>); + + + VisualScriptLanguage::singleton->add_register_func("operators/compare/equal",create_op_node<Variant::OP_EQUAL>); + VisualScriptLanguage::singleton->add_register_func("operators/compare/not_equal",create_op_node<Variant::OP_NOT_EQUAL>); + VisualScriptLanguage::singleton->add_register_func("operators/compare/less",create_op_node<Variant::OP_LESS>); + VisualScriptLanguage::singleton->add_register_func("operators/compare/less_equal",create_op_node<Variant::OP_LESS_EQUAL>); + VisualScriptLanguage::singleton->add_register_func("operators/compare/greater",create_op_node<Variant::OP_GREATER>); + VisualScriptLanguage::singleton->add_register_func("operators/compare/greater_equal",create_op_node<Variant::OP_GREATER_EQUAL>); + //mathematic + VisualScriptLanguage::singleton->add_register_func("operators/math/add",create_op_node<Variant::OP_ADD>); + VisualScriptLanguage::singleton->add_register_func("operators/math/subtract",create_op_node<Variant::OP_SUBSTRACT>); + VisualScriptLanguage::singleton->add_register_func("operators/math/multiply",create_op_node<Variant::OP_MULTIPLY>); + VisualScriptLanguage::singleton->add_register_func("operators/math/divide",create_op_node<Variant::OP_DIVIDE>); + VisualScriptLanguage::singleton->add_register_func("operators/math/negate",create_op_node<Variant::OP_NEGATE>); + VisualScriptLanguage::singleton->add_register_func("operators/math/remainder",create_op_node<Variant::OP_MODULE>); + VisualScriptLanguage::singleton->add_register_func("operators/math/string_concat",create_op_node<Variant::OP_STRING_CONCAT>); + //bitwise + VisualScriptLanguage::singleton->add_register_func("operators/bitwise/shift_left",create_op_node<Variant::OP_SHIFT_LEFT>); + VisualScriptLanguage::singleton->add_register_func("operators/bitwise/shift_right",create_op_node<Variant::OP_SHIFT_RIGHT>); + VisualScriptLanguage::singleton->add_register_func("operators/bitwise/bit_and",create_op_node<Variant::OP_BIT_AND>); + VisualScriptLanguage::singleton->add_register_func("operators/bitwise/bit_or",create_op_node<Variant::OP_BIT_OR>); + VisualScriptLanguage::singleton->add_register_func("operators/bitwise/bit_xor",create_op_node<Variant::OP_BIT_XOR>); + VisualScriptLanguage::singleton->add_register_func("operators/bitwise/bit_negate",create_op_node<Variant::OP_BIT_NEGATE>); + //logic + VisualScriptLanguage::singleton->add_register_func("operators/logic/and",create_op_node<Variant::OP_AND>); + VisualScriptLanguage::singleton->add_register_func("operators/logic/or",create_op_node<Variant::OP_OR>); + VisualScriptLanguage::singleton->add_register_func("operators/logic/xor",create_op_node<Variant::OP_XOR>); + VisualScriptLanguage::singleton->add_register_func("operators/logic/not",create_op_node<Variant::OP_NOT>); + VisualScriptLanguage::singleton->add_register_func("operators/logic/in",create_op_node<Variant::OP_IN>); + +} diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h new file mode 100644 index 0000000000..e10f9a7331 --- /dev/null +++ b/modules/visual_script/visual_script_nodes.h @@ -0,0 +1,394 @@ +#ifndef VISUAL_SCRIPT_NODES_H +#define VISUAL_SCRIPT_NODES_H + +#include "visual_script.h" + +class VisualScriptFunction : public VisualScriptNode { + + OBJ_TYPE(VisualScriptFunction,VisualScriptNode) + + + struct Argument { + String name; + Variant::Type type; + }; + + Vector<Argument> arguments; +protected: + + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; + +public: + + virtual int get_output_sequence_port_count() const; + virtual bool has_input_sequence_port() const; + + + virtual String get_output_sequence_port_text(int p_port) const; + + + virtual int get_input_value_port_count() const; + virtual int get_output_value_port_count() const; + + + virtual PropertyInfo get_input_value_port_info(int p_idx) const; + virtual PropertyInfo get_output_value_port_info(int p_idx) const; + + virtual String get_caption() const; + virtual String get_text() const; + + 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); + Variant::Type get_argument_type(int p_argidx) const; + void set_argument_name(int p_argidx,const String& p_name); + String get_argument_name(int p_argidx) const; + void remove_argument(int p_argidx); + int get_argument_count() const; + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptFunction(); +}; + + +class VisualScriptOperator : public VisualScriptNode { + + OBJ_TYPE(VisualScriptOperator,VisualScriptNode) + + + Variant::Operator op; +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; + + void set_operator(Variant::Operator p_op); + Variant::Operator get_operator() const; + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptOperator(); +}; + + +class VisualScriptVariable : public VisualScriptNode { + + OBJ_TYPE(VisualScriptVariable,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; + + void set_variable(StringName p_var); + StringName get_variable() const; + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptVariable(); +}; + +class VisualScriptConstant : public VisualScriptNode { + + OBJ_TYPE(VisualScriptConstant,VisualScriptNode) + + + Variant::Type type; + Variant value; +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; + + void set_constant_type(Variant::Type p_type); + Variant::Type get_constant_type() const; + + void set_constant_value(Variant p_value); + Variant get_constant_value() const; + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptConstant(); +}; + + +class VisualScriptIndexGet : public VisualScriptNode { + + OBJ_TYPE(VisualScriptIndexGet,VisualScriptNode) + + +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 VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptIndexGet(); +}; + + +class VisualScriptIndexSet : public VisualScriptNode { + + OBJ_TYPE(VisualScriptIndexSet,VisualScriptNode) + + +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 VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptIndexSet(); +}; + + + +class VisualScriptGlobalConstant : public VisualScriptNode { + + OBJ_TYPE(VisualScriptGlobalConstant,VisualScriptNode) + + int index; + + 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; + + void set_global_constant(int p_which); + int get_global_constant(); + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptGlobalConstant(); +}; + + + +class VisualScriptMathConstant : public VisualScriptNode { + + OBJ_TYPE(VisualScriptMathConstant,VisualScriptNode) +public: + + enum MathConstant { + MATH_CONSTANT_ONE, + MATH_CONSTANT_PI, + MATH_CONSTANT_2PI, + MATH_CONSTANT_HALF_PI, + MATH_CONSTANT_E, + MATH_CONSTANT_SQRT2, + MATH_CONSTANT_MAX, + }; + +private: + static const char* const_name[MATH_CONSTANT_MAX]; + MathConstant constant; +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; + + void set_math_constant(MathConstant p_which); + MathConstant get_math_constant(); + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptMathConstant(); +}; + +VARIANT_ENUM_CAST( VisualScriptMathConstant::MathConstant ) + +class VisualScriptSingleton : public VisualScriptNode { + + OBJ_TYPE(VisualScriptSingleton,VisualScriptNode) + + String singleton; + + 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; + + void set_singleton(const String &p_string); + String get_singleton(); + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptSingleton(); +}; + + + + +class VisualScriptSceneNode : public VisualScriptNode { + + OBJ_TYPE(VisualScriptSceneNode,VisualScriptNode) + + NodePath path; +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; + + void set_node_path(const NodePath &p_path); + NodePath get_node_path(); + + virtual VisualScriptNodeInstance* instance(VScriptInstance* p_instance); + + VisualScriptSceneNode(); +}; + + + +void register_visual_script_nodes(); + +#endif // VISUAL_SCRIPT_NODES_H |