From eff2931b2ab4db9d47d822e5ef66dce941c90d98 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 25 Aug 2015 00:08:45 -0300 Subject: [PATCH] Multiple, simultaneous node editing spuport!! ..but will you be brave enough to try it? :) --- tools/editor/editor_data.cpp | 6 +- tools/editor/editor_data.h | 2 +- tools/editor/editor_node.cpp | 11 +- tools/editor/icons/icon_multi_node_edit.png | Bin 0 -> 576 bytes tools/editor/multi_node_edit.cpp | 118 ++++++++++++++++++++ tools/editor/multi_node_edit.h | 32 ++++++ tools/editor/property_editor.cpp | 3 +- tools/editor/scene_tree_dock.cpp | 35 +++++- tools/editor/scene_tree_dock.h | 2 + 9 files changed, 199 insertions(+), 10 deletions(-) create mode 100644 tools/editor/icons/icon_multi_node_edit.png create mode 100644 tools/editor/multi_node_edit.cpp create mode 100644 tools/editor/multi_node_edit.h diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp index 7f42f19a9b4..ac68fcb07b4 100644 --- a/tools/editor/editor_data.cpp +++ b/tools/editor/editor_data.cpp @@ -39,7 +39,7 @@ void EditorHistory::_cleanup_history() { bool fail=false; for(int j=0;jcast_to(); + Reference *r = obj->cast_to(); Obj o; if (r) - o.res=RES(r); + o.ref=REF(r); o.object=p_object; o.property=p_property; diff --git a/tools/editor/editor_data.h b/tools/editor/editor_data.h index cbec2295f69..f888e3c14ff 100644 --- a/tools/editor/editor_data.h +++ b/tools/editor/editor_data.h @@ -45,7 +45,7 @@ class EditorHistory { struct Obj { - RES res; + REF ref; ObjectID object; String property; }; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 597fb236f59..113f7c8306c 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -1427,10 +1427,7 @@ void EditorNode::_edit_current() { resources_dock->add_resource(Ref(current_res)); //top_pallete->set_current_tab(1); - } - - - if (current_obj->is_type("Node")) { + } else if (current_obj->is_type("Node")) { Node * current_node = current_obj->cast_to(); ERR_FAIL_COND(!current_node); @@ -1445,6 +1442,12 @@ void EditorNode::_edit_current() { //top_pallete->set_current_tab(0); + } else { + + property_editor->edit( current_obj ); + //scene_tree_dock->set_selected(current_node); + //object_menu->get_popup()->clear(); + } /* Take care of PLUGIN EDITOR */ diff --git a/tools/editor/icons/icon_multi_node_edit.png b/tools/editor/icons/icon_multi_node_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..357c062cbd4fc457c52fa90c859cfb1b62a4d74b GIT binary patch literal 576 zcmV-G0>AxUh)Mte02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00F2;L_t(I%Wcy=YZYM-1>oo2 zyGFzyT3gx;Rw{ypSQ{(IEmzhsu8g!egQK{I4-xUIT-j_8cz|E!K!XLG zjEEnZd8xj?!&F4vsK%oS-9fS0ja}GL=O{DxRZ3?{>TIQO)RnMW3|5Nnpq8|rnP;(t zyLf_+lgLkE-r!SNvswCkt# z4=~lqL2q$!ak_2W%eWm8ZFg!H4c_AxK6mcIQros05iysUgKpTiUh%(;JisW1fAkpu O0000get_edited_scene(); + if (!es) + return false; + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + + ur->create_action("MultiNode Set "+String(p_name)); + for (const List::Element *E=nodes.front();E;E=E->next()) { + + if (!es->has_node(E->get())) + continue; + + Node*n=es->get_node(E->get()); + if (!n) + continue; + + ur->add_do_property(n,p_name,p_value); + ur->add_undo_property(n,p_name,n->get(p_name)); + + } + + ur->commit_action(); + return true; +} + +bool MultiNodeEdit::_get(const StringName& p_name,Variant &r_ret) const { + + Node *es = EditorNode::get_singleton()->get_edited_scene(); + if (!es) + return false; + + for (const List::Element *E=nodes.front();E;E=E->next()) { + + if (!es->has_node(E->get())) + continue; + + const Node*n=es->get_node(E->get()); + if (!n) + continue; + + bool found; + r_ret=n->get(p_name,&found); + if (found) + return true; + + } + + return false; +} + +void MultiNodeEdit::_get_property_list( List *p_list) const{ + + HashMap usage; + + Node *es = EditorNode::get_singleton()->get_edited_scene(); + if (!es) + return; + + int nc=0; + + List datas; + + for (const List::Element *E=nodes.front();E;E=E->next()) { + + if (!es->has_node(E->get())) + continue; + + Node*n=es->get_node(E->get()); + if (!n) + continue; + + List plist; + n->get_property_list(&plist,true); + + for(List::Element *F=plist.front();F;F=F->next()) { + + if (!usage.has(F->get().name)) { + PLData pld; + pld.uses=0; + pld.info=F->get(); + usage[F->get().name]=pld; + datas.push_back(usage.getptr(F->get().name)); + } + + usage[F->get().name].uses++; + } + + nc++; + } + + for (List::Element *E=datas.front();E;E=E->next()) { + + if (nc==E->get()->uses) { + p_list->push_back(E->get()->info); + } + } + + +} + +void MultiNodeEdit::clear_nodes() { + + nodes.clear(); +} + +void MultiNodeEdit::add_node(const NodePath& p_node){ + + nodes.push_back(p_node); +} + +MultiNodeEdit::MultiNodeEdit() +{ +} diff --git a/tools/editor/multi_node_edit.h b/tools/editor/multi_node_edit.h new file mode 100644 index 00000000000..5a0cabf4be7 --- /dev/null +++ b/tools/editor/multi_node_edit.h @@ -0,0 +1,32 @@ +#ifndef MULTI_NODE_EDIT_H +#define MULTI_NODE_EDIT_H + +#include "scene/main/node.h" + +class MultiNodeEdit : public Reference { + + OBJ_TYPE(MultiNodeEdit,Reference); + + List nodes; + struct PLData { + int uses; + PropertyInfo info; + }; + +protected: + + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List *p_list) const; + +public: + + + + void clear_nodes(); + void add_node(const NodePath& p_node); + + MultiNodeEdit(); +}; + +#endif // MULTI_NODE_EDIT_H diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 955c426d2b2..78a1f0ad15c 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -39,6 +39,7 @@ #include "editor_settings.h" #include "editor_import_export.h" #include "editor_node.h" +#include "multi_node_edit.h" void CustomPropertyEditor::_notification(int p_what) { @@ -2676,7 +2677,7 @@ void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value) { } } - if (!undo_redo) { + if (!undo_redo || obj->cast_to()) { //kind of hacky obj->set(p_name,p_value); _changed_callbacks(obj,p_name); diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index ae0b58a6653..276f2dea33a 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -35,7 +35,7 @@ #include "tools/editor/plugins/canvas_item_editor_plugin.h" #include "script_editor_debugger.h" #include "tools/editor/plugins/script_editor_plugin.h" - +#include "multi_node_edit.h" void SceneTreeDock::_unhandled_key_input(InputEvent p_event) { @@ -449,6 +449,19 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { reparent_dialog->popup_centered_ratio(); reparent_dialog->set_current( nodeset ); + } break; + case TOOL_MULTI_EDIT: { + + Node*root=EditorNode::get_singleton()->get_edited_scene(); + if (!root) + break; + Ref mne = memnew( MultiNodeEdit ); + for (const Map::Element *E=EditorNode::get_singleton()->get_editor_selection()->get_selection().front();E;E=E->next()) { + mne->add_node(root->get_path_to(E->key())); + } + + EditorNode::get_singleton()->push_item(mne.ptr()); + } break; case TOOL_ERASE: { @@ -507,6 +520,7 @@ void SceneTreeDock::_notification(int p_what) { "MoveDown", "Duplicate", "Reparent", + "MultiNodeEdit", "Remove", }; @@ -515,6 +529,8 @@ void SceneTreeDock::_notification(int p_what) { for(int i=0;iset_icon(get_icon(button_names[i],"EditorIcons")); + EditorNode::get_singleton()->get_editor_selection()->connect("selection_changed",this,"_selection_changed"); + } break; } } @@ -1075,9 +1091,19 @@ void SceneTreeDock::_update_tool_buttons() { tool_buttons[TOOL_DUPLICATE]->set_disabled(disable_root); tool_buttons[TOOL_REPARENT]->set_disabled(disable_root); tool_buttons[TOOL_ERASE]->set_disabled(disable); + tool_buttons[TOOL_MULTI_EDIT]->set_disabled(EditorNode::get_singleton()->get_editor_selection()->get_selection().size()<2); + } + +void SceneTreeDock::_selection_changed() { + + tool_buttons[TOOL_MULTI_EDIT]->set_disabled(EditorNode::get_singleton()->get_editor_selection()->get_selection().size()<2); + +} + + void SceneTreeDock::_create() { @@ -1262,6 +1288,7 @@ void SceneTreeDock::_bind_methods() { ObjectTypeDB::bind_method(_MD("_delete_confirm"),&SceneTreeDock::_delete_confirm); ObjectTypeDB::bind_method(_MD("_node_prerenamed"),&SceneTreeDock::_node_prerenamed); ObjectTypeDB::bind_method(_MD("_import_subscene"),&SceneTreeDock::_import_subscene); + ObjectTypeDB::bind_method(_MD("_selection_changed"),&SceneTreeDock::_selection_changed); ObjectTypeDB::bind_method(_MD("instance"),&SceneTreeDock::instance); } @@ -1364,6 +1391,12 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec hbc_bottom->add_spacer(); + tb = memnew( ToolButton ); + tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_MULTI_EDIT, false)); + tb->set_tooltip("Multi-Edit Selected Nodes"); + hbc_bottom->add_child(tb); + tool_buttons[TOOL_MULTI_EDIT]=tb; + tb = memnew( ToolButton ); tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_ERASE, false)); tb->set_tooltip("Erase Selected Node(s)"); diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h index f0bbbad6bec..b1c53d2ff94 100644 --- a/tools/editor/scene_tree_dock.h +++ b/tools/editor/scene_tree_dock.h @@ -62,6 +62,7 @@ class SceneTreeDock : public VBoxContainer { TOOL_MOVE_DOWN, TOOL_DUPLICATE, TOOL_REPARENT, + TOOL_MULTI_EDIT, TOOL_ERASE, TOOL_BUTTON_MAX }; @@ -119,6 +120,7 @@ class SceneTreeDock : public VBoxContainer { void _import_subscene(); bool _validate_no_foreign(); + void _selection_changed(); void _fill_path_renames(Vector base_path,Vector new_base_path,Node * p_node, List > *p_renames);