summaryrefslogtreecommitdiffstats
path: root/editor/editor_node.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/editor_node.cpp')
-rw-r--r--editor/editor_node.cpp232
1 files changed, 182 insertions, 50 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 8b7014fabe..745cdd59c0 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -58,7 +58,6 @@
#include "scene/gui/tab_container.h"
#include "scene/gui/tabs.h"
#include "scene/gui/texture_progress.h"
-#include "scene/gui/tool_button.h"
#include "scene/resources/packed_scene.h"
#include "servers/navigation_server_2d.h"
#include "servers/navigation_server_3d.h"
@@ -104,7 +103,6 @@
#include "editor/import_dock.h"
#include "editor/multi_node_edit.h"
#include "editor/node_dock.h"
-#include "editor/pane_drag.h"
#include "editor/plugin_config_dialog.h"
#include "editor/plugins/animation_blend_space_1d_editor.h"
#include "editor/plugins/animation_blend_space_2d_editor.h"
@@ -179,6 +177,111 @@
EditorNode *EditorNode::singleton = nullptr;
+void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames) {
+ // Keep track of a list of "index sets," i.e. sets of indices
+ // within disambiguated_scene_names which contain the same name.
+ Vector<Set<int>> index_sets;
+ Map<String, int> scene_name_to_set_index;
+ for (int i = 0; i < r_filenames.size(); i++) {
+ String scene_name = r_filenames[i];
+ if (!scene_name_to_set_index.has(scene_name)) {
+ index_sets.append(Set<int>());
+ scene_name_to_set_index.insert(r_filenames[i], index_sets.size() - 1);
+ }
+ index_sets.write[scene_name_to_set_index[scene_name]].insert(i);
+ }
+
+ // For each index set with a size > 1, we need to disambiguate
+ for (int i = 0; i < index_sets.size(); i++) {
+ Set<int> iset = index_sets[i];
+ while (iset.size() > 1) {
+ // Append the parent folder to each scene name
+ for (Set<int>::Element *E = iset.front(); E; E = E->next()) {
+ int set_idx = E->get();
+ String scene_name = r_filenames[set_idx];
+ String full_path = p_full_paths[set_idx];
+
+ // Get rid of file extensions and res:// prefixes
+ if (scene_name.rfind(".") >= 0) {
+ scene_name = scene_name.substr(0, scene_name.rfind("."));
+ }
+ if (full_path.begins_with("res://")) {
+ full_path = full_path.substr(6);
+ }
+ if (full_path.rfind(".") >= 0) {
+ full_path = full_path.substr(0, full_path.rfind("."));
+ }
+
+ int scene_name_size = scene_name.size();
+ int full_path_size = full_path.size();
+ int difference = full_path_size - scene_name_size;
+
+ // Find just the parent folder of the current path and append it.
+ // If the current name is foo.tscn, and the full path is /some/folder/foo.tscn
+ // then slash_idx is the second '/', so that we select just "folder", and
+ // append that to yield "folder/foo.tscn".
+ if (difference > 0) {
+ String parent = full_path.substr(0, difference);
+ int slash_idx = parent.rfind("/");
+ slash_idx = parent.rfind("/", slash_idx - 1);
+ parent = slash_idx >= 0 ? parent.substr(slash_idx + 1) : parent;
+ r_filenames.write[set_idx] = parent + r_filenames[set_idx];
+ }
+ }
+
+ // Loop back through scene names and remove non-ambiguous names
+ bool can_proceed = false;
+ Set<int>::Element *E = iset.front();
+ while (E) {
+ String scene_name = r_filenames[E->get()];
+ bool duplicate_found = false;
+ for (Set<int>::Element *F = iset.front(); F; F = F->next()) {
+ if (E->get() == F->get()) {
+ continue;
+ }
+ String other_scene_name = r_filenames[F->get()];
+ if (other_scene_name == scene_name) {
+ duplicate_found = true;
+ break;
+ }
+ }
+
+ Set<int>::Element *to_erase = duplicate_found ? nullptr : E;
+
+ // We need to check that we could actually append anymore names
+ // if we wanted to for disambiguation. If we can't, then we have
+ // to abort even with ambiguous names. We clean the full path
+ // and the scene name first to remove extensions so that this
+ // comparison actually works.
+ String path = p_full_paths[E->get()];
+ if (path.begins_with("res://")) {
+ path = path.substr(6);
+ }
+ if (path.rfind(".") >= 0) {
+ path = path.substr(0, path.rfind("."));
+ }
+ if (scene_name.rfind(".") >= 0) {
+ scene_name = scene_name.substr(0, scene_name.rfind("."));
+ }
+
+ // We can proceed iff the full path is longer than the scene name,
+ // meaning that there is at least one more parent folder we can
+ // tack onto the name.
+ can_proceed = can_proceed || (path.size() - scene_name.size()) >= 1;
+
+ E = E->next();
+ if (to_erase) {
+ iset.erase(to_erase);
+ }
+ }
+
+ if (!can_proceed) {
+ break;
+ }
+ }
+ }
+}
+
void EditorNode::_update_scene_tabs() {
bool show_rb = EditorSettings::get_singleton()->get("interface/scene_tabs/show_script_button");
@@ -186,6 +289,16 @@ void EditorNode::_update_scene_tabs() {
DisplayServer::get_singleton()->global_menu_clear("_dock");
}
+ // Get all scene names, which may be ambiguous
+ Vector<String> disambiguated_scene_names;
+ Vector<String> full_path_names;
+ for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
+ disambiguated_scene_names.append(editor_data.get_scene_title(i));
+ full_path_names.append(editor_data.get_scene_path(i));
+ }
+
+ disambiguate_filenames(full_path_names, disambiguated_scene_names);
+
scene_tabs->clear_tabs();
Ref<Texture2D> script_icon = gui_base->get_theme_icon("Script", "EditorIcons");
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
@@ -197,7 +310,7 @@ void EditorNode::_update_scene_tabs() {
int current = editor_data.get_edited_scene();
bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0;
- scene_tabs->add_tab(editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), icon);
+ scene_tabs->add_tab(disambiguated_scene_names[i] + (unsaved ? "(*)" : ""), icon);
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) {
DisplayServer::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), callable_mp(this, &EditorNode::_global_menu_scene), i);
@@ -361,7 +474,7 @@ void EditorNode::_notification(int p_what) {
bool dof_jitter = GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_use_jitter");
RS::get_singleton()->camera_effects_set_dof_blur_quality(dof_quality, dof_jitter);
RS::get_singleton()->environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size"));
- RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_curve"));
+ RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_enabled"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_amount"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_limit"));
bool glow_bicubic = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0;
RS::get_singleton()->environment_glow_set_use_bicubic_upscale(glow_bicubic);
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/quality/screen_space_reflection/roughness_quality")));
@@ -377,6 +490,12 @@ void EditorNode::_notification(int p_what) {
RS::get_singleton()->directional_shadow_quality_set(directional_shadow_quality);
float probe_update_speed = GLOBAL_GET("rendering/lightmapper/probe_capture_update_speed");
RS::get_singleton()->lightmap_set_probe_capture_update_speed(probe_update_speed);
+ RS::EnvironmentSDFGIFramesToConverge frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(int(GLOBAL_GET("rendering/sdfgi/frames_to_converge")));
+ RS::get_singleton()->environment_set_sdfgi_frames_to_converge(frames_to_converge);
+ RS::EnvironmentSDFGIRayCount ray_count = RS::EnvironmentSDFGIRayCount(int(GLOBAL_GET("rendering/sdfgi/probe_ray_count")));
+ RS::get_singleton()->environment_set_sdfgi_ray_count(ray_count);
+ RS::GIProbeQuality gi_probe_quality = RS::GIProbeQuality(int(GLOBAL_GET("rendering/quality/gi_probes/quality")));
+ RS::get_singleton()->gi_probe_set_quality(gi_probe_quality);
}
ResourceImporterTexture::get_singleton()->update_imports();
@@ -430,14 +549,14 @@ void EditorNode::_notification(int p_what) {
/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
} break;
- case NOTIFICATION_WM_FOCUS_IN: {
+ case NOTIFICATION_APPLICATION_FOCUS_IN: {
// Restore the original FPS cap after focusing back on the editor
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec")));
EditorFileSystem::get_singleton()->scan_changes();
} break;
- case NOTIFICATION_WM_FOCUS_OUT: {
+ case NOTIFICATION_APPLICATION_FOCUS_OUT: {
// Set a low FPS cap to decrease CPU/GPU usage while the editor is unfocused
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/unfocused_low_processor_mode_sleep_usec")));
} break;
@@ -485,7 +604,7 @@ void EditorNode::_notification(int p_what) {
// update_icons
for (int i = 0; i < singleton->main_editor_buttons.size(); i++) {
- ToolButton *tb = singleton->main_editor_buttons[i];
+ Button *tb = singleton->main_editor_buttons[i];
EditorPlugin *p_editor = singleton->editor_table[i];
Ref<Texture2D> icon = p_editor->get_icon();
@@ -619,7 +738,9 @@ void EditorNode::_fs_changed() {
preset.unref();
}
if (preset.is_null()) {
- export_error = vformat("Invalid export preset name: %s.", preset_name);
+ export_error = vformat(
+ "Invalid export preset name: %s. Make sure `export_presets.cfg` is present in the current directory.",
+ preset_name);
} else {
Ref<EditorExportPlatform> platform = preset->get_platform();
if (platform.is_null()) {
@@ -903,19 +1024,19 @@ void EditorNode::_dialog_display_load_error(String p_file, Error p_error) {
if (p_error) {
switch (p_error) {
case ERR_CANT_OPEN: {
- show_accept(vformat(TTR("Can't open '%s'. The file could have been moved or deleted."), p_file.get_file()), TTR("OK"));
+ show_accept(vformat(TTR("Can't open file '%s'. The file could have been moved or deleted."), p_file.get_file()), TTR("OK"));
} break;
case ERR_PARSE_ERROR: {
- show_accept(vformat(TTR("Error while parsing '%s'."), p_file.get_file()), TTR("OK"));
+ show_accept(vformat(TTR("Error while parsing file '%s'."), p_file.get_file()), TTR("OK"));
} break;
case ERR_FILE_CORRUPT: {
- show_accept(vformat(TTR("Unexpected end of file '%s'."), p_file.get_file()), TTR("OK"));
+ show_accept(vformat(TTR("Scene file '%s' appears to be invalid/corrupt."), p_file.get_file()), TTR("OK"));
} break;
case ERR_FILE_NOT_FOUND: {
- show_accept(vformat(TTR("Missing '%s' or its dependencies."), p_file.get_file()), TTR("OK"));
+ show_accept(vformat(TTR("Missing file '%s' or one its dependencies."), p_file.get_file()), TTR("OK"));
} break;
default: {
- show_accept(vformat(TTR("Error while loading '%s'."), p_file.get_file()), TTR("OK"));
+ show_accept(vformat(TTR("Error while loading file '%s'."), p_file.get_file()), TTR("OK"));
} break;
}
}
@@ -2774,7 +2895,8 @@ void EditorNode::select_editor_by_name(const String &p_name) {
void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed) {
if (p_editor->has_main_screen()) {
- ToolButton *tb = memnew(ToolButton);
+ Button *tb = memnew(Button);
+ tb->set_flat(true);
tb->set_toggle_mode(true);
tb->connect("pressed", callable_mp(singleton, &EditorNode::_editor_select), varray(singleton->main_editor_buttons.size()));
tb->set_text(p_editor->get_name());
@@ -3254,13 +3376,13 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
if (!new_scene) {
sdata.unref();
- _dialog_display_load_error(lpath, ERR_FILE_NOT_FOUND);
+ _dialog_display_load_error(lpath, ERR_FILE_CORRUPT);
opening_prev = false;
if (prev != -1) {
set_current_scene(prev);
editor_data.remove_scene(idx);
}
- return ERR_FILE_NOT_FOUND;
+ return ERR_FILE_CORRUPT;
}
if (p_set_inherited) {
@@ -3403,10 +3525,14 @@ void EditorNode::_update_recent_scenes() {
void EditorNode::_quick_opened() {
Vector<String> files = quick_open->get_selected_files();
+ bool open_scene_dialog = quick_open->get_base_type() == "PackedScene";
for (int i = 0; i < files.size(); i++) {
String res_path = files[i];
- if (quick_open->get_base_type() == "PackedScene") {
+ List<String> scene_extensions;
+ ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions);
+
+ if (open_scene_dialog || scene_extensions.find(files[i].get_extension())) {
open_request(res_path);
} else {
load_resource(res_path);
@@ -3635,22 +3761,14 @@ Ref<Texture2D> EditorNode::get_object_icon(const Object *p_object, const String
Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p_fallback) const {
ERR_FAIL_COND_V_MSG(p_class.empty(), nullptr, "Class name cannot be empty.");
- if (gui_base->has_theme_icon(p_class, "EditorIcons")) {
- return gui_base->get_theme_icon(p_class, "EditorIcons");
- }
-
if (ScriptServer::is_global_class(p_class)) {
- String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(p_class);
- Ref<ImageTexture> icon = _load_custom_class_icon(icon_path);
- if (icon.is_valid()) {
- return icon;
- }
-
- Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(p_class), "Script");
+ Ref<ImageTexture> icon;
+ Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(p_class);
+ StringName name = p_class;
while (script.is_valid()) {
- String current_icon_path;
- script->get_language()->get_global_class_name(script->get_path(), nullptr, &current_icon_path);
+ name = EditorNode::get_editor_data().script_class_get_name(script->get_path());
+ String current_icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name);
icon = _load_custom_class_icon(current_icon_path);
if (icon.is_valid()) {
return icon;
@@ -3659,10 +3777,8 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p
}
if (icon.is_null()) {
- icon = gui_base->get_theme_icon(ScriptServer::get_global_class_base(p_class), "EditorIcons");
+ icon = gui_base->get_theme_icon(ScriptServer::get_global_class_base(name), "EditorIcons");
}
-
- return icon;
}
const Map<String, Vector<EditorData::CustomType>> &p_map = EditorNode::get_editor_data().get_custom_types();
@@ -3677,6 +3793,10 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p
}
}
+ if (gui_base->has_theme_icon(p_class, "EditorIcons")) {
+ return gui_base->get_theme_icon(p_class, "EditorIcons");
+ }
+
if (p_fallback.length() && gui_base->has_theme_icon(p_fallback, "EditorIcons")) {
return gui_base->get_theme_icon(p_fallback, "EditorIcons");
}
@@ -4155,7 +4275,6 @@ void EditorNode::_update_dock_slots_visibility() {
}
right_hsplit->hide();
- bottom_panel->hide();
} else {
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
int tabs_visible = 0;
@@ -4185,7 +4304,6 @@ void EditorNode::_update_dock_slots_visibility() {
dock_slot[i]->set_current_tab(0);
}
}
- bottom_panel->show();
if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible()) {
right_hsplit->show();
@@ -4619,8 +4737,9 @@ void EditorNode::_scene_tab_changed(int p_tab) {
editor_data.get_undo_redo().commit_action();
}
-ToolButton *EditorNode::add_bottom_panel_item(String p_text, Control *p_item) {
- ToolButton *tb = memnew(ToolButton);
+Button *EditorNode::add_bottom_panel_item(String p_text, Control *p_item) {
+ Button *tb = memnew(Button);
+ tb->set_flat(true);
tb->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch), varray(bottom_panel_items.size()));
tb->set_text(p_text);
tb->set_toggle_mode(true);
@@ -4782,7 +4901,7 @@ void EditorNode::set_distraction_free_mode(bool p_enter) {
}
}
-bool EditorNode::get_distraction_free_mode() const {
+bool EditorNode::is_distraction_free_mode_enabled() const {
return distraction_free->is_pressed();
}
@@ -5696,7 +5815,8 @@ EditorNode::EditorNode() {
dock_select_popup->add_child(dock_vb);
HBoxContainer *dock_hb = memnew(HBoxContainer);
- dock_tab_move_left = memnew(ToolButton);
+ dock_tab_move_left = memnew(Button);
+ dock_tab_move_left->set_flat(true);
dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons"));
dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE);
dock_tab_move_left->connect("pressed", callable_mp(this, &EditorNode::_dock_move_left));
@@ -5708,7 +5828,8 @@ EditorNode::EditorNode() {
dock_label->set_align(Label::ALIGN_CENTER);
dock_hb->add_child(dock_label);
- dock_tab_move_right = memnew(ToolButton);
+ dock_tab_move_right = memnew(Button);
+ dock_tab_move_right->set_flat(true);
dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons"));
dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE);
dock_tab_move_right->connect("pressed", callable_mp(this, &EditorNode::_dock_move_right));
@@ -5802,7 +5923,8 @@ EditorNode::EditorNode() {
srt->add_child(tabbar_container);
tabbar_container->add_child(scene_tabs);
- distraction_free = memnew(ToolButton);
+ distraction_free = memnew(Button);
+ distraction_free->set_flat(true);
#ifdef OSX_ENABLED
distraction_free->set_shortcut(ED_SHORTCUT("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_D));
#else
@@ -5813,7 +5935,8 @@ EditorNode::EditorNode() {
distraction_free->set_icon(gui_base->get_theme_icon("DistractionFree", "EditorIcons"));
distraction_free->set_toggle_mode(true);
- scene_tab_add = memnew(ToolButton);
+ scene_tab_add = memnew(Button);
+ scene_tab_add->set_flat(true);
tabbar_container->add_child(scene_tab_add);
tabbar_container->add_child(distraction_free);
scene_tab_add->set_tooltip(TTR("Add a new scene."));
@@ -5850,7 +5973,8 @@ EditorNode::EditorNode() {
file_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles"));
left_menu_hb->add_child(file_menu);
- prev_scene = memnew(ToolButton);
+ prev_scene = memnew(Button);
+ prev_scene->set_flat(true);
prev_scene->set_icon(gui_base->get_theme_icon("PrevScene", "EditorIcons"));
prev_scene->set_tooltip(TTR("Go to previously opened scene."));
prev_scene->set_disabled(true);
@@ -6079,7 +6203,8 @@ EditorNode::EditorNode() {
HBoxContainer *play_hb = memnew(HBoxContainer);
menu_hb->add_child(play_hb);
- play_button = memnew(ToolButton);
+ play_button = memnew(Button);
+ play_button->set_flat(true);
play_hb->add_child(play_button);
play_button->set_toggle_mode(true);
play_button->set_icon(gui_base->get_theme_icon("MainPlay", "EditorIcons"));
@@ -6092,7 +6217,8 @@ EditorNode::EditorNode() {
play_button->set_shortcut(ED_SHORTCUT("editor/play", TTR("Play"), KEY_F5));
#endif
- pause_button = memnew(ToolButton);
+ pause_button = memnew(Button);
+ pause_button->set_flat(true);
pause_button->set_toggle_mode(true);
pause_button->set_icon(gui_base->get_theme_icon("Pause", "EditorIcons"));
pause_button->set_focus_mode(Control::FOCUS_NONE);
@@ -6105,7 +6231,8 @@ EditorNode::EditorNode() {
pause_button->set_shortcut(ED_SHORTCUT("editor/pause_scene", TTR("Pause Scene"), KEY_F7));
#endif
- stop_button = memnew(ToolButton);
+ stop_button = memnew(Button);
+ stop_button->set_flat(true);
play_hb->add_child(stop_button);
stop_button->set_focus_mode(Control::FOCUS_NONE);
stop_button->set_icon(gui_base->get_theme_icon("Stop", "EditorIcons"));
@@ -6122,7 +6249,8 @@ EditorNode::EditorNode() {
play_hb->add_child(run_native);
run_native->connect("native_run", callable_mp(this, &EditorNode::_run_native));
- play_scene_button = memnew(ToolButton);
+ play_scene_button = memnew(Button);
+ play_scene_button->set_flat(true);
play_hb->add_child(play_scene_button);
play_scene_button->set_toggle_mode(true);
play_scene_button->set_focus_mode(Control::FOCUS_NONE);
@@ -6135,7 +6263,8 @@ EditorNode::EditorNode() {
play_scene_button->set_shortcut(ED_SHORTCUT("editor/play_scene", TTR("Play Scene"), KEY_F6));
#endif
- play_custom_scene_button = memnew(ToolButton);
+ play_custom_scene_button = memnew(Button);
+ play_custom_scene_button->set_flat(true);
play_hb->add_child(play_custom_scene_button);
play_custom_scene_button->set_toggle_mode(true);
play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE);
@@ -6296,7 +6425,8 @@ EditorNode::EditorNode() {
version_label->set_self_modulate(Color(1, 1, 1, 0.6));
bottom_panel_hb->add_child(version_label);
- bottom_panel_raise = memnew(ToolButton);
+ bottom_panel_raise = memnew(Button);
+ bottom_panel_raise->set_flat(true);
bottom_panel_raise->set_icon(gui_base->get_theme_icon("ExpandBottomDock", "EditorIcons"));
bottom_panel_raise->set_shortcut(ED_SHORTCUT("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KEY_MASK_SHIFT | KEY_F12));
@@ -6307,7 +6437,7 @@ EditorNode::EditorNode() {
bottom_panel_raise->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_raise_toggled));
log = memnew(EditorLog);
- ToolButton *output_button = add_bottom_panel_item(TTR("Output"), log);
+ Button *output_button = add_bottom_panel_item(TTR("Output"), log);
log->set_tool_button(output_button);
old_split_ofs = 0;
@@ -6474,6 +6604,7 @@ EditorNode::EditorNode() {
}
resource_preview->add_preview_generator(Ref<EditorTexturePreviewPlugin>(memnew(EditorTexturePreviewPlugin)));
+ resource_preview->add_preview_generator(Ref<EditorImagePreviewPlugin>(memnew(EditorImagePreviewPlugin)));
resource_preview->add_preview_generator(Ref<EditorPackedScenePreviewPlugin>(memnew(EditorPackedScenePreviewPlugin)));
resource_preview->add_preview_generator(Ref<EditorMaterialPreviewPlugin>(memnew(EditorMaterialPreviewPlugin)));
resource_preview->add_preview_generator(Ref<EditorScriptPreviewPlugin>(memnew(EditorScriptPreviewPlugin)));
@@ -6568,6 +6699,7 @@ EditorNode::EditorNode() {
gui_base->add_child(load_error_dialog);
execute_outputs = memnew(RichTextLabel);
+ execute_outputs->set_selection_enabled(true);
execute_output_dialog = memnew(AcceptDialog);
execute_output_dialog->add_child(execute_outputs);
execute_output_dialog->set_title("");