Multiple, simultaneous node editing spuport!!
..but will you be brave enough to try it? :)
This commit is contained in:
parent
0d77277a86
commit
eff2931b2a
9 changed files with 199 additions and 10 deletions
|
@ -39,7 +39,7 @@ void EditorHistory::_cleanup_history() {
|
|||
bool fail=false;
|
||||
|
||||
for(int j=0;j<history[i].path.size();j++) {
|
||||
if (!history[i].path[j].res.is_null())
|
||||
if (!history[i].path[j].ref.is_null())
|
||||
continue;
|
||||
|
||||
if (ObjectDB::get_instance(history[i].path[j].object))
|
||||
|
@ -70,10 +70,10 @@ void EditorHistory::_add_object(ObjectID p_object,const String& p_property,int p
|
|||
|
||||
Object *obj = ObjectDB::get_instance(p_object);
|
||||
ERR_FAIL_COND(!obj);
|
||||
Resource *r = obj->cast_to<Resource>();
|
||||
Reference *r = obj->cast_to<Reference>();
|
||||
Obj o;
|
||||
if (r)
|
||||
o.res=RES(r);
|
||||
o.ref=REF(r);
|
||||
o.object=p_object;
|
||||
o.property=p_property;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class EditorHistory {
|
|||
|
||||
struct Obj {
|
||||
|
||||
RES res;
|
||||
REF ref;
|
||||
ObjectID object;
|
||||
String property;
|
||||
};
|
||||
|
|
|
@ -1427,10 +1427,7 @@ void EditorNode::_edit_current() {
|
|||
|
||||
resources_dock->add_resource(Ref<Resource>(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<Node>();
|
||||
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 */
|
||||
|
|
BIN
tools/editor/icons/icon_multi_node_edit.png
Normal file
BIN
tools/editor/icons/icon_multi_node_edit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 576 B |
118
tools/editor/multi_node_edit.cpp
Normal file
118
tools/editor/multi_node_edit.cpp
Normal file
|
@ -0,0 +1,118 @@
|
|||
#include "multi_node_edit.h"
|
||||
#include "editor_node.h"
|
||||
|
||||
bool MultiNodeEdit::_set(const StringName& p_name, const Variant& p_value){
|
||||
|
||||
Node *es = EditorNode::get_singleton()->get_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<NodePath>::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<NodePath>::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<PropertyInfo> *p_list) const{
|
||||
|
||||
HashMap<String,PLData> usage;
|
||||
|
||||
Node *es = EditorNode::get_singleton()->get_edited_scene();
|
||||
if (!es)
|
||||
return;
|
||||
|
||||
int nc=0;
|
||||
|
||||
List<PLData*> datas;
|
||||
|
||||
for (const List<NodePath>::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<PropertyInfo> plist;
|
||||
n->get_property_list(&plist,true);
|
||||
|
||||
for(List<PropertyInfo>::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<PLData*>::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()
|
||||
{
|
||||
}
|
32
tools/editor/multi_node_edit.h
Normal file
32
tools/editor/multi_node_edit.h
Normal file
|
@ -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<NodePath> 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<PropertyInfo> *p_list) const;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
|
||||
void clear_nodes();
|
||||
void add_node(const NodePath& p_node);
|
||||
|
||||
MultiNodeEdit();
|
||||
};
|
||||
|
||||
#endif // MULTI_NODE_EDIT_H
|
|
@ -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<MultiNodeEdit>()) { //kind of hacky
|
||||
|
||||
obj->set(p_name,p_value);
|
||||
_changed_callbacks(obj,p_name);
|
||||
|
|
|
@ -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<MultiNodeEdit> mne = memnew( MultiNodeEdit );
|
||||
for (const Map<Node*,Object*>::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;i<TOOL_BUTTON_MAX;i++)
|
||||
tool_buttons[i]->set_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)");
|
||||
|
|
|
@ -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<StringName> base_path,Vector<StringName> new_base_path,Node * p_node, List<Pair<NodePath,NodePath> > *p_renames);
|
||||
|
||||
|
|
Loading…
Reference in a new issue