summaryrefslogtreecommitdiff
path: root/editor/scene_tree_dock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/scene_tree_dock.cpp')
-rw-r--r--editor/scene_tree_dock.cpp188
1 files changed, 131 insertions, 57 deletions
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 935946bf24..f0114b393d 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -301,6 +301,8 @@ bool SceneTreeDock::_track_inherit(const String &p_target_scene_path, Node *p_de
Ref<PackedScene> data = ResourceLoader::load(path);
if (data.is_valid()) {
p = data->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
+ if (!p)
+ continue;
instances.push_back(p);
} else
break;
@@ -338,7 +340,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
tree->edit_selected();
}
} break;
- case TOOL_NEW: {
+ case TOOL_NEW:
+ case TOOL_REPARENT_TO_NEW_NODE: {
if (!profile_allow_editing) {
break;
@@ -394,7 +397,14 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
if (!profile_allow_editing) {
break;
}
- create_dialog->popup_create(false, true, scene_tree->get_selected()->get_class());
+
+ Node *selected = scene_tree->get_selected();
+ if (!selected && !editor_selection->get_selected_node_list().empty())
+ selected = editor_selection->get_selected_node_list().front()->get();
+
+ if (selected)
+ create_dialog->popup_create(false, true, selected->get_class());
+
} break;
case TOOL_ATTACH_SCRIPT: {
@@ -462,8 +472,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
Node *n = Object::cast_to<Node>(selection[i]);
Ref<Script> existing = n->get_script();
- if (existing.is_valid()) {
- const RefPtr empty;
+ Ref<Script> empty = EditorNode::get_singleton()->get_object_custom_type_base(n);
+ if (existing != empty) {
editor_data->get_undo_redo().add_do_method(n, "set_script", empty);
editor_data->get_undo_redo().add_undo_method(n, "set_script", existing);
}
@@ -976,9 +986,10 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
} else {
new_node = Object::cast_to<Node>(ClassDB::instance(selected_favorite_root));
}
+
if (!new_node) {
- ERR_EXPLAIN("Creating root from favorite '" + selected_favorite_root + "' failed. Creating 'Node' instead.");
new_node = memnew(Node);
+ ERR_PRINTS("Creating root from favorite '" + selected_favorite_root + "' failed. Creating 'Node' instead.");
}
} else {
switch (p_tool) {
@@ -1527,10 +1538,7 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
Node *validate = new_parent;
while (validate) {
- if (p_nodes.find(validate) != -1) {
- ERR_EXPLAIN("Selection changed at some point.. can't reparent");
- ERR_FAIL();
- }
+ ERR_FAIL_COND_MSG(p_nodes.find(validate) != -1, "Selection changed at some point.. can't reparent.");
validate = validate->get_parent();
}
//ok all valid
@@ -1905,6 +1913,54 @@ Node *SceneTreeDock::_get_selection_group_tail(Node *p_node, List<Node *> p_list
return tail;
}
+void SceneTreeDock::_do_create(Node *p_parent) {
+ Object *c = create_dialog->instance_selected();
+
+ ERR_FAIL_COND(!c);
+ Node *child = Object::cast_to<Node>(c);
+ ERR_FAIL_COND(!child);
+
+ editor_data->get_undo_redo().create_action(TTR("Create Node"));
+
+ if (edited_scene) {
+
+ editor_data->get_undo_redo().add_do_method(p_parent, "add_child", child);
+ editor_data->get_undo_redo().add_do_method(child, "set_owner", edited_scene);
+ editor_data->get_undo_redo().add_do_method(editor_selection, "clear");
+ editor_data->get_undo_redo().add_do_method(editor_selection, "add_node", child);
+ editor_data->get_undo_redo().add_do_reference(child);
+ editor_data->get_undo_redo().add_undo_method(p_parent, "remove_child", child);
+
+ String new_name = p_parent->validate_child_name(child);
+ ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
+ editor_data->get_undo_redo().add_do_method(sed, "live_debug_create_node", edited_scene->get_path_to(p_parent), child->get_class(), new_name);
+ editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(p_parent)).plus_file(new_name)));
+
+ } else {
+
+ editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", child);
+ editor_data->get_undo_redo().add_do_method(scene_tree, "update_tree");
+ editor_data->get_undo_redo().add_do_reference(child);
+ editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)NULL);
+ }
+
+ editor_data->get_undo_redo().commit_action();
+ editor->push_item(c);
+ editor_selection->clear();
+ editor_selection->add_node(child);
+ if (Object::cast_to<Control>(c)) {
+ //make editor more comfortable, so some controls don't appear super shrunk
+ Control *ct = Object::cast_to<Control>(c);
+
+ Size2 ms = ct->get_minimum_size();
+ if (ms.width < 4)
+ ms.width = 40;
+ if (ms.height < 4)
+ ms.height = 40;
+ ct->set_size(ms);
+ }
+}
+
void SceneTreeDock::_create() {
if (current_option == TOOL_NEW) {
@@ -1923,67 +1979,78 @@ void SceneTreeDock::_create() {
ERR_FAIL_COND(!parent);
}
- Object *c = create_dialog->instance_selected();
+ _do_create(parent);
- ERR_FAIL_COND(!c);
- Node *child = Object::cast_to<Node>(c);
- ERR_FAIL_COND(!child);
-
- editor_data->get_undo_redo().create_action(TTR("Create Node"));
-
- if (edited_scene) {
+ } else if (current_option == TOOL_REPLACE) {
+ List<Node *> selection = editor_selection->get_selected_node_list();
+ ERR_FAIL_COND(selection.size() <= 0);
- editor_data->get_undo_redo().add_do_method(parent, "add_child", child);
- editor_data->get_undo_redo().add_do_method(child, "set_owner", edited_scene);
- editor_data->get_undo_redo().add_do_method(editor_selection, "clear");
- editor_data->get_undo_redo().add_do_method(editor_selection, "add_node", child);
- editor_data->get_undo_redo().add_do_reference(child);
- editor_data->get_undo_redo().add_undo_method(parent, "remove_child", child);
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change type of node(s)"));
- String new_name = parent->validate_child_name(child);
- ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
- editor_data->get_undo_redo().add_do_method(sed, "live_debug_create_node", edited_scene->get_path_to(parent), child->get_class(), new_name);
- editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)).plus_file(new_name)));
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ Node *n = E->get();
+ ERR_FAIL_COND(!n);
- } else {
+ Object *c = create_dialog->instance_selected();
- editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", child);
- editor_data->get_undo_redo().add_do_method(scene_tree, "update_tree");
- editor_data->get_undo_redo().add_do_reference(child);
- editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)NULL);
- }
+ ERR_FAIL_COND(!c);
+ Node *newnode = Object::cast_to<Node>(c);
+ ERR_FAIL_COND(!newnode);
- editor_data->get_undo_redo().commit_action();
- editor->push_item(c);
- editor_selection->clear();
- editor_selection->add_node(child);
- if (Object::cast_to<Control>(c)) {
- //make editor more comfortable, so some controls don't appear super shrunk
- Control *ct = Object::cast_to<Control>(c);
-
- Size2 ms = ct->get_minimum_size();
- if (ms.width < 4)
- ms.width = 40;
- if (ms.height < 4)
- ms.height = 40;
- ct->set_size(ms);
+ ur->add_do_method(this, "replace_node", n, newnode, true, false);
+ ur->add_do_reference(newnode);
+ ur->add_undo_method(this, "replace_node", newnode, n, false, false);
+ ur->add_undo_reference(n);
}
- } else if (current_option == TOOL_REPLACE) {
+ ur->commit_action();
+ } else if (current_option == TOOL_REPARENT_TO_NEW_NODE) {
List<Node *> selection = editor_selection->get_selected_node_list();
ERR_FAIL_COND(selection.size() <= 0);
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+
+ // Find top level node in selection
+ bool only_one_top_node = true;
+
+ Node *first = selection.front()->get();
+ ERR_FAIL_COND(!first);
+ int smaller_path_to_top = first->get_path_to(scene_root).get_name_count();
+ Node *top_node = first;
+
+ for (List<Node *>::Element *E = selection.front()->next(); E; E = E->next()) {
Node *n = E->get();
ERR_FAIL_COND(!n);
- Object *c = create_dialog->instance_selected();
+ int path_length = n->get_path_to(scene_root).get_name_count();
- ERR_FAIL_COND(!c);
- Node *newnode = Object::cast_to<Node>(c);
- ERR_FAIL_COND(!newnode);
+ if (top_node != n) {
+ if (smaller_path_to_top > path_length) {
+ top_node = n;
+ smaller_path_to_top = path_length;
+ only_one_top_node = true;
+ } else if (smaller_path_to_top == path_length) {
+ if (only_one_top_node && top_node->get_parent() != n->get_parent())
+ only_one_top_node = false;
+ }
+ }
+ }
- replace_node(n, newnode);
+ Node *parent = NULL;
+ if (only_one_top_node)
+ parent = top_node->get_parent();
+ else
+ parent = top_node->get_parent()->get_parent();
+
+ _do_create(parent);
+
+ Vector<Node *> nodes;
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ nodes.push_back(E->get());
}
+
+ // This works because editor_selection was cleared and populated with last created node in _do_create()
+ Node *last_created = editor_selection->get_selected_node_list().front()->get();
+ _do_reparent(last_created, -1, nodes, true);
}
scene_tree->get_scene_tree()->call_deferred("grab_focus");
@@ -2184,8 +2251,7 @@ void SceneTreeDock::_normalize_drop(Node *&to_node, int &to_pos, int p_type) {
//drop at above selected node
if (to_node == EditorNode::get_singleton()->get_edited_scene()) {
to_node = NULL;
- ERR_EXPLAIN("Cannot perform drop above the root node!");
- ERR_FAIL();
+ ERR_FAIL_MSG("Cannot perform drop above the root node!");
}
to_pos = to_node->get_index();
@@ -2325,6 +2391,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->clear();
Ref<Script> existing_script;
+ bool exisiting_script_removable = true;
if (selection.size() == 1) {
Node *selected = selection[0];
@@ -2344,6 +2411,10 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->add_separator();
existing_script = selected->get_script();
+
+ if (EditorNode::get_singleton()->get_object_custom_type_base(selected) == existing_script) {
+ exisiting_script_removable = false;
+ }
}
if (profile_allow_script_editing) {
@@ -2355,7 +2426,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->add_icon_shortcut(get_icon("ScriptExtend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_ATTACH_SCRIPT);
}
}
- if (selection.size() > 1 || existing_script.is_valid()) {
+ if (selection.size() > 1 || (existing_script.is_valid() && exisiting_script_removable)) {
menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT);
}
menu->add_separator();
@@ -2373,6 +2444,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->add_icon_shortcut(get_icon("MoveDown", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN);
menu->add_icon_shortcut(get_icon("Duplicate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE);
menu->add_icon_shortcut(get_icon("Reparent", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT);
+ menu->add_icon_shortcut(get_icon("ReparentToNewNode", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent_to_new_node"), TOOL_REPARENT_TO_NEW_NODE);
menu->add_icon_shortcut(get_icon("NewRoot", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/make_root"), TOOL_MAKE_ROOT);
}
}
@@ -2637,6 +2709,7 @@ void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_feature_profile_changed"), &SceneTreeDock::_feature_profile_changed);
ClassDB::bind_method(D_METHOD("instance"), &SceneTreeDock::instance);
+ ClassDB::bind_method(D_METHOD("get_tree_editor"), &SceneTreeDock::get_tree_editor);
ClassDB::bind_method(D_METHOD("replace_node"), &SceneTreeDock::replace_node);
ADD_SIGNAL(MethodInfo("remote_tree_selected"));
@@ -2669,6 +2742,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
ED_SHORTCUT("scene_tree/move_down", TTR("Move Down"), KEY_MASK_CMD | KEY_DOWN);
ED_SHORTCUT("scene_tree/duplicate", TTR("Duplicate"), KEY_MASK_CMD | KEY_D);
ED_SHORTCUT("scene_tree/reparent", TTR("Reparent"));
+ ED_SHORTCUT("scene_tree/reparent_to_new_node", TTR("Reparent to New Node"));
ED_SHORTCUT("scene_tree/make_root", TTR("Make Scene Root"));
ED_SHORTCUT("scene_tree/merge_from_scene", TTR("Merge From Scene"));
ED_SHORTCUT("scene_tree/save_branch_as_scene", TTR("Save Branch as Scene"));