diff options
Diffstat (limited to 'editor/editor_node.cpp')
-rw-r--r-- | editor/editor_node.cpp | 479 |
1 files changed, 332 insertions, 147 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 52f356813a..353dce5b20 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -62,6 +62,8 @@ #include "editor/import/editor_scene_importer_gltf.h" #include "editor/import/resource_importer_bitmask.h" #include "editor/import/resource_importer_csv_translation.h" +#include "editor/import/resource_importer_image.h" +#include "editor/import/resource_importer_layered_texture.h" #include "editor/import/resource_importer_obj.h" #include "editor/import/resource_importer_scene.h" #include "editor/import/resource_importer_texture.h" @@ -72,14 +74,16 @@ #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/animation_state_machine_editor.h" #include "editor/plugins/animation_tree_editor_plugin.h" +#include "editor/plugins/animation_tree_player_editor_plugin.h" #include "editor/plugins/asset_library_editor_plugin.h" +#include "editor/plugins/audio_stream_editor_plugin.h" #include "editor/plugins/baked_lightmap_editor_plugin.h" #include "editor/plugins/camera_editor_plugin.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/collision_polygon_2d_editor_plugin.h" #include "editor/plugins/collision_polygon_editor_plugin.h" #include "editor/plugins/collision_shape_2d_editor_plugin.h" -#include "editor/plugins/cube_grid_theme_editor_plugin.h" +#include "editor/plugins/cpu_particles_editor_plugin.h" #include "editor/plugins/curve_editor_plugin.h" #include "editor/plugins/editor_preview_plugins.h" #include "editor/plugins/gi_probe_editor_plugin.h" @@ -90,6 +94,7 @@ #include "editor/plugins/material_editor_plugin.h" #include "editor/plugins/mesh_editor_plugin.h" #include "editor/plugins/mesh_instance_editor_plugin.h" +#include "editor/plugins/mesh_library_editor_plugin.h" #include "editor/plugins/multimesh_editor_plugin.h" #include "editor/plugins/navigation_polygon_editor_plugin.h" #include "editor/plugins/particles_2d_editor_plugin.h" @@ -103,18 +108,20 @@ #include "editor/plugins/script_editor_plugin.h" #include "editor/plugins/script_text_editor.h" #include "editor/plugins/shader_editor_plugin.h" -#include "editor/plugins/shader_graph_editor_plugin.h" #include "editor/plugins/skeleton_2d_editor_plugin.h" #include "editor/plugins/skeleton_editor_plugin.h" +#include "editor/plugins/skeleton_ik_editor_plugin.h" #include "editor/plugins/spatial_editor_plugin.h" #include "editor/plugins/sprite_editor_plugin.h" #include "editor/plugins/sprite_frames_editor_plugin.h" #include "editor/plugins/style_box_editor_plugin.h" +#include "editor/plugins/text_editor.h" #include "editor/plugins/texture_editor_plugin.h" #include "editor/plugins/texture_region_editor_plugin.h" #include "editor/plugins/theme_editor_plugin.h" #include "editor/plugins/tile_map_editor_plugin.h" #include "editor/plugins/tile_set_editor_plugin.h" +#include "editor/plugins/visual_shader_editor_plugin.h" #include "editor/pvrtc_compress.h" #include "editor/register_exporters.h" #include "editor/script_editor_debugger.h" @@ -153,7 +160,6 @@ void EditorNode::_update_scene_tabs() { scene_tabs->set_current_tab(editor_data.get_edited_scene()); - int current = editor_data.get_edited_scene(); if (scene_tabs->get_offset_buttons_visible()) { // move add button to fixed position on the tabbar if (scene_tab_add->get_parent() == scene_tabs) { @@ -405,6 +411,18 @@ void EditorNode::_notification(int p_what) { } } +void EditorNode::_on_plugin_ready(Object *p_script, const String &p_activate_name) { + Ref<Script> script = Object::cast_to<Script>(p_script); + if (script.is_null()) + return; + if (p_activate_name.length()) { + set_addon_plugin_enabled(p_activate_name, true); + } + project_settings->update_plugins(); + project_settings->hide(); + push_item(script.operator->()); +} + void EditorNode::_fs_changed() { for (Set<FileDialog *>::Element *E = file_dialogs.front(); E; E = E->next()) { @@ -587,7 +605,6 @@ void EditorNode::edit_node(Node *p_node) { void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path) { editor_data.apply_changes_in_editors(); - int flg = 0; if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources")) flg |= ResourceSaver::FLAG_COMPRESS; @@ -596,9 +613,7 @@ void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const St Error err = ResourceSaver::save(path, p_resource, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS); if (err != OK) { - current_option = -1; - accept->set_text(TTR("Error saving resource!")); - accept->popup_centered_minsize(); + show_accept(TTR("Error saving resource!"), TTR("OK")); return; } @@ -684,26 +699,21 @@ void EditorNode::_dialog_display_save_error(String p_file, Error p_error) { if (p_error) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - switch (p_error) { case ERR_FILE_CANT_WRITE: { - accept->set_text(TTR("Can't open file for writing:") + " " + p_file.get_extension()); + show_accept(TTR("Can't open file for writing:") + " " + p_file.get_extension(), TTR("OK")); } break; case ERR_FILE_UNRECOGNIZED: { - accept->set_text(TTR("Requested file format unknown:") + " " + p_file.get_extension()); + show_accept(TTR("Requested file format unknown:") + " " + p_file.get_extension(), TTR("OK")); } break; default: { - accept->set_text(TTR("Error while saving.")); + show_accept(TTR("Error while saving."), TTR("OK")); } break; } - - accept->popup_centered_minsize(); } } @@ -711,34 +721,29 @@ void EditorNode::_dialog_display_load_error(String p_file, Error p_error) { if (p_error) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - switch (p_error) { case ERR_CANT_OPEN: { - accept->set_text(vformat(TTR("Can't open '%s'. The file could have been moved or deleted."), p_file.get_file())); + show_accept(vformat(TTR("Can't open '%s'. The file could have been moved or deleted."), p_file.get_file()), TTR("OK")); } break; case ERR_PARSE_ERROR: { - accept->set_text(vformat(TTR("Error while parsing '%s'."), p_file.get_file())); + show_accept(vformat(TTR("Error while parsing '%s'."), p_file.get_file()), TTR("OK")); } break; case ERR_FILE_CORRUPT: { - accept->set_text(vformat(TTR("Unexpected end of file '%s'."), p_file.get_file())); + show_accept(vformat(TTR("Unexpected end of file '%s'."), p_file.get_file()), TTR("OK")); } break; case ERR_FILE_NOT_FOUND: { - accept->set_text(vformat(TTR("Missing '%s' or its dependencies."), p_file.get_file())); + show_accept(vformat(TTR("Missing '%s' or its dependencies."), p_file.get_file()), TTR("OK")); } break; default: { - accept->set_text(vformat(TTR("Error while loading '%s'."), p_file.get_file())); + show_accept(vformat(TTR("Error while loading '%s'."), p_file.get_file()), TTR("OK")); } break; } - - accept->popup_centered_minsize(); } } @@ -956,8 +961,6 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { int x = (img->get_width() - vp_size) / 2; int y = (img->get_height() - vp_size) / 2; - img->convert(Image::FORMAT_RGB8); - if (vp_size < preview_size) { // just square it. img->crop_from_point(x, y, vp_size, vp_size); @@ -972,6 +975,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { // We could get better pictures with better filters img->resize(preview_size, preview_size, Image::INTERPOLATE_CUBIC); } + img->convert(Image::FORMAT_RGB8); img->flip_y(); @@ -999,10 +1003,7 @@ void EditorNode::_save_scene(String p_file, int idx) { if (!scene) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("This operation can't be done without a tree root.")); - accept->popup_centered_minsize(); + show_accept(TTR("This operation can't be done without a tree root."), TTR("OK")); return; } @@ -1030,10 +1031,7 @@ void EditorNode::_save_scene(String p_file, int idx) { if (err != OK) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied.")); - accept->popup_centered_minsize(); + show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("OK")); return; } @@ -1041,10 +1039,7 @@ void EditorNode::_save_scene(String p_file, int idx) { // (hacky but needed for the tree to update properly) Node *dummy_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); if (!dummy_scene) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied.")); - accept->popup_centered_minsize(); + show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("OK")); return; } memdelete(dummy_scene); @@ -1055,8 +1050,23 @@ void EditorNode::_save_scene(String p_file, int idx) { flg |= ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS; err = ResourceSaver::save(p_file, sdata, flg); - Map<RES, bool> processed; - _save_edited_subresources(scene, processed, flg); + //Map<RES, bool> processed; + //this method is slow and not always works, deprecating + //_save_edited_subresources(scene, processed, flg); + { //instead, just find globally unsaved subresources and save them + + List<Ref<Resource> > cached; + ResourceCache::get_cached_resources(&cached); + for (List<Ref<Resource> >::Element *E = cached.front(); E; E = E->next()) { + + Ref<Resource> res = E->get(); + if (res->is_edited() && res->get_path().is_resource_file()) { + ResourceSaver::save(res->get_path(), res, flg); + res->set_edited(false); + } + } + } + editor_data.save_editor_external_data(); if (err == OK) { scene->set_filename(ProjectSettings::get_singleton()->localize_path(p_file)); @@ -1072,10 +1082,35 @@ void EditorNode::_save_scene(String p_file, int idx) { } } +void EditorNode::save_all_scenes_and_restart() { + + _menu_option_confirm(RUN_STOP, true); + exiting = true; + + _save_all_scenes(); + + String to_reopen; + if (get_tree()->get_edited_scene_root()) { + to_reopen = get_tree()->get_edited_scene_root()->get_filename(); + } + + get_tree()->quit(); + String exec = OS::get_singleton()->get_executable_path(); + + List<String> args; + args.push_back("--path"); + args.push_back(ProjectSettings::get_singleton()->get_resource_path()); + args.push_back("-e"); + if (to_reopen != String()) { + args.push_back(to_reopen); + } + + OS::get_singleton()->set_restart_on_exit(true, args); +} + void EditorNode::_save_all_scenes() { - int i = _next_unsaved_scene(true, 0); - while (i != -1) { + for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { Node *scene = editor_data.get_edited_scene_root(i); if (scene && scene->get_filename() != "") { if (i != editor_data.get_edited_scene()) @@ -1083,7 +1118,6 @@ void EditorNode::_save_all_scenes() { else _save_scene_with_preview(scene->get_filename()); } // else: ignore new scenes - i = _next_unsaved_scene(true, ++i); } _save_default_environment(); @@ -1167,10 +1201,7 @@ void EditorNode::_dialog_action(String p_file) { ml = ResourceLoader::load(p_file, "MeshLibrary"); if (ml.is_null()) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("Can't load MeshLibrary for merging!")); - accept->popup_centered_minsize(); + show_accept(TTR("Can't load MeshLibrary for merging!"), TTR("OK")); return; } } @@ -1183,11 +1214,7 @@ void EditorNode::_dialog_action(String p_file) { Error err = ResourceSaver::save(p_file, ml); if (err) { - - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("Error saving MeshLibrary!")); - accept->popup_centered_minsize(); + show_accept(TTR("Error saving MeshLibrary!"), TTR("OK")); return; } @@ -1199,10 +1226,7 @@ void EditorNode::_dialog_action(String p_file) { tileset = ResourceLoader::load(p_file, "TileSet"); if (tileset.is_null()) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("Can't load TileSet for merging!")); - accept->popup_centered_minsize(); + show_accept(TTR("Can't load TileSet for merging!"), TTR("OK")); return; } @@ -1215,10 +1239,7 @@ void EditorNode::_dialog_action(String p_file) { Error err = ResourceSaver::save(p_file, tileset); if (err) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("Error saving TileSet!")); - accept->popup_centered_minsize(); + show_accept(TTR("Error saving TileSet!"), TTR("OK")); return; } } break; @@ -1359,8 +1380,7 @@ void EditorNode::_save_default_environment() { if (fallback.is_valid() && fallback->get_path().is_resource_file()) { Map<RES, bool> processed; _find_and_save_edited_subresources(fallback.ptr(), processed, 0); - if (fallback->get_last_modified_time() != fallback->get_import_last_modified_time()) - save_resource_in_path(fallback, fallback->get_path()); + save_resource_in_path(fallback, fallback->get_path()); } } @@ -1496,7 +1516,7 @@ void EditorNode::_edit_current() { if (main_plugin) { // special case if use of external editor is true - if (main_plugin->get_name() == "Script" && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) { + if (main_plugin->get_name() == "Script" && current_obj->get_class_name() != StringName("VisualScript") && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) { if (!changing_scene) main_plugin->edit(current_obj); } @@ -1573,10 +1593,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { Node *scene = editor_data.get_edited_scene_root(); if (!scene) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("There is no defined scene to run.")); - accept->popup_centered_minsize(); + show_accept(TTR("There is no defined scene to run."), TTR("OK")); return; } @@ -1630,10 +1647,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { if (scene->get_filename() == "") { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("Current scene was never saved, please save it prior to running.")); - accept->popup_centered_minsize(); + show_accept(TTR("Current scene was never saved, please save it prior to running."), TTR("OK")); return; } @@ -1664,10 +1678,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { if (error != OK) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("Could not start subprocess!")); - accept->popup_centered_minsize(); + show_accept(TTR("Could not start subprocess!"), TTR("OK")); return; } @@ -1756,6 +1767,11 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } else { tab_closing = editor_data.get_edited_scene(); } + if (!editor_data.get_edited_scene_root(tab_closing)) { + // empty tab + _scene_tab_closed(tab_closing); + break; + } } // fallthrough case SCENE_TAB_CLOSE: @@ -1785,10 +1801,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (!scene) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("This operation can't be done without a tree root.")); - accept->popup_centered_minsize(); + show_accept(TTR("This operation can't be done without a tree root."), TTR("OK")); break; } @@ -1851,10 +1864,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (!editor_data.get_edited_scene_root()) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("This operation can't be done without a scene.")); - accept->popup_centered_minsize(); + show_accept(TTR("This operation can't be done without a scene."), TTR("OK")); break; } @@ -1874,10 +1884,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { //Make sure that the scene has a root before trying to convert to tileset if (!editor_data.get_edited_scene_root()) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("This operation can't be done without a root node.")); - accept->popup_centered_minsize(); + show_accept(TTR("This operation can't be done without a root node."), TTR("OK")); break; } @@ -1894,18 +1901,11 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; - case SETTINGS_EXPORT_PREFERENCES: { - - //project_export_settings->popup_centered_ratio(); - } break; case FILE_IMPORT_SUBSCENE: { if (!editor_data.get_edited_scene_root()) { - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("This operation can't be done without a selected node.")); - accept->popup_centered_minsize(); + show_accept(TTR("This operation can't be done without a selected node."), TTR("OK")); break; } @@ -1935,25 +1935,29 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case EDIT_UNDO: { if (Input::get_singleton()->get_mouse_button_mask() & 0x7) { - break; // can't undo while mouse buttons are pressed - } - - String action = editor_data.get_undo_redo().get_current_action_name(); - if (action != "") - log->add_message("UNDO: " + action); + log->add_message("Can't UNDO while mouse buttons are pressed."); + } else { + String action = editor_data.get_undo_redo().get_current_action_name(); - editor_data.get_undo_redo().undo(); + if (!editor_data.get_undo_redo().undo()) { + log->add_message("There is nothing to UNDO."); + } else if (action != "") { + log->add_message("UNDO: " + action); + } + } } break; case EDIT_REDO: { - if (Input::get_singleton()->get_mouse_button_mask() & 0x7) - break; // can't redo while mouse buttons are pressed - - editor_data.get_undo_redo().redo(); - String action = editor_data.get_undo_redo().get_current_action_name(); - if (action != "") - log->add_message("REDO: " + action); - + if (Input::get_singleton()->get_mouse_button_mask() & 0x7) { + log->add_message("Can't REDO while mouse buttons are pressed."); + } else { + if (!editor_data.get_undo_redo().redo()) { + log->add_message("There is nothing to REDO."); + } else { + String action = editor_data.get_undo_redo().get_current_action_name(); + log->add_message("REDO: " + action); + } + } } break; case EDIT_REVERT: { @@ -2062,6 +2066,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { project_settings->popup_project_settings(); } break; + case RUN_PROJECT_DATA_FOLDER: { + + OS::get_singleton()->shell_open(OS::get_singleton()->get_user_data_dir()); + } break; case FILE_QUIT: case RUN_PROJECT_MANAGER: { @@ -2174,10 +2182,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { OS::get_singleton()->set_low_processor_usage_mode(false); EditorSettings::get_singleton()->set_project_metadata("editor_options", "update_always", true); - current_option = -1; - accept->get_ok()->set_text(TTR("I see...")); - accept->set_text(TTR("This option is deprecated. Situations where refresh must be forced are now considered a bug. Please report.")); - accept->popup_centered_minsize(); + show_accept(TTR("This option is deprecated. Situations where refresh must be forced are now considered a bug. Please report."), TTR("OK")); } break; case SETTINGS_UPDATE_CHANGES: { @@ -2197,6 +2202,14 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { settings_config_dialog->popup_edit_settings(); } break; + case SETTINGS_EDITOR_DATA_FOLDER: { + + OS::get_singleton()->shell_open(EditorSettings::get_singleton()->get_data_dir()); + } break; + case SETTINGS_EDITOR_CONFIG_FOLDER: { + + OS::get_singleton()->shell_open(EditorSettings::get_singleton()->get_settings_dir()); + } break; case SETTINGS_MANAGE_EXPORT_TEMPLATES: { export_template_manager->popup_manager(); @@ -2248,6 +2261,13 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { about->popup_centered_minsize(Size2(780, 500) * EDSCALE); } break; + case SET_VIDEO_DRIVER_SAVE_AND_RESTART: { + + ProjectSettings::get_singleton()->set("rendering/quality/driver/driver_name", video_driver_request); + ProjectSettings::get_singleton()->save(); + + save_all_scenes_and_restart(); + } break; default: { if (p_option >= IMPORT_PLUGIN_BASE) { } @@ -2539,6 +2559,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled) EditorPlugin *ep = memnew(EditorPlugin); ep->set_script(script.get_ref_ptr()); + ep->set_dir_cache(p_addon); plugin_addons[p_addon] = ep; add_editor_plugin(ep); @@ -2776,10 +2797,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b if (!lpath.begins_with("res://")) { - current_option = -1; - accept->get_ok()->set_text(TTR("Ugh")); - accept->set_text(TTR("Error loading scene, it must be inside the project path. Use 'Import' to open the scene, then save it inside the project path.")); - accept->popup_centered_minsize(); + show_accept(TTR("Error loading scene, it must be inside the project path. Use 'Import' to open the scene, then save it inside the project path."), TTR("OK")); opening_prev = false; return ERR_FILE_NOT_FOUND; } @@ -3079,6 +3097,7 @@ void EditorNode::register_editor_types() { ClassDB::register_class<EditorInspectorPlugin>(); ClassDB::register_class<EditorProperty>(); ClassDB::register_class<AnimationTrackEditPlugin>(); + ClassDB::register_class<ScriptCreateDialog>(); // FIXME: Is this stuff obsolete, or should it be ported to new APIs? ClassDB::register_class<EditorScenePostImport>(); @@ -3193,6 +3212,13 @@ Error EditorNode::export_preset(const String &p_preset, const String &p_path, bo return OK; } +void EditorNode::show_accept(const String &p_text, const String &p_title) { + current_option = -1; + accept->get_ok()->set_text(p_title); + accept->set_text(p_text); + accept->popup_centered_minsize(); +} + void EditorNode::show_warning(const String &p_text, const String &p_title) { warning->set_text(p_text); @@ -3839,6 +3865,7 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseButton> mb = p_input; if (mb.is_valid()) { + if (scene_tabs->get_hovered_tab() >= 0) { if (mb->get_button_index() == BUTTON_MIDDLE && mb->is_pressed()) { _scene_tab_closed(scene_tabs->get_hovered_tab()); @@ -3848,6 +3875,26 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { _menu_option_confirm(FILE_NEW_SCENE, true); } } + if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { + + // context menu + scene_tabs_context_menu->clear(); + scene_tabs_context_menu->set_size(Size2(1, 1)); + + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/new_scene"), FILE_NEW_SCENE); + if (scene_tabs->get_hovered_tab() >= 0) { + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene"), FILE_SAVE_SCENE); + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene_as"), FILE_SAVE_AS_SCENE); + } + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_all_scenes"), FILE_SAVE_ALL_SCENES); + if (scene_tabs->get_hovered_tab() >= 0) { + scene_tabs_context_menu->add_separator(); + scene_tabs_context_menu->add_item(TTR("Play This Scene"), RUN_PLAY_SCENE); + scene_tabs_context_menu->add_item(TTR("Close Tab"), FILE_CLOSE); + } + scene_tabs_context_menu->set_position(mb->get_global_position()); + scene_tabs_context_menu->popup(); + } } } @@ -3897,7 +3944,7 @@ ToolButton *EditorNode::add_bottom_panel_item(String p_text, Control *p_item) { tb->set_focus_mode(Control::FOCUS_NONE); bottom_panel_vb->add_child(p_item); bottom_panel_hb->raise(); - bottom_panel_hb->add_child(tb); + bottom_panel_hb_editors->add_child(tb); p_item->set_v_size_flags(Control::SIZE_EXPAND_FILL); p_item->hide(); BottomPanelItem bpi; @@ -3941,7 +3988,7 @@ void EditorNode::raise_bottom_panel_item(Control *p_item) { if (bottom_panel_items[i].control == p_item) { bottom_panel_items[i].button->raise(); - SWAP(bottom_panel_items[i], bottom_panel_items[bottom_panel_items.size() - 1]); + SWAP(bottom_panel_items.write[i], bottom_panel_items.write[bottom_panel_items.size() - 1]); break; } } @@ -3961,7 +4008,7 @@ void EditorNode::remove_bottom_panel_item(Control *p_item) { _bottom_panel_switch(false, 0); } bottom_panel_vb->remove_child(bottom_panel_items[i].control); - bottom_panel_hb->remove_child(bottom_panel_items[i].button); + bottom_panel_hb_editors->remove_child(bottom_panel_items[i].button); memdelete(bottom_panel_items[i].button); bottom_panel_items.remove(i); break; @@ -3991,6 +4038,11 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { } center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE); center_split->set_collapsed(false); + if (bottom_panel_raise->is_pressed()) { + top_split->hide(); + } + bottom_panel_raise->show(); + } else { bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer")); for (int i = 0; i < bottom_panel_items.size(); i++) { @@ -4000,6 +4052,10 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { } center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN); center_split->set_collapsed(true); + bottom_panel_raise->hide(); + if (bottom_panel_raise->is_pressed()) { + top_split->show(); + } } } @@ -4216,7 +4272,7 @@ void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) { for (int i = 0; i < p_files.size(); i++) { String from = p_files[i]; - if (!ResourceFormatImporter::get_singleton()->can_be_imported(from) && (just_copy.find(from.get_extension().to_lower()) != -1)) { + if (!ResourceFormatImporter::get_singleton()->can_be_imported(from) && (just_copy.find(from.get_extension().to_lower()) == -1)) { continue; } String to = to_path.plus_file(from.get_file()); @@ -4409,6 +4465,32 @@ Vector<Ref<EditorResourceConversionPlugin> > EditorNode::find_resource_conversio return ret; } +void EditorNode::_bottom_panel_raise_toggled(bool p_pressed) { + + if (p_pressed) { + top_split->hide(); + bottom_panel_raise->set_icon(gui_base->get_icon("ShrinkBottomDock", "EditorIcons")); + } else { + top_split->show(); + bottom_panel_raise->set_icon(gui_base->get_icon("ExpandBottomDock", "EditorIcons")); + } +} + +void EditorNode::_video_driver_selected(int p_which) { + + String driver = video_driver->get_item_metadata(p_which); + + String current = OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver()); + + if (driver == current) { + return; + } + + video_driver_request = driver; + video_restart_dialog->popup_centered_minsize(); + video_driver->select(video_driver_current); +} + void EditorNode::_bind_methods() { ClassDB::bind_method("_menu_option", &EditorNode::_menu_option); @@ -4434,6 +4516,8 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("stop_child_process", &EditorNode::stop_child_process); + ClassDB::bind_method("get_script_create_dialog", &EditorNode::get_script_create_dialog); + ClassDB::bind_method("_sources_changed", &EditorNode::_sources_changed); ClassDB::bind_method("_fs_changed", &EditorNode::_fs_changed); ClassDB::bind_method("_dock_select_draw", &EditorNode::_dock_select_draw); @@ -4475,6 +4559,11 @@ void EditorNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_dim_timeout"), &EditorNode::_dim_timeout); ClassDB::bind_method(D_METHOD("_resources_reimported"), &EditorNode::_resources_reimported); + ClassDB::bind_method(D_METHOD("_bottom_panel_raise_toggled"), &EditorNode::_bottom_panel_raise_toggled); + + ClassDB::bind_method(D_METHOD("_on_plugin_ready"), &EditorNode::_on_plugin_ready); + + ClassDB::bind_method(D_METHOD("_video_driver_selected"), &EditorNode::_video_driver_selected); ADD_SIGNAL(MethodInfo("play_pressed")); ADD_SIGNAL(MethodInfo("pause_pressed")); @@ -4492,7 +4581,7 @@ static Node *_resource_get_edited_scene() { void EditorNode::_print_handler(void *p_this, const String &p_string, bool p_error) { EditorNode *en = (EditorNode *)p_this; - en->log->add_message(p_string, p_error); + en->log->add_message(p_string, p_error ? EditorLog::MSG_TYPE_ERROR : EditorLog::MSG_TYPE_STD); } EditorNode::EditorNode() { @@ -4502,6 +4591,10 @@ EditorNode::EditorNode() { VisualServer::get_singleton()->textures_keep_original(true); VisualServer::get_singleton()->set_debug_generate_wireframes(true); + PhysicsServer::get_singleton()->set_active(false); // no physics by default if editor + Physics2DServer::get_singleton()->set_active(false); // no physics by default if editor + ScriptServer::set_scripting_enabled(false); // no scripting by default if editor + EditorHelp::generate_doc(); //before any editor classes are crated SceneState::set_disable_placeholders(true); ResourceLoader::clear_translation_remaps(); //no remaps using during editor @@ -4593,6 +4686,20 @@ EditorNode::EditorNode() { import_texture.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_texture); + Ref<ResourceImporterLayeredTexture> import_3d; + import_3d.instance(); + import_3d->set_3d(true); + ResourceFormatImporter::get_singleton()->add_importer(import_3d); + + Ref<ResourceImporterLayeredTexture> import_array; + import_array.instance(); + import_array->set_3d(false); + ResourceFormatImporter::get_singleton()->add_importer(import_array); + + Ref<ResourceImporterImage> import_image; + import_image.instance(); + ResourceFormatImporter::get_singleton()->add_importer(import_image); + Ref<ResourceImporterCSVTranslation> import_csv_translation; import_csv_translation.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_csv_translation); @@ -4640,6 +4747,10 @@ EditorNode::EditorNode() { Ref<EditorInspectorRootMotionPlugin> rmp; rmp.instance(); EditorInspector::add_inspector_plugin(rmp); + + Ref<EditorInspectorShaderModePlugin> smp; + smp.instance(); + EditorInspector::add_inspector_plugin(smp); } _pvrtc_register_compressors(); @@ -4668,20 +4779,23 @@ EditorNode::EditorNode() { ClassDB::set_class_enabled("RootMotionView", true); //defs here, use EDITOR_GET in logic - EDITOR_DEF("interface/scene_tabs/always_show_close_button", false); - EDITOR_DEF("interface/scene_tabs/resize_if_many_tabs", true); - EDITOR_DEF("interface/scene_tabs/minimum_width", 50); + EDITOR_DEF_RST("interface/scene_tabs/always_show_close_button", false); + EDITOR_DEF_RST("interface/scene_tabs/resize_if_many_tabs", true); + EDITOR_DEF_RST("interface/scene_tabs/minimum_width", 50); EDITOR_DEF("run/output/always_clear_output_on_play", true); EDITOR_DEF("run/output/always_open_output_on_play", true); EDITOR_DEF("run/output/always_close_output_on_stop", true); EDITOR_DEF("run/auto_save/save_before_running", true); - EDITOR_DEF("interface/editor/save_each_scene_on_quit", true); + EDITOR_DEF_RST("interface/editor/save_each_scene_on_quit", true); EDITOR_DEF("interface/editor/quit_confirmation", true); - EDITOR_DEF("interface/scene_tabs/restore_scenes_on_load", false); - EDITOR_DEF("interface/scene_tabs/show_thumbnail_on_hover", true); - EDITOR_DEF("interface/inspector/capitalize_properties", true); - EDITOR_DEF("interface/inspector/disable_folding", false); - EDITOR_DEF("interface/inspector/open_resources_in_new_inspector", false); + EDITOR_DEF_RST("interface/scene_tabs/restore_scenes_on_load", false); + EDITOR_DEF_RST("interface/scene_tabs/show_thumbnail_on_hover", true); + EDITOR_DEF_RST("interface/inspector/capitalize_properties", true); + EDITOR_DEF_RST("interface/inspector/disable_folding", false); + EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false); + EDITOR_DEF("interface/inspector/horizontal_vector3_editing", true); + EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true); + EDITOR_DEF("interface/inspector/resources_types_to_open_in_new_inspector", "SpatialMaterial,Script"); EDITOR_DEF("run/auto_save/save_before_running", true); theme_base = memnew(Control); @@ -4858,6 +4972,7 @@ EditorNode::EditorNode() { scene_tabs = memnew(Tabs); scene_tabs->add_style_override("tab_fg", gui_base->get_stylebox("SceneTabFG", "EditorStyles")); scene_tabs->add_style_override("tab_bg", gui_base->get_stylebox("SceneTabBG", "EditorStyles")); + scene_tabs->set_select_with_rmb(true); scene_tabs->add_tab("unsaved"); scene_tabs->set_tab_align(Tabs::ALIGN_LEFT); scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); @@ -4875,6 +4990,11 @@ EditorNode::EditorNode() { tabbar_container = memnew(HBoxContainer); scene_tabs->set_h_size_flags(Control::SIZE_EXPAND_FILL); + scene_tabs_context_menu = memnew(PopupMenu); + tabbar_container->add_child(scene_tabs_context_menu); + scene_tabs_context_menu->connect("id_pressed", this, "_menu_option"); + scene_tabs_context_menu->set_hide_on_window_lose_focus(true); + srt->add_child(tabbar_container); tabbar_container->add_child(scene_tabs); distraction_free = memnew(ToolButton); @@ -4981,6 +5101,7 @@ EditorNode::EditorNode() { file_menu->set_tooltip(TTR("Operations with scene files.")); p = file_menu->get_popup(); + p->set_hide_on_window_lose_focus(true); p->add_shortcut(ED_SHORTCUT("editor/new_scene", TTR("New Scene")), FILE_NEW_SCENE); p->add_shortcut(ED_SHORTCUT("editor/new_inherited_scene", TTR("New Inherited Scene...")), FILE_NEW_INHERITED_SCENE); p->add_shortcut(ED_SHORTCUT("editor/open_scene", TTR("Open Scene..."), KEY_MASK_CMD + KEY_O), FILE_OPEN_SCENE); @@ -5026,11 +5147,16 @@ EditorNode::EditorNode() { left_menu_hb->add_child(project_menu); p = project_menu->get_popup(); + p->set_hide_on_window_lose_focus(true); p->add_item(TTR("Project Settings"), RUN_SETTINGS); p->add_separator(); p->connect("id_pressed", this, "_menu_option"); p->add_item(TTR("Export"), FILE_EXPORT_PROJECT); + plugin_config_dialog = memnew(PluginConfigDialog); + plugin_config_dialog->connect("plugin_ready", this, "_on_plugin_ready"); + gui_base->add_child(plugin_config_dialog); + tool_menu = memnew(PopupMenu); tool_menu->set_name("Tools"); tool_menu->connect("index_pressed", this, "_tool_menu_option"); @@ -5039,6 +5165,9 @@ EditorNode::EditorNode() { tool_menu->add_item(TTR("Orphan Resource Explorer"), TOOLS_ORPHAN_RESOURCES); p->add_separator(); + p->add_item(TTR("Open Project Data Folder"), RUN_PROJECT_DATA_FOLDER); + p->add_separator(); + #ifdef OSX_ENABLED p->add_item(TTR("Quit to Project List"), RUN_PROJECT_MANAGER, KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q); #else @@ -5058,6 +5187,7 @@ EditorNode::EditorNode() { left_menu_hb->add_child(debug_menu); p = debug_menu->get_popup(); + p->set_hide_on_window_lose_focus(true); p->set_hide_on_item_selection(false); p->add_check_item(TTR("Deploy with Remote Debug"), RUN_DEPLOY_REMOTE_DEBUG); p->set_item_tooltip(p->get_item_count() - 1, TTR("When exporting or deploying, the resulting executable will attempt to connect to the IP of this computer in order to be debugged.")); @@ -5082,10 +5212,12 @@ EditorNode::EditorNode() { settings_menu->set_text(TTR("Editor")); settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); left_menu_hb->add_child(settings_menu); - p = settings_menu->get_popup(); + p = settings_menu->get_popup(); + p->set_hide_on_window_lose_focus(true); p->add_item(TTR("Editor Settings"), SETTINGS_PREFERENCES); p->add_separator(); + editor_layouts = memnew(PopupMenu); editor_layouts->set_name("Layouts"); p->add_child(editor_layouts); @@ -5097,6 +5229,17 @@ EditorNode::EditorNode() { p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_SHIFT | KEY_F11), SETTINGS_TOGGLE_FULLSCREEN); #endif p->add_separator(); + + if (OS::get_singleton()->get_data_path() == OS::get_singleton()->get_config_path()) { + // Configuration and data folders are located in the same place (Windows/macOS) + p->add_item(TTR("Open Editor Data/Settings Folder"), SETTINGS_EDITOR_DATA_FOLDER); + } else { + // Separate configuration and data folders (Linux) + p->add_item(TTR("Open Editor Data Folder"), SETTINGS_EDITOR_DATA_FOLDER); + p->add_item(TTR("Open Editor Settings Folder"), SETTINGS_EDITOR_CONFIG_FOLDER); + } + p->add_separator(); + p->add_item(TTR("Manage Export Templates"), SETTINGS_MANAGE_EXPORT_TEMPLATES); // Help Menu @@ -5107,6 +5250,7 @@ EditorNode::EditorNode() { left_menu_hb->add_child(help_menu); p = help_menu->get_popup(); + p->set_hide_on_window_lose_focus(true); p->connect("id_pressed", this, "_menu_option"); p->add_icon_item(gui_base->get_icon("ClassList", "EditorIcons"), TTR("Classes"), HELP_CLASSES); p->add_icon_item(gui_base->get_icon("HelpSearch", "EditorIcons"), TTR("Search"), HELP_SEARCH); @@ -5202,6 +5346,37 @@ EditorNode::EditorNode() { play_custom_scene_button->set_shortcut(ED_SHORTCUT("editor/play_custom_scene", TTR("Play Custom Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F5)); #endif + video_driver = memnew(OptionButton); + video_driver->set_flat(true); + video_driver->set_focus_mode(Control::FOCUS_NONE); + video_driver->set_v_size_flags(Control::SIZE_SHRINK_CENTER); + String video_drivers = ProjectSettings::get_singleton()->get_custom_property_info()["rendering/quality/driver/driver_name"].hint_string; + String current_video_driver = OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver()); + menu_hb->add_child(video_driver); + video_driver_current = 0; + for (int i = 0; i < video_drivers.get_slice_count(","); i++) { + String driver = video_drivers.get_slice(",", i); + if (gui_base->has_icon(driver, "EditorIcons")) { + video_driver->add_icon_item(gui_base->get_icon(driver, "EditorIcons"), ""); + } else { + video_driver->add_item(driver); + } + + video_driver->set_item_metadata(i, driver); + + if (current_video_driver == driver) { + video_driver->select(i); + video_driver_current = i; + } + } + + video_driver->connect("item_selected", this, "_video_driver_selected"); + video_restart_dialog = memnew(ConfirmationDialog); + video_restart_dialog->set_text(TTR("Changing the video driver requires restarting the editor.")); + video_restart_dialog->get_ok()->set_text(TTR("Save & Restart")); + video_restart_dialog->connect("confirmed", this, "_menu_option", varray(SET_VIDEO_DRIVER_SAVE_AND_RESTART)); + gui_base->add_child(video_restart_dialog); + progress_hb = memnew(BackgroundProgress); HBoxContainer *right_menu_hb = memnew(HBoxContainer); @@ -5219,8 +5394,8 @@ EditorNode::EditorNode() { update_menu->set_icon(gui_base->get_icon("Progress1", "EditorIcons")); update_menu->get_popup()->connect("id_pressed", this, "_menu_option"); p = update_menu->get_popup(); - p->add_check_item(TTR("Update Always"), SETTINGS_UPDATE_ALWAYS); - p->add_check_item(TTR("Update Changes"), SETTINGS_UPDATE_CHANGES); + p->add_radio_check_item(TTR("Update Always"), SETTINGS_UPDATE_ALWAYS); + p->add_radio_check_item(TTR("Update Changes"), SETTINGS_UPDATE_CHANGES); p->add_separator(); p->add_check_item(TTR("Disable Update Spinner"), SETTINGS_UPDATE_SPINNER_HIDE); int update_always = EditorSettings::get_singleton()->get_project_metadata("editor_options", "update_always", false); @@ -5257,7 +5432,7 @@ EditorNode::EditorNode() { } filesystem_dock = memnew(FileSystemDock(this)); - filesystem_dock->set_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"))); + filesystem_dock->set_file_list_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"))); if (use_single_dock_column) { dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(filesystem_dock); @@ -5296,8 +5471,22 @@ EditorNode::EditorNode() { bottom_panel->add_child(bottom_panel_vb); bottom_panel_hb = memnew(HBoxContainer); + bottom_panel_hb->set_custom_minimum_size(Size2(0, 24)); // Adjust for the height of the "Expand Bottom Dock" icon. bottom_panel_vb->add_child(bottom_panel_hb); + bottom_panel_hb_editors = memnew(HBoxContainer); + bottom_panel_hb_editors->set_h_size_flags(Control::SIZE_EXPAND_FILL); + bottom_panel_hb->add_child(bottom_panel_hb_editors); + bottom_panel_raise = memnew(ToolButton); + bottom_panel_raise->set_icon(gui_base->get_icon("ExpandBottomDock", "EditorIcons")); + + bottom_panel_raise->set_shortcut(ED_SHORTCUT("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KEY_MASK_SHIFT | KEY_F12)); + + bottom_panel_hb->add_child(bottom_panel_raise); + bottom_panel_raise->hide(); + bottom_panel_raise->set_toggle_mode(true); + bottom_panel_raise->connect("toggled", this, "_bottom_panel_raise_toggled"); + log = memnew(EditorLog); ToolButton *output_button = add_bottom_panel_item(TTR("Output"), log); log->set_tool_button(output_button); @@ -5386,6 +5575,7 @@ EditorNode::EditorNode() { EditorAudioBuses *audio_bus_editor = EditorAudioBuses::register_editor(); ScriptTextEditor::register_editor(); //register one for text scripts + TextEditor::register_editor(); if (StreamPeerSSL::is_available()) { add_editor_plugin(memnew(AssetLibraryEditorPlugin(this))); @@ -5402,23 +5592,20 @@ EditorNode::EditorNode() { raise_bottom_panel_item(AnimationPlayerEditor::singleton); add_editor_plugin(memnew(ShaderEditorPlugin(this))); - // FIXME: Disabled for Godot 3.0 as made incompatible, it needs to be ported to the new API. - //add_editor_plugin(memnew(ShaderGraphEditorPlugin(this))); - add_editor_plugin(memnew(AnimationNodeBlendTreeEditorPlugin(this))); - add_editor_plugin(memnew(AnimationNodeBlendSpace1DEditorPlugin(this))); - add_editor_plugin(memnew(AnimationNodeBlendSpace2DEditorPlugin(this))); - add_editor_plugin(memnew(AnimationNodeStateMachineEditorPlugin(this))); + add_editor_plugin(memnew(VisualShaderEditorPlugin(this))); add_editor_plugin(memnew(CameraEditorPlugin(this))); add_editor_plugin(memnew(ThemeEditorPlugin(this))); add_editor_plugin(memnew(MultiMeshEditorPlugin(this))); add_editor_plugin(memnew(MeshInstanceEditorPlugin(this))); add_editor_plugin(memnew(AnimationTreeEditorPlugin(this))); + add_editor_plugin(memnew(AnimationTreePlayerEditorPlugin(this))); add_editor_plugin(memnew(MeshLibraryEditorPlugin(this))); add_editor_plugin(memnew(StyleBoxEditorPlugin(this))); add_editor_plugin(memnew(SpriteEditorPlugin(this))); add_editor_plugin(memnew(Skeleton2DEditorPlugin(this))); add_editor_plugin(memnew(ParticlesEditorPlugin(this))); + add_editor_plugin(memnew(CPUParticlesEditorPlugin(this))); add_editor_plugin(memnew(ResourcePreloaderEditorPlugin(this))); add_editor_plugin(memnew(ItemListEditorPlugin(this))); add_editor_plugin(memnew(Polygon3DEditorPlugin(this))); @@ -5440,9 +5627,11 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(CollisionShape2DEditorPlugin(this))); add_editor_plugin(memnew(CurveEditorPlugin(this))); add_editor_plugin(memnew(TextureEditorPlugin(this))); + add_editor_plugin(memnew(AudioStreamEditorPlugin(this))); add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); add_editor_plugin(memnew(SkeletonEditorPlugin(this))); + add_editor_plugin(memnew(SkeletonIKEditorPlugin(this))); add_editor_plugin(memnew(PhysicalBonePlugin(this))); // FIXME: Disabled as (according to reduz) users were complaining that it gets in the way @@ -5495,10 +5684,6 @@ EditorNode::EditorNode() { _edit_current(); current = NULL; - PhysicsServer::get_singleton()->set_active(false); // no physics by default if editor - Physics2DServer::get_singleton()->set_active(false); // no physics by default if editor - ScriptServer::set_scripting_enabled(false); // no scripting by default if editor - reference_resource_mem = true; save_external_resources_mem = true; |