summaryrefslogtreecommitdiff
path: root/tools/editor/scene_tree_dock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/editor/scene_tree_dock.cpp')
-rw-r--r--tools/editor/scene_tree_dock.cpp125
1 files changed, 102 insertions, 23 deletions
diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp
index f693036bc2..84b34cf130 100644
--- a/tools/editor/scene_tree_dock.cpp
+++ b/tools/editor/scene_tree_dock.cpp
@@ -79,10 +79,22 @@ Node* SceneTreeDock::instance(const String& p_file) {
//accept->get_cancel()->hide();
accept->get_ok()->set_text("Ugh");
accept->set_text(String("Error loading scene from ")+p_file);
- accept->popup_centered(Size2(300,70));;
+ accept->popup_centered(Size2(300,70));
return NULL;
}
+ // If the scene hasn't been saved yet a cyclical dependency cannot exist.
+ if (edited_scene->get_filename()!="") {
+
+ if (_cyclical_dependency_exists(edited_scene->get_filename(), instanced_scene)) {
+
+ accept->get_ok()->set_text("Ok");
+ accept->set_text(String("Cannot instance the scene '")+p_file+String("' because the current scene exists within one of its' nodes."));
+ accept->popup_centered(Size2(300,90));
+ return NULL;
+ }
+ }
+
instanced_scene->generate_instance_state();
instanced_scene->set_filename( Globals::get_singleton()->localize_path(p_file) );
@@ -100,6 +112,35 @@ Node* SceneTreeDock::instance(const String& p_file) {
}
+bool SceneTreeDock::_cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node) {
+ int childCount = p_desired_node->get_child_count();
+
+ if (p_desired_node->get_filename()==p_target_scene_path) {
+ return true;
+ }
+
+ for (int i=0;i<childCount;i++) {
+ Node* child=p_desired_node->get_child(i);
+
+ if(_cyclical_dependency_exists(p_target_scene_path,child)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+static String _get_name_num_separator() {
+ switch(EditorSettings::get_singleton()->get("scenetree_editor/duplicate_node_name_num_separator").operator int()) {
+ case 0: return "";
+ case 1: return " ";
+ case 2: return "_";
+ case 3: return "-";
+ }
+ return " ";
+}
+
void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
current_option=p_tool;
@@ -212,17 +253,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;
+
+ 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());
- if (next_pos< 0 || next_pos>=node->get_parent()->get_child_count())
- break; // invalid position
+ 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;
@@ -285,17 +359,21 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
int num=nums.to_int();
- if (num<2)
- num=2;
+ if (num<1)
+ num=1;
else
num++;
- name=name.substr(0,name.length()-nums.length()).strip_edges();
- String attempt=name+" "+itos(num);
+ String nnsep = _get_name_num_separator();
+ name = name.substr(0,name.length()-nums.length()).strip_edges();
+ if ( name.substr(name.length()-nnsep.length(),nnsep.length()) == nnsep) {
+ name = name.substr(0,name.length()-nnsep.length());
+ }
+ String attempt = (name + nnsep + itos(num)).strip_edges();
while(parent->has_node(attempt)) {
num++;
- attempt=name+" "+itos(num);
+ attempt = (name + nnsep + itos(num)).strip_edges();
}
dup->set_name(attempt);
@@ -393,7 +471,7 @@ void SceneTreeDock::_notification(int p_what) {
switch(p_what) {
- case NOTIFICATION_ENTER_SCENE: {
+ case NOTIFICATION_ENTER_TREE: {
static const char* button_names[TOOL_BUTTON_MAX]={
"New",
@@ -913,7 +991,7 @@ void SceneTreeDock::_delete_confirm() {
//delete from animation
for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) {
Node *n = E->get();
- if (!n->is_inside_scene() || !n->get_parent())
+ if (!n->is_inside_tree() || !n->get_parent())
continue;
fill_path_renames(n,NULL,&path_renames);
@@ -924,7 +1002,7 @@ void SceneTreeDock::_delete_confirm() {
//delete for read
for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) {
Node *n = E->get();
- if (!n->is_inside_scene() || !n->get_parent())
+ if (!n->is_inside_tree() || !n->get_parent())
continue;
List<Node*> owned;
@@ -981,14 +1059,15 @@ void SceneTreeDock::_create() {
if (edited_scene) {
-
+ // If root exists in edited scene
parent = scene_tree->get_selected();
- ERR_FAIL_COND(!parent);
- } else {
+ if( !parent )
+ parent = edited_scene;
+ } else {
+ // If no root exist in edited scene
parent = scene_root;
ERR_FAIL_COND(!parent);
-
}
Object *c = create_dialog->instance_selected();
@@ -1176,7 +1255,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
tb = memnew( ToolButton );
tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_INSTANCE, false));
- tb->set_tooltip("Instance a Node from scene file.");
+ tb->set_tooltip("Instance a scene file as a Node.");
hbc_top->add_child(tb);
tool_buttons[TOOL_INSTANCE]=tb;