/*************************************************************************/ /* scene_tree_dock.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "scene_tree_dock.h" #include "editor_node.h" #include "globals.h" #include "os/keyboard.h" #include "scene/resources/packed_scene.h" #include "editor_settings.h" #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) { uint32_t sc = p_event.key.get_scancode_with_modifiers(); if (!p_event.key.pressed || p_event.key.echo) return; switch(sc) { case KEY_MASK_CMD|KEY_A: { _tool_selected(TOOL_NEW); } break; case KEY_MASK_CMD|KEY_D: { _tool_selected(TOOL_DUPLICATE); } break; case KEY_MASK_CMD|KEY_UP: { _tool_selected(TOOL_MOVE_UP); } break; case KEY_MASK_CMD|KEY_DOWN: { _tool_selected(TOOL_MOVE_DOWN); } break; case KEY_MASK_SHIFT|KEY_DELETE: { _tool_selected(TOOL_ERASE, true); } break; case KEY_DELETE: { _tool_selected(TOOL_ERASE); } break; } } Node* SceneTreeDock::instance(const String& p_file) { Node *parent = scene_tree->get_selected(); if (!parent || !edited_scene) { current_option=-1; //accept->get_cancel()->hide(); accept->get_ok()->set_text("Ok :( "); accept->set_text("No parent to instance a child at."); accept->popup_centered_minsize(); return NULL; }; ERR_FAIL_COND_V(!parent,NULL); Node*instanced_scene=NULL; Ref sdata = ResourceLoader::load(p_file); if (sdata.is_valid()) instanced_scene=sdata->instance(); if (!instanced_scene) { current_option=-1; //accept->get_cancel()->hide(); accept->get_ok()->set_text("Ugh"); accept->set_text(String("Error loading scene from ")+p_file); accept->popup_centered_minsize(); 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_minsize(); return NULL; } } instanced_scene->generate_instance_state(); instanced_scene->set_filename( Globals::get_singleton()->localize_path(p_file) ); editor_data->get_undo_redo().create_action("Instance Scene"); editor_data->get_undo_redo().add_do_method(parent,"add_child",instanced_scene); editor_data->get_undo_redo().add_do_method(instanced_scene,"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",instanced_scene); editor_data->get_undo_redo().add_do_reference(instanced_scene); editor_data->get_undo_redo().add_undo_method(parent,"remove_child",instanced_scene); String new_name = parent->validate_child_name(instanced_scene->get_name()); ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); editor_data->get_undo_redo().add_do_method(sed,"live_debug_instance_node",edited_scene->get_path_to(parent),p_file,new_name); editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+new_name)); editor_data->get_undo_redo().commit_action(); return instanced_scene; } 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;iget_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; switch(p_tool) { case TOOL_NEW: { if (!_validate_no_foreign()) break; create_dialog->popup_centered_ratio(); } break; case TOOL_INSTANCE: { Node *scene = edited_scene; if (!scene) { current_option=-1; //confirmation->get_cancel()->hide(); accept->get_ok()->set_text("I see.."); accept->set_text("This operation can't be done without a tree root."); accept->popup_centered_minsize(); break; } if (!_validate_no_foreign()) break; file->set_mode(EditorFileDialog::MODE_OPEN_FILE); List extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions); file->clear_filters(); for(int i=0;iadd_filter("*."+extensions[i]+" ; "+extensions[i].to_upper()); } //file->set_current_path(current_path); file->popup_centered_ratio(); } break; case TOOL_REPLACE: { create_dialog->popup_centered_ratio(); } break; case TOOL_CONNECT: { Node *current = scene_tree->get_selected(); if (!current) break; if (!_validate_no_foreign()) break; connect_dialog->popup_centered_ratio(); connect_dialog->set_node(current); } break; case TOOL_GROUP: { Node *current = scene_tree->get_selected(); if (!current) break; if (!_validate_no_foreign()) break; groups_editor->set_current(current); groups_editor->popup_centered_ratio(); } break; case TOOL_SCRIPT: { Node *selected = scene_tree->get_selected(); if (!selected) break; if (!_validate_no_foreign()) break; Ref