diff options
Diffstat (limited to 'tools')
71 files changed, 1726 insertions, 1052 deletions
diff --git a/tools/SCsub b/tools/SCsub index 875663b849..4d8b05fe79 100644 --- a/tools/SCsub +++ b/tools/SCsub @@ -5,13 +5,16 @@ env.add_source_files(env.tool_sources,"*.cpp") Export('env') -SConscript('editor/SCsub'); -#SConscript('scintilla/SCsub'); -SConscript('collada/SCsub'); -SConscript('docdump/SCsub'); -SConscript('freetype/SCsub'); -SConscript('doc/SCsub'); -SConscript('pck/SCsub'); +if (env["tools"]!="no"): + SConscript('editor/SCsub'); + #SConscript('scintilla/SCsub'); + SConscript('collada/SCsub'); + SConscript('docdump/SCsub'); + SConscript('freetype/SCsub'); + SConscript('doc/SCsub') + SConscript('pck/SCsub') + + lib = env.Library("tool",env.tool_sources) diff --git a/tools/doc/doc_data.cpp b/tools/doc/doc_data.cpp index d13c7ea73c..75759e7d30 100644 --- a/tools/doc/doc_data.cpp +++ b/tools/doc/doc_data.cpp @@ -186,8 +186,10 @@ void DocData::generate(bool p_basic_types) { arginfo=E->get().return_val; if (arginfo.type==Variant::NIL) continue; - - method.return_type=(arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE)?arginfo.hint_string:Variant::get_type_name(arginfo.type); + if (m && m->get_return_type()!=StringName()) + method.return_type=m->get_return_type(); + else + method.return_type=(arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE)?arginfo.hint_string:Variant::get_type_name(arginfo.type); } else { diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp index 95f9ee6509..db70a2675a 100644 --- a/tools/editor/animation_editor.cpp +++ b/tools/editor/animation_editor.cpp @@ -2909,11 +2909,11 @@ void AnimationKeyEditor::set_anim_pos(float p_pos) { void AnimationKeyEditor::_pane_drag(const Point2& p_delta) { - Size2 ecs = ec->get_minsize(); + Size2 ecs = ec->get_custom_minimum_size(); ecs.y-=p_delta.y; if (ecs.y<100) ecs.y=100; - ec->set_minsize(ecs);; + ec->set_custom_minimum_size(ecs);; } @@ -3238,7 +3238,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h move_down_button->connect("pressed",this,"_menu_track",make_binds(TRACK_MENU_MOVE_DOWN)); move_down_button->set_focus_mode(FOCUS_NONE); move_down_button->set_disabled(true); - move_down_button->set_tooltip("Move current track dosn."); + move_down_button->set_tooltip("Move current track down."); remove_button = memnew( ToolButton ); hb->add_child(remove_button); @@ -3296,8 +3296,8 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h // menu->get_popup()->connect("item_pressed",this,"_menu_callback"); - ec = memnew (EmptyControl); - ec->set_minsize(Size2(0,50)); + ec = memnew (Control); + ec->set_custom_minimum_size(Size2(0,50)); add_child(ec); ec->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/tools/editor/animation_editor.h b/tools/editor/animation_editor.h index 9d3e692fad..1f17922552 100644 --- a/tools/editor/animation_editor.h +++ b/tools/editor/animation_editor.h @@ -37,7 +37,7 @@ #include "scene/gui/scroll_bar.h" #include "scene/gui/tool_button.h" #include "scene/gui/file_dialog.h" -#include "scene/gui/empty_control.h" + #include "scene/resources/animation.h" #include "scene/animation/animation_cache.h" #include "scene_tree_editor.h" @@ -157,7 +157,7 @@ class AnimationKeyEditor : public VBoxContainer { PopupMenu *track_menu; PopupMenu *type_menu; - EmptyControl *ec; + Control *ec; TextureFrame *zoomicon; HSlider *zoom; //MenuButton *menu; diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp index 6de59f184a..2209b24245 100644 --- a/tools/editor/code_editor.cpp +++ b/tools/editor/code_editor.cpp @@ -487,6 +487,7 @@ FindReplaceDialog::FindReplaceDialog() { vb->add_child(error_label); + set_hide_on_ok(false); } @@ -507,15 +508,19 @@ void CodeTextEditor::_text_changed() { } void CodeTextEditor::_code_complete_timer_timeout() { + if (!is_visible()) + return; if (enable_complete_timer) text_editor->query_code_comple(); } -void CodeTextEditor::_complete_request(const String& p_request, int p_line) { +void CodeTextEditor::_complete_request() { List<String> entries; - _code_complete_script(text_editor->get_text(),p_request,p_line,&entries); + _code_complete_script(text_editor->get_text_for_completion(),&entries); // print_line("COMPLETE: "+p_request); + if (entries.size()==0) + return; Vector<String> strs; strs.resize(entries.size()); int i=0; @@ -555,7 +560,7 @@ void CodeTextEditor::_on_settings_change() { // AUTO BRACE COMPLETION text_editor->set_auto_brace_completion( - EDITOR_DEF("text_editor/auto_brace_complete", false) + EDITOR_DEF("text_editor/auto_brace_complete", true) ); code_complete_timer->set_wait_time( @@ -594,8 +599,21 @@ CodeTextEditor::CodeTextEditor() { add_child(text_editor); text_editor->set_area_as_parent_rect(); text_editor->set_margin(MARGIN_BOTTOM,20); - text_editor->add_font_override("font",get_font("source","Fonts")); + + String editor_font = EDITOR_DEF("text_editor/font", ""); + bool font_overrode = false; + if (editor_font!="") { + Ref<Font> fnt = ResourceLoader::load(editor_font); + if (fnt.is_valid()) { + text_editor->add_font_override("font",fnt); + font_overrode = true; + } + } + + if (!font_overrode) + text_editor->add_font_override("font",get_font("source","Fonts")); text_editor->set_show_line_numbers(true); + text_editor->set_brace_matching(true); line_col = memnew( Label ); add_child(line_col); @@ -632,6 +650,8 @@ CodeTextEditor::CodeTextEditor() { text_editor->connect("request_completion", this,"_complete_request"); Vector<String> cs; cs.push_back("."); + cs.push_back(","); + cs.push_back("("); text_editor->set_completion(true,cs); idle->connect("timeout", this,"_text_changed_idle_timeout"); diff --git a/tools/editor/code_editor.h b/tools/editor/code_editor.h index 1804237f18..f82eaf5ec5 100644 --- a/tools/editor/code_editor.h +++ b/tools/editor/code_editor.h @@ -135,7 +135,7 @@ class CodeTextEditor : public Control { void _on_settings_change(); - void _complete_request(const String& p_request,int p_line); + void _complete_request(); protected: void set_error(const String& p_error); @@ -143,7 +143,7 @@ protected: virtual void _load_theme_settings() {} virtual void _validate_script()=0; - virtual void _code_complete_script(const String& p_code, const String& p_keyword,int p_line, List<String>* r_options) {}; + virtual void _code_complete_script(const String& p_code, List<String>* r_options) {}; void _text_changed_idle_timeout(); diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp index 8408436a6c..2283a2df14 100644 --- a/tools/editor/editor_help.cpp +++ b/tools/editor/editor_help.cpp @@ -1361,8 +1361,8 @@ EditorHelp::EditorHelp(EditorNode *p_editor) { Separator *hs = memnew( VSeparator ); panel_hb->add_child(hs); - EmptyControl *ec = memnew( EmptyControl ); - ec->set_minsize(Size2(200,1)); + Control *ec = memnew( Control ); + ec->set_custom_minimum_size(Size2(200,1)); panel_hb->add_child(ec); search = memnew( LineEdit ); ec->add_child(search); diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp index a511e78863..58f9afaa5d 100644 --- a/tools/editor/editor_import_export.cpp +++ b/tools/editor/editor_import_export.cpp @@ -292,7 +292,11 @@ Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const _add_filter_to_list(exported,"*"); } else { _add_to_list(EditorFileSystem::get_singleton()->get_filesystem(),exported); - _add_filter_to_list(exported,EditorImportExport::get_singleton()->get_export_custom_filter()); + String cf = EditorImportExport::get_singleton()->get_export_custom_filter(); + if (cf!="") + cf+=","; + cf+="*.flags"; + _add_filter_to_list(exported,cf); } @@ -361,8 +365,12 @@ Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const } } } + String cf = EditorImportExport::get_singleton()->get_export_custom_filter(); + if (cf!="") + cf+=","; + cf+="*.flags"; + _add_filter_to_list(exported,cf); - _add_filter_to_list(exported,EditorImportExport::get_singleton()->get_export_custom_filter()); } diff --git a/tools/editor/editor_log.cpp b/tools/editor/editor_log.cpp index f7f5f596d7..7c3fa6c1bd 100644 --- a/tools/editor/editor_log.cpp +++ b/tools/editor/editor_log.cpp @@ -203,9 +203,9 @@ EditorLog::EditorLog() { tb->connect("pressed",this,"_close_request"); - ec = memnew( EmptyControl); + ec = memnew( Control); vb->add_child(ec); - ec->set_minsize(Size2(0,100)); + ec->set_custom_minimum_size(Size2(0,100)); ec->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/tools/editor/editor_log.h b/tools/editor/editor_log.h index b6cd951287..27cce4a584 100644 --- a/tools/editor/editor_log.h +++ b/tools/editor/editor_log.h @@ -33,7 +33,7 @@ #include "scene/gui/label.h" #include "scene/gui/rich_text_label.h" #include "scene/gui/texture_button.h" -#include "scene/gui/empty_control.h" +//#include "scene/gui/empty_control.h" #include "scene/gui/box_container.h" #include "scene/gui/panel_container.h" #include "scene/gui/texture_frame.h" @@ -50,7 +50,7 @@ class EditorLog : public PanelContainer { TextureButton *tb; HBoxContainer *title_hb; // PaneDrag *pd; - EmptyControl *ec; + Control *ec; static void _error_handler(void *p_self, const char*p_func, const char*p_file,int p_line, const char*p_error,const char*p_errorexp,ErrorHandlerType p_type); diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 2927e7c870..52c75c6d7e 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -75,6 +75,7 @@ #include "plugins/tile_map_editor_plugin.h" #include "plugins/cube_grid_theme_editor_plugin.h" #include "plugins/shader_editor_plugin.h" +#include "plugins/shader_graph_editor_plugin.h" #include "plugins/path_editor_plugin.h" #include "plugins/rich_text_editor_plugin.h" #include "plugins/collision_polygon_editor_plugin.h" @@ -977,6 +978,15 @@ void EditorNode::_dialog_action(String p_file) { } } break; + + case FILE_SAVE_AND_RUN: { + if (file->get_mode()==FileDialog::MODE_SAVE_FILE) { + + _save_scene(p_file); + _run(false); + } + } break; + case FILE_EXPORT_MESH_LIBRARY: { Ref<MeshLibrary> ml; @@ -1390,13 +1400,10 @@ void EditorNode::_run(bool p_current,const String& p_custom) { } if (scene->get_filename()=="") { - - current_option=-1; //accept->get_cancel()->hide(); - accept->get_ok()->set_text("I see.."); - accept->set_text("Scene has never been saved. Save before running!"); - accept->popup_centered(Size2(300,70));; + /**/ + _menu_option_confirm(FILE_SAVE_BEFORE_RUN, false); return; } @@ -1663,6 +1670,18 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { } break; + case FILE_SAVE_BEFORE_RUN: { + if (!p_confirmed) { + accept->get_ok()->set_text("Yes"); + accept->set_text("This scene has never been saved. Save before running?"); + accept->popup_centered(Size2(300, 70)); + break; + } + + _menu_option(FILE_SAVE_AS_SCENE); + _menu_option_confirm(FILE_SAVE_AND_RUN, true); + } break; + case FILE_DUMP_STRINGS: { Node *scene = edited_scene; @@ -3245,7 +3264,7 @@ EditorNode::EditorNode() { gui_base->set_area_as_parent_rect(); - Ref<Theme> theme( memnew( Theme ) ); + theme = Ref<Theme>( memnew( Theme ) ); gui_base->set_theme( theme ); editor_register_icons(theme); editor_register_fonts(theme); @@ -3308,13 +3327,13 @@ EditorNode::EditorNode() { main_editor_tabs->connect("tab_changed",this,"_editor_select"); HBoxContainer *srth = memnew( HBoxContainer ); srt->add_child( srth ); - EmptyControl *tec = memnew( EmptyControl ); - tec->set_minsize(Size2(100,0)); + Control *tec = memnew( Control ); + tec->set_custom_minimum_size(Size2(100,0)); tec->set_h_size_flags(Control::SIZE_EXPAND_FILL); srth->add_child(tec); srth->add_child(main_editor_tabs); - tec = memnew( EmptyControl ); - tec->set_minsize(Size2(100,0)); + tec = memnew( Control ); + tec->set_custom_minimum_size(Size2(100,0)); srth->add_child(tec); tec->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -3422,7 +3441,7 @@ EditorNode::EditorNode() { p->add_item("New Scene",FILE_NEW_SCENE); p->add_item("Open Scene..",FILE_OPEN_SCENE,KEY_MASK_CMD+KEY_O); p->add_item("Save Scene",FILE_SAVE_SCENE,KEY_MASK_CMD+KEY_S); - p->add_item("Save Scene As..",FILE_SAVE_AS_SCENE); + p->add_item("Save Scene As..",FILE_SAVE_AS_SCENE,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_S); p->add_separator(); p->add_item("Goto Prev. Scene",FILE_OPEN_PREV,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_P); p->add_submenu_item("Open Recent","RecentScenes",FILE_OPEN_RECENT); @@ -3674,8 +3693,8 @@ EditorNode::EditorNode() { top_pallete->add_child(resources_dock); top_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL); - EmptyControl *editor_spacer = memnew( EmptyControl ); - editor_spacer->set_minsize(Size2(260,200)); + Control *editor_spacer = memnew( Control ); + editor_spacer->set_custom_minimum_size(Size2(260,200)); editor_spacer->set_v_size_flags(Control::SIZE_EXPAND_FILL); editor_vsplit->add_child( editor_spacer ); editor_spacer->add_child( top_pallete ); @@ -3686,8 +3705,8 @@ EditorNode::EditorNode() { prop_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL); - editor_spacer = memnew( EmptyControl ); - editor_spacer->set_minsize(Size2(260,200)); + editor_spacer = memnew( Control ); + editor_spacer->set_custom_minimum_size(Size2(260,200)); editor_spacer->set_v_size_flags(Control::SIZE_EXPAND_FILL); editor_vsplit->add_child( editor_spacer ); editor_spacer->add_child( prop_pallete ); @@ -4016,6 +4035,7 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( ScriptEditorPlugin(this) ) ); add_editor_plugin( memnew( EditorHelpPlugin(this) ) ); add_editor_plugin( memnew( AnimationPlayerEditorPlugin(this) ) ); + add_editor_plugin( memnew( ShaderGraphEditorPlugin(this) ) ); add_editor_plugin( memnew( ShaderEditorPlugin(this) ) ); add_editor_plugin( memnew( CameraEditorPlugin(this) ) ); add_editor_plugin( memnew( SampleEditorPlugin(this) ) ); diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 7b66a7809e..7560c2b149 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -108,6 +108,8 @@ class EditorNode : public Node { FILE_OPEN_SCENE, FILE_SAVE_SCENE, FILE_SAVE_AS_SCENE, + FILE_SAVE_BEFORE_RUN, + FILE_SAVE_AND_RUN, FILE_IMPORT_SUBSCENE, FILE_EXPORT_PROJECT, FILE_EXPORT_MESH_LIBRARY, @@ -212,6 +214,7 @@ class EditorNode : public Node { AcceptDialog *load_error_dialog; Control *scene_root_base; + Ref<Theme> theme; PopupMenu *recent_scenes; Button *property_back; @@ -472,6 +475,9 @@ public: void stop_child_process(); + Ref<Theme> get_editor_theme() const { return theme; } + + Error export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after=false); static void register_editor_types(); diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index 8b4d899437..bc800d7e9e 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -403,6 +403,7 @@ void EditorSettings::_load_defaults() { set("text_editor/string_color",Color::html("ef6ebe")); set("text_editor/symbol_color",Color::html("badfff")); set("text_editor/selection_color",Color::html("7b5dbe")); + set("text_editor/brace_mismatch_color",Color(1,0.2,0.2)); set("text_editor/idle_parse_delay",2); set("text_editor/create_signal_callbacks",true); @@ -418,6 +419,8 @@ void EditorSettings::_load_defaults() { set("3d_editor/navigation_scheme",0); hints["3d_editor/navigation_scheme"]=PropertyInfo(Variant::INT,"3d_editor/navigation_scheme",PROPERTY_HINT_ENUM,"Godot,Maya,Modo"); + set("3d_editor/zoom_style",0); + hints["3d_editor/zoom_style"]=PropertyInfo(Variant::INT,"3d_editor/zoom_style",PROPERTY_HINT_ENUM,"Vertical, Horizontal"); set("3d_editor/orbit_modifier",0); hints["3d_editor/orbit_modifier"]=PropertyInfo(Variant::INT,"3d_editor/orbit_modifier",PROPERTY_HINT_ENUM,"None,Shift,Alt,Meta,Ctrl"); set("3d_editor/pan_modifier",1); @@ -443,6 +446,7 @@ void EditorSettings::_load_defaults() { set("animation/confirm_insert_track",true); set("property_editor/texture_preview_width",48); + set("property_editor/auto_refresh_interval",0.3); set("help/doc_path",""); set("import/ask_save_before_reimport",false); diff --git a/tools/editor/icons/icon_canvas_item_shader.png b/tools/editor/icons/icon_canvas_item_shader.png Binary files differnew file mode 100644 index 0000000000..a5f4e7bf85 --- /dev/null +++ b/tools/editor/icons/icon_canvas_item_shader.png diff --git a/tools/editor/icons/icon_canvas_item_shader_graph.png b/tools/editor/icons/icon_canvas_item_shader_graph.png Binary files differnew file mode 100644 index 0000000000..bba966b43e --- /dev/null +++ b/tools/editor/icons/icon_canvas_item_shader_graph.png diff --git a/tools/editor/icons/icon_graph_comment.png b/tools/editor/icons/icon_graph_comment.png Binary files differnew file mode 100644 index 0000000000..bf7889c510 --- /dev/null +++ b/tools/editor/icons/icon_graph_comment.png diff --git a/tools/editor/icons/icon_graph_cube_uniform.png b/tools/editor/icons/icon_graph_cube_uniform.png Binary files differnew file mode 100644 index 0000000000..d1b92b4943 --- /dev/null +++ b/tools/editor/icons/icon_graph_cube_uniform.png diff --git a/tools/editor/icons/icon_graph_input.png b/tools/editor/icons/icon_graph_input.png Binary files differnew file mode 100644 index 0000000000..a396bc2350 --- /dev/null +++ b/tools/editor/icons/icon_graph_input.png diff --git a/tools/editor/icons/icon_graph_rgb.png b/tools/editor/icons/icon_graph_rgb.png Binary files differnew file mode 100644 index 0000000000..abffaedd34 --- /dev/null +++ b/tools/editor/icons/icon_graph_rgb.png diff --git a/tools/editor/icons/icon_graph_rgb_op.png b/tools/editor/icons/icon_graph_rgb_op.png Binary files differnew file mode 100644 index 0000000000..642fc838c2 --- /dev/null +++ b/tools/editor/icons/icon_graph_rgb_op.png diff --git a/tools/editor/icons/icon_graph_rgb_uniform.png b/tools/editor/icons/icon_graph_rgb_uniform.png Binary files differnew file mode 100644 index 0000000000..92c79997ef --- /dev/null +++ b/tools/editor/icons/icon_graph_rgb_uniform.png diff --git a/tools/editor/icons/icon_graph_scalar.png b/tools/editor/icons/icon_graph_scalar.png Binary files differnew file mode 100644 index 0000000000..028d0e9ea4 --- /dev/null +++ b/tools/editor/icons/icon_graph_scalar.png diff --git a/tools/editor/icons/icon_graph_scalar_interp.png b/tools/editor/icons/icon_graph_scalar_interp.png Binary files differnew file mode 100644 index 0000000000..4f178a27c4 --- /dev/null +++ b/tools/editor/icons/icon_graph_scalar_interp.png diff --git a/tools/editor/icons/icon_graph_scalar_op.png b/tools/editor/icons/icon_graph_scalar_op.png Binary files differnew file mode 100644 index 0000000000..0fc4cae94c --- /dev/null +++ b/tools/editor/icons/icon_graph_scalar_op.png diff --git a/tools/editor/icons/icon_graph_scalar_uniform.png b/tools/editor/icons/icon_graph_scalar_uniform.png Binary files differnew file mode 100644 index 0000000000..fc6590a8cf --- /dev/null +++ b/tools/editor/icons/icon_graph_scalar_uniform.png diff --git a/tools/editor/icons/icon_graph_scalars_to_vec.png b/tools/editor/icons/icon_graph_scalars_to_vec.png Binary files differnew file mode 100644 index 0000000000..7ca39a2f56 --- /dev/null +++ b/tools/editor/icons/icon_graph_scalars_to_vec.png diff --git a/tools/editor/icons/icon_graph_texscreen.png b/tools/editor/icons/icon_graph_texscreen.png Binary files differnew file mode 100644 index 0000000000..e183a8fa56 --- /dev/null +++ b/tools/editor/icons/icon_graph_texscreen.png diff --git a/tools/editor/icons/icon_graph_texture_uniform.png b/tools/editor/icons/icon_graph_texture_uniform.png Binary files differnew file mode 100644 index 0000000000..7517ac1d92 --- /dev/null +++ b/tools/editor/icons/icon_graph_texture_uniform.png diff --git a/tools/editor/icons/icon_graph_time.png b/tools/editor/icons/icon_graph_time.png Binary files differnew file mode 100644 index 0000000000..b61e45589f --- /dev/null +++ b/tools/editor/icons/icon_graph_time.png diff --git a/tools/editor/icons/icon_graph_vec_dp.png b/tools/editor/icons/icon_graph_vec_dp.png Binary files differnew file mode 100644 index 0000000000..059c3025e7 --- /dev/null +++ b/tools/editor/icons/icon_graph_vec_dp.png diff --git a/tools/editor/icons/icon_graph_vec_interp.png b/tools/editor/icons/icon_graph_vec_interp.png Binary files differnew file mode 100644 index 0000000000..daf7a00203 --- /dev/null +++ b/tools/editor/icons/icon_graph_vec_interp.png diff --git a/tools/editor/icons/icon_graph_vec_length.png b/tools/editor/icons/icon_graph_vec_length.png Binary files differnew file mode 100644 index 0000000000..60ade8c90a --- /dev/null +++ b/tools/editor/icons/icon_graph_vec_length.png diff --git a/tools/editor/icons/icon_graph_vec_op.png b/tools/editor/icons/icon_graph_vec_op.png Binary files differnew file mode 100644 index 0000000000..f2a7a51123 --- /dev/null +++ b/tools/editor/icons/icon_graph_vec_op.png diff --git a/tools/editor/icons/icon_graph_vec_scalar_op.png b/tools/editor/icons/icon_graph_vec_scalar_op.png Binary files differnew file mode 100644 index 0000000000..f0f4e7a196 --- /dev/null +++ b/tools/editor/icons/icon_graph_vec_scalar_op.png diff --git a/tools/editor/icons/icon_graph_vec_to_scalars.png b/tools/editor/icons/icon_graph_vec_to_scalars.png Binary files differnew file mode 100644 index 0000000000..a677a7cc53 --- /dev/null +++ b/tools/editor/icons/icon_graph_vec_to_scalars.png diff --git a/tools/editor/icons/icon_graph_vecs_to_xform.png b/tools/editor/icons/icon_graph_vecs_to_xform.png Binary files differnew file mode 100644 index 0000000000..51216c93eb --- /dev/null +++ b/tools/editor/icons/icon_graph_vecs_to_xform.png diff --git a/tools/editor/icons/icon_graph_vector.png b/tools/editor/icons/icon_graph_vector.png Binary files differnew file mode 100644 index 0000000000..9dfe47d757 --- /dev/null +++ b/tools/editor/icons/icon_graph_vector.png diff --git a/tools/editor/icons/icon_graph_vector_uniform.png b/tools/editor/icons/icon_graph_vector_uniform.png Binary files differnew file mode 100644 index 0000000000..611539fca7 --- /dev/null +++ b/tools/editor/icons/icon_graph_vector_uniform.png diff --git a/tools/editor/icons/icon_graph_xform.png b/tools/editor/icons/icon_graph_xform.png Binary files differnew file mode 100644 index 0000000000..22df472be4 --- /dev/null +++ b/tools/editor/icons/icon_graph_xform.png diff --git a/tools/editor/icons/icon_graph_xform_mult.png b/tools/editor/icons/icon_graph_xform_mult.png Binary files differnew file mode 100644 index 0000000000..5d0ce7982d --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_mult.png diff --git a/tools/editor/icons/icon_graph_xform_scalar_func.png b/tools/editor/icons/icon_graph_xform_scalar_func.png Binary files differnew file mode 100644 index 0000000000..e53f08a564 --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_scalar_func.png diff --git a/tools/editor/icons/icon_graph_xform_to_vecs.png b/tools/editor/icons/icon_graph_xform_to_vecs.png Binary files differnew file mode 100644 index 0000000000..847261f726 --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_to_vecs.png diff --git a/tools/editor/icons/icon_graph_xform_uniform.png b/tools/editor/icons/icon_graph_xform_uniform.png Binary files differnew file mode 100644 index 0000000000..94c9759b25 --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_uniform.png diff --git a/tools/editor/icons/icon_graph_xform_vec_func.png b/tools/editor/icons/icon_graph_xform_vec_func.png Binary files differnew file mode 100644 index 0000000000..f3ba528896 --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_vec_func.png diff --git a/tools/editor/icons/icon_graph_xform_vec_imult.png b/tools/editor/icons/icon_graph_xform_vec_imult.png Binary files differnew file mode 100644 index 0000000000..7e7330cb8c --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_vec_imult.png diff --git a/tools/editor/icons/icon_graph_xform_vec_mult.png b/tools/editor/icons/icon_graph_xform_vec_mult.png Binary files differnew file mode 100644 index 0000000000..f80a28c80d --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_vec_mult.png diff --git a/tools/editor/icons/icon_material_shader.png b/tools/editor/icons/icon_material_shader.png Binary files differnew file mode 100644 index 0000000000..0e476b2540 --- /dev/null +++ b/tools/editor/icons/icon_material_shader.png diff --git a/tools/editor/icons/icon_material_shader_graph.png b/tools/editor/icons/icon_material_shader_graph.png Binary files differnew file mode 100644 index 0000000000..68d8b4cb49 --- /dev/null +++ b/tools/editor/icons/icon_material_shader_graph.png diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp index 8bb37f1d71..f706d67f6d 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.cpp +++ b/tools/editor/plugins/animation_player_editor_plugin.cpp @@ -76,6 +76,8 @@ void AnimationPlayerEditor::_notification(int p_what) { seek->set_val(player->get_current_animation_pos()); if (edit_anim->is_pressed()) editor->get_animation_editor()->set_anim_pos(player->get_current_animation_pos()); + EditorNode::get_singleton()->get_property_editor()->refresh(); + } else if (last_active) { //need the last frame after it stopped @@ -854,6 +856,8 @@ void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos) { return; seek->set_val(p_pos); + EditorNode::get_singleton()->get_property_editor()->refresh(); + //seekit diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index 599160eb46..43ebebeb22 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -2307,7 +2307,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { } break; case ANIM_INSERT_ROT: { - key_pos = key_rot_button->is_pressed(); + key_rot = key_rot_button->is_pressed(); } break; case ANIM_INSERT_SCALE: { @@ -2683,6 +2683,11 @@ void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) { hb->add_child(p_control); } +HSplitContainer *CanvasItemEditor::get_palette_split() { + + return palette_split; +} + CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { tool = TOOL_SELECT; @@ -2697,15 +2702,20 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { add_child( hb ); hb->set_area_as_parent_rect(); + palette_split = memnew( HSplitContainer); + palette_split->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(palette_split); + Control *vp_base = memnew (Control); - add_child(vp_base); vp_base->set_v_size_flags(SIZE_EXPAND_FILL); + palette_split->add_child(vp_base); Control *vp = memnew (Control); vp_base->add_child(vp); vp->set_area_as_parent_rect(); vp->add_child(p_editor->get_scene_root()); + viewport = memnew( Control ); vp_base->add_child(viewport); viewport->set_area_as_parent_rect(); @@ -2878,7 +2888,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_separator(); p->add_item("Copy Pose",ANIM_COPY_POSE); p->add_item("Paste Pose",ANIM_PASTE_POSE); - p->add_item("Clear Pose",ANIM_CLEAR_POSE,KEY_MASK_ALT|KEY_K); + p->add_item("Clear Pose",ANIM_CLEAR_POSE,KEY_MASK_SHIFT|KEY_K); value_dialog = memnew( AcceptDialog ); value_dialog->set_title("Set a Value"); diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h index 15ac7b1bb3..c56570d43f 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.h +++ b/tools/editor/plugins/canvas_item_editor_plugin.h @@ -289,6 +289,10 @@ class CanvasItemEditor : public VBoxContainer { void _viewport_input_event(const InputEvent& p_event); void _viewport_draw(); + +private: + HSplitContainer *palette_split; + friend class CanvasItemEditorPlugin; protected: @@ -341,6 +345,8 @@ public: void add_control_to_menu_panel(Control *p_control); + HSplitContainer *get_palette_split(); + Control *get_viewport_control() { return viewport; } diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp index 6bae0d2fd0..ed228e9a1c 100644 --- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp +++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp @@ -398,11 +398,13 @@ CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) { add_child(button_create); button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE)); button_create->set_toggle_mode(true); + button_create->set_tooltip("Create a new polygon from scratch"); button_edit = memnew( ToolButton ); add_child(button_edit); button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT)); button_edit->set_toggle_mode(true); + button_edit->set_tooltip("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point."); //add_constant_override("separation",0); diff --git a/tools/editor/plugins/collision_polygon_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_editor_plugin.cpp index 35f22aa6f8..b92acb60f9 100644 --- a/tools/editor/plugins/collision_polygon_editor_plugin.cpp +++ b/tools/editor/plugins/collision_polygon_editor_plugin.cpp @@ -120,6 +120,8 @@ void CollisionPolygonEditor::_wip_close() { bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event) { + if (!node) + return false; Transform gt = node->get_global_transform(); float depth = node->get_depth()*0.5; diff --git a/tools/editor/plugins/item_list_editor_plugin.cpp b/tools/editor/plugins/item_list_editor_plugin.cpp index eb7ab69987..a8b34ef503 100644 --- a/tools/editor/plugins/item_list_editor_plugin.cpp +++ b/tools/editor/plugins/item_list_editor_plugin.cpp @@ -210,6 +210,7 @@ void ItemListEditor::_bind_methods() { } bool ItemListEditor::handles(Object *p_object) const { + return false; for(int i=0;i<item_plugins.size();i++) { if (item_plugins[i]->handles(p_object)) { return true; diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index c5fb574c71..55957887dc 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -209,6 +209,7 @@ void ScriptTextEditor::_load_theme_settings() { get_text_edit()->add_color_override("font_color",EDITOR_DEF("text_editor/text_color",Color(0,0,0))); get_text_edit()->add_color_override("font_selected_color",EDITOR_DEF("text_editor/text_selected_color",Color(1,1,1))); get_text_edit()->add_color_override("selection_color",EDITOR_DEF("text_editor/selection_color",Color(0.2,0.2,1))); + get_text_edit()->add_color_override("brace_mismatch_color",EDITOR_DEF("text_editor/brace_mismatch_color",Color(1,0.2,0.2))); Color keyword_color= EDITOR_DEF("text_editor/keyword_color",Color(0.5,0.0,0.2)); @@ -384,9 +385,35 @@ void ScriptTextEditor::_validate_script() { _update_name(); } -void ScriptTextEditor::_code_complete_script(const String& p_code, const String& p_keyword,int p_line, List<String>* r_options) { - Error err = script->get_language()->complete_keyword(p_code,p_line,script->get_path().get_base_dir(),p_keyword,r_options); +static Node* _find_node_for_script(Node* p_base, Node*p_current, const Ref<Script>& p_script) { + + if (p_current->get_owner()!=p_base && p_base!=p_current) + return NULL; + Ref<Script> c = p_current->get_script(); + if (c==p_script) + return p_current; + for(int i=0;i<p_current->get_child_count();i++) { + Node *found = _find_node_for_script(p_base,p_current->get_child(i),p_script); + if (found) + return found; + } + + return NULL; +} + +void ScriptTextEditor::_code_complete_script(const String& p_code, List<String>* r_options) { + + Node *base = get_tree()->get_edited_scene_root(); + if (base) { + base = _find_node_for_script(base,base,script); + } + String hint; + Error err = script->get_language()->complete_code(p_code,script->get_path().get_base_dir(),base,r_options,hint); + if (hint!="") { + get_text_edit()->set_code_hint(hint); + print_line("hint: "+hint.replace(String::chr(0xFFFF),"|")); + } } @@ -1551,7 +1578,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { menu_hb->add_child(file_menu); file_menu->set_text("File"); file_menu->get_popup()->add_item("Open",FILE_OPEN); - file_menu->get_popup()->add_item("Save",FILE_SAVE,KEY_MASK_ALT|KEY_S); + file_menu->get_popup()->add_item("Save",FILE_SAVE,KEY_MASK_ALT|KEY_MASK_CMD|KEY_S); file_menu->get_popup()->add_item("Save As..",FILE_SAVE_AS); file_menu->get_popup()->add_item("Save All",FILE_SAVE_ALL,KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_S); file_menu->get_popup()->connect("item_pressed", this,"_menu_option"); @@ -1559,23 +1586,27 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { edit_menu = memnew( MenuButton ); menu_hb->add_child(edit_menu); edit_menu->set_text("Edit"); - edit_menu->get_popup()->add_item("Undo",EDIT_UNDO,KEY_MASK_CMD|KEY_Z); - edit_menu->get_popup()->add_item("Redo",EDIT_REDO,KEY_MASK_CMD|KEY_Y); + edit_menu->get_popup()->add_item("Undo",EDIT_UNDO,KEY_MASK_CMD|KEY_Z); + edit_menu->get_popup()->add_item("Redo",EDIT_REDO,KEY_MASK_CMD|KEY_Y); edit_menu->get_popup()->add_separator(); edit_menu->get_popup()->add_item("Cut",EDIT_CUT,KEY_MASK_CMD|KEY_X); edit_menu->get_popup()->add_item("Copy",EDIT_COPY,KEY_MASK_CMD|KEY_C); edit_menu->get_popup()->add_item("Paste",EDIT_PASTE,KEY_MASK_CMD|KEY_V); edit_menu->get_popup()->add_separator(); edit_menu->get_popup()->add_item("Select All",EDIT_SELECT_ALL,KEY_MASK_CMD|KEY_A); - edit_menu->get_popup()->add_separator(); - edit_menu->get_popup()->add_item("Move Up",EDIT_MOVE_LINE_UP,KEY_MASK_ALT|KEY_UP); - edit_menu->get_popup()->add_item("Move Down",EDIT_MOVE_LINE_DOWN,KEY_MASK_ALT|KEY_DOWN); - edit_menu->get_popup()->add_item("Indent Left",EDIT_INDENT_LEFT,KEY_MASK_ALT|KEY_LEFT); - edit_menu->get_popup()->add_item("Indent Right",EDIT_INDENT_RIGHT,KEY_MASK_ALT|KEY_RIGHT); - edit_menu->get_popup()->add_item("Toggle Comment",EDIT_TOGGLE_COMMENT,KEY_MASK_CMD|KEY_SLASH); - edit_menu->get_popup()->add_item("Clone Down",EDIT_CLONE_DOWN,KEY_MASK_CMD|KEY_B); edit_menu->get_popup()->add_separator(); + edit_menu->get_popup()->add_item("Move Up",EDIT_MOVE_LINE_UP,KEY_MASK_ALT|KEY_UP); + edit_menu->get_popup()->add_item("Move Down",EDIT_MOVE_LINE_DOWN,KEY_MASK_ALT|KEY_DOWN); + edit_menu->get_popup()->add_item("Indent Left",EDIT_INDENT_LEFT,KEY_MASK_ALT|KEY_LEFT); + edit_menu->get_popup()->add_item("Indent Right",EDIT_INDENT_RIGHT,KEY_MASK_ALT|KEY_RIGHT); + edit_menu->get_popup()->add_item("Toggle Comment",EDIT_TOGGLE_COMMENT,KEY_MASK_CMD|KEY_K); + edit_menu->get_popup()->add_item("Clone Down",EDIT_CLONE_DOWN,KEY_MASK_CMD|KEY_B); + edit_menu->get_popup()->add_separator(); +#ifdef OSX_ENABLED + edit_menu->get_popup()->add_item("Complete Symbol",EDIT_COMPLETE,KEY_MASK_META|KEY_SPACE); +#else edit_menu->get_popup()->add_item("Complete Symbol",EDIT_COMPLETE,KEY_MASK_CMD|KEY_SPACE); +#endif edit_menu->get_popup()->add_item("Auto Indent",EDIT_AUTO_INDENT,KEY_MASK_CMD|KEY_I); edit_menu->get_popup()->connect("item_pressed", this,"_menu_option"); diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h index 01942fab2a..136d966587 100644 --- a/tools/editor/plugins/script_editor_plugin.h +++ b/tools/editor/plugins/script_editor_plugin.h @@ -85,7 +85,7 @@ protected: virtual void _validate_script(); - virtual void _code_complete_script(const String& p_code,const String& p_keyword, int p_line, List<String>* r_options); + virtual void _code_complete_script(const String& p_code, List<String>* r_options); virtual void _load_theme_settings(); void _notification(int p_what); diff --git a/tools/editor/plugins/shader_editor_plugin.cpp b/tools/editor/plugins/shader_editor_plugin.cpp index a6172ee098..3166383fc8 100644 --- a/tools/editor/plugins/shader_editor_plugin.cpp +++ b/tools/editor/plugins/shader_editor_plugin.cpp @@ -80,6 +80,7 @@ void ShaderTextEditor::_load_theme_settings() { get_text_edit()->add_color_override("font_color",EDITOR_DEF("text_editor/text_color",Color(0,0,0))); get_text_edit()->add_color_override("font_selected_color",EDITOR_DEF("text_editor/text_selected_color",Color(1,1,1))); get_text_edit()->add_color_override("selection_color",EDITOR_DEF("text_editor/selection_color",Color(0.2,0.2,1))); + get_text_edit()->add_color_override("brace_mismatch_color",EDITOR_DEF("text_editor/brace_mismatch_color",Color(1,0.2,0.2))); Color keyword_color= EDITOR_DEF("text_editor/keyword_color",Color(0.5,0.0,0.2)); diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp index 2686ca895e..0a206c4a45 100644 --- a/tools/editor/plugins/shader_graph_editor_plugin.cpp +++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp @@ -28,1082 +28,1518 @@ /*************************************************************************/ #include "shader_graph_editor_plugin.h" -#if 0 + #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" +#include "spatial_editor_plugin.h" + +////cbacks +/// +void ShaderGraphView::_scalar_const_changed(double p_value,int p_id) { + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Scalar Constant",true); + ur->add_do_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,p_value); + ur->add_undo_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,graph->scalar_const_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} -class _ShaderTester : public ShaderCodeGenerator { -public: +void ShaderGraphView::_vec_const_changed(double p_value, int p_id,Array p_arr){ - Set<int> *_set; + Vector3 val; + for(int i=0;i<p_arr.size();i++) { + val[i]=p_arr[i].call("get_val"); + } - virtual void begin() {} - virtual Error add_node(VS::ShaderNodeType p_type,int p_node_pos,int p_id,const Variant& p_param,const Vector<int>& p_in_connections,const Vector<int>& p_out_connections,const Vector<int>& p_out_connection_outputs) { if (_set) _set->insert(p_id); return OK; } - virtual void end() {} + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Vec Constant",true); + ur->add_do_method(graph.ptr(),"vec_const_node_set_value",type,p_id,val); + ur->add_undo_method(graph.ptr(),"vec_const_node_set_value",type,p_id,graph->vec_const_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; - _ShaderTester() { _set=NULL; } -}; +} +void ShaderGraphView::_rgb_const_changed(const Color& p_color, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change RGB Constant",true); + ur->add_do_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,p_color); + ur->add_undo_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,graph->rgb_const_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_scalar_op_changed(int p_op, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Scalar Operator"); + ur->add_do_method(graph.ptr(),"scalar_op_node_set_op",type,p_id,p_op); + ur->add_undo_method(graph.ptr(),"scalar_op_node_set_op",type,p_id,graph->scalar_op_node_get_op(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_vec_op_changed(int p_op, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Vec Operator"); + ur->add_do_method(graph.ptr(),"vec_op_node_set_op",type,p_id,p_op); + ur->add_undo_method(graph.ptr(),"vec_op_node_set_op",type,p_id,graph->vec_op_node_get_op(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_vec_scalar_op_changed(int p_op, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change VecxScalar Operator"); + ur->add_do_method(graph.ptr(),"vec_scalar_op_node_set_op",type,p_id,p_op); + ur->add_undo_method(graph.ptr(),"vec_scalar_op_node_set_op",type,p_id,graph->vec_scalar_op_node_get_op(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; -void ShaderEditor::edit(Ref<Shader> p_shader) { +} +void ShaderGraphView::_rgb_op_changed(int p_op, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change RGB Operator"); + ur->add_do_method(graph.ptr(),"rgb_op_node_set_op",type,p_id,p_op); + ur->add_undo_method(graph.ptr(),"rgb_op_node_set_op",type,p_id,graph->rgb_op_node_get_op(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_xform_inv_rev_changed(bool p_enabled, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Toggle Rot Only"); + ur->add_do_method(graph.ptr(),"xform_vec_mult_node_set_no_translation",type,p_id,p_enabled); + ur->add_undo_method(graph.ptr(),"xform_vec_mult_node_set_no_translation",type,p_id,graph->xform_vec_mult_node_get_no_translation(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_scalar_func_changed(int p_func, int p_id){ + + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Scalar Function"); + ur->add_do_method(graph.ptr(),"scalar_func_node_set_function",type,p_id,p_func); + ur->add_undo_method(graph.ptr(),"scalar_func_node_set_function",type,p_id,graph->scalar_func_node_get_function(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_vec_func_changed(int p_func, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Vec Function"); + ur->add_do_method(graph.ptr(),"vec_func_node_set_function",type,p_id,p_func); + ur->add_undo_method(graph.ptr(),"vec_func_node_set_function",type,p_id,graph->vec_func_node_get_function(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_scalar_input_changed(double p_value,int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Scalar Uniform",true); + ur->add_do_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,p_value); + ur->add_undo_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,graph->scalar_input_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; - shader=p_shader; +} +void ShaderGraphView::_vec_input_changed(double p_value, int p_id,Array p_arr){ - if (shader.is_null()) - hide(); - else { - _read_shader_graph(); + Vector3 val; + for(int i=0;i<p_arr.size();i++) { + val[i]=p_arr[i].call("get_val"); } + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Vec Uniform",true); + ur->add_do_method(graph.ptr(),"vec_input_node_set_value",type,p_id,val); + ur->add_undo_method(graph.ptr(),"vec_input_node_set_value",type,p_id,graph->vec_input_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; + } +void ShaderGraphView::_xform_input_changed(int p_id, Node *p_button){ -Size2 ShaderEditor::_get_maximum_size() { - Size2 max; + ToolButton *tb = p_button->cast_to<ToolButton>(); + ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height)); + ped_popup->set_size(tb->get_size()); + edited_id=p_id; + ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_input_node_get_value(type,p_id),PROPERTY_HINT_NONE,""); + ped_popup->popup(); - for(List<int>::Element *E=order.front();E;E=E->next()) { +} +void ShaderGraphView::_xform_const_changed(int p_id, Node *p_button){ - Point2 pos = Point2( shader_graph.node_get_pos_x(E->get()), shader_graph.node_get_pos_y(E->get()) ); + ToolButton *tb = p_button->cast_to<ToolButton>(); + ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height)); + ped_popup->set_size(tb->get_size()); + edited_id=p_id; + ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_const_node_get_value(type,p_id),PROPERTY_HINT_NONE,""); + ped_popup->popup(); - if (click_type==CLICK_NODE && click_node==E->get()) { +} - pos+=click_motion-click_pos; - } - pos+=get_node_size(E->get()); - if (pos.x>max.x) - max.x=pos.x; - if (pos.y>max.y) - max.y=pos.y; +void ShaderGraphView::_rgb_input_changed(const Color& p_color, int p_id){ - } - return max; + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change RGB Uniform",true); + ur->add_do_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,p_color); + ur->add_undo_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,graph->rgb_input_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; } +void ShaderGraphView::_tex_input_change(int p_id, Node *p_button){ -Size2 ShaderEditor::get_node_size(int p_node) const { - VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node); - Ref<StyleBox> style = get_stylebox("panel","PopupMenu"); - Ref<Font> font = get_font("font","PopupMenu"); - Color font_color = get_color("font_color","PopupMenu"); - - Size2 size = style->get_minimum_size(); - - int count=1; // title - count += VisualServer::shader_get_input_count( type) + VisualServer::shader_get_output_count( type); +} +void ShaderGraphView::_cube_input_change(int p_id){ - float max_w=font->get_string_size( VisualServer::shader_node_get_type_info(type).name ).width; - for(int i=0;i<VisualServer::shader_get_input_count(type);i++) - max_w = MAX( max_w, font->get_string_size( VisualServer::shader_get_input_name(type,i) ).width ); +} +void ShaderGraphView::_variant_edited() { - for(int i=0;i<VisualServer::shader_get_output_count(type);i++) - max_w = MAX( max_w, font->get_string_size( VisualServer::shader_get_output_name(type,i) ).width ); + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_CONST) { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change XForm Uniform"); + ur->add_do_method(graph.ptr(),"xform_const_node_set_value",type,edited_id,ped_popup->get_variant()); + ur->add_undo_method(graph.ptr(),"xform_const_node_set_value",type,edited_id,graph->xform_const_node_get_value(type,edited_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + } + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_INPUT) { - switch(type) { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change XForm Uniform"); + ur->add_do_method(graph.ptr(),"xform_input_node_set_value",type,edited_id,ped_popup->get_variant()); + ur->add_undo_method(graph.ptr(),"xform_input_node_set_value",type,edited_id,graph->xform_input_node_get_value(type,edited_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + } - case VS::NODE_IN: - case VS::NODE_OUT: - case VS::NODE_VEC_IN: - case VS::NODE_VEC_OUT: - case VS::NODE_PARAMETER: - case VS::NODE_VEC_PARAMETER: - case VS::NODE_COLOR_PARAMETER: - case VS::NODE_TEXTURE_PARAMETER: - case VS::NODE_TEXTURE_2D_PARAMETER: - case VS::NODE_TEXTURE_CUBE_PARAMETER: - case VS::NODE_TRANSFORM_PARAMETER: - case VS::NODE_LABEL: { + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_TEXTURE_INPUT) { - max_w=MAX( max_w, font->get_string_size( shader_graph.node_get_param(p_node) ).width ); - count++; - } break; - case VS::NODE_TIME: - case VS::NODE_CONSTANT: - case VS::NODE_VEC_CONSTANT: - case VS::NODE_COLOR_CONSTANT: - case VS::NODE_TRANSFORM_CONSTANT: { - count++; - } break; - case VS::NODE_TEXTURE: - case VS::NODE_VEC_TEXTURE_2D: - case VS::NODE_VEC_TEXTURE_CUBE: { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Texture Uniform"); + ur->add_do_method(graph.ptr(),"texture_input_node_set_value",type,edited_id,ped_popup->get_variant()); + ur->add_undo_method(graph.ptr(),"texture_input_node_set_value",type,edited_id,graph->texture_input_node_get_value(type,edited_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + } - RefPtr res = shader_graph.node_get_param(p_node); - Ref<Texture> texture = res; - if (texture.is_null() || texture->get_width()==0) { + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_CUBEMAP_INPUT) { - size.y+=max_w; - } else { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Cubemap Uniform"); + ur->add_do_method(graph.ptr(),"cubemap_input_node_set_value",type,edited_id,ped_popup->get_variant()); + ur->add_undo_method(graph.ptr(),"cubemap_input_node_set_value",type,edited_id,graph->cubemap_input_node_get_value(type,edited_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + } - size.y+=max_w * texture->get_height() / texture->get_width(); - } - } break; - default: {} +} - } +void ShaderGraphView::_comment_edited(int p_id,Node* p_button) { - size.x+=max_w; - size.y+=count*(font->get_height()+get_constant("vseparation","PopupMenu")); + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + TextEdit *te=p_button->cast_to<TextEdit>(); + ur->create_action("Change Comment",true); + ur->add_do_method(graph.ptr(),"comment_node_set_text",type,p_id,te->get_text()); + ur->add_undo_method(graph.ptr(),"comment_node_set_text",type,p_id,graph->comment_node_get_text(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; - return size; } -Error ShaderEditor::validate_graph() { +void ShaderGraphView::_input_name_changed(const String& p_name, int p_id, Node *p_line_edit) { + + LineEdit *le=p_line_edit->cast_to<LineEdit>(); + ERR_FAIL_COND(!le); - _ShaderTester st; - active_nodes.clear(); - st._set=&active_nodes; - return shader_graph.generate(&st); + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Input Name"); + ur->add_do_method(graph.ptr(),"input_node_set_name",type,p_id,p_name); + ur->add_undo_method(graph.ptr(),"input_node_set_name",type,p_id,graph->input_node_get_name(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; + le->set_text(graph->input_node_get_name(type,p_id)); } -void ShaderEditor::_draw_node(int p_node) { +void ShaderGraphView::_tex_edited(int p_id,Node* p_button) { - VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node); - Ref<StyleBox> style = active_nodes.has(p_node)?get_stylebox("panel","PopupMenu"):get_stylebox("panel_disabled","PopupMenu"); - Ref<Font> font = get_font("font","PopupMenu"); - Color font_color = get_color("font_color","PopupMenu"); - Color font_color_title = get_color("font_color_hover","PopupMenu"); - Size2 size=get_node_size(p_node); - Point2 pos = Point2( shader_graph.node_get_pos_x(p_node), shader_graph.node_get_pos_y(p_node) )-offset; + ToolButton *tb = p_button->cast_to<ToolButton>(); + ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height)); + ped_popup->set_size(tb->get_size()); + edited_id=p_id; + ped_popup->edit(NULL,"",Variant::OBJECT,graph->texture_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"Texture"); +} - if (click_type==CLICK_NODE && click_node==p_node) { +void ShaderGraphView::_cube_edited(int p_id,Node* p_button) { - pos+=click_motion-click_pos; - } + ToolButton *tb = p_button->cast_to<ToolButton>(); + ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height)); + ped_popup->set_size(tb->get_size()); + edited_id=p_id; + ped_popup->edit(NULL,"",Variant::OBJECT,graph->cubemap_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"CubeMap"); +} - RID ci = get_canvas_item(); - style->draw(ci,Rect2(pos,size)); - Point2 ofs=style->get_offset()+pos; - Point2 ascent=Point2(0,font->get_ascent()); - float w = size.width-style->get_minimum_size().width; - float h = font->get_height()+get_constant("vseparation","PopupMenu"); +//////////////view///////////// - font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, VisualServer::shader_node_get_type_info(type).name,font_color_title); - ofs.y+=h; - Ref<Texture> vec_icon = get_icon("NodeVecSlot","EditorIcons"); - Ref<Texture> real_icon = get_icon("NodeRealSlot","EditorIcons"); - float icon_h_ofs = Math::floor(( font->get_height()-vec_icon->get_height())/2.0 )+1; +void ShaderGraphView::_connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot) { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); - for(int i=0;i<VisualServer::shader_get_input_count(type);i++) { + int from_idx=-1; + int to_idx=-1; + for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) { - String name = VisualServer::shader_get_input_name(type,i); - font->draw_halign( ci, ofs+ascent, HALIGN_LEFT,w, name,font_color); - Ref<Texture> icon = VisualServer::shader_is_input_vector(type,i)?vec_icon:real_icon; - icon->draw(ci,ofs+Point2(-real_icon->get_width(),icon_h_ofs)); - ofs.y+=h; + if (p_from==E->get()->get_name()) + from_idx=E->key(); + if (p_to==E->get()->get_name()) + to_idx=E->key(); } - for(int i=0;i<VisualServer::shader_get_output_count(type);i++) { + ERR_FAIL_COND(from_idx==-1); + ERR_FAIL_COND(to_idx==-1); - String name = VisualServer::shader_get_output_name(type,i); - font->draw_halign( ci, ofs+ascent, HALIGN_RIGHT,w, name,font_color); - Ref<Texture> icon = VisualServer::shader_is_output_vector(type,i)?vec_icon:real_icon; - icon->draw(ci,ofs+Point2(w,icon_h_ofs)); - ofs.y+=h; - } - - switch(type) { - - case VS::NODE_IN: - case VS::NODE_OUT: - case VS::NODE_PARAMETER: - case VS::NODE_VEC_IN: - case VS::NODE_COLOR_PARAMETER: - case VS::NODE_VEC_OUT: - case VS::NODE_TEXTURE_PARAMETER: - case VS::NODE_TEXTURE_2D_PARAMETER: - case VS::NODE_TEXTURE_CUBE_PARAMETER: - case VS::NODE_TRANSFORM_CONSTANT: - case VS::NODE_TRANSFORM_PARAMETER: - case VS::NODE_VEC_PARAMETER: - case VS::NODE_LABEL: { - String text = shader_graph.node_get_param(p_node); - font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, text,font_color); - } break; - case VS::NODE_TIME: - case VS::NODE_CONSTANT: { - String text = rtos(shader_graph.node_get_param(p_node)); - font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, text,font_color); + ur->create_action("Connect Graph Nodes"); - } break; - case VS::NODE_VEC_CONSTANT: { - String text = Vector3(shader_graph.node_get_param(p_node)); - font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, text,font_color); - } break; - case VS::NODE_COLOR_CONSTANT: { + List<ShaderGraph::Connection> conns; - Color color = shader_graph.node_get_param(p_node); - Rect2 r(ofs,Size2(w,h)); - VisualServer::get_singleton()->canvas_item_add_rect(ci,r,color); - } break; - case VS::NODE_TEXTURE: - case VS::NODE_VEC_TEXTURE_2D: - case VS::NODE_VEC_TEXTURE_CUBE: { - - Rect2 r(ofs,Size2(w,(pos.y+size.y-style->get_margin(MARGIN_BOTTOM))-ofs.y)); - Vector<Point2> points; - Vector<Point2> uvs; - points.resize(4); - uvs.resize(4); - points[0]=r.pos; - points[1]=r.pos+Point2(r.size.x,0); - points[2]=r.pos+r.size; - points[3]=r.pos+Point2(0,r.size.y); - uvs[0]=Point2(0,0); - uvs[1]=Point2(1,0); - uvs[2]=Point2(1,1); - uvs[3]=Point2(0,1); - - Ref<Texture> texture = shader_graph.node_get_param(p_node).operator RefPtr(); - if (texture.is_null() || texture->get_width()==0) { - texture=get_icon("Click2Edit","EditorIcons"); - } + graph->get_node_connections(type,&conns); + //disconnect/reconnect dependencies + ur->add_undo_method(graph.ptr(),"disconnect_node",type,from_idx,p_from_slot,to_idx,p_to_slot); + for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) { - VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid()); - } break; - default: {} + if (E->get().dst_id==to_idx && E->get().dst_slot==p_to_slot) { + ur->add_do_method(graph.ptr(),"disconnect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot); + ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot); + } } -} + ur->add_do_method(graph.ptr(),"connect_node",type,from_idx,p_from_slot,to_idx,p_to_slot); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); -void ShaderEditor::_node_param_changed() { - shader_graph.node_set_param( click_node,property_editor->get_variant() ); - update(); - _write_shader_graph(); } -ShaderEditor::ClickType ShaderEditor::_locate_click(const Point2& p_click,int *p_node_id,int *p_slot_index) const { - - Ref<StyleBox> style = get_stylebox("panel","PopupMenu"); - Ref<Texture> real_icon = get_icon("NodeRealSlot","EditorIcons"); - Ref<Font> font = get_font("font","PopupMenu"); - float h = font->get_height()+get_constant("vseparation","PopupMenu"); - float extra_left=MAX( real_icon->get_width()-style->get_margin(MARGIN_LEFT), 0 ); - float extra_right=MAX( real_icon->get_width()-style->get_margin(MARGIN_RIGHT), 0 ); - +void ShaderGraphView::_disconnection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot) { - for(const List<int>::Element *E=order.back();E;E=E->prev()) { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); - Size2 size=get_node_size(E->get()); - size.width+=extra_left+extra_right; - Point2 pos = Point2( shader_graph.node_get_pos_x(E->get()), shader_graph.node_get_pos_y(E->get()) )-offset; - pos.x-=extra_left; + int from_idx=-1; + int to_idx=-1; + for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) { - Rect2 rect( pos, size ); - if (!rect.has_point(p_click)) - continue; - VisualServer::ShaderNodeType type=shader_graph.node_get_type(E->get()); - if (p_node_id) - *p_node_id=E->get(); - float y=p_click.y-(pos.y+style->get_margin(MARGIN_TOP)); - if (y<h) - return CLICK_NODE; - y-=h; - - for(int i=0;i<VisualServer::shader_get_input_count(type);i++) { + if (p_from==E->get()->get_name()) + from_idx=E->key(); + if (p_to==E->get()->get_name()) + to_idx=E->key(); + } - if (y<h) { - if (p_slot_index) - *p_slot_index=i; - return CLICK_INPUT_SLOT; - } - y-=h; - } + ERR_FAIL_COND(from_idx==-1); + ERR_FAIL_COND(to_idx==-1); - for(int i=0;i<VisualServer::shader_get_output_count(type);i++) { + if (!graph->is_node_connected(type,from_idx,p_from_slot,to_idx,p_to_slot)) + return; //nothing to disconnect - if (y<h) { - if (p_slot_index) - *p_slot_index=i; - return CLICK_OUTPUT_SLOT; - } - y-=h; - } + ur->create_action("Disconnect Graph Nodes"); - if (p_click.y<(rect.pos.y+rect.size.height-style->get_margin(MARGIN_BOTTOM))) - return CLICK_PARAMETER; - else - return CLICK_NODE; + List<ShaderGraph::Connection> conns; - } + graph->get_node_connections(type,&conns); + //disconnect/reconnect dependencies + ur->add_do_method(graph.ptr(),"disconnect_node",type,from_idx,p_from_slot,to_idx,p_to_slot); + ur->add_undo_method(graph.ptr(),"connect_node",type,from_idx,p_from_slot,to_idx,p_to_slot); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); - return CLICK_NONE; } -Point2 ShaderEditor::_get_slot_pos(int p_node_id,bool p_input,int p_slot) { +void ShaderGraphView::_node_removed(int p_id) { - Ref<StyleBox> style = get_stylebox("panel","PopupMenu"); - float w = get_node_size(p_node_id).width; - Ref<Font> font = get_font("font","PopupMenu"); - float h = font->get_height()+get_constant("vseparation","PopupMenu"); - Ref<Texture> vec_icon = get_icon("NodeVecSlot","EditorIcons"); - Point2 pos = Point2( shader_graph.node_get_pos_x(p_node_id), shader_graph.node_get_pos_y(p_node_id) )-offset; - pos+=style->get_offset(); - pos.y+=h; + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Remove Shader Graph Node"); - if(p_input) { + ur->add_do_method(graph.ptr(),"node_remove",type,p_id); + ur->add_undo_method(graph.ptr(),"node_add",type,graph->node_get_type(type,p_id),p_id); + ur->add_undo_method(graph.ptr(),"node_set_state",type,p_id,graph->node_get_state(type,p_id)); + List<ShaderGraph::Connection> conns; - pos.y+=p_slot*h; - pos+=Point2( -vec_icon->get_width()/2.0, h/2.0).floor(); - return pos; - } else { + graph->get_node_connections(type,&conns); + for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) { - pos.y+=VisualServer::shader_get_input_count( shader_graph.node_get_type(p_node_id ) )*h; + if (E->get().dst_id==p_id || E->get().src_id==p_id) { + ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot); + } } - - pos.y+=p_slot*h; - pos+=Point2( w-style->get_minimum_size().width+vec_icon->get_width()/2.0, h/2.0).floor(); - - return pos; + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); } -void ShaderEditor::_node_edit_property(int p_node) { - - Ref<StyleBox> style = get_stylebox("panel","PopupMenu"); - Size2 size = get_node_size(p_node); - Point2 pos = Point2( shader_graph.node_get_pos_x(p_node), shader_graph.node_get_pos_y(p_node) )-offset; +void ShaderGraphView::_node_moved(const Vector2& p_from, const Vector2& p_to,int p_id) { - VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node); - PropertyInfo ph = VisualServer::get_singleton()->shader_node_get_type_info(type); - if (ph.type==Variant::NIL) - return; - if (ph.type==Variant::_RID) - ph.type=Variant::OBJECT; - - property_editor->edit(NULL,ph.name,ph.type,shader_graph.node_get_param(p_node),ph.hint,ph.hint_string); - - Point2 popup_pos=Point2( pos.x+(size.width-property_editor->get_size().width)/2.0,pos.y+(size.y-style->get_margin(MARGIN_BOTTOM))).floor(); - popup_pos+=get_global_pos(); - property_editor->set_pos(popup_pos); + ERR_FAIL_COND(!node_map.has(p_id)); + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Move Shader Graph Node"); + ur->add_do_method(this,"_move_node",p_id,p_to); + ur->add_undo_method(this,"_move_node",p_id,p_from); + ur->commit_action(); +} - property_editor->popup(); +void ShaderGraphView::_move_node(int p_id,const Vector2& p_to) { + ERR_FAIL_COND(!node_map.has(p_id)); + node_map[p_id]->set_offset(p_to); + graph->node_set_pos(type,p_id,p_to); } -bool ShaderEditor::has_point(const Point2& p_point) const { - int n,si; +void ShaderGraphView::_create_node(int p_id) { - return _locate_click(p_point,&n,&si)!=CLICK_NONE; -} -void ShaderEditor::_input_event(InputEvent p_event) { - - switch(p_event.type) { - - case InputEvent::MOUSE_BUTTON: { - - if (p_event.mouse_button.pressed) { - - - if (p_event.mouse_button.button_index==1) { - click_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y); - click_motion=click_pos; - click_type = _locate_click(click_pos,&click_node,&click_slot); - if( click_type!=CLICK_NONE) { - - order.erase(click_node); - order.push_back(click_node); - update(); - } - switch(click_type) { - case CLICK_INPUT_SLOT: { - click_pos=_get_slot_pos(click_node,true,click_slot); - } break; - case CLICK_OUTPUT_SLOT: { - click_pos=_get_slot_pos(click_node,false,click_slot); - } break; - case CLICK_PARAMETER: { - //open editor - _node_edit_property(click_node); - } break; - } - } - if (p_event.mouse_button.button_index==2) { + GraphNode *gn = memnew( GraphNode ); + gn->set_show_close_button(true); + Color typecol[4]={ + Color(0.9,0.4,1), + Color(0.8,1,0.2), + Color(1,0.2,0.2), + Color(0,1,1) + }; - if (click_type!=CLICK_NONE) { - click_type=CLICK_NONE; - update(); - } else { - // try to disconnect/remove - Point2 rclick_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y); - rclick_type = _locate_click(rclick_pos,&rclick_node,&rclick_slot); - if (rclick_type==CLICK_INPUT_SLOT || rclick_type==CLICK_OUTPUT_SLOT) { + switch(graph->node_get_type(type,p_id)) { - node_popup->clear(); - node_popup->add_item("Disconnect",NODE_DISCONNECT); - node_popup->set_pos(rclick_pos); - node_popup->popup(); + case ShaderGraph::NODE_INPUT: { - } + gn->set_title("Input"); - if (rclick_type==CLICK_NODE) { - node_popup->clear(); - node_popup->add_item("Remove",NODE_ERASE); - node_popup->set_pos(rclick_pos); - node_popup->popup(); - } + List<ShaderGraph::SlotInfo> si; + ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si); + int idx=0; + for (List<ShaderGraph::SlotInfo>::Element *E=si.front();E;E=E->next()) { + ShaderGraph::SlotInfo& s=E->get(); + if (s.dir==ShaderGraph::SLOT_IN) { - } + Label *l= memnew( Label ); + l->set_text(s.name); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + gn->set_slot(idx,false,0,Color(),true,s.type,typecol[s.type]); + idx++; } - } else { + } - if (p_event.mouse_button.button_index==1 && click_type!=CLICK_NONE) { + } break; // all inputs (case Shader type dependent) + case ShaderGraph::NODE_SCALAR_CONST: { + gn->set_title("Scalar"); + SpinBox *sb = memnew( SpinBox ); + sb->set_min(-100000); + sb->set_max(100000); + sb->set_step(0.001); + sb->set_val(graph->scalar_const_node_get_value(type,p_id)); + sb->connect("value_changed",this,"_scalar_const_changed",varray(p_id)); + gn->add_child(sb); + gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; //scalar constant + case ShaderGraph::NODE_VEC_CONST: { + + gn->set_title("Vector"); + Array v3p(true); + for(int i=0;i<3;i++) { + HBoxContainer *hbc = memnew( HBoxContainer ); + Label *l = memnew( Label ); + l->set_text(String::chr('X'+i)); + hbc->add_child(l); + SpinBox *sb = memnew( SpinBox ); + sb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + sb->set_min(-100000); + sb->set_max(100000); + sb->set_step(0.001); + sb->set_val(graph->vec_const_node_get_value(type,p_id)[i]); + sb->connect("value_changed",this,"_vec_const_changed",varray(p_id,v3p)); + v3p.push_back(sb); + hbc->add_child(sb); + gn->add_child(hbc); + } + gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; //vec3 constant + case ShaderGraph::NODE_RGB_CONST: { + + gn->set_title("Color"); + ColorPickerButton *cpb = memnew( ColorPickerButton ); + cpb->set_color(graph->rgb_const_node_get_value(type,p_id)); + cpb->connect("color_changed",this,"_rgb_const_changed",varray(p_id)); + gn->add_child(cpb); + Label *l = memnew( Label ); + l->set_text("RGB"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; //rgb constant (shows a color picker instead) + case ShaderGraph::NODE_XFORM_CONST: { + gn->set_title("XForm"); + ToolButton *edit = memnew( ToolButton ); + edit->set_text("edit.."); + edit->connect("pressed",this,"_xform_const_changed",varray(p_id,edit)); + gn->add_child(edit); + gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]); + + } break; // 4x4 matrix constant + case ShaderGraph::NODE_TIME: { + + gn->set_title("Time"); + Label *l = memnew( Label ); + l->set_text("(s)"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // time in seconds + case ShaderGraph::NODE_SCREEN_TEX: { + + gn->set_title("ScreenTex"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("UV"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("RGB"))); + gn->add_child(hbc); + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; // screen texture sampler (takes UV) (only usable in fragment case Shader) + case ShaderGraph::NODE_SCALAR_OP: { + + gn->set_title("ScalarOp"); + static const char* op_name[ShaderGraph::SCALAR_MAX_OP]={ + "Add", + "Sub", + "Mul", + "Div", + "Mod", + "Pow", + "Max", + "Min", + "Atan2" + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::SCALAR_MAX_OP;i++) { + + ob->add_item(op_name[i],i); + } - switch(click_type) { - case CLICK_INPUT_SLOT: - case CLICK_OUTPUT_SLOT: { + ob->select(graph->scalar_op_node_get_op(type,p_id)); + ob->connect("item_selected",this,"_scalar_op_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + + } break; // scalar vs scalar op (mul: { } break; add: { } break; div: { } break; etc) + case ShaderGraph::NODE_VEC_OP: { + + gn->set_title("VecOp"); + static const char* op_name[ShaderGraph::VEC_MAX_OP]={ + "Add", + "Sub", + "Mul", + "Div", + "Mod", + "Pow", + "Max", + "Min", + "Cross" + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::VEC_MAX_OP;i++) { + + ob->add_item(op_name[i],i); + } - Point2 dst_click_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y); - int id; - int slot; - ClickType dst_click_type = _locate_click(dst_click_pos,&id,&slot); - if (dst_click_type==CLICK_INPUT_SLOT && click_type==CLICK_OUTPUT_SLOT) { + ob->select(graph->vec_op_node_get_op(type,p_id)); + ob->connect("item_selected",this,"_vec_op_changed",varray(p_id)); + gn->add_child(ob); - shader_graph.connect(click_node,click_slot,id,slot); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); - Error err = validate_graph(); - if (err==ERR_CYCLIC_LINK) - shader_graph.disconnect(click_node,click_slot,id,slot); - _write_shader_graph(); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); - } - if (click_type==CLICK_INPUT_SLOT && dst_click_type==CLICK_OUTPUT_SLOT) { - shader_graph.connect(id,slot,click_node,click_slot); + } break; // vec3 vs vec3 op (mul: { } break;ad: { } break;div: { } break;crossprod: { } break;etc) + case ShaderGraph::NODE_VEC_SCALAR_OP: { - Error err = validate_graph(); - if (err==ERR_CYCLIC_LINK) - shader_graph.disconnect(id,slot,click_node,click_slot); - _write_shader_graph(); - } + gn->set_title("VecScalarOp"); + static const char* op_name[ShaderGraph::VEC_SCALAR_MAX_OP]={ + "Mul", + "Div", + "Pow", + }; - } break; - case CLICK_NODE: { - int new_x=shader_graph.node_get_pos_x(click_node)+(click_motion.x-click_pos.x); - int new_y=shader_graph.node_get_pos_y(click_node)+(click_motion.y-click_pos.y); - shader_graph.node_set_pos(click_node,new_x,new_y); - _write_shader_graph(); + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::VEC_SCALAR_MAX_OP;i++) { - } break; - } + ob->add_item(op_name[i],i); + } - click_type=CLICK_NONE; - update(); - } + ob->select(graph->vec_scalar_op_node_get_op(type,p_id)); + ob->connect("item_selected",this,"_vec_scalar_op_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + + } break; // vec3 vs scalar op (mul: { } break; add: { } break; div: { } break; etc) + case ShaderGraph::NODE_RGB_OP: { + + gn->set_title("RGB Op"); + static const char* op_name[ShaderGraph::RGB_MAX_OP]={ + "Screen", + "Difference", + "Darken", + "Lighten", + "Overlay", + "Dodge", + "Burn", + "SoftLight", + "HardLight" + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::RGB_MAX_OP;i++) { + + ob->add_item(op_name[i],i); } - } + ob->select(graph->rgb_op_node_get_op(type,p_id)); + ob->connect("item_selected",this,"_rgb_op_changed",varray(p_id)); + gn->add_child(ob); - case InputEvent::MOUSE_MOTION: { + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); - if (p_event.mouse_motion.button_mask&1 && click_type!=CLICK_NONE) { + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); - click_motion=Point2(p_event.mouse_button.x,p_event.mouse_button.y); - update(); - } + } break; // vec3 vs vec3 rgb op (with scalar amount): { } break; like brighten: { } break; darken: { } break; burn: { } break; dodge: { } break; multiply: { } break; etc. + case ShaderGraph::NODE_XFORM_MULT: { - } break; - } -} + gn->set_title("XFMult"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); -void ShaderEditor::_notification(int p_what) { + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],false,0,Color()); - switch(p_what) { + } break; // mat4 x mat4 + case ShaderGraph::NODE_XFORM_VEC_MULT: { - case NOTIFICATION_DRAW: { + gn->set_title("XFVecMult"); - _update_scrollbars(); - //VisualServer::get_singleton()->canvas_item_add_rect(get_canvas_item(),Rect2(Point2(),get_size()),Color(0,0,0,1)); + Button *button = memnew( Button("RotOnly")); + button->set_toggle_mode(true); + button->set_pressed(graph->xform_vec_mult_node_get_no_translation(type,p_id)); + button->connect("toggled",this,"_xform_inv_rev_changed",varray(p_id)); - for(List<int>::Element *E=order.front();E;E=E->next()) { + gn->add_child(button); - _draw_node(E->get()); - } + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("xf"))); + hbc->add_spacer(); + Label *l = memnew(Label("out")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + gn->add_child( memnew(Label("vec"))); - if (click_type==CLICK_INPUT_SLOT || click_type==CLICK_OUTPUT_SLOT) { + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); - VisualServer::get_singleton()->canvas_item_add_line(get_canvas_item(),click_pos,click_motion,Color(0.5,1,0.5,0.8),2); + } break; + case ShaderGraph::NODE_XFORM_VEC_INV_MULT: { + + gn->set_title("XFVecInvMult"); + + + Button *button = memnew( Button("RotOnly")); + button->set_toggle_mode(true); + button->set_pressed(graph->xform_vec_mult_node_get_no_translation(type,p_id)); + button->connect("toggled",this,"_xform_inv_rev_changed",varray(p_id)); + + gn->add_child(button); + + gn->add_child( memnew(Label("vec"))); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("xf"))); + hbc->add_spacer(); + Label *l = memnew(Label("out")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + + } break; // mat4 x vec3 inverse mult (with no-translation option) + case ShaderGraph::NODE_SCALAR_FUNC: { + + gn->set_title("ScalarFunc"); + static const char* func_name[ShaderGraph::SCALAR_MAX_FUNC]={ + "Sin", + "Cos", + "Tan", + "ASin", + "ACos", + "ATan", + "SinH", + "CosH", + "TanH", + "Log", + "Exp", + "Sqrt", + "Abs", + "Sign", + "Floor", + "Round", + "Ceil", + "Frac", + "Satr", + "Neg" + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::SCALAR_MAX_FUNC;i++) { + + ob->add_item(func_name[i],i); } - List<ShaderGraph::Connection> connections = shader_graph.get_connection_list(); - for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) { - - const ShaderGraph::Connection &c=E->get(); - Point2 source = _get_slot_pos(c.src_id,false,c.src_slot); - Point2 dest = _get_slot_pos(c.dst_id,true,c.dst_slot); - bool vec = VisualServer::shader_is_input_vector( shader_graph.node_get_type(c.dst_id), c.dst_slot ); - Color col = vec?Color(1,0.5,0.5,0.8):Color(1,1,0.5,0.8); - - if (click_type==CLICK_NODE && click_node==c.src_id) { + ob->select(graph->scalar_func_node_get_function(type,p_id)); + ob->connect("item_selected",this,"_scalar_func_changed",varray(p_id)); + gn->add_child(ob); - source+=click_motion-click_pos; - } + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("in"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); - if (click_type==CLICK_NODE && click_node==c.dst_id) { + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); - dest+=click_motion-click_pos; - } - VisualServer::get_singleton()->canvas_item_add_line(get_canvas_item(),source,dest,col,2); + } break; // scalar function (sin: { } break; cos: { } break; etc) + case ShaderGraph::NODE_VEC_FUNC: { - } - } break; - } -} -void ShaderEditor::_update_scrollbars() { + gn->set_title("VecFunc"); + static const char* func_name[ShaderGraph::VEC_MAX_FUNC]={ + "Normalize", + "Saturate", + "Negate", + "Reciprocal", + "RGB to HSV", + "HSV to RGB", + }; - Size2 size = get_size(); - Size2 hmin = h_scroll->get_minimum_size(); - Size2 vmin = v_scroll->get_minimum_size(); + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::VEC_MAX_FUNC;i++) { - v_scroll->set_begin( Point2(size.width - vmin.width, 0) ); - v_scroll->set_end( Point2(size.width, size.height) ); + ob->add_item(func_name[i],i); + } - h_scroll->set_begin( Point2( 0, size.height - hmin.height) ); - h_scroll->set_end( Point2(size.width-vmin.width, size.height) ); + ob->select(graph->vec_func_node_get_function(type,p_id)); + ob->connect("item_selected",this,"_vec_func_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("in"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; // vector function (normalize: { } break; negate: { } break; reciprocal: { } break; rgb2hsv: { } break; hsv2rgb: { } break; etc: { } break; etc) + case ShaderGraph::NODE_VEC_LEN: { + gn->set_title("VecLength"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("in"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("len"))); + gn->add_child(hbc); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // vec3 length + case ShaderGraph::NODE_DOT_PROD: { + + gn->set_title("DotProduct"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("dp"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + + } break; // vec3 . vec3 (dot product -> scalar output) + case ShaderGraph::NODE_VEC_TO_SCALAR: { + + gn->set_title("Vec2Scalar"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("vec"))); + hbc->add_spacer(); + Label *l=memnew(Label("x")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + l=memnew(Label("y")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l ); + l=memnew(Label("z")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + + + } break; // 1 vec3 input: { } break; 3 scalar outputs + case ShaderGraph::NODE_SCALAR_TO_VEC: { + + gn->set_title("Scalar2Vec"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("x"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("vec"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("y"))); + gn->add_child( memnew(Label("z"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + } break; // 3 scalar input: { } break; 1 vec3 output + case ShaderGraph::NODE_VEC_TO_XFORM: { + + gn->set_title("Vec2XForm"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("x"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("xf"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("y"))); + gn->add_child( memnew(Label("z"))); + gn->add_child( memnew(Label("ofs"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + gn->set_slot(3,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + + } break; // 3 vec input: { } break; 1 xform output + case ShaderGraph::NODE_XFORM_TO_VEC: { + + gn->set_title("XForm2Vec"); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("xf"))); + hbc->add_spacer(); + Label *l=memnew(Label("x")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + l=memnew(Label("y")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l ); + l=memnew(Label("z")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l); + l=memnew(Label("ofs")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; // 3 vec input: { } break; 1 xform output + case ShaderGraph::NODE_SCALAR_INTERP: { + + gn->set_title("ScalarInterp"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("interp"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + gn->add_child( memnew(Label("c"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + + } break; // scalar interpolation (with optional curve) + case ShaderGraph::NODE_VEC_INTERP: { + + gn->set_title("VecInterp"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("interp"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + gn->add_child( memnew(Label("c"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + } break; // vec3 interpolation (with optional curve) + case ShaderGraph::NODE_SCALAR_INPUT: { + + gn->set_title("ScalarUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + SpinBox *sb = memnew( SpinBox ); + sb->set_min(-100000); + sb->set_max(100000); + sb->set_step(0.001); + sb->set_val(graph->scalar_input_node_get_value(type,p_id)); + sb->connect("value_changed",this,"_scalar_input_changed",varray(p_id)); + gn->add_child(sb); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // scalar uniform (assignable in material) + case ShaderGraph::NODE_VEC_INPUT: { + + gn->set_title("VectorUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + Array v3p(true); + for(int i=0;i<3;i++) { + HBoxContainer *hbc = memnew( HBoxContainer ); + Label *l = memnew( Label ); + l->set_text(String::chr('X'+i)); + hbc->add_child(l); + SpinBox *sb = memnew( SpinBox ); + sb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + sb->set_min(-100000); + sb->set_max(100000); + sb->set_step(0.001); + sb->set_val(graph->vec_input_node_get_value(type,p_id)[i]); + sb->connect("value_changed",this,"_vec_input_changed",varray(p_id,v3p)); + v3p.push_back(sb); + hbc->add_child(sb); + gn->add_child(hbc); + } + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; // vec3 uniform (assignable in material) + case ShaderGraph::NODE_RGB_INPUT: { + + gn->set_title("ColorUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + ColorPickerButton *cpb = memnew( ColorPickerButton ); + cpb->set_color(graph->rgb_input_node_get_value(type,p_id)); + cpb->connect("color_changed",this,"_rgb_input_changed",varray(p_id)); + gn->add_child(cpb); + Label *l = memnew( Label ); + l->set_text("RGB"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + } break; // color uniform (assignable in material) + case ShaderGraph::NODE_XFORM_INPUT: { + gn->set_title("XFUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + ToolButton *edit = memnew( ToolButton ); + edit->set_text("edit.."); + edit->connect("pressed",this,"_xform_input_changed",varray(p_id,edit)); + gn->add_child(edit); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]); + + } break; // mat4 uniform (assignable in material) + case ShaderGraph::NODE_TEXTURE_INPUT: { + + gn->set_title("TexUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + TextureFrame *tex = memnew( TextureFrame ); + tex->set_expand(true); + tex->set_custom_minimum_size(Size2(80,80)); + gn->add_child(tex); + tex->set_texture(graph->texture_input_node_get_value(type,p_id)); + ToolButton *edit = memnew( ToolButton ); + edit->set_text("edit.."); + edit->connect("pressed",this,"_tex_edited",varray(p_id,edit)); + gn->add_child(edit); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("UV"))); + hbc->add_spacer(); + Label *l=memnew(Label("RGB")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child(l); + gn->add_child(hbc); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(3,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(4,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // texture input (assignable in material) + case ShaderGraph::NODE_CUBEMAP_INPUT: { + + gn->set_title("TexUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + + ToolButton *edit = memnew( ToolButton ); + edit->set_text("edit.."); + edit->connect("pressed",this,"_cube_edited",varray(p_id,edit)); + gn->add_child(edit); + + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("UV"))); + hbc->add_spacer(); + Label *l=memnew(Label("RGB")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child(l); + gn->add_child(hbc); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // cubemap input (assignable in material) + case ShaderGraph::NODE_OUTPUT: { + gn->set_title("Output"); + + List<ShaderGraph::SlotInfo> si; + ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si); + + int idx=0; + for (List<ShaderGraph::SlotInfo>::Element *E=si.front();E;E=E->next()) { + ShaderGraph::SlotInfo& s=E->get(); + if (s.dir==ShaderGraph::SLOT_OUT) { + + Label *l= memnew( Label ); + l->set_text(s.name); + l->set_align(Label::ALIGN_LEFT); + gn->add_child(l); + gn->set_slot(idx,true,s.type,typecol[s.type],false,0,Color()); + idx++; + } + } + } break; // output (case Shader type dependent) + case ShaderGraph::NODE_COMMENT: { + gn->set_title("Comment"); + TextEdit *te = memnew(TextEdit); + te->set_custom_minimum_size(Size2(100,100)); + gn->add_child(te); + te->set_text(graph->comment_node_get_text(type,p_id)); + te->connect("text_changed",this,"_comment_edited",varray(p_id,te)); - Size2 min = _get_maximum_size(); + } break; // comment - if (min.height < size.height - hmin.height) { - v_scroll->hide(); - offset.y=0; - } else { - v_scroll->show(); - v_scroll->set_max(min.height); - v_scroll->set_page(size.height - hmin.height); - offset.y=v_scroll->get_val(); } - if (min.width < size.width - vmin.width) { - - h_scroll->hide(); - offset.x=0; - } else { - - h_scroll->show(); - h_scroll->set_max(min.width); - h_scroll->set_page(size.width - vmin.width); - offset.x=h_scroll->get_val(); - } -} + gn->connect("dragged",this,"_node_moved",varray(p_id)); + gn->connect("close_request",this,"_node_removed",varray(p_id),CONNECT_DEFERRED); + graph_edit->add_child(gn); + node_map[p_id]=gn; + gn->set_offset(graph->node_get_pos(type,p_id)); -void ShaderEditor::_scroll_moved() { - offset.x=h_scroll->get_val(); - offset.y=v_scroll->get_val(); - update(); } -void ShaderEditor::_bind_methods() { - - ObjectTypeDB::bind_method( "_node_menu_item", &ShaderEditor::_node_menu_item ); - ObjectTypeDB::bind_method( "_node_add_callback", &ShaderEditor::_node_add_callback ); - ObjectTypeDB::bind_method( "_input_event", &ShaderEditor::_input_event ); - ObjectTypeDB::bind_method( "_node_param_changed", &ShaderEditor::_node_param_changed ); - ObjectTypeDB::bind_method( "_scroll_moved", &ShaderEditor::_scroll_moved ); - ObjectTypeDB::bind_method( "_vertex_item", &ShaderEditor::_vertex_item ); - ObjectTypeDB::bind_method( "_fragment_item", &ShaderEditor::_fragment_item ); - ObjectTypeDB::bind_method( "_post_item", &ShaderEditor::_post_item ); -} +void ShaderGraphView::_update_graph() { -void ShaderEditor::_read_shader_graph() { - shader_graph.clear();; - order.clear(); - List<int> nodes; - shader->get_node_list(&nodes); - int larger_id=0; - for(List<int>::Element *E=nodes.front();E;E=E->next()) { + if (block_update) + return; - if (E->get() > larger_id) - larger_id = E->get(); + for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) { - shader_graph.node_add( (VS::ShaderNodeType)shader->node_get_type(E->get()), E->get() ); - shader_graph.node_set_param( E->get(), shader->node_get_param( E->get() ) ); - Point2 pos = shader->node_get_pos(E->get()); - shader_graph.node_set_pos( E->get(), pos.x,pos.y ); - order.push_back(E->get()); + memdelete(E->get()); } - last_id=larger_id+1; + node_map.clear(); - List<Shader::Connection> connections; - shader->get_connections(&connections); - - for(List<Shader::Connection>::Element *E=connections.front();E;E=E->next()) { - - Shader::Connection &c=E->get(); - shader_graph.connect(c.src_id,c.src_slot,c.dst_id,c.dst_slot); - } + if (!graph.is_valid()) + return; - validate_graph(); - update(); -} -void ShaderEditor::_write_shader_graph() { + List<int> nl; + graph->get_node_list(type,&nl); - shader->clear(); - List<int> nodes; - shader_graph.get_node_list(&nodes); - for(List<int>::Element *E=nodes.front();E;E=E->next()) { + for(List<int>::Element *E=nl.front();E;E=E->next()) { - shader->node_add((Shader::NodeType)shader_graph.node_get_type(E->get()),E->get()); - shader->node_set_param(E->get(),shader_graph.node_get_param(E->get())); - shader->node_set_pos(E->get(),Point2( shader_graph.node_get_pos_x(E->get()),shader_graph.node_get_pos_y(E->get()) ) ); + _create_node(E->get()); } + graph_edit->clear_connections(); - List<ShaderGraph::Connection> connections = shader_graph.get_connection_list(); + List<ShaderGraph::Connection> connections; + graph->get_node_connections(type,&connections); for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) { - const ShaderGraph::Connection &c=E->get(); - shader->connect(c.src_id,c.src_slot,c.dst_id,c.dst_slot); + ERR_CONTINUE(!node_map.has(E->get().src_id) || !node_map.has(E->get().dst_id)); + graph_edit->connect_node(node_map[E->get().src_id]->get_name(),E->get().src_slot,node_map[E->get().dst_id]->get_name(),E->get().dst_slot); } -} -void ShaderEditor::_add_node_from_text(const String& p_text) { - ERR_FAIL_COND( p_text.get_slice_count(" ") != 3 ); - bool input = p_text.get_slice(" ",0)=="In:"; - String name = p_text.get_slice(" ",1); - bool vec = p_text.get_slice(" ",2)=="(vec3)"; - _node_add( input? - ( vec? VisualServer::NODE_VEC_IN : VisualServer::NODE_IN ) : - ( vec? VisualServer::NODE_VEC_OUT : VisualServer::NODE_OUT ) ); - - shader_graph.node_set_param( last_id-1,name ); - _write_shader_graph(); } -void ShaderEditor::_vertex_item(int p_item) { - - _add_node_from_text(vertex_popup->get_item_text(p_item)); -} -void ShaderEditor::_fragment_item(int p_item) { - - _add_node_from_text(fragment_popup->get_item_text(p_item)); -} -void ShaderEditor::_post_item(int p_item) { - - _add_node_from_text(post_popup->get_item_text(p_item)); -} - - -void ShaderEditor::_node_menu_item(int p_item) { - - switch(p_item) { - - case GRAPH_ADD_NODE: { - add_popup->popup_centered_ratio(); - validate_graph(); - } break; - case NODE_DISCONNECT: { - - if (rclick_type==CLICK_INPUT_SLOT) { - - List<ShaderGraph::Connection> connections = shader_graph.get_connection_list(); - for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) { - - const ShaderGraph::Connection &c=E->get(); - if( c.dst_id==rclick_node && c.dst_slot==rclick_slot) { +void ShaderGraphView::_sg_updated() { - shader_graph.disconnect(c.src_id,c.src_slot,c.dst_id,c.dst_slot); - } - } - update(); - _write_shader_graph(); - validate_graph(); - } - - if (rclick_type==CLICK_OUTPUT_SLOT) { - - List<ShaderGraph::Connection> connections = shader_graph.get_connection_list(); - for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) { - - const ShaderGraph::Connection &c=E->get(); - if( c.src_id==rclick_node && c.src_slot==rclick_slot) { - - shader_graph.disconnect(c.src_id,c.src_slot,c.dst_id,c.dst_slot); - } - } - update(); - _write_shader_graph(); - validate_graph(); - } - - } break; - case NODE_ERASE: { - - order.erase(rclick_node); - shader_graph.node_remove(rclick_node); - update(); - _write_shader_graph(); - validate_graph(); - } break; - case GRAPH_CLEAR: { - - order.clear(); - shader_graph.clear(); - last_id=1; - last_x=20; - last_y=20; - update(); - _write_shader_graph(); - validate_graph(); - - } break; + if (!graph.is_valid()) + return; + switch(graph->get_graph_error(type)) { + case ShaderGraph::GRAPH_OK: status->set_text(""); break; + case ShaderGraph::GRAPH_ERROR_CYCLIC: status->set_text("Error: Cyclic Connection Link"); break; + case ShaderGraph::GRAPH_ERROR_MISSING_CONNECTIONS: status->set_text("Error: Missing Input Connections"); break; } } -void ShaderEditor::_node_add(VisualServer::ShaderNodeType p_type) { - - shader_graph.node_add(p_type,last_id ); - shader_graph.node_set_pos(last_id ,last_x,last_y); - String test_param; - - switch(p_type) { - case VS::NODE_PARAMETER: { +void ShaderGraphView::set_graph(Ref<ShaderGraph> p_graph){ - test_param="param"; - } break; - case VS::NODE_VEC_PARAMETER: { - - test_param="vec"; - } break; - case VS::NODE_COLOR_PARAMETER: { - test_param="color"; - } break; - case VS::NODE_TEXTURE_PARAMETER: { - - test_param="tex"; - } break; - case VS::NODE_TEXTURE_2D_PARAMETER: { - - test_param="tex2D"; - } break; - case VS::NODE_TEXTURE_CUBE_PARAMETER: { - - test_param="cubemap"; - } break; - case VS::NODE_TRANSFORM_PARAMETER: { - test_param="xform"; - } break; - case VS::NODE_LABEL: { - - test_param="label"; - } break; + if (graph.is_valid()) { + graph->disconnect("updated",this,"_sg_updated"); + } + graph=p_graph; + if (graph.is_valid()) { + graph->connect("updated",this,"_sg_updated"); } + _update_graph(); + _sg_updated(); - if(test_param!="") { +} - int iter=0; - List<int> l; +void ShaderGraphView::_notification(int p_what) { - shader_graph.get_node_list(&l); + if (p_what==NOTIFICATION_ENTER_TREE) { - bool found; - String test; - do { - iter++; - test=test_param; - if (iter>1) - test+="_"+itos(iter); - found=false; - for(List<int>::Element *E=l.front();E;E=E->next()) { + ped_popup->connect("variant_changed",this,"_variant_edited"); + } + } + +void ShaderGraphView::add_node(int p_type) { + + List<int> existing; + graph->get_node_list(type,&existing); + existing.sort(); + int newid=1; + for(List<int>::Element *E=existing.front();E;E=E->next()) { + if (!E->next() || (E->get()+1!=E->next()->get())){ + newid=E->get()+1; + break; + } + } + Vector2 init_ofs(20,20); + while(true) { + bool valid=true; + for(List<int>::Element *E=existing.front();E;E=E->next()) { + Vector2 pos = graph->node_get_pos(type,E->get()); + if (init_ofs==pos) { + init_ofs+=Vector2(20,20); + valid=false; + break; - String param = shader_graph.node_get_param( E->get() ); - if (param==test) { - found=true; - break; - } } + } - } while (found); - - - shader_graph.node_set_param(last_id,test); - + if (valid) + break; } - order.push_back(last_id); - last_x+=10; - last_y+=10; - last_id++; - last_x=last_x % (int)get_size().width; - last_y=last_y % (int)get_size().height; - update(); - add_popup->hide();; - _write_shader_graph(); + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Add Shader Graph Node"); + ur->add_do_method(graph.ptr(),"node_add",type,p_type,newid); + ur->add_do_method(graph.ptr(),"node_set_pos",type,newid,init_ofs); + ur->add_undo_method(graph.ptr(),"node_remove",type,newid); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); } -void ShaderEditor::_node_add_callback() { - - TreeItem * item = add_types->get_selected(); - ERR_FAIL_COND(!item); - _node_add((VisualServer::ShaderNodeType)(int)item->get_metadata(0)); - add_popup->hide() ; +void ShaderGraphView::_bind_methods() { + + ObjectTypeDB::bind_method("_update_graph",&ShaderGraphView::_update_graph); + ObjectTypeDB::bind_method("_node_moved",&ShaderGraphView::_node_moved); + ObjectTypeDB::bind_method("_move_node",&ShaderGraphView::_move_node); + ObjectTypeDB::bind_method("_node_removed",&ShaderGraphView::_node_removed); + ObjectTypeDB::bind_method("_connection_request",&ShaderGraphView::_connection_request); + ObjectTypeDB::bind_method("_disconnection_request",&ShaderGraphView::_disconnection_request); + + ObjectTypeDB::bind_method("_scalar_const_changed",&ShaderGraphView::_scalar_const_changed); + ObjectTypeDB::bind_method("_vec_const_changed",&ShaderGraphView::_vec_const_changed); + ObjectTypeDB::bind_method("_rgb_const_changed",&ShaderGraphView::_rgb_const_changed); + ObjectTypeDB::bind_method("_xform_const_changed",&ShaderGraphView::_xform_const_changed); + ObjectTypeDB::bind_method("_scalar_op_changed",&ShaderGraphView::_scalar_op_changed); + ObjectTypeDB::bind_method("_vec_op_changed",&ShaderGraphView::_vec_op_changed); + ObjectTypeDB::bind_method("_vec_scalar_op_changed",&ShaderGraphView::_vec_scalar_op_changed); + ObjectTypeDB::bind_method("_rgb_op_changed",&ShaderGraphView::_rgb_op_changed); + ObjectTypeDB::bind_method("_xform_inv_rev_changed",&ShaderGraphView::_xform_inv_rev_changed); + ObjectTypeDB::bind_method("_scalar_func_changed",&ShaderGraphView::_scalar_func_changed); + ObjectTypeDB::bind_method("_vec_func_changed",&ShaderGraphView::_vec_func_changed); + ObjectTypeDB::bind_method("_scalar_input_changed",&ShaderGraphView::_scalar_input_changed); + ObjectTypeDB::bind_method("_vec_input_changed",&ShaderGraphView::_vec_input_changed); + ObjectTypeDB::bind_method("_xform_input_changed",&ShaderGraphView::_xform_input_changed); + ObjectTypeDB::bind_method("_rgb_input_changed",&ShaderGraphView::_rgb_input_changed); + ObjectTypeDB::bind_method("_tex_input_change",&ShaderGraphView::_tex_input_change); + ObjectTypeDB::bind_method("_cube_input_change",&ShaderGraphView::_cube_input_change); + ObjectTypeDB::bind_method("_input_name_changed",&ShaderGraphView::_input_name_changed); + ObjectTypeDB::bind_method("_tex_edited",&ShaderGraphView::_tex_edited); + ObjectTypeDB::bind_method("_variant_edited",&ShaderGraphView::_variant_edited); + ObjectTypeDB::bind_method("_cube_edited",&ShaderGraphView::_cube_edited); + ObjectTypeDB::bind_method("_comment_edited",&ShaderGraphView::_comment_edited); + + ObjectTypeDB::bind_method("_sg_updated",&ShaderGraphView::_sg_updated); } -ShaderEditor::ShaderEditor() { - - set_focus_mode(FOCUS_ALL); - - Panel* menu_panel = memnew( Panel ); - menu_panel->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END ); - menu_panel->set_end( Point2(0,22) ); - - add_child( menu_panel ); - - PopupMenu *p; - List<PropertyInfo> defaults; - - MenuButton* node_menu = memnew( MenuButton ); - node_menu->set_text("Graph"); - node_menu->set_pos( Point2( 5,0) ); - menu_panel->add_child( node_menu ); - - p=node_menu->get_popup(); - p->add_item("Add Node",GRAPH_ADD_NODE); - p->add_separator(); - p->add_item("Clear",GRAPH_CLEAR); - p->connect("item_pressed", this,"_node_menu_item"); - - MenuButton* vertex_menu = memnew( MenuButton ); - vertex_menu->set_text("Vertex"); - vertex_menu->set_pos( Point2( 49,0) ); - menu_panel->add_child( vertex_menu ); - - p=vertex_menu->get_popup(); - defaults.clear(); - VisualServer::shader_get_default_input_nodes(VisualServer::SHADER_VERTEX,&defaults); - - int id=0; - for(int i=0;i<defaults.size();i++) { - - p->add_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); - } - p->add_separator(); - id++; - - defaults.clear(); - VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_VERTEX,&defaults); - - for(int i=0;i<defaults.size();i++) { - - p->add_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); - } +ShaderGraphView::ShaderGraphView(ShaderGraph::ShaderType p_type) { + + type=p_type; + graph_edit = memnew( GraphEdit ); + block_update=false; + ped_popup = memnew( CustomPropertyEditor ); + graph_edit->add_child(ped_popup); + status = memnew( Label ); + graph_edit->get_top_layer()->add_child(status); + status->set_pos(Vector2(5,5)); + status->add_color_override("font_color_shadow",Color(0,0,0)); + status->add_color_override("font_color",Color(1,0.4,0.3)); + status->add_constant_override("shadow_as_outline",1); + status->add_constant_override("shadow_offset_x",2); + status->add_constant_override("shadow_offset_y",2); + status->set_text(""); +} - vertex_popup=p; - vertex_popup->connect("item_pressed", this,"_vertex_item"); - MenuButton* fragment_menu = memnew( MenuButton ); - fragment_menu->set_text("Fragment"); - fragment_menu->set_pos( Point2( 95 ,0) ); - menu_panel->add_child( fragment_menu ); - p=fragment_menu->get_popup(); - defaults.clear(); - VisualServer::shader_get_default_input_nodes(VisualServer::SHADER_FRAGMENT,&defaults); - id=0; - for(int i=0;i<defaults.size();i++) { +//////////////edit////////////// +void ShaderGraphEditor::edit(Ref<ShaderGraph> p_shader) { - p->add_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); + for(int i=0;i<ShaderGraph::SHADER_TYPE_MAX;i++) { + graph_edits[i]->set_graph(p_shader); } - p->add_separator(); - id++; - defaults.clear(); - VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_FRAGMENT,&defaults); +} - for(int i=0;i<defaults.size();i++) { +void ShaderGraphEditor::_add_node(int p_type) { - p->add_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); - } + ShaderGraph::ShaderType shader_type=ShaderGraph::ShaderType(tabs->get_current_tab()); - fragment_popup=p; - fragment_popup->connect("item_pressed", this,"_fragment_item"); + graph_edits[shader_type]->add_node(p_type); +} - MenuButton* post_menu = memnew( MenuButton ); - post_menu->set_text("Post"); - post_menu->set_pos( Point2( 161,0) ); - menu_panel->add_child( post_menu ); - p=post_menu->get_popup(); - defaults.clear(); - VisualServer::shader_get_default_input_nodes(VisualServer::SHADER_POST_PROCESS,&defaults); - id=0; - for(int i=0;i<defaults.size();i++) { +void ShaderGraphEditor::_notification(int p_what) { + if (p_what==NOTIFICATION_ENTER_TREE) { - p->add_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); - } - p->add_separator(); - id++; + for(int i=0;i<ShaderGraph::NODE_TYPE_MAX;i++) { - defaults.clear(); - VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_POST_PROCESS,&defaults); + if (i==ShaderGraph::NODE_OUTPUT) + continue; + String nn = node_names[i]; + String ic = nn.get_slice(":",0); + String v = nn.get_slice(":",1); + bool addsep=false; + if (nn.ends_with(":")) { + addsep=true; + } + menu->get_popup()->add_icon_item(get_icon(ic,"EditorIcons"),v,i); + if (addsep) + menu->get_popup()->add_separator(); + } + menu->get_popup()->connect("item_pressed",this,"_add_node"); - for(int i=0;i<defaults.size();i++) { - p->add_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); } +} - post_popup=p; - post_popup->connect("item_pressed", this,"_post_item"); - - - /* add popup */ - - add_popup = memnew( Popup ); - add_child(add_popup); - add_popup->set_as_toplevel(true); - Panel *add_panel = memnew( Panel ); - add_popup->add_child(add_panel); - add_panel->set_area_as_parent_rect(); +void ShaderGraphEditor::_bind_methods() { - Label *add_label = memnew (Label ); - add_label->set_pos(Point2(5,5)); - add_label->set_text("Available Nodes:"); - add_panel->add_child(add_label); + ObjectTypeDB::bind_method("_add_node",&ShaderGraphEditor::_add_node); +} - add_types = memnew( Tree ); - add_types->set_anchor( MARGIN_RIGHT, ANCHOR_END ); - add_types->set_anchor( MARGIN_BOTTOM, ANCHOR_END ); - add_types->set_begin( Point2( 20,25 ) ); - add_types->set_end( Point2( 10, 30 ) ); - add_types->set_hide_root(true); - add_types->set_columns(4); - add_types->set_select_mode(Tree::SELECT_ROW); +const char* ShaderGraphEditor::node_names[ShaderGraph::NODE_TYPE_MAX]={ + "GraphInput:Input", // all inputs (shader type dependent) + "GraphScalar:Scalar Constant", //scalar constant + "GraphVector:Vector Constant", //vec3 constant + "GraphRgb:RGB Constant", //rgb constant (shows a color picker instead) + "GraphXform:XForm Constant", // 4x4 matrix constant + "GraphTime:Time:", // time in seconds + "GraphTexscreen:Screen Sample", // screen texture sampler (takes uv) (only usable in fragment shader) + "GraphScalarOp:Scalar Operator", // scalar vs scalar op (mul", add", div", etc) + "GraphVecOp:Vector Operator", // vec3 vs vec3 op (mul",ad",div",crossprod",etc) + "GraphVecScalarOp:Scalar+Vector Operator", // vec3 vs scalar op (mul", add", div", etc) + "GraphRgbOp:RGB Operator:", // vec3 vs vec3 rgb op (with scalar amount)", like brighten", darken", burn", dodge", multiply", etc. + "GraphXformMult:XForm Multiply", // mat4 x mat4 + "GraphXformVecMult:XForm+Vector Multiply", // mat4 x vec3 mult (with no-translation option) + "GraphXformVecImult:Form+Vector InvMultiply:", // mat4 x vec3 inverse mult (with no-translation option) + "GraphXformScalarFunc:Scalar Function", // scalar function (sin", cos", etc) + "GraphXformVecFunc:Vector Function", // vector function (normalize", negate", reciprocal", rgb2hsv", hsv2rgb", etc", etc) + "GraphVecLength:Vector Length", // vec3 length + "GraphVecDp:Dot Product:", // vec3 . vec3 (dot product -> scalar output) + "GraphVecToScalars:Vector -> Scalars", // 1 vec3 input", 3 scalar outputs + "GraphScalarsToVec:Scalars -> Vector", // 3 scalar input", 1 vec3 output + "GraphXformToVecs:XForm -> Vectors", // 3 vec input", 1 xform output + "GraphVecsToXform:Vectors -> XForm:", // 3 vec input", 1 xform output + "GraphScalarInterp:Scalar Interpolate", // scalar interpolation (with optional curve) + "GraphVecInterp:Vector Interpolate:", // vec3 interpolation (with optional curve) + "GraphScalarUniform:Scalar Uniform", // scalar uniform (assignable in material) + "GraphVectorUniform:Vector Uniform", // vec3 uniform (assignable in material) + "GraphRgbUniform:RGB Uniform", // color uniform (assignable in material) + "GraphXformUniform:XForm Uniform", // mat4 uniform (assignable in material) + "GraphTextureUniform:Texture Uniform", // texture input (assignable in material) + "GraphCubeUniform:CubeMap Uniform:", // cubemap input (assignable in material) + "Output", // output (shader type dependent) + "GraphComment:Comment", // comment - TreeItem *add_types_root = add_types->create_item(NULL); - TreeItem *info_item = add_types->create_item(add_types_root); - for(int i=0;i<VisualServer::NODE_TYPE_MAX;i++) { +}; +ShaderGraphEditor::ShaderGraphEditor() { + + HBoxContainer *hbc = memnew( HBoxContainer ); + menu = memnew( MenuButton ); + menu->set_text("Add Node.."); + hbc->add_child(menu); + add_child(hbc); + + + tabs = memnew(TabContainer); + tabs->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(tabs); + const char* sname[ShaderGraph::SHADER_TYPE_MAX]={ + "Vertex", + "Fragment", + "Light" + }; + for(int i=0;i<ShaderGraph::SHADER_TYPE_MAX;i++) { + + graph_edits[i]= memnew( ShaderGraphView(ShaderGraph::ShaderType(i)) ); + add_child(graph_edits[i]); + graph_edits[i]->get_graph_edit()->set_name(sname[i]); + tabs->add_child(graph_edits[i]->get_graph_edit()); + graph_edits[i]->get_graph_edit()->connect("connection_request",graph_edits[i],"_connection_request"); + graph_edits[i]->get_graph_edit()->connect("disconnection_request",graph_edits[i],"_disconnection_request"); + graph_edits[i]->get_graph_edit()->set_right_disconnects(true); - TreeItem *item = add_types->create_item(add_types_root); - PropertyInfo prop = VisualServer::shader_node_get_type_info((VisualServer::ShaderNodeType)i); - item->set_text(0,prop.name); - item->set_text(1,itos(VisualServer::shader_get_input_count((VisualServer::ShaderNodeType)i))); - item->set_text(2,itos(VisualServer::shader_get_output_count((VisualServer::ShaderNodeType)i))); - String hint = (prop.type==Variant::_RID)?prop.hint_string:Variant::get_type_name(prop.type); - item->set_text(3,hint); - item->set_metadata(0,i); } - info_item->set_text(0,"::NODE::"); - info_item->set_custom_color(0,Color(0.6,0.1,0.1)); - info_item->set_text(1,"::INPUTS::"); - info_item->set_custom_color(1,Color(0.6,0.1,0.1)); - info_item->set_text(2,"::OUTPUTS::"); - info_item->set_custom_color(2,Color(0.6,0.1,0.1)); - info_item->set_text(3,"::PARAM::"); - info_item->set_custom_color(3,Color(0.6,0.1,0.1)); - info_item->set_selectable(0,false); - info_item->set_selectable(1,false); - info_item->set_selectable(2,false); - info_item->set_selectable(3,false); - - add_panel->add_child(add_types); - - add_confirm = memnew( Button ); - add_confirm->set_anchor( MARGIN_LEFT, ANCHOR_END ); - add_confirm->set_anchor( MARGIN_TOP, ANCHOR_END ); - add_confirm->set_anchor( MARGIN_RIGHT, ANCHOR_END ); - add_confirm->set_anchor( MARGIN_BOTTOM, ANCHOR_END ); - add_confirm->set_begin( Point2( 75, 29 ) ); - add_confirm->set_end( Point2( 10, 15 ) ); - add_confirm->set_text("Add"); - add_panel->add_child(add_confirm); - add_confirm->connect("pressed", this,"_node_add_callback"); - - last_id=1; - last_x=20; - last_y=20; - - property_editor = memnew( CustomPropertyEditor ); - add_child(property_editor); - property_editor->connect("variant_changed", this,"_node_param_changed"); - - h_scroll = memnew( HScrollBar ); - v_scroll = memnew( VScrollBar ); - - add_child(h_scroll); - add_child(v_scroll); - - h_scroll->connect("value_changed", this,"_scroll_moved"); - v_scroll->connect("value_changed", this,"_scroll_moved"); - - node_popup= memnew(PopupMenu ); - add_child(node_popup); - node_popup->set_as_toplevel(true); - - node_popup->connect("item_pressed", this,"_node_menu_item"); + tabs->set_current_tab(1); + + set_custom_minimum_size(Size2(100,300)); } -void ShaderEditorPlugin::edit(Object *p_object) { +void ShaderGraphEditorPlugin::edit(Object *p_object) { - shader_editor->edit(p_object->cast_to<Shader>()); + shader_editor->edit(p_object->cast_to<ShaderGraph>()); } -bool ShaderEditorPlugin::handles(Object *p_object) const { +bool ShaderGraphEditorPlugin::handles(Object *p_object) const { - return p_object->is_type("Shader"); + return p_object->is_type("ShaderGraph"); } -void ShaderEditorPlugin::make_visible(bool p_visible) { +void ShaderGraphEditorPlugin::make_visible(bool p_visible) { if (p_visible) { shader_editor->show(); - shader_editor->set_process(true); } else { shader_editor->hide(); - shader_editor->set_process(false); } } -ShaderEditorPlugin::ShaderEditorPlugin(EditorNode *p_node) { +ShaderGraphEditorPlugin::ShaderGraphEditorPlugin(EditorNode *p_node) { editor=p_node; - shader_editor = memnew( ShaderEditor ); - editor->get_viewport()->add_child(shader_editor); - shader_editor->set_area_as_parent_rect(); + shader_editor = memnew( ShaderGraphEditor ); shader_editor->hide(); + SpatialEditor::get_singleton()->get_shader_split()->add_child(shader_editor); +// editor->get_viewport()->add_child(shader_editor); +// shader_editor->set_area_as_parent_rect(); +// shader_editor->hide(); } -ShaderEditorPlugin::~ShaderEditorPlugin() +ShaderGraphEditorPlugin::~ShaderGraphEditorPlugin() { } -#endif + diff --git a/tools/editor/plugins/shader_graph_editor_plugin.h b/tools/editor/plugins/shader_graph_editor_plugin.h index 5b0767dc82..bd983c59be 100644 --- a/tools/editor/plugins/shader_graph_editor_plugin.h +++ b/tools/editor/plugins/shader_graph_editor_plugin.h @@ -29,122 +29,124 @@ #ifndef SHADER_GRAPH_EDITOR_PLUGIN_H #define SHADER_GRAPH_EDITOR_PLUGIN_H -#if 0 + #include "tools/editor/editor_plugin.h" #include "tools/editor/editor_node.h" #include "scene/resources/shader.h" #include "servers/visual/shader_graph.h" #include "scene/gui/tree.h" #include "scene/gui/button.h" +#include "scene/gui/graph_edit.h" #include "scene/gui/popup.h" #include "tools/editor/property_editor.h" +#include "scene/resources/shader_graph.h" /** @author Juan Linietsky <reduzio@gmail.com> */ -class ShaderEditor : public Control { - - OBJ_TYPE(ShaderEditor, Control ); - - enum MenuAction { - - GRAPH_ADD_NODE, - GRAPH_CLEAR, - NODE_DISCONNECT, - NODE_ERASE, - - }; - - enum ClickType { - CLICK_NONE, - CLICK_NODE, - CLICK_INPUT_SLOT, - CLICK_OUTPUT_SLOT, - CLICK_PARAMETER - }; - - PopupMenu *node_popup; - Popup *add_popup; - PopupMenu *vertex_popup; - PopupMenu *fragment_popup; - PopupMenu *post_popup; - Tree *add_types; - Button *add_confirm; - HScrollBar *h_scroll; - VScrollBar *v_scroll; - - Ref<Shader> shader; - List<int> order; - Set<int> active_nodes; - ShaderGraph shader_graph; - int last_x,last_y; - uint32_t last_id; - - CustomPropertyEditor *property_editor; - - Point2 offset; - ClickType click_type; - Point2 click_pos; - int click_node; - int click_slot; - Point2 click_motion; - ClickType rclick_type; - int rclick_node; - int rclick_slot; - - Size2 _get_maximum_size(); - Size2 get_node_size(int p_node) const; - void _draw_node(int p_node); - - void _add_node_from_text(const String& p_text); - void _update_scrollbars(); - void _scroll_moved(); - void _node_param_changed(); - void _node_add_callback(); - void _node_add(VisualServer::ShaderNodeType p_type); - void _node_edit_property(int p_node); - void _node_menu_item(int p_item); - void _vertex_item(int p_item); - void _fragment_item(int p_item); - void _post_item(int p_item); - - ClickType _locate_click(const Point2& p_click,int *p_node_id,int *p_slot_index) const; - Point2 _get_slot_pos(int p_node_id,bool p_input,int p_slot); - - Error validate_graph(); - - void _read_shader_graph(); - void _write_shader_graph(); - - virtual bool has_point(const Point2& p_point) const; + +class ShaderGraphView : public Node { + + OBJ_TYPE(ShaderGraphView,Node); + + + + CustomPropertyEditor *ped_popup; + bool block_update; + + Label *status; + GraphEdit *graph_edit; + Ref<ShaderGraph> graph; + int edited_id; + + ShaderGraph::ShaderType type; + + void _update_graph(); + void _create_node(int p_id); + + + + void _connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot); + void _disconnection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot); + + void _node_removed(int p_id); + void _node_moved(const Vector2& p_from, const Vector2& p_to,int p_id); + void _move_node(int p_id,const Vector2& p_to); + + void _scalar_const_changed(double p_value,int p_id); + void _vec_const_changed(double p_value, int p_id, Array p_arr); + void _rgb_const_changed(const Color& p_color, int p_id); + void _xform_const_changed(int p_id,Node* p_button); + void _scalar_op_changed(int p_op, int p_id); + void _vec_op_changed(int p_op, int p_id); + void _vec_scalar_op_changed(int p_op, int p_id); + void _rgb_op_changed(int p_op, int p_id); + void _xform_inv_rev_changed(bool p_enabled, int p_id); + void _scalar_func_changed(int p_func, int p_id); + void _vec_func_changed(int p_func, int p_id); + void _scalar_input_changed(double p_value,int p_id); + void _vec_input_changed(double p_value, int p_id, Array p_arr); + void _xform_input_changed(int p_id,Node* p_button); + void _rgb_input_changed(const Color& p_color, int p_id); + void _tex_input_change(int p_id,Node* p_button); + void _cube_input_change(int p_id); + void _input_name_changed(const String& p_name,int p_id,Node* p_line_edit); + void _tex_edited(int p_id,Node* p_button); + void _cube_edited(int p_id,Node* p_button); + void _variant_edited(); + void _comment_edited(int p_id,Node* p_button); + + void _sg_updated(); + Map<int,GraphNode*> node_map; protected: void _notification(int p_what); - void _input_event(InputEvent p_event); static void _bind_methods(); public: - void edit(Ref<Shader> p_shader); - ShaderEditor(); + void add_node(int p_type); + GraphEdit *get_graph_edit() { return graph_edit; } + void set_graph(Ref<ShaderGraph> p_graph); + + ShaderGraphView(ShaderGraph::ShaderType p_type=ShaderGraph::SHADER_TYPE_FRAGMENT); }; -class ShaderEditorPlugin : public EditorPlugin { +class ShaderGraphEditor : public VBoxContainer { - OBJ_TYPE( ShaderEditorPlugin, EditorPlugin ); + OBJ_TYPE(ShaderGraphEditor,VBoxContainer); - ShaderEditor *shader_editor; + MenuButton *menu; + TabContainer *tabs; + ShaderGraphView *graph_edits[ShaderGraph::SHADER_TYPE_MAX]; + static const char* node_names[ShaderGraph::NODE_TYPE_MAX]; + + void _add_node(int p_type); +protected: + void _notification(int p_what); + static void _bind_methods(); +public: + + void edit(Ref<ShaderGraph> p_shader); + ShaderGraphEditor(); +}; + +class ShaderGraphEditorPlugin : public EditorPlugin { + + OBJ_TYPE( ShaderGraphEditorPlugin, EditorPlugin ); + + ShaderGraphEditor *shader_editor; EditorNode *editor; public: - virtual String get_name() const { return "Shader"; } + virtual String get_name() const { return "ShaderGraph"; } bool has_main_screen() const { return false; } virtual void edit(Object *p_node); virtual bool handles(Object *p_node) const; virtual void make_visible(bool p_visible); - ShaderEditorPlugin(EditorNode *p_node); - ~ShaderEditorPlugin(); + ShaderGraphEditorPlugin(EditorNode *p_node); + ~ShaderGraphEditorPlugin(); }; #endif -#endif // SHADER_GRAPH_EDITOR_PLUGIN_H + diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp index a1f1ccf5e3..87bd8105af 100644 --- a/tools/editor/plugins/spatial_editor_plugin.cpp +++ b/tools/editor/plugins/spatial_editor_plugin.cpp @@ -535,6 +535,14 @@ SpatialEditorViewport::NavigationScheme SpatialEditorViewport::_get_navigation_s return NAVIGATION_GODOT; } +SpatialEditorViewport::NavigationZoomStyle SpatialEditorViewport::_get_navigation_zoom_style(const String& p_property) { + switch(EditorSettings::get_singleton()->get(p_property).operator int()) { + case 0: return NAVIGATION_ZOOM_VERTICAL; + case 1: return NAVIGATION_ZOOM_HORIZONTAL; + } + return NAVIGATION_ZOOM_VERTICAL; +} + bool SpatialEditorViewport::_gizmo_select(const Vector2& p_screenpos,bool p_hilite_only) { if (!spatial_editor->is_gizmo_visible()) @@ -1429,10 +1437,19 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { if (nav_scheme==NAVIGATION_MAYA && m.mod.shift) zoom_speed *= zoom_speed_modifier; - if ( m.relative_y > 0) - cursor.distance*=1+m.relative_y*zoom_speed; - else if (m.relative_y < 0) - cursor.distance/=1-m.relative_y*zoom_speed; + NavigationZoomStyle zoom_style = _get_navigation_zoom_style("3d_editor/zoom_style"); + if (zoom_style == NAVIGATION_ZOOM_HORIZONTAL) { + if ( m.relative_x > 0) + cursor.distance*=1-m.relative_x*zoom_speed; + else if (m.relative_x < 0) + cursor.distance/=1+m.relative_x*zoom_speed; + } + else { + if ( m.relative_y > 0) + cursor.distance*=1+m.relative_y*zoom_speed; + else if (m.relative_y < 0) + cursor.distance/=1-m.relative_y*zoom_speed; + } } break; @@ -3633,12 +3650,12 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { p->add_check_item("Use Default sRGB",MENU_VIEW_USE_DEFAULT_SRGB); p->add_separator(); - p->add_check_item("1 Viewport",MENU_VIEW_USE_1_VIEWPORT,KEY_MASK_ALT+KEY_1); - p->add_check_item("2 Viewports",MENU_VIEW_USE_2_VIEWPORTS,KEY_MASK_ALT+KEY_2); - p->add_check_item("2 Viewports (Alt)",MENU_VIEW_USE_2_VIEWPORTS_ALT,KEY_MASK_SHIFT+KEY_MASK_ALT+KEY_2); - p->add_check_item("3 Viewports",MENU_VIEW_USE_3_VIEWPORTS,KEY_MASK_ALT+KEY_3); - p->add_check_item("3 Viewports (Alt)",MENU_VIEW_USE_3_VIEWPORTS_ALT,KEY_MASK_SHIFT+KEY_MASK_ALT+KEY_3); - p->add_check_item("4 Viewports",MENU_VIEW_USE_4_VIEWPORTS,KEY_MASK_ALT+KEY_4); + p->add_check_item("1 Viewport",MENU_VIEW_USE_1_VIEWPORT,KEY_MASK_CMD+KEY_1); + p->add_check_item("2 Viewports",MENU_VIEW_USE_2_VIEWPORTS,KEY_MASK_CMD+KEY_2); + p->add_check_item("2 Viewports (Alt)",MENU_VIEW_USE_2_VIEWPORTS_ALT,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_2); + p->add_check_item("3 Viewports",MENU_VIEW_USE_3_VIEWPORTS,KEY_MASK_CMD+KEY_3); + p->add_check_item("3 Viewports (Alt)",MENU_VIEW_USE_3_VIEWPORTS_ALT,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_3); + p->add_check_item("4 Viewports",MENU_VIEW_USE_4_VIEWPORTS,KEY_MASK_CMD+KEY_4); p->add_separator(); p->add_check_item("Display Normal",MENU_VIEW_DISPLAY_NORMAL); diff --git a/tools/editor/plugins/spatial_editor_plugin.h b/tools/editor/plugins/spatial_editor_plugin.h index 1fdc97c49d..646a4d2d86 100644 --- a/tools/editor/plugins/spatial_editor_plugin.h +++ b/tools/editor/plugins/spatial_editor_plugin.h @@ -144,6 +144,12 @@ private: }; NavigationScheme _get_navigation_schema(const String& p_property); + enum NavigationZoomStyle { + NAVIGATION_ZOOM_VERTICAL, + NAVIGATION_ZOOM_HORIZONTAL + }; + NavigationZoomStyle _get_navigation_zoom_style(const String& p_property); + enum NavigationMode { NAVIGATION_NONE, NAVIGATION_PAN, diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index a25997108b..a7e6a0d1f9 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -42,7 +42,6 @@ void TileMapEditor::_notification(int p_what) { case NOTIFICATION_READY: { - pane_drag->connect("dragged", this,"_pane_drag"); mirror_x->set_icon( get_icon("MirrorX","EditorIcons")); mirror_y->set_icon( get_icon("MirrorY","EditorIcons")); @@ -701,23 +700,10 @@ void TileMapEditor::_tileset_settings_changed() { canvas_item_editor->update(); } -void TileMapEditor::_pane_drag(const Point2& p_to) { - - int x = theme_panel->get_margin(MARGIN_RIGHT); - - x+=p_to.x; - if (x<10) - x=10; - if (x>300) - x=300; - theme_panel->set_margin(MARGIN_RIGHT,x); -} - void TileMapEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_menu_option"),&TileMapEditor::_menu_option); ObjectTypeDB::bind_method(_MD("_canvas_draw"),&TileMapEditor::_canvas_draw); - ObjectTypeDB::bind_method(_MD("_pane_drag"),&TileMapEditor::_pane_drag); ObjectTypeDB::bind_method(_MD("_canvas_mouse_enter"),&TileMapEditor::_canvas_mouse_enter); ObjectTypeDB::bind_method(_MD("_canvas_mouse_exit"),&TileMapEditor::_canvas_mouse_exit); ObjectTypeDB::bind_method(_MD("_tileset_settings_changed"),&TileMapEditor::_tileset_settings_changed); @@ -731,36 +717,31 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { editor=p_editor; undo_redo = editor->get_undo_redo(); - theme_panel = memnew( Panel ); - theme_panel->set_anchor(MARGIN_BOTTOM,ANCHOR_END); - theme_panel->set_begin( Point2(0,26)); - theme_panel->set_end( Point2(100,0) ); - p_editor->get_viewport()->add_child(theme_panel); - theme_panel->hide(); + int mw = EDITOR_DEF("tile_map/palette_min_width",80); + Control *ec = memnew( Control); + ec->set_custom_minimum_size(Size2(mw,0)); + add_child(ec); + // Add tile palette palette = memnew( Tree ); - palette->set_area_as_parent_rect(4); - palette->set_margin(MARGIN_TOP,25);; - theme_panel->add_child(palette); - - pane_drag = memnew( PaneDrag ) ; - pane_drag->set_anchor(MARGIN_LEFT,ANCHOR_END); - pane_drag->set_begin(Point2(16,4)); - theme_panel->add_child(pane_drag); - - add_child( memnew( VSeparator )); + palette->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(palette); + // Add menu items + canvas_item_editor_hb = memnew( HBoxContainer ); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(canvas_item_editor_hb); + canvas_item_editor_hb->add_child( memnew( VSeparator )); mirror_x = memnew( ToolButton ); mirror_x->set_toggle_mode(true); mirror_x->set_tooltip("Mirror X (A)"); mirror_x->set_focus_mode(FOCUS_NONE); - add_child(mirror_x); + canvas_item_editor_hb->add_child(mirror_x); mirror_y = memnew( ToolButton ); mirror_y->set_toggle_mode(true); mirror_y->set_tooltip("Mirror Y (S)"); mirror_y->set_focus_mode(FOCUS_NONE); - add_child(mirror_y); - + canvas_item_editor_hb->add_child(mirror_y); + canvas_item_editor_hb->hide(); tool=TOOL_NONE; selection_active=false; @@ -782,12 +763,12 @@ void TileMapEditorPlugin::make_visible(bool p_visible) { if (p_visible) { tile_map_editor->show(); - tile_map_editor->theme_panel->show(); + tile_map_editor->get_canvas_item_editor_hb()->show(); } else { tile_map_editor->hide(); - tile_map_editor->theme_panel->hide(); + tile_map_editor->get_canvas_item_editor_hb()->hide(); tile_map_editor->edit(NULL); } @@ -797,7 +778,8 @@ TileMapEditorPlugin::TileMapEditorPlugin(EditorNode *p_node) { editor=p_node; tile_map_editor = memnew( TileMapEditor(p_node) ); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(tile_map_editor); + CanvasItemEditor::get_singleton()->get_palette_split()->add_child(tile_map_editor); + CanvasItemEditor::get_singleton()->get_palette_split()->move_child(tile_map_editor,0); tile_map_editor->hide(); diff --git a/tools/editor/plugins/tile_map_editor_plugin.h b/tools/editor/plugins/tile_map_editor_plugin.h index 2336507f1b..ef869591bd 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.h +++ b/tools/editor/plugins/tile_map_editor_plugin.h @@ -34,15 +34,14 @@ #include "scene/2d/tile_map.h" #include "scene/gui/tool_button.h" #include "scene/gui/button_group.h" -#include "tools/editor/pane_drag.h" /** @author Juan Linietsky <reduzio@gmail.com> */ class CanvasItemEditor; -class TileMapEditor : public HBoxContainer { +class TileMapEditor : public VBoxContainer { - OBJ_TYPE(TileMapEditor, BoxContainer ); + OBJ_TYPE(TileMapEditor, VBoxContainer ); UndoRedo *undo_redo; @@ -63,7 +62,6 @@ class TileMapEditor : public HBoxContainer { Panel *panel; TileMap *node; MenuButton *options; - PaneDrag *pane_drag; bool selection_active; Point2i selection_begin; @@ -75,6 +73,8 @@ class TileMapEditor : public HBoxContainer { ToolButton *mirror_x; ToolButton *mirror_y; + HBoxContainer *canvas_item_editor_hb; + struct CellOp { int idx; @@ -88,7 +88,6 @@ class TileMapEditor : public HBoxContainer { int get_selected_tile() const; void _update_palette(); - void _pane_drag(const Point2& p_to); void _canvas_draw(); void _menu_option(int p_option); @@ -99,14 +98,13 @@ class TileMapEditor : public HBoxContainer { void _tileset_settings_changed(); -friend class TileMapEditorPlugin; - Panel *theme_panel; protected: void _notification(int p_what); void _node_removed(Node *p_node); static void _bind_methods(); public: + HBoxContainer *get_canvas_item_editor_hb() const { return canvas_item_editor_hb; } Vector2 snap_point(const Vector2& p_point) const; bool forward_input_event(const InputEvent& p_event); void edit(Node *p_tile_map); @@ -120,6 +118,7 @@ class TileMapEditorPlugin : public EditorPlugin { TileMapEditor *tile_map_editor; EditorNode *editor; + public: virtual bool forward_input_event(const InputEvent& p_event) { return tile_map_editor->forward_input_event(p_event); } diff --git a/tools/editor/progress_dialog.cpp b/tools/editor/progress_dialog.cpp index ac54796c64..df40c5d5a5 100644 --- a/tools/editor/progress_dialog.cpp +++ b/tools/editor/progress_dialog.cpp @@ -29,7 +29,7 @@ #include "progress_dialog.h" #include "main/main.h" #include "message_queue.h" -#include "scene/gui/empty_control.h" + void BackgroundProgress::_add_task(const String& p_task,const String& p_label, int p_steps) { @@ -43,12 +43,12 @@ void BackgroundProgress::_add_task(const String& p_task,const String& p_label, i t.progress = memnew( ProgressBar ); t.progress->set_max(p_steps); t.progress->set_val(p_steps); - EmptyControl *ec = memnew( EmptyControl ); + Control *ec = memnew( Control ); ec->set_h_size_flags(SIZE_EXPAND_FILL); ec->set_v_size_flags(SIZE_EXPAND_FILL); t.progress->set_area_as_parent_rect(); ec->add_child(t.progress); - ec->set_minsize(Size2(80,5)); + ec->set_custom_minimum_size(Size2(80,5)); t.hb->add_child(ec); add_child(t.hb); diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp index 3a0f1e76b5..449e54e12f 100644 --- a/tools/editor/project_export.cpp +++ b/tools/editor/project_export.cpp @@ -1240,8 +1240,8 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) { group_options->add_child(atlas_preview); atlas_preview->show(); atlas_preview->connect("pressed",this,"_group_atlas_preview"); - EmptyControl *ec = memnew(EmptyControl ); - ec->set_minsize(Size2(150,1)); + Control *ec = memnew(Control ); + ec->set_custom_minimum_size(Size2(150,1)); gvb->add_child(ec); VBoxContainer *group_vb_right = memnew( VBoxContainer ); diff --git a/tools/editor/project_export.h b/tools/editor/project_export.h index dfe7a2d900..e437497dd2 100644 --- a/tools/editor/project_export.h +++ b/tools/editor/project_export.h @@ -40,7 +40,7 @@ #include "os/dir_access.h" #include "os/thread.h" #include "scene/gui/option_button.h" -#include "scene/gui/empty_control.h" + #include "scene/gui/slider.h" #include "tools/editor/editor_file_system.h" #include "property_editor.h" diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index 4eadd980f4..0af4a23547 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -39,7 +39,7 @@ #include "scene/gui/line_edit.h" #include "scene/gui/panel_container.h" -#include "scene/gui/empty_control.h" + #include "scene/gui/texture_frame.h" #include "scene/gui/margin_container.h" #include "io/resource_saver.h" @@ -65,7 +65,7 @@ class NewProjectDialog : public ConfirmationDialog { error->set_text(""); get_ok()->set_disabled(true); DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - if (d->change_dir(project_path->get_text())!=OK) { + if (project_path->get_text() != "" && d->change_dir(project_path->get_text())!=OK) { error->set_text("Invalid Path for Project, Path Must Exist!"); memdelete(d); return false; @@ -82,7 +82,7 @@ class NewProjectDialog : public ConfirmationDialog { } else { - if (!d->file_exists("engine.cfg")) { + if (project_path->get_text() != "" && !d->file_exists("engine.cfg")) { error->set_text("Invalid Project Path (engine.cfg must exist)."); memdelete(d); @@ -580,8 +580,8 @@ void ProjectManager::_load_recent_projects() { VBoxContainer *vb = memnew(VBoxContainer); hb->add_child(vb); - EmptyControl *ec = memnew( EmptyControl ); - ec->set_minsize(Size2(0,1)); + Control *ec = memnew( Control ); + ec->set_custom_minimum_size(Size2(0,1)); vb->add_child(ec); Label *title = memnew( Label(project_name) ); title->add_font_override("font",get_font("large","Fonts")); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 777694481b..a600683097 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -142,7 +142,7 @@ void CustomPropertyEditor::_menu_option(int p_which) { } String orig_type = res_orig->get_type(); - print_line("orig type: "+orig_type); + Object *inst = ObjectTypeDB::instance( orig_type ); Ref<Resource> res = Ref<Resource>( inst->cast_to<Resource>() ); @@ -187,6 +187,7 @@ void CustomPropertyEditor::_menu_option(int p_which) { ERR_FAIL_COND( inheritors_array.empty() ); + String intype=inheritors_array[p_which-TYPE_BASE_ID]; Object *obj = ObjectTypeDB::instance(intype); @@ -603,6 +604,7 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty if (hint_text!="") { + int idx=0; for(int i=0;i<hint_text.get_slice_count(",");i++) { @@ -620,19 +622,19 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty E=E->next(); } - int idx=0; for(Set<String>::Element *E=valid_inheritors.front();E;E=E->next()) { String t = E->get(); if (!ObjectTypeDB::can_instance(t)) continue; inheritors_array.push_back(t); + int id = TYPE_BASE_ID+idx; if (has_icon(t,"EditorIcons")) { - menu->add_icon_item(get_icon(t,"EditorIcons"),"New "+t,TYPE_BASE_ID+idx); + menu->add_icon_item(get_icon(t,"EditorIcons"),"New "+t,id); } else { - menu->add_item("New "+t,TYPE_BASE_ID+idx); + menu->add_item("New "+t,id); } idx++; @@ -970,9 +972,11 @@ void CustomPropertyEditor::_action_pressed(int p_which) { if (p_which==0) { + ERR_FAIL_COND( inheritors_array.empty() ); String intype=inheritors_array[0]; + if (hint==PROPERTY_HINT_RESOURCE_TYPE) { @@ -1876,6 +1880,14 @@ void PropertyEditor::_notification(int p_what) { if (p_what==NOTIFICATION_FIXED_PROCESS) { + if (refresh_countdown>0) { + refresh_countdown-=get_fixed_process_delta_time(); + if (refresh_countdown<=0) { + TreeItem *root = tree->get_root(); + _refresh_item(root); + } + } + changing=true; if (update_tree_pending) { @@ -1982,7 +1994,71 @@ TreeItem *PropertyEditor::get_parent_node(String p_path,HashMap<String,TreeItem* } +void PropertyEditor::_refresh_item(TreeItem *p_item) { + + if (!p_item) + return; + + String name = p_item->get_metadata(1); + + if (name!=String()) { + + if (get_instanced_node()) { + + Dictionary d = get_instanced_node()->get_instance_state(); + if (d.has(name)) { + Variant v = obj->get(name); + Variant vorig = d[name]; + + int found=-1; + for(int i=0;i<p_item->get_button_count(1);i++) { + + if (p_item->get_button_id(1,i)==3) { + found=i; + break; + } + } + + bool changed = ! (v==vorig); + + if ((found!=-1)!=changed) { + + if (changed) { + + p_item->add_button(1,get_icon("Reload","EditorIcons"),3); + } else { + + p_item->erase_button(1,found); + } + + } + + } + + } + + Dictionary d=p_item->get_metadata(0); + set_item_text(p_item,d["type"],d["name"],d["hint"],d["hint_text"]); + } + + TreeItem *c=p_item->get_children(); + + while (c) { + + _refresh_item(c); + + c=c->get_next(); + } + +} + +void PropertyEditor::refresh() { + + if (refresh_countdown>0) + return; + refresh_countdown=EditorSettings::get_singleton()->get("property_editor/auto_refresh_interval"); +} void PropertyEditor::update_tree() { @@ -3021,6 +3097,7 @@ PropertyEditor::PropertyEditor() { keying=false; read_only=false; show_categories=false; + refresh_countdown=0; } diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h index 08435ad75d..c05e13b90e 100644 --- a/tools/editor/property_editor.h +++ b/tools/editor/property_editor.h @@ -156,6 +156,7 @@ class PropertyEditor : public Control { bool keying; bool read_only; bool show_categories; + float refresh_countdown; HashMap<String,String> pending; String selected_property; @@ -185,6 +186,7 @@ class PropertyEditor : public Control { void _draw_flags(Object *ti,const Rect2& p_rect); Node *get_instanced_node(); + void _refresh_item(TreeItem *p_item); UndoRedo *undo_redo; protected: @@ -203,6 +205,8 @@ public: void update_tree(); void update_property(const String& p_prop); + void refresh(); + void edit(Object* p_object); void set_keying(bool p_active); diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index 3455582bbc..f5d9e83bf8 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -212,17 +212,50 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (!_validate_no_foreign()) break; - Node * node=scene_tree->get_selected(); - ERR_FAIL_COND(!node->get_parent()); - int current_pos = node->get_index(); - int next_pos = current_pos + ((p_tool==TOOL_MOVE_DOWN)?1:-1); + bool MOVING_DOWN = (p_tool == TOOL_MOVE_DOWN); + bool MOVING_UP = !MOVING_DOWN; - if (next_pos< 0 || next_pos>=node->get_parent()->get_child_count()) - break; // invalid position + Node *common_parent = scene_tree->get_selected()->get_parent(); + List<Node*> selection = editor_selection->get_selected_node_list(); + selection.sort_custom<Node::Comparator>(); // sort by index + if (MOVING_DOWN) + selection.invert(); + + int lowest_id = common_parent->get_child_count() - 1; + int highest_id = 0; + for (List<Node*>::Element *E = selection.front(); E; E = E->next()) { + int index = E->get()->get_index(); + + if (index > highest_id) highest_id = index; + if (index < lowest_id) lowest_id = index; + + if (E->get()->get_parent() != common_parent) + common_parent = NULL; + } + + if (!common_parent || (MOVING_DOWN && highest_id >= common_parent->get_child_count() - MOVING_DOWN) || (MOVING_UP && lowest_id == 0)) + break; // one or more nodes can not be moved + + if (selection.size() == 1) editor_data->get_undo_redo().create_action("Move Node In Parent"); + if (selection.size() > 1) editor_data->get_undo_redo().create_action("Move Nodes In Parent"); + + for (int i = 0; i < selection.size(); i++) { + Node *top_node = selection[i]; + Node *bottom_node = selection[selection.size() - 1 - i]; + + ERR_FAIL_COND(!top_node->get_parent()); + ERR_FAIL_COND(!bottom_node->get_parent()); + + int top_node_pos = top_node->get_index(); + int bottom_node_pos = bottom_node->get_index(); + + int top_node_pos_next = top_node_pos + (MOVING_DOWN ? 1 : -1); + int bottom_node_pos_next = bottom_node_pos + (MOVING_DOWN ? 1 : -1); + + editor_data->get_undo_redo().add_do_method(top_node->get_parent(), "move_child", top_node, top_node_pos_next); + editor_data->get_undo_redo().add_undo_method(bottom_node->get_parent(), "move_child", bottom_node, bottom_node_pos); + } - editor_data->get_undo_redo().create_action("Move Node In Parent"); - editor_data->get_undo_redo().add_do_method(node->get_parent(),"move_child",node,next_pos); - editor_data->get_undo_redo().add_undo_method(node->get_parent(),"move_child",node,current_pos); editor_data->get_undo_redo().commit_action(); } break; diff --git a/tools/editor/script_editor_debugger.cpp b/tools/editor/script_editor_debugger.cpp index 024377ad18..5043c5cdcd 100644 --- a/tools/editor/script_editor_debugger.cpp +++ b/tools/editor/script_editor_debugger.cpp @@ -478,8 +478,6 @@ void ScriptEditorDebugger::_notification(int p_what) { if (!connection->is_connected()) { stop(); editor->notify_child_process_exited(); //somehow, exited - msgdialog->set_text("Process being debugged exited."); - msgdialog->popup_centered(Size2(250,100)); break; }; |