diff options
35 files changed, 1703 insertions, 248 deletions
diff --git a/core/object.cpp b/core/object.cpp index 26319d42dd..b036efa501 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -59,30 +59,112 @@ struct _ObjectDebugLock { #endif + +PropertyInfo::operator Dictionary() const { + + Dictionary d; + d["name"]=name; + d["type"]=type; + d["hint"]=hint; + d["hint_string"]=hint_string; + d["usage"]=usage; + return d; + +} + +PropertyInfo PropertyInfo::from_dict(const Dictionary& p_dict) { + + PropertyInfo pi; + + if (p_dict.has("type")) + pi.type=Variant::Type(int(p_dict["type"])); + + if (p_dict.has("name")) + pi.name=p_dict["name"]; + + if (p_dict.has("hint")) + pi.hint=PropertyHint(int(p_dict["hint"])); + + if (p_dict.has("hint_string")) + + pi.hint_string=p_dict["hint_string"]; + + if (p_dict.has("usage")) + pi.usage=p_dict["usage"]; + + return pi; +} + + Array convert_property_list(const List<PropertyInfo> * p_list) { Array va; for (const List<PropertyInfo>::Element *E=p_list->front();E;E=E->next()) { - const PropertyInfo &pi = E->get(); - Dictionary d; - d["name"]=pi.name; - d["type"]=pi.type; - d["hint"]=pi.hint; - d["hint_string"]=pi.hint_string; - d["usage"]=pi.usage; - va.push_back(d); + + va.push_back(Dictionary(E->get())); } return va; } +MethodInfo::operator Dictionary() const { + + + Dictionary d; + d["name"]=name; + d["args"]=convert_property_list(&arguments); + Array da; + for(int i=0;i<default_arguments.size();i++) + da.push_back(default_arguments[i]); + d["default_args"]=da; + d["flags"]=flags; + d["id"]=id; + Dictionary r = return_val; + d["return"]=r; + return d; + +} + MethodInfo::MethodInfo() { id=0; flags=METHOD_FLAG_NORMAL; } +MethodInfo MethodInfo::from_dict(const Dictionary& p_dict) { + + MethodInfo mi; + + if (p_dict.has("name")) + mi.name=p_dict["name"]; + Array args; + if (p_dict.has("args")) { + args=p_dict["args"]; + } + + for(int i=0;i<args.size();i++) { + Dictionary d = args[i]; + mi.arguments.push_back(PropertyInfo::from_dict(d)); + } + Array defargs; + if (p_dict.has("default_args")) { + defargs=p_dict["default_args"]; + } + for(int i=0;i<defargs.size();i++) { + mi.default_arguments.push_back(defargs[i]); + } + + if (p_dict.has("return")) { + mi.return_val=PropertyInfo::from_dict(p_dict["return"]); + } + + if (p_dict.has("flags")) + mi.flags=p_dict["flags"]; + + return mi; +} + MethodInfo::MethodInfo(const String& p_name) { id=0; @@ -1012,25 +1094,6 @@ Array Object::_get_property_list_bind() const { } -static Dictionary _get_dict_from_method(const MethodInfo &mi) { - - Dictionary d; - d["name"]=mi.name; - d["args"]=convert_property_list(&mi.arguments); - Array da; - for(int i=0;i<mi.default_arguments.size();i++) - da.push_back(mi.default_arguments[i]); - d["default_args"]=da; - d["flags"]=mi.flags; - d["id"]=mi.id; - Dictionary r; - r["type"]=mi.return_val.type; - r["hint"]=mi.return_val.hint; - r["hint_string"]=mi.return_val.hint_string; - d["return_type"]=r; - return d; - -} Array Object::_get_method_list_bind() const { @@ -1040,7 +1103,7 @@ Array Object::_get_method_list_bind() const { for(List<MethodInfo>::Element *E=ml.front();E;E=E->next()) { - Dictionary d = _get_dict_from_method(E->get()); + Dictionary d = E->get(); //va.push_back(d); ret.push_back(d); } @@ -1305,7 +1368,7 @@ Array Object::_get_signal_list() const{ Array ret; for (List<MethodInfo>::Element *E=signal_list.front();E;E=E->next()) { - ret.push_back(_get_dict_from_method(E->get())); + ret.push_back(Dictionary(E->get())); } return ret; diff --git a/core/object.h b/core/object.h index 6ea794ec71..ac3fc51b3e 100644 --- a/core/object.h +++ b/core/object.h @@ -126,6 +126,11 @@ struct PropertyInfo { _FORCE_INLINE_ PropertyInfo added_usage(int p_fl) const { PropertyInfo pi=*this; pi.usage|=p_fl; return pi; } + + operator Dictionary() const; + + static PropertyInfo from_dict(const Dictionary& p_dict); + PropertyInfo() { type=Variant::NIL; hint=PROPERTY_HINT_NONE; usage = PROPERTY_USAGE_DEFAULT; } PropertyInfo( Variant::Type p_type, const String p_name, PropertyHint p_hint=PROPERTY_HINT_NONE, const String& p_hint_string="",uint32_t p_usage=PROPERTY_USAGE_DEFAULT) { type=p_type; name=p_name; hint=p_hint; hint_string=p_hint_string; usage=p_usage; @@ -150,6 +155,9 @@ struct MethodInfo { inline bool operator<(const MethodInfo& p_method) const { return id==p_method.id?(name < p_method.name):(id<p_method.id); } + operator Dictionary() const; + + static MethodInfo from_dict(const Dictionary& p_dict); MethodInfo(); MethodInfo(const String& p_name); MethodInfo(const String& p_name, const PropertyInfo& p_param1); diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index ba98797a89..b6a69e3bd4 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -642,7 +642,7 @@ void ObjectTypeDB::get_property_list(StringName p_type, List<PropertyInfo> *p_li TypeInfo *check=type; while(check) { - for(List<PropertyInfo>::Element *E=type->property_list.front();E;E=E->next()) { + for(List<PropertyInfo>::Element *E=check->property_list.front();E;E=E->next()) { if (p_validator) { diff --git a/core/script_language.cpp b/core/script_language.cpp index 75d8b6d285..fa1d01d3eb 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -33,6 +33,7 @@ int ScriptServer::_language_count=0; bool ScriptServer::scripting_enabled=true; bool ScriptServer::reload_scripts_on_save=false; +ScriptEditRequestFunction ScriptServer::edit_request_func=NULL; void Script::_notification( int p_what) { diff --git a/core/script_language.h b/core/script_language.h index 36ed11efec..1b037e908c 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -38,6 +38,8 @@ class ScriptLanguage; +typedef void (*ScriptEditRequestFunction)(const String& p_path); + class ScriptServer { enum { @@ -50,6 +52,8 @@ class ScriptServer { static bool reload_scripts_on_save; public: + static ScriptEditRequestFunction edit_request_func; + static void set_scripting_enabled(bool p_enabled); static bool is_scripting_enabled(); static int get_language_count(); @@ -88,6 +92,8 @@ public: virtual bool can_instance() const=0; + virtual Ref<Script> get_base_script() const=0; //for script inheritance + virtual StringName get_instance_base_type() const=0; // this may not work in all scripts, will return empty if so virtual ScriptInstance* instance_create(Object *p_this)=0; virtual bool instance_has(const Object *p_this) const=0; diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp index 13fbfb6ec0..b97a0fcbb6 100644 --- a/modules/gdscript/gd_script.cpp +++ b/modules/gdscript/gd_script.cpp @@ -179,6 +179,15 @@ bool GDScript::can_instance() const { } +Ref<Script> GDScript::get_base_script() const { + + if (_base) { + return Ref<GDScript>( _base ); + } else { + return Ref<Script>(); + } +} + StringName GDScript::get_instance_base_type() const { if (native.is_valid()) diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h index 856211b2fd..0c3e1eb614 100644 --- a/modules/gdscript/gd_script.h +++ b/modules/gdscript/gd_script.h @@ -162,6 +162,8 @@ public: Variant _new(const Variant** p_args,int p_argcount,Variant::CallError& r_error); virtual bool can_instance() const; + virtual Ref<Script> get_base_script() const; + virtual StringName get_instance_base_type() const; // this may not work in all scripts, will return empty if so virtual ScriptInstance* instance_create(Object *p_this); virtual bool instance_has(const Object *p_this) const; diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index 6e60b6a314..2c3ad7c5af 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -43,6 +43,10 @@ VisualScriptLanguage *visual_script_language=NULL; void register_visual_script_types() { + visual_script_language=memnew( VisualScriptLanguage ); + //script_language_gd->init(); + ScriptServer::register_language(visual_script_language); + ObjectTypeDB::register_type<VisualScript>(); ObjectTypeDB::register_virtual_type<VisualScriptNode>(); ObjectTypeDB::register_virtual_type<VisualScriptFunctionState>(); @@ -62,6 +66,7 @@ void register_visual_script_types() { ObjectTypeDB::register_type<VisualScriptSelf>(); ObjectTypeDB::register_type<VisualScriptCustomNode>(); ObjectTypeDB::register_type<VisualScriptSubCall>(); + ObjectTypeDB::register_type<VisualScriptComment>(); ObjectTypeDB::register_type<VisualScriptFunctionCall>(); ObjectTypeDB::register_type<VisualScriptPropertySet>(); @@ -82,9 +87,6 @@ void register_visual_script_types() { 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(); diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 82e538d781..61e5d45d8f 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -1,7 +1,7 @@ #include "visual_script.h" #include "visual_script_nodes.h" #include "scene/main/node.h" - +#include "os/os.h" #include "globals.h" #define SCRIPT_VARIABLES_PREFIX "script_variables/" @@ -31,11 +31,13 @@ void VisualScriptNode::_notification(int p_what) { void VisualScriptNode::ports_changed_notify(){ + default_input_values.resize( MAX(default_input_values.size(),get_input_value_port_count()) ); //let it grow as big as possible, we don't want to lose values on resize + emit_signal("ports_changed"); } -void VisualScriptNode::set_default_input_value(int p_port,const Variant& p_value) { +void VisualScriptNode::set_default_input_value(int p_port,const Variant& p_value) { ERR_FAIL_INDEX(p_port,default_input_values.size()); @@ -54,35 +56,40 @@ void VisualScriptNode::_set_default_input_values(Array p_values) { default_input_values=p_values; } -Array VisualScriptNode::_get_default_input_values() const { - //validate on save, since on load there is little info about this +void VisualScriptNode::validate_input_default_values() { + - Array saved_values; + + default_input_values.resize(get_input_value_port_count()); //actually validate on save for(int i=0;i<get_input_value_port_count();i++) { Variant::Type expected = get_input_value_port_info(i).type; - if (i>=default_input_values.size()) { + if (expected==Variant::NIL || expected==default_input_values[i].get_type()) { + continue; + } else { + //not the same, reconvert Variant::CallError ce; - saved_values.push_back(Variant::construct(expected,NULL,0,ce,false)); - } else { - - if (expected==Variant::NIL || expected==default_input_values[i].get_type()) { - saved_values.push_back(default_input_values[i]); - } else { - //not the same, reconvert - Variant::CallError ce; - Variant existing = default_input_values[i]; - const Variant *existingp=&existing; - saved_values.push_back( Variant::construct(expected,&existingp,1,ce,false) ); + Variant existing = default_input_values[i]; + const Variant *existingp=&existing; + default_input_values[i] = Variant::construct(expected,&existingp,1,ce,false); + if (ce.error!=Variant::CallError::CALL_OK) { + //could not convert? force.. + default_input_values[i] = Variant::construct(expected,NULL,0,ce,false); } } } - return saved_values; +} + +Array VisualScriptNode::_get_default_input_values() const { + + //validate on save, since on load there is little info about this + + return default_input_values; } @@ -224,6 +231,7 @@ int VisualScript::get_function_node_id(const StringName& p_name) const { void VisualScript::_node_ports_changed(int p_id) { + StringName function; for (Map<StringName,Function>::Element *E=functions.front();E;E=E->next()) { @@ -239,6 +247,10 @@ void VisualScript::_node_ports_changed(int p_id) { Function &func = functions[function]; Ref<VisualScriptNode> vsn = func.nodes[p_id].node; + if (OS::get_singleton()->get_main_loop() && OS::get_singleton()->get_main_loop()->cast_to<SceneTree>() && OS::get_singleton()->get_main_loop()->cast_to<SceneTree>()->is_editor_hint()) { + vsn->validate_input_default_values(); //force validate default values when editing on editor + } + //must revalidate all the functions { @@ -836,6 +848,10 @@ StringName VisualScript::get_instance_base_type() const { return base_type; } +Ref<Script> VisualScript::get_base_script() const { + return Ref<Script>(); // no inheritance in visual script +} + #ifdef TOOLS_ENABLED void VisualScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) { @@ -1884,8 +1900,23 @@ Ref<Script> VisualScriptInstance::get_script() const{ ScriptInstance::RPCMode VisualScriptInstance::get_rpc_mode(const StringName& p_method) const { + const Map<StringName,VisualScript::Function>::Element *E = script->functions.find(p_method); + if (!E) { + return RPC_MODE_DISABLED; + } + + if (E->get().function_id>=0 && E->get().nodes.has(E->get().function_id)) { + + Ref<VisualScriptFunction> vsf = E->get().nodes[E->get().function_id].node; + if (vsf.is_valid()) { + + return vsf->get_rpc_mode(); + } + } + return RPC_MODE_DISABLED; } + ScriptInstance::RPCMode VisualScriptInstance::get_rset_mode(const StringName& p_variable) const { return RPC_MODE_DISABLED; diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index bad50c1cc8..c9734d1b11 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -20,6 +20,8 @@ friend class VisualScript; void _set_default_input_values(Array p_values); Array _get_default_input_values() const; + + void validate_input_default_values(); protected: virtual bool _use_builtin_script() const { return false; } @@ -300,6 +302,7 @@ public: virtual bool can_instance() const; + virtual Ref<Script> get_base_script() const; virtual StringName get_instance_base_type() const; virtual ScriptInstance* instance_create(Object *p_this); virtual bool instance_has(const Object *p_this) const; diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 3424395d3f..66abccf2b0 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -347,6 +347,8 @@ void VisualScriptEditor::_update_graph_connections() { void VisualScriptEditor::_update_graph(int p_only_id) { + if (updating_graph) + return; updating_graph=true; @@ -451,10 +453,21 @@ void VisualScriptEditor::_update_graph(int p_only_id) { gnode->set_show_close_button(true); } + Label *text = memnew( Label ); text->set_text(node->get_text()); gnode->add_child(text); + if (node->cast_to<VisualScriptComment>()) { + Ref<VisualScriptComment> vsc=node; + gnode->set_comment(true); + gnode->set_resizeable(true); + gnode->set_custom_minimum_size(vsc->get_size()*EDSCALE); + gnode->connect("resize_request",this,"_comment_node_resized",varray(E->get())); + + } + + int slot_idx=0; bool single_seq_output = node->get_output_sequence_port_count()==1 && node->get_output_sequence_port_text(0)==String(); @@ -480,6 +493,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { 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; @@ -563,6 +577,10 @@ void VisualScriptEditor::_update_graph(int p_only_id) { } graph->add_child(gnode); + + if (gnode->is_comment()) { + graph->move_child(gnode,0); + } } _update_graph_connections(); @@ -2340,6 +2358,39 @@ void VisualScriptEditor::_graph_ofs_changed(const Vector2& p_ofs) { updating_graph=false; } +void VisualScriptEditor::_comment_node_resized(const Vector2& p_new_size,int p_node) { + + if (updating_graph) + return; + + Ref<VisualScriptComment> vsc = script->get_node(edited_func,p_node); + if (vsc.is_null()) + return; + + Node *node = graph->get_node(itos(p_node)); + if (!node) + return; + GraphNode *gn = node->cast_to<GraphNode>(); + if (!gn) + return; + + updating_graph=true; + + graph->set_block_minimum_size_adjust(true); //faster resize + + undo_redo->create_action("Resize Comment",true); + undo_redo->add_do_method(vsc.ptr(),"set_size",p_new_size/EDSCALE); + undo_redo->add_undo_method(vsc.ptr(),"set_size",vsc->get_size()); + undo_redo->commit_action(); + + gn->set_custom_minimum_size(p_new_size); //for this time since graph update is blocked + gn->set_size(Size2(1,1)); + graph->set_block_minimum_size_adjust(false); + updating_graph=false; + + +} + void VisualScriptEditor::_menu_option(int p_what) { switch(p_what) { @@ -2375,7 +2426,150 @@ void VisualScriptEditor::_menu_option(int p_what) { //popup disappearing grabs focus to owner, so use call deferred node_filter->call_deferred("grab_focus"); node_filter->call_deferred("select_all"); + } break; + case EDIT_COPY_NODES: + case EDIT_CUT_NODES: { + + if (!script->has_function(edited_func)) + break; + + clipboard.nodes.clear(); + clipboard.data_connections.clear(); + clipboard.sequence_connections.clear(); + + 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()) { + + int id = String(gn->get_name()).to_int(); + Ref<VisualScriptNode> node = script->get_node(edited_func,id); + if (node->cast_to<VisualScriptFunction>()) { + EditorNode::get_singleton()->show_warning("Can't copy the function node."); + return; + } + if (node.is_valid()) { + clipboard.nodes[id]=node->duplicate(); + clipboard.nodes_positions[id]=script->get_node_pos(edited_func,id); + } + + } + } + } + + if (clipboard.nodes.empty()) + break; + + List<VisualScript::SequenceConnection> sequence_connections; + + script->get_sequence_connection_list(edited_func,&sequence_connections); + + for (List<VisualScript::SequenceConnection>::Element *E=sequence_connections.front();E;E=E->next()) { + + if (clipboard.nodes.has(E->get().from_node) && clipboard.nodes.has(E->get().to_node)) { + + clipboard.sequence_connections.insert(E->get()); + } + } + + List<VisualScript::DataConnection> data_connections; + + script->get_data_connection_list(edited_func,&data_connections); + + for (List<VisualScript::DataConnection>::Element *E=data_connections.front();E;E=E->next()) { + + if (clipboard.nodes.has(E->get().from_node) && clipboard.nodes.has(E->get().to_node)) { + + clipboard.data_connections.insert(E->get()); + } + } + + if (p_what==EDIT_CUT_NODES) { + _on_nodes_delete(); // oh yeah, also delete on cut + } + + } break; + case EDIT_PASTE_NODES: { + if (!script->has_function(edited_func)) + break; + + if (clipboard.nodes.empty()) { + EditorNode::get_singleton()->show_warning("Clipboard is empty!"); + break; + } + + Map<int,int> remap; + + undo_redo->create_action("Paste VisualScript Nodes"); + int idc=script->get_available_id()+1; + + Set<int> to_select; + + Set<Vector2> existing_positions; + + { + List<int> nodes; + script->get_node_list(edited_func,&nodes); + for (List<int>::Element *E=nodes.front();E;E=E->next()) { + Vector2 pos = script->get_node_pos(edited_func,E->get()).snapped(Vector2(2,2)); + existing_positions.insert(pos); + } + } + + for (Map<int,Ref<VisualScriptNode> >::Element *E=clipboard.nodes.front();E;E=E->next()) { + + + Ref<VisualScriptNode> node = E->get()->duplicate(); + + int new_id = idc++; + to_select.insert(new_id); + + remap[E->key()]=new_id; + + Vector2 paste_pos = clipboard.nodes_positions[E->key()]; + + while(existing_positions.has(paste_pos.snapped(Vector2(2,2)))) { + paste_pos+=Vector2(20,20)*EDSCALE; + } + + + undo_redo->add_do_method(script.ptr(),"add_node",edited_func,new_id,node,paste_pos); + undo_redo->add_undo_method(script.ptr(),"remove_node",edited_func,new_id); + + } + + for (Set<VisualScript::SequenceConnection>::Element *E=clipboard.sequence_connections.front();E;E=E->next()) { + + + undo_redo->add_do_method(script.ptr(),"sequence_connect",edited_func,remap[E->get().from_node],E->get().from_output,remap[E->get().to_node]); + undo_redo->add_undo_method(script.ptr(),"sequence_disconnect",edited_func,remap[E->get().from_node],E->get().from_output,remap[E->get().to_node]); + + } + + for (Set<VisualScript::DataConnection>::Element *E=clipboard.data_connections.front();E;E=E->next()) { + + + undo_redo->add_do_method(script.ptr(),"data_connect",edited_func,remap[E->get().from_node],E->get().from_port,remap[E->get().to_node],E->get().to_port); + undo_redo->add_undo_method(script.ptr(),"data_disconnect",edited_func,remap[E->get().from_node],E->get().from_port,remap[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(); + + 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)); + + } + } + } break; + } } @@ -2403,6 +2597,7 @@ void VisualScriptEditor::_bind_methods() { ObjectTypeDB::bind_method("_menu_option",&VisualScriptEditor::_menu_option); ObjectTypeDB::bind_method("_graph_ofs_changed",&VisualScriptEditor::_graph_ofs_changed); ObjectTypeDB::bind_method("_center_on_node",&VisualScriptEditor::_center_on_node); + ObjectTypeDB::bind_method("_comment_node_resized",&VisualScriptEditor::_comment_node_resized); @@ -2437,6 +2632,11 @@ VisualScriptEditor::VisualScriptEditor() { edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/delete_selected"), EDIT_DELETE_NODES); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/toggle_breakpoint"), EDIT_TOGGLE_BREAKPOINT); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/find_node_type"), EDIT_FIND_NODE_TYPE); + edit_menu->get_popup()->add_separator(); + edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/copy_nodes"), EDIT_COPY_NODES); + edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/cut_nodes"), EDIT_CUT_NODES); + edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/paste_nodes"), EDIT_PASTE_NODES); + edit_menu->get_popup()->connect("item_pressed",this,"_menu_option"); main_hsplit = memnew( HSplitContainer ); @@ -2619,7 +2819,10 @@ static void register_editor_callback() { ED_SHORTCUT("visual_script_editor/delete_selected", TTR("Delete Selected")); ED_SHORTCUT("visual_script_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9); - ED_SHORTCUT("visual_script_editor/find_node_type", TTR("Find Node Tyoe"), KEY_MASK_CMD+KEY_F); + ED_SHORTCUT("visual_script_editor/find_node_type", TTR("Find Node Type"), KEY_MASK_CMD+KEY_F); + ED_SHORTCUT("visual_script_editor/copy_nodes", TTR("Copy Nodes"), KEY_MASK_CMD+KEY_C); + ED_SHORTCUT("visual_script_editor/cut_nodes", TTR("Cut Nodes"), KEY_MASK_CMD+KEY_X); + ED_SHORTCUT("visual_script_editor/paste_nodes", TTR("Paste Nodes"), KEY_MASK_CMD+KEY_V); } diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 1ce7e5a6c7..d0cd09bfa9 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -27,6 +27,9 @@ class VisualScriptEditor : public ScriptEditorBase { EDIT_DELETE_NODES, EDIT_TOGGLE_BREAKPOINT, EDIT_FIND_NODE_TYPE, + EDIT_COPY_NODES, + EDIT_CUT_NODES, + EDIT_PASTE_NODES, }; MenuButton *edit_menu; @@ -98,6 +101,15 @@ class VisualScriptEditor : public ScriptEditorBase { String _validate_name(const String& p_name) const; + struct Clipboard { + + Map<int,Ref<VisualScriptNode> > nodes; + Map<int,Vector2 > nodes_positions; + + Set<VisualScript::SequenceConnection> sequence_connections; + Set<VisualScript::DataConnection> data_connections; + } clipboard; + int error_line; @@ -149,6 +161,7 @@ class VisualScriptEditor : public ScriptEditorBase { void _menu_option(int p_what); void _graph_ofs_changed(const Vector2& p_ofs); + void _comment_node_resized(const Vector2& p_new_size,int p_node); protected: @@ -179,6 +192,7 @@ public: virtual void set_debugger_active(bool p_active); virtual void set_tooltip_request_func(String p_method,Object* p_obj); virtual Control *get_edit_menu(); + virtual bool can_lose_focus_on_node_selection() { return false; } static void register_editor(); diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index cb0ff4086c..78b3f76590 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -2,6 +2,7 @@ #include "os/keyboard.h" #include "globals.h" + ////////////////////////////////////////// ////////////////RETURN//////////////////// ////////////////////////////////////////// @@ -1660,6 +1661,197 @@ VisualScriptInputFilter::VisualScriptInputFilter() { } +////////////////////////////////////////// +////////////////EVENT TYPE FILTER/////////// +////////////////////////////////////////// + + +int VisualScriptTypeCast::get_output_sequence_port_count() const { + + return 2; +} + +bool VisualScriptTypeCast::has_input_sequence_port() const{ + + return true; +} + +int VisualScriptTypeCast::get_input_value_port_count() const{ + + + return 1; +} +int VisualScriptTypeCast::get_output_value_port_count() const{ + + return 1; +} + +String VisualScriptTypeCast::get_output_sequence_port_text(int p_port) const { + + return p_port==0 ? "yes" : "no"; +} + +PropertyInfo VisualScriptTypeCast::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(Variant::OBJECT,"instance"); +} + +PropertyInfo VisualScriptTypeCast::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(Variant::OBJECT,""); +} + + +String VisualScriptTypeCast::get_caption() const { + + return "TypeCast"; +} + +String VisualScriptTypeCast::get_text() const { + + if (script!=String()) + return "Is "+script.get_file()+"?"; + else + return "Is "+base_type+"?"; +} + +void VisualScriptTypeCast::set_base_type(const StringName& p_type) { + + if (base_type==p_type) + return; + + base_type=p_type; + _change_notify(); + ports_changed_notify(); +} + +StringName VisualScriptTypeCast::get_base_type() const{ + + return base_type; +} + +void VisualScriptTypeCast::set_base_script(const String& p_path){ + + if (script==p_path) + return; + + script=p_path; + _change_notify(); + ports_changed_notify(); + +} +String VisualScriptTypeCast::get_base_script() const{ + + return script; +} + + +class VisualScriptNodeInstanceTypeCast : public VisualScriptNodeInstance { +public: + + VisualScriptInstance* instance; + StringName base_type; + String script; + + //virtual int get_working_memory_size() const { return 0; } + //virtual bool is_output_port_unsequenced(int p_idx) const { return false; } + //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; } + + virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) { + + Object *obj = *p_inputs[0]; + + *p_outputs[0]=Variant(); + + if (!obj) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str="Instance is null"; + return 0; + } + + if (script!=String()) { + + Ref<Script> obj_script = obj->get_script(); + if (!obj_script.is_valid()) { + return 1; //well, definitely not the script because object we got has no script. + } + + if (!ResourceCache::has(script)) { + //if the script is not in use by anyone, we can safely assume whathever we got is not casting to it. + return 1; + } + Ref<Script> cast_script = Ref<Resource>(ResourceCache::get(script)); + if (!cast_script.is_valid()) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + r_error_str="Script path is not a script: "+script; + return 1; + } + + while(obj_script.is_valid()) { + + if (cast_script==obj_script) { + *p_outputs[0]=*p_inputs[0]; //copy + return 0; // it is the script, yey + } + + obj_script=obj_script->get_base_script(); + } + + return 1; //not found sorry + } + + if (ObjectTypeDB::is_type(obj->get_type_name(),base_type)) { + *p_outputs[0]=*p_inputs[0]; //copy + return 0; + } else + return 1; + + } + + +}; + +VisualScriptNodeInstance* VisualScriptTypeCast::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceTypeCast * instance = memnew(VisualScriptNodeInstanceTypeCast ); + instance->instance=p_instance; + instance->base_type=base_type; + instance->script=script; + return instance; +} + + + +void VisualScriptTypeCast::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_base_type","type"),&VisualScriptTypeCast::set_base_type); + ObjectTypeDB::bind_method(_MD("get_base_type"),&VisualScriptTypeCast::get_base_type); + + ObjectTypeDB::bind_method(_MD("set_base_script","path"),&VisualScriptTypeCast::set_base_script); + ObjectTypeDB::bind_method(_MD("get_base_script"),&VisualScriptTypeCast::get_base_script); + + + List<String> script_extensions; + for(int i=0;i>ScriptServer::get_language_count();i++) { + ScriptServer::get_language(i)->get_recognized_extensions(&script_extensions); + } + + String script_ext_hint; + for (List<String>::Element *E=script_extensions.front();E;E=E->next()) { + if (script_ext_hint!=String()) + script_ext_hint+=","; + script_ext_hint+="*."+E->get(); + } + + 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::STRING,"property/base_script",PROPERTY_HINT_FILE,script_ext_hint),_SCS("set_base_script"),_SCS("get_base_script")); + +} + +VisualScriptTypeCast::VisualScriptTypeCast() { + + base_type="Object"; +} void register_visual_script_flow_control_nodes() { @@ -1672,6 +1864,7 @@ void register_visual_script_flow_control_nodes() { VisualScriptLanguage::singleton->add_register_func("flow_control/sequence",create_node_generic<VisualScriptSequence>); VisualScriptLanguage::singleton->add_register_func("flow_control/input_select",create_node_generic<VisualScriptInputSelector>); VisualScriptLanguage::singleton->add_register_func("flow_control/input_filter",create_node_generic<VisualScriptInputFilter>); + VisualScriptLanguage::singleton->add_register_func("flow_control/type_cast",create_node_generic<VisualScriptTypeCast>); diff --git a/modules/visual_script/visual_script_flow_control.h b/modules/visual_script/visual_script_flow_control.h index ed0e328629..879d3ceab1 100644 --- a/modules/visual_script/visual_script_flow_control.h +++ b/modules/visual_script/visual_script_flow_control.h @@ -273,6 +273,53 @@ public: VisualScriptInputFilter(); }; + + + + +class VisualScriptTypeCast : public VisualScriptNode { + + OBJ_TYPE(VisualScriptTypeCast,VisualScriptNode) + + + StringName base_type; + String script; + +protected: + + static void _bind_methods(); +public: + + virtual int get_output_sequence_port_count() const; + virtual bool has_input_sequence_port() const; + + + virtual String get_output_sequence_port_text(int p_port) const; + + + virtual int get_input_value_port_count() const; + virtual int get_output_value_port_count() const; + + + virtual PropertyInfo get_input_value_port_info(int p_idx) const; + virtual PropertyInfo get_output_value_port_info(int p_idx) const; + + virtual String get_caption() const; + virtual String get_text() const; + virtual String get_category() const { return "flow_control"; } + + void set_base_type(const StringName& p_type); + StringName get_base_type() const; + + void set_base_script(const String& p_path); + String get_base_script() const; + + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + + + VisualScriptTypeCast(); +}; + void register_visual_script_flow_control_nodes(); diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 12bc395474..7cd91c7d50 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -3,6 +3,7 @@ #include "os/os.h" #include "scene/main/node.h" #include "visual_script_nodes.h" +#include "io/resource_loader.h" ////////////////////////////////////////// ////////////////CALL////////////////////// @@ -91,20 +92,23 @@ StringName VisualScriptFunctionCall::_get_base_type() const { return base_type; } + int VisualScriptFunctionCall::get_input_value_port_count() const{ if (call_mode==CALL_MODE_BASIC_TYPE) { Vector<StringName> names = Variant::get_method_argument_names(basic_type,function); - return names.size()+1; + return names.size() + (rpc_call_mode>=RPC_RELIABLE_TO_ID?1:0) + 1; } else { + MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); - if (!mb) - return 0; + if (mb) { + return mb->get_argument_count() + (call_mode==CALL_MODE_INSTANCE?1:0) + (rpc_call_mode>=RPC_RELIABLE_TO_ID?1:0) - use_default_args; + } - return mb->get_argument_count() + (call_mode==CALL_MODE_INSTANCE?1:0) - use_default_args; + return method_cache.arguments.size() + (call_mode==CALL_MODE_INSTANCE?1:0) + (rpc_call_mode>=RPC_RELIABLE_TO_ID?1:0) - use_default_args; } } @@ -118,10 +122,11 @@ int VisualScriptFunctionCall::get_output_value_port_count() const{ } else { MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); - if (!mb) - return 0; + if (mb) { + return mb->has_return() ? 1 : 0; + } - return mb->has_return() ? 1 : 0; + return 1; //it is assumed that script always returns something } } @@ -143,6 +148,16 @@ PropertyInfo VisualScriptFunctionCall::get_input_value_port_info(int p_idx) cons } } + if (rpc_call_mode>=RPC_RELIABLE_TO_ID) { + + if (p_idx==0) { + return PropertyInfo(Variant::INT,"peer_id"); + } else { + p_idx--; + } + + } + #ifdef DEBUG_METHODS_ENABLED if (call_mode==CALL_MODE_BASIC_TYPE) { @@ -155,10 +170,15 @@ PropertyInfo VisualScriptFunctionCall::get_input_value_port_info(int p_idx) cons } else { MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); - if (!mb) - return PropertyInfo(); + if (mb) { + return mb->get_argument_info(p_idx); + } + + if (p_idx>=0 && p_idx < method_cache.arguments.size()) { + return method_cache.arguments[p_idx]; + } - return mb->get_argument_info(p_idx); + return PropertyInfo(); } #else return PropertyInfo(); @@ -178,12 +198,14 @@ PropertyInfo VisualScriptFunctionCall::get_output_value_port_info(int p_idx) con } else { MethodBind *mb = ObjectTypeDB::get_method(_get_base_type(),function); - if (!mb) - return PropertyInfo(); + if (mb) { + + PropertyInfo pi = mb->get_argument_info(-1); + pi.name=""; + return pi; + } - PropertyInfo pi = mb->get_argument_info(-1); - pi.name=""; - return pi; + return method_cache.return_val; } #else return PropertyInfo(); @@ -200,7 +222,13 @@ String VisualScriptFunctionCall::get_caption() const { "CallBasic" }; - return cname[call_mode]; + String caption = cname[call_mode]; + + if (rpc_call_mode) { + caption+=" (RPC)"; + } + + return caption; } String VisualScriptFunctionCall::get_text() const { @@ -214,38 +242,6 @@ String VisualScriptFunctionCall::get_text() const { } -void VisualScriptFunctionCall::_update_defargs() { - - //save base type if accessible - - if (call_mode==CALL_MODE_NODE_PATH) { - - Node* node=_get_base_node(); - if (node) { - base_type=node->get_type(); - } - } else if (call_mode==CALL_MODE_SELF) { - - if (get_visual_script().is_valid()) { - base_type=get_visual_script()->get_instance_base_type(); - } - } - - - if (call_mode==CALL_MODE_BASIC_TYPE) { - use_default_args = Variant::get_method_default_arguments(basic_type,function).size(); - } else { - 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_basic_type(Variant::Type p_type) { @@ -253,7 +249,7 @@ void VisualScriptFunctionCall::set_basic_type(Variant::Type p_type) { return; basic_type=p_type; - _update_defargs(); + _change_notify(); ports_changed_notify(); } @@ -269,7 +265,6 @@ void VisualScriptFunctionCall::set_base_type(const StringName& p_type) { return; base_type=p_type; - _update_defargs(); _change_notify(); ports_changed_notify(); } @@ -279,13 +274,102 @@ StringName VisualScriptFunctionCall::get_base_type() const{ return base_type; } +void VisualScriptFunctionCall::set_base_script(const String& p_path) { + + if (base_script==p_path) + return; + + base_script=p_path; + _change_notify(); + ports_changed_notify(); +} + +String VisualScriptFunctionCall::get_base_script() const { + + return base_script; +} + + +void VisualScriptFunctionCall::_update_method_cache() { + StringName type; + Ref<Script> script; + + if (call_mode==CALL_MODE_NODE_PATH) { + + Node* node=_get_base_node(); + if (node) { + type=node->get_type(); + base_type=type; //cache, too + script = node->get_script(); + } + } else if (call_mode==CALL_MODE_SELF) { + + if (get_visual_script().is_valid()) { + type=get_visual_script()->get_instance_base_type(); + base_type=type; //cache, too + script=get_visual_script(); + } + } else if (call_mode==CALL_MODE_INSTANCE) { + + type=base_type; + if (base_script!=String()) { + + if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) { + + ScriptServer::edit_request_func(base_script); //make sure it's loaded + } + + if (ResourceCache::has(base_script)) { + + script = Ref<Resource>( ResourceCache::get(base_script) ); + } else { + return; + } + } + } + + +// print_line("BASE: "+String(type)+" FUNC: "+String(function)); + MethodBind *mb = ObjectTypeDB::get_method(type,function); + if (mb) { + use_default_args=mb->get_default_argument_count(); + method_cache = MethodInfo(); + for(int i=0;i<mb->get_argument_count();i++) { +#ifdef DEBUG_METHODS_ENABLED + method_cache.arguments.push_back(mb->get_argument_info(i)); +#else + method_cache.arguments.push_back(PropertyInfo()); +#endif + } + +#ifdef DEBUG_METHODS_ENABLED + + method_cache.return_val = mb->get_argument_info(-1); +#endif + } else if (script.is_valid() && script->has_method(function)) { + + method_cache = script->get_method_info(function); + use_default_args=method_cache.default_arguments.size(); + } +} + void VisualScriptFunctionCall::set_function(const StringName& p_type){ if (function==p_type) return; function=p_type; - _update_defargs(); + + if (call_mode==CALL_MODE_BASIC_TYPE) { + use_default_args = Variant::get_method_default_arguments(basic_type,function).size(); + } else { + //update all caches + + _update_method_cache(); + + } + + _change_notify(); ports_changed_notify(); } @@ -301,7 +385,6 @@ void VisualScriptFunctionCall::set_base_path(const NodePath& p_type) { return; base_path=p_type; - _update_defargs(); _change_notify(); ports_changed_notify(); } @@ -318,7 +401,6 @@ void VisualScriptFunctionCall::set_call_mode(CallMode p_mode) { return; call_mode=p_mode; - _update_defargs(); _change_notify(); ports_changed_notify(); @@ -339,10 +421,40 @@ void VisualScriptFunctionCall::set_use_default_args(int p_amount) { } +void VisualScriptFunctionCall::set_rpc_call_mode(VisualScriptFunctionCall::RPCCallMode p_mode) { + + if (rpc_call_mode==p_mode) + return; + rpc_call_mode=p_mode; + ports_changed_notify(); + _change_notify(); +} + +VisualScriptFunctionCall::RPCCallMode VisualScriptFunctionCall::get_rpc_call_mode() const{ + + return rpc_call_mode; +} + + int VisualScriptFunctionCall::get_use_default_args() const{ return use_default_args; } + + + + +void VisualScriptFunctionCall::_set_argument_cache(const Dictionary& p_cache) { + //so everything works in case all else fails + method_cache=MethodInfo::from_dict(p_cache); + +} + +Dictionary VisualScriptFunctionCall::_get_argument_cache() const { + + return method_cache; +} + void VisualScriptFunctionCall::_validate_property(PropertyInfo& property) const { if (property.name=="function/base_type") { @@ -351,6 +463,12 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo& property) const } } + if (property.name=="function/base_script") { + if (call_mode!=CALL_MODE_INSTANCE) { + property.usage=0; + } + } + if (property.name=="function/basic_type") { if (call_mode!=CALL_MODE_BASIC_TYPE) { property.usage=0; @@ -384,6 +502,24 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo& property) const } else if (call_mode==CALL_MODE_INSTANCE) { property.hint=PROPERTY_HINT_METHOD_OF_BASE_TYPE; property.hint_string=base_type; + + if (base_script!=String()) { + if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) { + + ScriptServer::edit_request_func(base_script); //make sure it's loaded + } + + if (ResourceCache::has(base_script)) { + + Ref<Script> script = Ref<Resource>( ResourceCache::get(base_script) ); + if (script.is_valid()) { + + property.hint=PROPERTY_HINT_METHOD_OF_SCRIPT; + property.hint_string=itos(script->get_instance_ID()); + } + } + } + } else if (call_mode==CALL_MODE_NODE_PATH) { Node *node = _get_base_node(); if (node) { @@ -422,6 +558,13 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo& property) const property.hint_string="0,"+itos(mc)+",1"; } } + + if (property.name=="rpc/call_mode") { + if (call_mode==CALL_MODE_BASIC_TYPE) { + property.usage=0; + } + } + } @@ -430,6 +573,9 @@ 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_base_script","base_script"),&VisualScriptFunctionCall::set_base_script); + ObjectTypeDB::bind_method(_MD("get_base_script"),&VisualScriptFunctionCall::get_base_script); + ObjectTypeDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptFunctionCall::set_basic_type); ObjectTypeDB::bind_method(_MD("get_basic_type"),&VisualScriptFunctionCall::get_basic_type); @@ -445,6 +591,11 @@ void VisualScriptFunctionCall::_bind_methods() { 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); + ObjectTypeDB::bind_method(_MD("_set_argument_cache","argument_cache"),&VisualScriptFunctionCall::_set_argument_cache); + ObjectTypeDB::bind_method(_MD("_get_argument_cache"),&VisualScriptFunctionCall::_get_argument_cache); + + ObjectTypeDB::bind_method(_MD("set_rpc_call_mode","mode"),&VisualScriptFunctionCall::set_rpc_call_mode); + ObjectTypeDB::bind_method(_MD("get_rpc_call_mode"),&VisualScriptFunctionCall::get_rpc_call_mode); String bt; for(int i=0;i<Variant::VARIANT_MAX;i++) { @@ -454,12 +605,28 @@ void VisualScriptFunctionCall::_bind_methods() { bt+=Variant::get_type_name(Variant::Type(i)); } + + List<String> script_extensions; + for(int i=0;i<ScriptServer::get_language_count();i++) { + ScriptServer::get_language(i)->get_recognized_extensions(&script_extensions); + } + + String script_ext_hint; + for (List<String>::Element *E=script_extensions.front();E;E=E->next()) { + if (script_ext_hint!=String()) + script_ext_hint+=","; + script_ext_hint+="*."+E->get(); + } + ADD_PROPERTY(PropertyInfo(Variant::INT,"function/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type"),_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::STRING,"function/base_script",PROPERTY_HINT_FILE,script_ext_hint),_SCS("set_base_script"),_SCS("get_base_script")); ADD_PROPERTY(PropertyInfo(Variant::INT,"function/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_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::DICTIONARY,"function/argument_cache",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_argument_cache"),_SCS("_get_argument_cache")); + ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/function"),_SCS("set_function"),_SCS("get_function")); //when set, if loaded properly, will override argument count. ADD_PROPERTY(PropertyInfo(Variant::INT,"function/use_default_args"),_SCS("set_use_default_args"),_SCS("get_use_default_args")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"rpc/call_mode",PROPERTY_HINT_ENUM,"Disabled,Reliable,Unreliable,ReliableToID,UnreliableToID"),_SCS("set_rpc_call_mode"),_SCS("get_rpc_call_mode")); //when set, if loaded properly, will override argument count. BIND_CONSTANT( CALL_MODE_SELF ); BIND_CONSTANT( CALL_MODE_NODE_PATH); @@ -475,6 +642,7 @@ public: NodePath node_path; int input_args; bool returns; + VisualScriptFunctionCall::RPCCallMode rpc_mode; StringName function; VisualScriptFunctionCall *node; @@ -486,6 +654,35 @@ public: //virtual bool is_output_port_unsequenced(int p_idx) const { return false; } //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } + + _FORCE_INLINE_ bool call_rpc(Object* p_base,const Variant** p_args,int p_argcount) { + + if (!p_base) + return false; + + Node * node = p_base->cast_to<Node>(); + if (!node) + return false; + + int to_id=0; + bool reliable=true; + + if (rpc_mode>=VisualScriptFunctionCall::RPC_RELIABLE_TO_ID) { + to_id = *p_args[0]; + p_args+=1; + p_argcount-=1; + if (rpc_mode==VisualScriptFunctionCall::RPC_UNRELIABLE_TO_ID) { + reliable=false; + } + } else if (rpc_mode==VisualScriptFunctionCall::RPC_UNRELIABLE) { + reliable=false; + } + + node->rpcp(to_id,!reliable,function,p_args,p_argcount); + + return true; + } + virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) { @@ -495,7 +692,9 @@ public: Object *object=instance->get_owner_ptr(); - if (returns) { + if (rpc_mode) { + call_rpc(object,p_inputs,input_args); + } else if (returns) { *p_outputs[0] = object->call(function,p_inputs,input_args,r_error); } else { object->call(function,p_inputs,input_args,r_error); @@ -517,7 +716,9 @@ public: return 0; } - if (returns) { + if (rpc_mode) { + call_rpc(node,p_inputs,input_args); + } else if (returns) { *p_outputs[0] = another->call(function,p_inputs,input_args,r_error); } else { another->call(function,p_inputs,input_args,r_error); @@ -529,7 +730,12 @@ public: Variant v = *p_inputs[0]; - if (returns) { + if (rpc_mode) { + Object *obj = v; + if (obj) { + call_rpc(obj,p_inputs+1,input_args-1); + } + } else if (returns) { *p_outputs[0] = v.call(function,p_inputs+1,input_args,r_error); } else { v.call(function,p_inputs+1,input_args,r_error); @@ -555,6 +761,7 @@ VisualScriptNodeInstance* VisualScriptFunctionCall::instance(VisualScriptInstanc instance->returns=get_output_value_port_count(); instance->node_path=base_path; instance->input_args = get_input_value_port_count() - ( (call_mode==CALL_MODE_BASIC_TYPE || call_mode==CALL_MODE_INSTANCE) ? 1: 0 ); + instance->rpc_mode=rpc_call_mode; return instance; } VisualScriptFunctionCall::VisualScriptFunctionCall() { @@ -563,6 +770,8 @@ VisualScriptFunctionCall::VisualScriptFunctionCall() { basic_type=Variant::NIL; use_default_args=0; base_type="Object"; + rpc_call_mode=RPC_DISABLED; + } @@ -687,55 +896,9 @@ PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const } } -#ifdef DEBUG_METHODS_ENABLED - - //not very efficient but.. - - - List<PropertyInfo> pinfo; - - if (call_mode==CALL_MODE_BASIC_TYPE) { - - - Variant v; - if (basic_type==Variant::INPUT_EVENT) { - InputEvent ev; - ev.type=event_type; - v=ev; - } else { - Variant::CallError ce; - v = Variant::construct(basic_type,NULL,0,ce); - } - v.get_property_list(&pinfo); - - } else if (call_mode==CALL_MODE_NODE_PATH) { - - Node *n = _get_base_node(); - 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 pinfo=type_cache; + pinfo.name="value"; + return pinfo; } PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) const{ @@ -821,6 +984,9 @@ void VisualScriptPropertySet::set_event_type(InputEvent::Type p_type) { if (event_type==p_type) return; event_type=p_type; + if (call_mode==CALL_MODE_BASIC_TYPE) { + _update_cache(); + } _change_notify(); _update_base_type(); ports_changed_notify(); @@ -847,12 +1013,133 @@ StringName VisualScriptPropertySet::get_base_type() const{ return base_type; } + +void VisualScriptPropertySet::set_base_script(const String& p_path) { + + if (base_script==p_path) + return; + + base_script=p_path; + _change_notify(); + ports_changed_notify(); +} + +String VisualScriptPropertySet::get_base_script() const { + + return base_script; +} + + +void VisualScriptPropertySet::_update_cache() { + + + if (!OS::get_singleton()->get_main_loop()) + return; + if (!OS::get_singleton()->get_main_loop()->cast_to<SceneTree>()) + return; + + if (!OS::get_singleton()->get_main_loop()->cast_to<SceneTree>()->is_editor_hint()) //only update cache if editor exists, it's pointless otherwise + return; + + if (call_mode==CALL_MODE_BASIC_TYPE) { + + //not super efficient.. + + Variant v; + if (basic_type==Variant::INPUT_EVENT) { + InputEvent ev; + ev.type=event_type; + v=ev; + } else { + Variant::CallError ce; + v = Variant::construct(basic_type,NULL,0,ce); + } + + List<PropertyInfo> pinfo; + v.get_property_list(&pinfo); + + for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) { + + if (E->get().name==property) { + + type_cache=E->get(); + } + } + + } else { + + + StringName type; + Ref<Script> script; + Node *node=NULL; + + if (call_mode==CALL_MODE_NODE_PATH) { + + node=_get_base_node(); + if (node) { + type=node->get_type(); + base_type=type; //cache, too + script = node->get_script(); + } + } else if (call_mode==CALL_MODE_SELF) { + + if (get_visual_script().is_valid()) { + type=get_visual_script()->get_instance_base_type(); + base_type=type; //cache, too + script=get_visual_script(); + } + } else if (call_mode==CALL_MODE_INSTANCE) { + + type=base_type; + if (base_script!=String()) { + + if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) { + + ScriptServer::edit_request_func(base_script); //make sure it's loaded + } + + if (ResourceCache::has(base_script)) { + + script = Ref<Resource>( ResourceCache::get(base_script) ); + } else { + return; + } + } + } + + List<PropertyInfo> pinfo; + + + if (node) { + + node->get_property_list(&pinfo); + } else { + ObjectTypeDB::get_property_list(type,&pinfo); + } + + if (script.is_valid()) { + + script->get_script_property_list(&pinfo); + } + + for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) { + + if (E->get().name==property) { + type_cache=E->get(); + return; + } + } + + } +} + void VisualScriptPropertySet::set_property(const StringName& p_type){ if (property==p_type) return; property=p_type; + _update_cache(); _change_notify(); ports_changed_notify(); } @@ -918,12 +1205,24 @@ void VisualScriptPropertySet::set_builtin_value(const Variant& p_value){ return; builtin_value=p_value; + ports_changed_notify(); } Variant VisualScriptPropertySet::get_builtin_value() const{ return builtin_value; } + + +void VisualScriptPropertySet::_set_type_cache(const Dictionary &p_type) { + type_cache=PropertyInfo::from_dict(p_type); +} + +Dictionary VisualScriptPropertySet::_get_type_cache() const { + + return type_cache; +} + void VisualScriptPropertySet::_validate_property(PropertyInfo& property) const { if (property.name=="property/base_type") { @@ -932,6 +1231,11 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo& property) const { } } + if (property.name=="property/base_script") { + if (call_mode!=CALL_MODE_INSTANCE) { + property.usage=0; + } + } if (property.name=="property/basic_type") { if (call_mode!=CALL_MODE_BASIC_TYPE) { @@ -972,6 +1276,24 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo& property) const { } else if (call_mode==CALL_MODE_INSTANCE) { property.hint=PROPERTY_HINT_PROPERTY_OF_BASE_TYPE; property.hint_string=base_type; + + if (base_script!=String()) { + if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) { + + ScriptServer::edit_request_func(base_script); //make sure it's loaded + } + + if (ResourceCache::has(base_script)) { + + Ref<Script> script = Ref<Resource>( ResourceCache::get(base_script) ); + if (script.is_valid()) { + + property.hint=PROPERTY_HINT_PROPERTY_OF_SCRIPT; + property.hint_string=itos(script->get_instance_ID()); + } + } + } + } else if (call_mode==CALL_MODE_NODE_PATH) { Node *node = _get_base_node(); if (node) { @@ -991,34 +1313,9 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo& property) const { if (!use_builtin_value) { property.usage=0; } else { - List<PropertyInfo> pinfo; - - if (call_mode==CALL_MODE_BASIC_TYPE) { - Variant::CallError ce; - Variant v = Variant::construct(basic_type,NULL,0,ce); - v.get_property_list(&pinfo); - - } else if (call_mode==CALL_MODE_NODE_PATH) { - - Node *n = _get_base_node(); - 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; - } - } + property.type=type_cache.type; + property.hint=type_cache.hint; + property.hint_string=type_cache.hint_string; } } @@ -1029,10 +1326,15 @@ 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_base_script","base_script"),&VisualScriptPropertySet::set_base_script); + ObjectTypeDB::bind_method(_MD("get_base_script"),&VisualScriptPropertySet::get_base_script); ObjectTypeDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptPropertySet::set_basic_type); ObjectTypeDB::bind_method(_MD("get_basic_type"),&VisualScriptPropertySet::get_basic_type); + ObjectTypeDB::bind_method(_MD("_set_type_cache","type_cache"),&VisualScriptPropertySet::_set_type_cache); + ObjectTypeDB::bind_method(_MD("_get_type_cache"),&VisualScriptPropertySet::_get_type_cache); + ObjectTypeDB::bind_method(_MD("set_event_type","event_type"),&VisualScriptPropertySet::set_event_type); ObjectTypeDB::bind_method(_MD("get_event_type"),&VisualScriptPropertySet::get_event_type); @@ -1067,9 +1369,22 @@ void VisualScriptPropertySet::_bind_methods() { et+=event_type_names[i]; } + List<String> script_extensions; + for(int i=0;i<ScriptServer::get_language_count();i++) { + ScriptServer::get_language(i)->get_recognized_extensions(&script_extensions); + } + + String script_ext_hint; + for (List<String>::Element *E=script_extensions.front();E;E=E->next()) { + if (script_ext_hint!=String()) + script_ext_hint+=","; + script_ext_hint+="*."+E->get(); + } ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type"),_SCS("set_call_mode"),_SCS("get_call_mode")); ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type")); + ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_script",PROPERTY_HINT_FILE,script_ext_hint),_SCS("set_base_script"),_SCS("get_base_script")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"property/type_cache",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_type_cache"),_SCS("_get_type_cache")); ADD_PROPERTY(PropertyInfo(Variant::INT,"property/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_type")); ADD_PROPERTY(PropertyInfo(Variant::INT,"property/event_type",PROPERTY_HINT_ENUM,et),_SCS("set_event_type"),_SCS("get_event_type")); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path")); @@ -1299,6 +1614,7 @@ StringName VisualScriptPropertyGet::_get_base_type() const { return base_type; } + int VisualScriptPropertyGet::get_input_value_port_count() const{ return (call_mode==CALL_MODE_BASIC_TYPE || call_mode==CALL_MODE_INSTANCE)?1:0; @@ -1332,17 +1648,69 @@ PropertyInfo VisualScriptPropertyGet::get_input_value_port_info(int p_idx) const PropertyInfo VisualScriptPropertyGet::get_output_value_port_info(int p_idx) const{ + return PropertyInfo(type_cache,"value"); +} -#ifdef DEBUG_METHODS_ENABLED +String VisualScriptPropertyGet::get_caption() const { + + static const char*cname[4]= { + "SelfGet", + "NodeGet", + "InstanceGet", + "BasicGet" + }; - //not very efficient but.. + return cname[call_mode]; +} +String VisualScriptPropertyGet::get_text() const { + + + if (call_mode==CALL_MODE_BASIC_TYPE) + return Variant::get_type_name(basic_type)+"."+property; + else + return property; + +} + +void VisualScriptPropertyGet::set_base_type(const StringName& p_type) { + + if (base_type==p_type) + return; + + base_type=p_type; + _change_notify(); + ports_changed_notify(); +} + +StringName VisualScriptPropertyGet::get_base_type() const{ + + return base_type; +} + +void VisualScriptPropertyGet::set_base_script(const String& p_path) { + + if (base_script==p_path) + return; + + base_script=p_path; + _change_notify(); + ports_changed_notify(); +} + +String VisualScriptPropertyGet::get_base_script() const { + + return base_script; +} + + +void VisualScriptPropertyGet::_update_cache() { - List<PropertyInfo> pinfo; if (call_mode==CALL_MODE_BASIC_TYPE) { + //not super efficient.. Variant v; if (basic_type==Variant::INPUT_EVENT) { @@ -1353,71 +1721,91 @@ PropertyInfo VisualScriptPropertyGet::get_output_value_port_info(int p_idx) cons Variant::CallError ce; v = Variant::construct(basic_type,NULL,0,ce); } + + List<PropertyInfo> pinfo; v.get_property_list(&pinfo); - } else 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); + for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) { + + if (E->get().name==property) { + + type_cache=E->get().type; + return; + } } + } 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) { + StringName type; + Ref<Script> script; + Node *node=NULL; - PropertyInfo info=E->get(); - info.name=""; - return info; - } - } + if (call_mode==CALL_MODE_NODE_PATH) { + node=_get_base_node(); + if (node) { + type=node->get_type(); + base_type=type; //cache, too + script = node->get_script(); + } + } else if (call_mode==CALL_MODE_SELF) { -#endif + if (get_visual_script().is_valid()) { + type=get_visual_script()->get_instance_base_type(); + base_type=type; //cache, too + script=get_visual_script(); + } + } else if (call_mode==CALL_MODE_INSTANCE) { - return PropertyInfo(Variant::NIL,""); -} + type=base_type; + if (base_script!=String()) { + if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) { -String VisualScriptPropertyGet::get_caption() const { + ScriptServer::edit_request_func(base_script); //make sure it's loaded + } - static const char*cname[4]= { - "SelfGet", - "NodeGet", - "InstanceGet", - "BasicGet" - }; + if (ResourceCache::has(base_script)) { - return cname[call_mode]; -} + script = Ref<Resource>( ResourceCache::get(base_script) ); + } else { + return; + } + } + } -String VisualScriptPropertyGet::get_text() const { + bool valid=false; - if (call_mode==CALL_MODE_BASIC_TYPE) - return Variant::get_type_name(basic_type)+"."+property; - else - return property; + Variant::Type type_ret; -} + type_ret=ObjectTypeDB::get_property_type(base_type,property,&valid); -void VisualScriptPropertyGet::set_base_type(const StringName& p_type) { + if (valid) { + type_cache=type_ret; + return; //all dandy + } - if (base_type==p_type) - return; + if (node) { - base_type=p_type; - _change_notify(); - ports_changed_notify(); -} + Variant prop = node->get(property,&valid); + if (valid) { + type_cache=prop.get_type(); + return; //all dandy again + } + } -StringName VisualScriptPropertyGet::get_base_type() const{ + if (script.is_valid()) { - return base_type; + type_ret=script->get_static_property_type(property,&valid); + + if (valid) { + type_cache=type_ret; + return; //all dandy + } + } + } } void VisualScriptPropertyGet::set_property(const StringName& p_type){ @@ -1426,6 +1814,9 @@ void VisualScriptPropertyGet::set_property(const StringName& p_type){ return; property=p_type; + + + _update_cache(); _change_notify(); ports_changed_notify(); } @@ -1492,6 +1883,9 @@ void VisualScriptPropertyGet::set_event_type(InputEvent::Type p_type) { if (event_type==p_type) return; event_type=p_type; + if(call_mode==CALL_MODE_BASIC_TYPE) { + _update_cache(); + } _change_notify(); _update_base_type(); ports_changed_notify(); @@ -1502,6 +1896,17 @@ InputEvent::Type VisualScriptPropertyGet::get_event_type() const{ return event_type; } + +void VisualScriptPropertyGet::_set_type_cache(Variant::Type p_type) { + type_cache=p_type; +} + +Variant::Type VisualScriptPropertyGet::_get_type_cache() const { + + return type_cache; +} + + void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const { if (property.name=="property/base_type") { @@ -1510,6 +1915,11 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const { } } + if (property.name=="property/base_script") { + if (call_mode!=CALL_MODE_INSTANCE) { + property.usage=0; + } + } if (property.name=="property/basic_type") { if (call_mode!=CALL_MODE_BASIC_TYPE) { @@ -1549,6 +1959,23 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const { } else if (call_mode==CALL_MODE_INSTANCE) { property.hint=PROPERTY_HINT_PROPERTY_OF_BASE_TYPE; property.hint_string=base_type; + + if (base_script!=String()) { + if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) { + + ScriptServer::edit_request_func(base_script); //make sure it's loaded + } + + if (ResourceCache::has(base_script)) { + + Ref<Script> script = Ref<Resource>( ResourceCache::get(base_script) ); + if (script.is_valid()) { + + property.hint=PROPERTY_HINT_PROPERTY_OF_SCRIPT; + property.hint_string=itos(script->get_instance_ID()); + } + } + } } else if (call_mode==CALL_MODE_NODE_PATH) { Node *node = _get_base_node(); if (node) { @@ -1570,10 +1997,15 @@ 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_base_script","base_script"),&VisualScriptPropertyGet::set_base_script); + ObjectTypeDB::bind_method(_MD("get_base_script"),&VisualScriptPropertyGet::get_base_script); ObjectTypeDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptPropertyGet::set_basic_type); ObjectTypeDB::bind_method(_MD("get_basic_type"),&VisualScriptPropertyGet::get_basic_type); + ObjectTypeDB::bind_method(_MD("_set_type_cache","type_cache"),&VisualScriptPropertyGet::_set_type_cache); + ObjectTypeDB::bind_method(_MD("_get_type_cache"),&VisualScriptPropertyGet::_get_type_cache); + ObjectTypeDB::bind_method(_MD("set_event_type","event_type"),&VisualScriptPropertyGet::set_event_type); ObjectTypeDB::bind_method(_MD("get_event_type"),&VisualScriptPropertyGet::get_event_type); @@ -1603,9 +2035,22 @@ void VisualScriptPropertyGet::_bind_methods() { et+=event_type_names[i]; } + List<String> script_extensions; + for(int i=0;i<ScriptServer::get_language_count();i++) { + ScriptServer::get_language(i)->get_recognized_extensions(&script_extensions); + } + + String script_ext_hint; + for (List<String>::Element *E=script_extensions.front();E;E=E->next()) { + if (script_ext_hint!=String()) + script_ext_hint+=","; + script_ext_hint+="."+E->get(); + } - 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::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type"),_SCS("set_call_mode"),_SCS("get_call_mode")); ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type")); + ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_script",PROPERTY_HINT_FILE,script_ext_hint),_SCS("set_base_script"),_SCS("get_base_script")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"property/type_cache",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_type_cache"),_SCS("_get_type_cache")); ADD_PROPERTY(PropertyInfo(Variant::INT,"property/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_type")); ADD_PROPERTY(PropertyInfo(Variant::INT,"property/event_type",PROPERTY_HINT_ENUM,et),_SCS("set_event_type"),_SCS("get_event_type")); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path")); @@ -1725,6 +2170,7 @@ VisualScriptPropertyGet::VisualScriptPropertyGet() { base_type="Object"; basic_type=Variant::NIL; event_type=InputEvent::NONE; + type_cache=Variant::NIL; } diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h index 7bb5ec49a2..9d2c26faf0 100644 --- a/modules/visual_script/visual_script_func_nodes.h +++ b/modules/visual_script/visual_script_func_nodes.h @@ -14,19 +14,36 @@ public: CALL_MODE_INSTANCE, CALL_MODE_BASIC_TYPE, }; + + enum RPCCallMode { + RPC_DISABLED, + RPC_RELIABLE, + RPC_UNRELIABLE, + RPC_RELIABLE_TO_ID, + RPC_UNRELIABLE_TO_ID + }; + private: CallMode call_mode; StringName base_type; + String base_script; Variant::Type basic_type; NodePath base_path; StringName function; int use_default_args; + RPCCallMode rpc_call_mode; + Node *_get_base_node() const; StringName _get_base_type() const; - void _update_defargs(); + MethodInfo method_cache; + void _update_method_cache(); + + void _set_argument_cache(const Dictionary& p_args); + Dictionary _get_argument_cache() const; + protected: virtual void _validate_property(PropertyInfo& property) const; @@ -58,6 +75,9 @@ public: void set_base_type(const StringName& p_type); StringName get_base_type() const; + void set_base_script(const String& p_path); + String get_base_script() const; + void set_function(const StringName& p_type); StringName get_function() const; @@ -70,12 +90,16 @@ public: void set_use_default_args(int p_amount); int get_use_default_args() const; + void set_rpc_call_mode(RPCCallMode p_mode); + RPCCallMode get_rpc_call_mode() const; + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptFunctionCall(); }; VARIANT_ENUM_CAST(VisualScriptFunctionCall::CallMode ); +VARIANT_ENUM_CAST(VisualScriptFunctionCall::RPCCallMode ); class VisualScriptPropertySet : public VisualScriptNode { @@ -92,9 +116,12 @@ public: }; private: + PropertyInfo type_cache; + CallMode call_mode; Variant::Type basic_type; StringName base_type; + String base_script; NodePath base_path; StringName property; bool use_builtin_value; @@ -106,6 +133,12 @@ private: void _update_base_type(); + void _update_cache(); + + void _set_type_cache(const Dictionary& p_type); + Dictionary _get_type_cache() const; + + protected: virtual void _validate_property(PropertyInfo& property) const; @@ -134,6 +167,9 @@ public: void set_base_type(const StringName& p_type); StringName get_base_type() const; + void set_base_script(const String& p_path); + String get_base_script() const; + void set_basic_type(Variant::Type p_type); Variant::Type get_basic_type() const; @@ -171,14 +207,17 @@ public: CALL_MODE_SELF, CALL_MODE_NODE_PATH, CALL_MODE_INSTANCE, - CALL_MODE_BASIC_TYPE + CALL_MODE_BASIC_TYPE, }; private: + Variant::Type type_cache; + CallMode call_mode; Variant::Type basic_type; StringName base_type; + String base_script; NodePath base_path; StringName property; InputEvent::Type event_type; @@ -187,6 +226,10 @@ private: Node *_get_base_node() const; StringName _get_base_type() const; + void _update_cache(); + + void _set_type_cache(Variant::Type p_type); + Variant::Type _get_type_cache() const; protected: virtual void _validate_property(PropertyInfo& property) const; @@ -216,6 +259,9 @@ public: void set_base_type(const StringName& p_type); StringName get_base_type() const; + void set_base_script(const String& p_path); + String get_base_script() const; + void set_basic_type(Variant::Type p_type); Variant::Type get_basic_type() const; diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index d205a40f76..01b6c661ab 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -62,6 +62,12 @@ bool VisualScriptFunction::_set(const StringName& p_name, const Variant& p_valu stack_size=p_value; return true; } + + if (p_name=="rpc/mode") { + rpc_mode=ScriptInstance::RPCMode(int(p_value)); + return true; + } + return false; } @@ -99,6 +105,11 @@ bool VisualScriptFunction::_get(const StringName& p_name,Variant &r_ret) const return true; } + if (p_name=="rpc/mode") { + r_ret=rpc_mode; + return true; + } + return false; } void VisualScriptFunction::_get_property_list( List<PropertyInfo> *p_list) const { @@ -118,6 +129,7 @@ void VisualScriptFunction::_get_property_list( List<PropertyInfo> *p_list) cons p_list->push_back(PropertyInfo(Variant::INT,"stack/size",PROPERTY_HINT_RANGE,"1,100000")); } p_list->push_back(PropertyInfo(Variant::BOOL,"stack/stackless")); + p_list->push_back(PropertyInfo(Variant::INT,"rpc/mode",PROPERTY_HINT_ENUM,"Disabled,Remote,Sync,Master,Slave")); } @@ -224,6 +236,16 @@ int VisualScriptFunction::get_argument_count() const { return arguments.size(); } + +void VisualScriptFunction::set_rpc_mode(ScriptInstance::RPCMode p_mode) { + rpc_mode=p_mode; +} + +ScriptInstance::RPCMode VisualScriptFunction::get_rpc_mode() const { + return rpc_mode; +} + + class VisualScriptNodeInstanceFunction : public VisualScriptNodeInstance { public: @@ -272,6 +294,7 @@ VisualScriptFunction::VisualScriptFunction() { stack_size=256; stack_less=false; + rpc_mode=ScriptInstance::RPC_MODE_DISABLED; } @@ -2432,6 +2455,153 @@ VisualScriptSubCall::VisualScriptSubCall() { } +////////////////////////////////////////// +////////////////Comment/////////// +////////////////////////////////////////// + +int VisualScriptComment::get_output_sequence_port_count() const { + + return 0; +} + +bool VisualScriptComment::has_input_sequence_port() const{ + + return false; +} + +int VisualScriptComment::get_input_value_port_count() const{ + return 0; +} +int VisualScriptComment::get_output_value_port_count() const{ + + return 0; +} + +String VisualScriptComment::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptComment::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + +PropertyInfo VisualScriptComment::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(); +} + + +String VisualScriptComment::get_caption() const { + + return title; +} + + +String VisualScriptComment::get_text() const { + + return description; +} + +void VisualScriptComment::set_title(const String& p_title) { + + + if (title==p_title) + return; + title=p_title; + ports_changed_notify(); +} + +String VisualScriptComment::get_title() const{ + + return title; +} + +void VisualScriptComment::set_description(const String& p_description){ + + if (description==p_description) + return; + description=p_description; + ports_changed_notify(); + +} +String VisualScriptComment::get_description() const{ + + return description; +} + +void VisualScriptComment::set_size(const Size2& p_size){ + + if (size==p_size) + return; + size=p_size; + ports_changed_notify(); + +} +Size2 VisualScriptComment::get_size() const{ + + return size; +} + + +String VisualScriptComment::get_category() const { + + return "data"; +} + +class VisualScriptNodeInstanceComment : public VisualScriptNodeInstance { +public: + + VisualScriptInstance* instance; + + //virtual int get_working_memory_size() const { return 0; } + //virtual bool is_output_port_unsequenced(int p_idx) const { return false; } + //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }; + + virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) { + + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptComment::instance(VisualScriptInstance* p_instance) { + + VisualScriptNodeInstanceComment * instance = memnew(VisualScriptNodeInstanceComment ); + instance->instance=p_instance; + return instance; +} + + + +void VisualScriptComment::_bind_methods() { + + + ObjectTypeDB::bind_method(_MD("set_title","title"),&VisualScriptComment::set_title); + ObjectTypeDB::bind_method(_MD("get_title"),&VisualScriptComment::get_title); + + ObjectTypeDB::bind_method(_MD("set_description","description"),&VisualScriptComment::set_description); + ObjectTypeDB::bind_method(_MD("get_description"),&VisualScriptComment::get_description); + + ObjectTypeDB::bind_method(_MD("set_size","size"),&VisualScriptComment::set_size); + ObjectTypeDB::bind_method(_MD("get_size"),&VisualScriptComment::get_size); + + ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),_SCS("set_title"),_SCS("get_title")); + ADD_PROPERTY( PropertyInfo(Variant::STRING,"description",PROPERTY_HINT_MULTILINE_TEXT),_SCS("set_description"),_SCS("get_description")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"size"),_SCS("set_size"),_SCS("get_size")); + +} + +VisualScriptComment::VisualScriptComment() { + + title="Comment"; + size=Size2(150,150); +} + + void register_visual_script_nodes() { @@ -2447,6 +2617,7 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("data/self",create_node_generic<VisualScriptSelf>); VisualScriptLanguage::singleton->add_register_func("custom/custom_node",create_node_generic<VisualScriptCustomNode>); VisualScriptLanguage::singleton->add_register_func("custom/sub_call",create_node_generic<VisualScriptSubCall>); + VisualScriptLanguage::singleton->add_register_func("data/comment",create_node_generic<VisualScriptComment>); VisualScriptLanguage::singleton->add_register_func("index/get_index",create_node_generic<VisualScriptIndexGet>); diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index 50f61ecfcc..11b6a32605 100644 --- a/modules/visual_script/visual_script_nodes.h +++ b/modules/visual_script/visual_script_nodes.h @@ -17,6 +17,7 @@ class VisualScriptFunction : public VisualScriptNode { bool stack_less; int stack_size; + ScriptInstance::RPCMode rpc_mode; protected: @@ -60,6 +61,9 @@ public: void set_stack_size(int p_size); int get_stack_size() const; + void set_rpc_mode(ScriptInstance::RPCMode p_mode); + ScriptInstance::RPCMode get_rpc_mode() const; + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); VisualScriptFunction(); @@ -645,6 +649,51 @@ public: VisualScriptSubCall(); }; +class VisualScriptComment: public VisualScriptNode { + + OBJ_TYPE(VisualScriptComment,VisualScriptNode) + + + String title; + String description; + Size2 size; +protected: + + virtual bool _use_builtin_script() const { return true; } + + static void _bind_methods(); +public: + virtual int get_output_sequence_port_count() const; + virtual bool has_input_sequence_port() const; + + + virtual String get_output_sequence_port_text(int p_port) const; + + + virtual int get_input_value_port_count() const; + virtual int get_output_value_port_count() const; + + + virtual PropertyInfo get_input_value_port_info(int p_idx) const; + virtual PropertyInfo get_output_value_port_info(int p_idx) const; + + virtual String get_caption() const; + virtual String get_text() const; + virtual String get_category() const; + + void set_title(const String& p_title); + String get_title() const; + + void set_description(const String& p_description); + String get_description() const; + + void set_size(const Size2& p_size); + Size2 get_size() const; + + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + + VisualScriptComment(); +}; void register_visual_script_nodes(); diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp index 24d5b7cf1a..221c46b6fd 100644 --- a/modules/visual_script/visual_script_yield_nodes.cpp +++ b/modules/visual_script/visual_script_yield_nodes.cpp @@ -45,12 +45,13 @@ PropertyInfo VisualScriptYield::get_output_value_port_info(int p_idx) const{ String VisualScriptYield::get_caption() const { - return "Wait"; + return yield_mode==YIELD_RETURN?"Yield":"Wait"; } String VisualScriptYield::get_text() const { switch (yield_mode) { + case YIELD_RETURN: return ""; break; case YIELD_FRAME: return "Next Frame"; break; case YIELD_FIXED_FRAME: return "Next Fixed Frame"; break; case YIELD_WAIT: return rtos(wait_time)+" sec(s)"; break; @@ -88,8 +89,10 @@ public: Ref<VisualScriptFunctionState> state; state.instance(); + int ret = STEP_YIELD_BIT; switch(mode) { + case VisualScriptYield::YIELD_RETURN: ret=STEP_EXIT_FUNCTION_BIT; break; //return the yield case VisualScriptYield::YIELD_FRAME: state->connect_to_signal(tree,"idle_frame",Array()); break; case VisualScriptYield::YIELD_FIXED_FRAME: state->connect_to_signal(tree,"fixed_frame",Array()); break; case VisualScriptYield::YIELD_WAIT: state->connect_to_signal(tree->create_timer(wait_time).ptr(),"timeout",Array()); break; @@ -98,7 +101,7 @@ public: *p_working_mem=state; - return STEP_YIELD_BIT; + return ret; } } @@ -487,7 +490,7 @@ void VisualScriptYieldSignal::_bind_methods() { bt+=Variant::get_type_name(Variant::Type(i)); } - ADD_PROPERTY(PropertyInfo(Variant::INT,"signal/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance",PROPERTY_USAGE_NOEDITOR),_SCS("set_call_mode"),_SCS("get_call_mode")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"signal/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance"),_SCS("set_call_mode"),_SCS("get_call_mode")); ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type")); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"signal/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path")); ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/signal"),_SCS("set_signal"),_SCS("get_signal")); @@ -615,8 +618,8 @@ void register_visual_script_yield_nodes() { VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_fixed_frame",create_yield_node<VisualScriptYield::YIELD_FIXED_FRAME>); VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_time",create_yield_node<VisualScriptYield::YIELD_WAIT>); - VisualScriptLanguage::singleton->add_register_func("functions/yield/instance_signal",create_yield_signal_node<VisualScriptYieldSignal::CALL_MODE_INSTANCE>); - VisualScriptLanguage::singleton->add_register_func("functions/yield/self_signal",create_yield_signal_node<VisualScriptYieldSignal::CALL_MODE_SELF>); - VisualScriptLanguage::singleton->add_register_func("functions/yield/node_signal",create_yield_signal_node<VisualScriptYieldSignal::CALL_MODE_NODE_PATH>); + + VisualScriptLanguage::singleton->add_register_func("functions/yield",create_yield_node<VisualScriptYield::YIELD_RETURN>); + VisualScriptLanguage::singleton->add_register_func("functions/yield_signal",create_node_generic<VisualScriptYieldSignal>); } diff --git a/modules/visual_script/visual_script_yield_nodes.h b/modules/visual_script/visual_script_yield_nodes.h index a7e200305d..ae7f8c15c1 100644 --- a/modules/visual_script/visual_script_yield_nodes.h +++ b/modules/visual_script/visual_script_yield_nodes.h @@ -9,6 +9,7 @@ class VisualScriptYield : public VisualScriptNode { public: enum YieldMode { + YIELD_RETURN, YIELD_FRAME, YIELD_FIXED_FRAME, YIELD_WAIT diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 71ec508c81..97133a2a3b 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2214,7 +2214,7 @@ void Control::grab_click_focus() { void Control::minimum_size_changed() { - if (!is_inside_tree()) + if (!is_inside_tree() || data.block_minimum_size_adjust) return; if (data.pending_min_size_update) @@ -2374,8 +2374,14 @@ Control *Control::get_root_parent_control() const { return const_cast<Control*>(root); } +void Control::set_block_minimum_size_adjust(bool p_block) { + data.block_minimum_size_adjust=p_block; +} +bool Control::is_minimum_size_adjust_blocked() const { + return data.block_minimum_size_adjust; +} void Control::_bind_methods() { @@ -2603,6 +2609,7 @@ Control::Control() { data.scale=Vector2(1,1); data.drag_owner=0; data.modal_frame=0; + data.block_minimum_size_adjust=false; for (int i=0;i<4;i++) { diff --git a/scene/gui/control.h b/scene/gui/control.h index b9ac53067a..e6b0844869 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -128,6 +128,8 @@ private: bool ignore_mouse; bool stop_mouse; + bool block_minimum_size_adjust; + Control *parent; ObjectID drag_owner; bool modal; @@ -396,6 +398,10 @@ public: Control *get_root_parent_control() const; + + void set_block_minimum_size_adjust(bool p_block); + bool is_minimum_size_adjust_blocked() const; + Control(); ~Control(); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 3ef77f551d..a7a813d335 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -193,6 +193,9 @@ void GraphEdit::_graph_node_raised(Node* p_gn) { GraphNode *gn=p_gn->cast_to<GraphNode>(); ERR_FAIL_COND(!gn); gn->raise(); + if (gn->is_comment()) { + move_child(gn,0); + } top_layer->raise(); emit_signal("node_selected",p_gn); @@ -261,6 +264,7 @@ void GraphEdit::_notification(int p_what) { } if (p_what==NOTIFICATION_DRAW) { + draw_style_box( get_stylebox("bg"),Rect2(Point2(),get_size()) ); VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true); @@ -712,6 +716,10 @@ void GraphEdit::_top_layer_draw() { col.g+=0.4; col.b+=0.4; } + + if (!connecting_out) { + SWAP(pos,topos); + } _draw_cos_line(top_layer,pos,topos,col,col); } @@ -856,6 +864,10 @@ void GraphEdit::_input_event(const InputEvent& p_ev) { gn=get_child(i)->cast_to<GraphNode>(); if (gn) { + + if (gn->is_resizing()) + continue; + Rect2 r = gn->get_rect(); r.size*=zoom; if (r.has_point(get_local_mouse_pos())) diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 9f5dd56ed5..c3276ceacc 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -133,6 +133,7 @@ private: bool lines_on_bg; + struct ConnType { union { @@ -205,6 +206,7 @@ public: int get_snap() const; void set_snap(int p_snap); + GraphEdit(); }; diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 66d2725ad2..5ece970936 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -188,11 +188,13 @@ void GraphNode::_notification(int p_what) { if (p_what==NOTIFICATION_DRAW) { - Ref<StyleBox> sb=get_stylebox(selected ? "selectedframe" : "frame"); + Ref<StyleBox> sb=get_stylebox(comment? "comment": (selected ? "selectedframe" : "frame")); + sb=sb->duplicate(); sb->call("set_modulate",modulate); Ref<Texture> port =get_icon("port"); Ref<Texture> close =get_icon("close"); + Ref<Texture> resizer =get_icon("resizer"); int close_offset = get_constant("close_offset"); Ref<Font> title_font = get_font("title_font"); int title_offset = get_constant("title_offset"); @@ -258,6 +260,11 @@ void GraphNode::_notification(int p_what) { } } + + + if (resizeable) { + draw_texture(resizer,get_size()-resizer->get_size()); + } } if (p_what==NOTIFICATION_SORT_CHILDREN) { @@ -594,19 +601,49 @@ void GraphNode::_input_event(const InputEvent& p_ev) { ERR_EXPLAIN("GraphNode must be the child of a GraphEdit node."); ERR_FAIL_COND(get_parent_control() == NULL); - get_parent_control()->grab_focus(); - if(p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { Vector2 mpos = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y); if (close_rect.size!=Size2() && close_rect.has_point(mpos)) { emit_signal("close_request"); + accept_event(); + return; + } + + Ref<Texture> resizer =get_icon("resizer"); + + if (resizeable && mpos.x > get_size().x-resizer->get_width() && mpos.y > get_size().y-resizer->get_height()) { + + resizing=true; + resizing_from=mpos; + resizing_from_size=get_size(); + accept_event(); return; } + + //send focus to parent emit_signal("raise_request"); + get_parent_control()->grab_focus(); + } + + if(!p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { + resizing=false; + } + + } + + + if (resizing && p_ev.type==InputEvent::MOUSE_MOTION) { + Vector2 mpos = Vector2(p_ev.mouse_motion.x,p_ev.mouse_motion.y); + + Vector2 diff = mpos - resizing_from; + + emit_signal("resize_request",resizing_from_size+diff); + } + } void GraphNode::set_modulate(const Color &p_color) { @@ -630,6 +667,30 @@ GraphNode::Overlay GraphNode::get_overlay() const{ return overlay; } +void GraphNode::set_comment(bool p_enable) { + + comment=p_enable; + update(); +} + +bool GraphNode::is_comment() const{ + + return comment; +} + + +void GraphNode::set_resizeable(bool p_enable) { + + resizeable=p_enable; + update(); +} + +bool GraphNode::is_resizeable() const{ + + return resizeable; +} + + void GraphNode::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_title","title"),&GraphNode::set_title); @@ -649,6 +710,12 @@ void GraphNode::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_offset","offset"),&GraphNode::set_offset); ObjectTypeDB::bind_method(_MD("get_offset"),&GraphNode::get_offset); + ObjectTypeDB::bind_method(_MD("set_comment","comment"),&GraphNode::set_comment); + ObjectTypeDB::bind_method(_MD("is_comment"),&GraphNode::is_comment); + + ObjectTypeDB::bind_method(_MD("set_resizeable","resizeable"),&GraphNode::set_resizeable); + ObjectTypeDB::bind_method(_MD("is_resizeable"),&GraphNode::is_resizeable); + ObjectTypeDB::bind_method(_MD("get_connection_output_count"),&GraphNode::get_connection_output_count); ObjectTypeDB::bind_method(_MD("get_connection_input_count"),&GraphNode::get_connection_input_count); @@ -675,6 +742,7 @@ void GraphNode::_bind_methods() { ADD_SIGNAL(MethodInfo("dragged",PropertyInfo(Variant::VECTOR2,"from"),PropertyInfo(Variant::VECTOR2,"to"))); ADD_SIGNAL(MethodInfo("raise_request")); ADD_SIGNAL(MethodInfo("close_request")); + ADD_SIGNAL(MethodInfo("resize_request",PropertyInfo(Variant::VECTOR2,"new_minsize"))); BIND_CONSTANT( OVERLAY_DISABLED ); BIND_CONSTANT( OVERLAY_BREAKPOINT ); @@ -688,4 +756,7 @@ GraphNode::GraphNode() { connpos_dirty=true; set_stop_mouse(false); modulate=Color(1,1,1,1); + comment=false; + resizeable=false; + resizing=false; } diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index e87fb15b93..7357ab5a45 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -60,6 +60,12 @@ private: String title; bool show_close; Vector2 offset; + bool comment; + bool resizeable; + + bool resizing; + Vector2 resizing_from; + Vector2 resizing_from_size; Rect2 close_rect; @@ -144,8 +150,16 @@ public: void set_overlay(Overlay p_overlay); Overlay get_overlay() const; + void set_comment(bool p_enable); + bool is_comment() const; + + void set_resizeable(bool p_enable); + bool is_resizeable() const; + virtual Size2 get_minimum_size() const; + bool is_resizing() const { return resizing; } + GraphNode(); }; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 90f63a5053..8c1233b634 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -627,6 +627,7 @@ void fill_default_theme(Ref<Theme>& t,const Ref<Font> & default_font,const Ref<F // GraphNode Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png,6,24,6,5,16,24,16,5); + Ref<StyleBoxTexture> graphsbcomment = make_stylebox(graph_node_comment_png,6,24,6,5,16,24,16,5); Ref<StyleBoxTexture> graphsbselected = make_stylebox(graph_node_selected_png,6,24,6,5,16,24,16,5); Ref<StyleBoxTexture> graphsbdefault = make_stylebox(graph_node_default_png,4,4,4,4,6,4,4,4); Ref<StyleBoxTexture> graphsbdeffocus = make_stylebox(graph_node_default_focus_png,4,4,4,4,6,4,4,4); @@ -639,11 +640,13 @@ void fill_default_theme(Ref<Theme>& t,const Ref<Font> & default_font,const Ref<F t->set_stylebox("selectedframe","GraphNode", graphsbselected ); t->set_stylebox("defaultframe", "GraphNode", graphsbdefault ); t->set_stylebox("defaultfocus", "GraphNode", graphsbdeffocus ); + t->set_stylebox("comment", "GraphNode", graphsbcomment ); t->set_stylebox("breakpoint", "GraphNode", graph_bpoint ); t->set_stylebox("position", "GraphNode", graph_position ); t->set_constant("separation","GraphNode", 1 *scale); t->set_icon("port","GraphNode", make_icon( graph_port_png ) ); t->set_icon("close","GraphNode", make_icon( graph_node_close_png ) ); + t->set_icon("resizer","GraphNode", make_icon( window_resizer_png ) ); t->set_font("title_font","GraphNode", default_font ); t->set_color("title_color","GraphNode", Color(0,0,0,1)); t->set_constant("title_offset","GraphNode", 20 *scale); diff --git a/scene/resources/default_theme/graph_node_comment.png b/scene/resources/default_theme/graph_node_comment.png Binary files differnew file mode 100644 index 0000000000..f2d6daa259 --- /dev/null +++ b/scene/resources/default_theme/graph_node_comment.png diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index dea55088d5..ea68901196 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -114,6 +114,11 @@ static const unsigned char graph_node_close_png[]={ }; +static const unsigned char graph_node_comment_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x19,0x11,0x2a,0x1d,0xd6,0x78,0x8b,0x40,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x74,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0xbf,0x4e,0xc2,0x50,0x14,0xc6,0x7f,0x6d,0x91,0x56,0x1b,0x90,0x80,0x2c,0x44,0xc2,0xa0,0x2e,0xe,0x3e,0x3,0x89,0x93,0xf1,0x1d,0x4c,0x18,0x4d,0x1c,0x7c,0xb,0x57,0x7,0x13,0x47,0x13,0x77,0x46,0xe3,0xc4,0x4b,0x98,0x60,0x4c,0xd4,0x81,0x60,0x58,0x94,0xff,0x22,0x2d,0xd0,0xd6,0xe5,0xde,0x88,0x8,0x2,0x35,0x6e,0xf7,0x5b,0x6e,0x9a,0x9c,0xef,0x77,0xee,0x39,0x37,0x1d,0x3e,0x8d,0x2f,0x69,0x80,0xe,0x18,0xe2,0xd4,0xf8,0xae,0x0,0xf0,0x1,0x4f,0x9c,0x1,0x63,0x45,0x3a,0xb0,0x6,0x24,0x81,0x34,0x10,0x7,0x56,0x26,0x0,0x43,0xa0,0x3,0xbc,0x2,0xd,0xe0,0x3,0xf0,0x65,0x57,0x1b,0xd8,0x5e,0x8f,0x25,0x8e,0x2d,0xd3,0x3a,0x88,0x46,0xcd,0x4d,0xa6,0x68,0x30,0x70,0x5f,0x1c,0xd7,0xb9,0x6d,0x77,0x5b,0x97,0xc0,0x13,0xd0,0xd3,0x44,0xa7,0x5c,0x32,0x91,0x3a,0xdf,0xca,0xed,0x1c,0x16,0x52,0xdd,0x2a,0xbf,0xe8,0xaa,0x1e,0xcb,0x3e,0x57,0x1e,0x6f,0x1a,0xad,0xfa,0x29,0x50,0x91,0x33,0xa7,0x4d,0xd3,0xca,0xcf,0x33,0x3,0x14,0x52,0xdd,0xaa,0x69,0x5a,0x79,0x31,0xaa,0x21,0x97,0x65,0x47,0x8c,0x88,0xcd,0x82,0x12,0xb5,0x36,0xa0,0x49,0x80,0xc1,0xf2,0x32,0x24,0x20,0x90,0x4f,0x12,0x46,0x3a,0x7f,0x94,0x2,0x28,0x80,0x2,0x88,0x5f,0x7b,0xfc,0xe3,0xec,0xe1,0x3d,0x1b,0x1a,0x30,0x1a,0x7a,0x1c,0x65,0xd8,0x5f,0xc4,0x74,0x5d,0xa3,0xa4,0x5e,0x41,0x1,0x14,0x40,0x1,0x14,0x40,0x1,0x14,0x40,0x1,0xfe,0x15,0xa0,0x4d,0xc9,0x88,0x4b,0xdf,0xc0,0xf,0xe1,0xf5,0x25,0xc0,0x7,0x1c,0xcf,0xf3,0xdc,0x45,0x9d,0xa2,0xd6,0x1,0x7c,0x5d,0x44,0xd9,0xba,0xe3,0xf6,0xcb,0xc5,0xa6,0x5d,0x9a,0x67,0x2e,0x36,0xed,0x92,0xe3,0xf6,0xcb,0x40,0x1d,0xf0,0x64,0x72,0x5d,0x7,0xf6,0xe2,0x76,0xe2,0xc2,0x32,0x57,0x77,0xd,0xc3,0xd0,0x67,0x74,0xf6,0x1d,0xb7,0x7f,0xdf,0xe9,0xb5,0x4e,0x80,0x3b,0xa0,0xad,0x8d,0x45,0xb8,0x38,0x90,0x1,0x36,0x0,0x73,0x46,0xf8,0x76,0x81,0x37,0xa0,0x26,0x72,0xb4,0xa7,0x4d,0x2c,0x34,0x22,0xf3,0xe0,0x8c,0x9,0x2,0x31,0xf2,0x28,0xe4,0xe2,0x7f,0xea,0x13,0x64,0x47,0x6c,0x83,0x36,0x6d,0xd2,0x40,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + static const unsigned char graph_node_default_png[]={ 0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x39,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x16,0x12,0x19,0xe,0xb,0x10,0xe,0xb,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x16,0x12,0x19,0x0,0x0,0x0,0x19,0x15,0x1c,0x24,0x1e,0x27,0x16,0x12,0x19,0xff,0xff,0xff,0x2b,0x4d,0xfd,0x66,0x0,0x0,0x0,0xf,0x74,0x52,0x4e,0x53,0x0,0x46,0x47,0x3f,0x2b,0x11,0x3,0xfd,0xd3,0xcd,0x2a,0x73,0x45,0xf8,0x3d,0x3f,0x57,0xda,0x84,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x12,0x7b,0xbc,0x6c,0x0,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x38,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0x64,0x2,0x2,0x46,0x8,0xc9,0xcc,0xc2,0xca,0xc6,0xc0,0x8f,0x4,0xd8,0x39,0x98,0x59,0x19,0x50,0x80,0x0,0x27,0x17,0xaa,0x0,0x83,0x20,0x37,0x9a,0x0,0x3f,0xd3,0xc0,0x8,0xf0,0xa0,0x9,0xf0,0xf2,0x61,0x3a,0x1d,0xc3,0x73,0xe8,0xde,0x7,0x0,0x89,0x4d,0x2,0xf2,0x16,0xd3,0x74,0x45,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -544,6 +549,11 @@ static const unsigned char vsplitter_png[]={ }; +static const unsigned char window_resizer_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x19,0x11,0x33,0x13,0xaa,0xc0,0xf,0x5f,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x2f,0x49,0x44,0x41,0x54,0x38,0xcb,0x63,0x60,0x18,0x5,0x24,0x81,0x17,0x2f,0x5e,0xf4,0xa3,0x8b,0x31,0x91,0xa2,0xb9,0xb9,0xb9,0x99,0x7c,0x9b,0xb3,0xb3,0xb3,0xfb,0x87,0x81,0x66,0x6c,0x81,0x48,0x92,0x66,0xa2,0x5c,0x43,0x91,0xe6,0x11,0xa,0x0,0x73,0x5b,0x34,0x19,0x10,0xa0,0xb6,0x7d,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + diff --git a/scene/resources/default_theme/window_resizer.png b/scene/resources/default_theme/window_resizer.png Binary files differnew file mode 100644 index 0000000000..ed51968c4e --- /dev/null +++ b/scene/resources/default_theme/window_resizer.png diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 85c560bf9d..ea553c5597 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -1673,7 +1673,7 @@ void EditorNode::_edit_current() { if (main_plugin) { - if (main_plugin!=editor_plugin_screen) { + if (main_plugin!=editor_plugin_screen && (!ScriptEditor::get_singleton() || !ScriptEditor::get_singleton()->is_visible() || ScriptEditor::get_singleton()->can_take_away_focus())) { // update screen main_plugin diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index 74c8ac9766..fdb7856b83 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -987,6 +987,20 @@ void ScriptEditor::_notification(int p_what) { } +bool ScriptEditor::can_take_away_focus() const { + + int selected = tab_container->get_current_tab(); + if (selected<0 || selected>=tab_container->get_child_count()) + return true; + + ScriptEditorBase *current = tab_container->get_child(selected)->cast_to<ScriptEditorBase>(); + if (!current) + return true; + + + return current->can_lose_focus_on_node_selection(); + +} void ScriptEditor::close_builtin_scripts_from_scene(const String& p_scene) { @@ -1397,7 +1411,7 @@ void ScriptEditor::_update_script_names() { -void ScriptEditor::edit(const Ref<Script>& p_script) { +void ScriptEditor::edit(const Ref<Script>& p_script, bool p_grab_focus) { if (p_script.is_null()) return; @@ -1471,7 +1485,9 @@ void ScriptEditor::edit(const Ref<Script>& p_script) { } - _go_to_tab(tab_container->get_tab_count()-1); + if (p_grab_focus) { + _go_to_tab(tab_container->get_tab_count()-1); + } @@ -1932,6 +1948,13 @@ void ScriptEditor::_help_search(String p_text) { help_search_dialog->popup(p_text); } +void ScriptEditor::_open_script_request(const String& p_path) { + + Ref<Script> script = ResourceLoader::load(p_path); + if (script.is_valid()) { + script_editor->edit(script,false); + } +} int ScriptEditor::script_editor_func_count=0; CreateScriptEditorFunc ScriptEditor::script_editor_funcs[ScriptEditor::SCRIPT_EDITOR_FUNC_MAX]; @@ -2208,6 +2231,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { edit_pass=0; trim_trailing_whitespace_on_save = false; + + ScriptServer::edit_request_func=_open_script_request; } diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h index 0ba2efce34..1a23ffed72 100644 --- a/tools/editor/plugins/script_editor_plugin.h +++ b/tools/editor/plugins/script_editor_plugin.h @@ -101,6 +101,7 @@ public: virtual void add_callback(const String& p_function,StringArray p_args)=0; virtual void update_settings()=0; virtual void set_debugger_active(bool p_active)=0; + virtual bool can_lose_focus_on_node_selection() { return true; } virtual void set_tooltip_request_func(String p_method,Object* p_obj)=0; virtual Control *get_edit_menu()=0; @@ -285,6 +286,8 @@ class ScriptEditor : public VBoxContainer { int file_dialog_option; void _file_dialog_action(String p_file); + static void _open_script_request(const String& p_path); + static ScriptEditor *script_editor; protected: void _notification(int p_what); @@ -297,7 +300,7 @@ public: void apply_scripts() const; void ensure_select_current(); - void edit(const Ref<Script>& p_script); + void edit(const Ref<Script>& p_script,bool p_grab_focus=true); Dictionary get_state() const; void set_state(const Dictionary& p_state); @@ -322,6 +325,8 @@ public: void goto_help(const String& p_desc) { _help_class_goto(p_desc); } + bool can_take_away_focus() const; + ScriptEditorDebugger *get_debugger() { return debugger; } void set_live_auto_reload_running_scripts(bool p_enabled); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index ea036593b8..d7e527f473 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -1151,6 +1151,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) { file->clear_filters(); + if (hint_text!="") { Vector<String> extensions=hint_text.split(","); for(int i=0;i<extensions.size();i++) { diff --git a/tools/editor/property_selector.cpp b/tools/editor/property_selector.cpp index e960a0e0d3..20b72240d9 100644 --- a/tools/editor/property_selector.cpp +++ b/tools/editor/property_selector.cpp @@ -508,6 +508,7 @@ void PropertySelector::select_property_from_base_type(const String& p_base,const void PropertySelector::select_property_from_script(const Ref<Script>& p_script,const String& p_current){ ERR_FAIL_COND( p_script.is_null() ); + base_type=p_script->get_instance_base_type(); selected=p_current; type=Variant::NIL; |