Add theme contexts to various parts of the editor

This change defines additional theme contexts for editor
branches to prevent theme leaking between the default
theme, the project theme, and the editor theme.

- Both editor window and EditorNode define an editor-specific
context with the editor theme and the default theme.
- The 2D viewport defines a project-specific context with
the project theme and the default theme.
- Theme editor preview tabs define the default-only context
with the default theme.

Additionally, the default theme context now only includes
the project theme for running projects (both export and debug).
This prevents the project theme from leaking into the editor.

This commit also does a little clean up on the theming aspects
of the EditorNode.
This commit is contained in:
Yuri Sizov 2023-09-06 16:11:05 +02:00
parent 58126e479c
commit 512182f147
9 changed files with 181 additions and 150 deletions

View file

@ -63,6 +63,7 @@
#include "scene/resources/image_texture.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/portable_compressed_texture.h"
#include "scene/theme/theme_db.h"
#include "servers/display_server.h"
#include "servers/navigation_server_3d.h"
#include "servers/physics_server_2d.h"
@ -454,6 +455,85 @@ void EditorNode::_select_default_main_screen_plugin() {
editor_select(-1);
}
void EditorNode::_update_theme(bool p_skip_creation) {
if (!p_skip_creation) {
theme = create_custom_theme(theme);
DisplayServer::set_early_window_clear_color_override(true, theme->get_color(SNAME("background"), EditorStringName(Editor)));
}
List<Ref<Theme>> editor_themes;
editor_themes.push_back(theme);
editor_themes.push_back(ThemeDB::get_singleton()->get_default_theme());
ThemeContext *node_tc = ThemeDB::get_singleton()->get_theme_context(this);
if (node_tc) {
node_tc->set_themes(editor_themes);
} else {
ThemeDB::get_singleton()->create_theme_context(this, editor_themes);
}
Window *window = get_window();
if (window) {
ThemeContext *window_tc = ThemeDB::get_singleton()->get_theme_context(window);
if (window_tc) {
window_tc->set_themes(editor_themes);
} else {
ThemeDB::get_singleton()->create_theme_context(window, editor_themes);
}
}
gui_base->add_theme_style_override("panel", theme->get_stylebox(SNAME("Background"), EditorStringName(EditorStyles)));
main_vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, theme->get_constant(SNAME("window_border_margin"), EditorStringName(Editor)));
main_vbox->add_theme_constant_override("separation", theme->get_constant(SNAME("top_bar_separation"), EditorStringName(Editor)));
scene_root_parent->add_theme_style_override("panel", theme->get_stylebox(SNAME("Content"), EditorStringName(EditorStyles)));
bottom_panel->add_theme_style_override("panel", theme->get_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles)));
main_menu->add_theme_style_override("hover", theme->get_stylebox(SNAME("MenuHover"), EditorStringName(EditorStyles)));
prev_scene->set_icon(theme->get_icon(SNAME("PrevScene"), EditorStringName(EditorIcons)));
distraction_free->set_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons)));
bottom_panel_raise->set_icon(theme->get_icon(SNAME("ExpandBottomDock"), EditorStringName(EditorIcons)));
if (gui_base->is_layout_rtl()) {
dock_tab_move_left->set_icon(theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
dock_tab_move_right->set_icon(theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
} else {
dock_tab_move_left->set_icon(theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
dock_tab_move_right->set_icon(theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
}
help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), theme->get_icon(SNAME("HelpSearch"), EditorStringName(EditorIcons)));
help_menu->set_item_icon(help_menu->get_item_index(HELP_DOCS), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)));
help_menu->set_item_icon(help_menu->get_item_index(HELP_QA), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)));
help_menu->set_item_icon(help_menu->get_item_index(HELP_REPORT_A_BUG), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)));
help_menu->set_item_icon(help_menu->get_item_index(HELP_COPY_SYSTEM_INFO), theme->get_icon(SNAME("ActionCopy"), EditorStringName(EditorIcons)));
help_menu->set_item_icon(help_menu->get_item_index(HELP_SUGGEST_A_FEATURE), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)));
help_menu->set_item_icon(help_menu->get_item_index(HELP_SEND_DOCS_FEEDBACK), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)));
help_menu->set_item_icon(help_menu->get_item_index(HELP_COMMUNITY), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)));
help_menu->set_item_icon(help_menu->get_item_index(HELP_ABOUT), theme->get_icon(SNAME("Godot"), EditorStringName(EditorIcons)));
help_menu->set_item_icon(help_menu->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), theme->get_icon(SNAME("Heart"), EditorStringName(EditorIcons)));
for (int i = 0; i < main_editor_buttons.size(); i++) {
main_editor_buttons.write[i]->add_theme_font_override("font", theme->get_font(SNAME("main_button_font"), EditorStringName(EditorFonts)));
main_editor_buttons.write[i]->add_theme_font_size_override("font_size", theme->get_font_size(SNAME("main_button_font_size"), EditorStringName(EditorFonts)));
}
if (EditorDebuggerNode::get_singleton()->is_visible()) {
bottom_panel->add_theme_style_override("panel", theme->get_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles)));
}
for (int i = 0; i < main_editor_buttons.size(); i++) {
Button *tb = main_editor_buttons[i];
EditorPlugin *p_editor = editor_table[i];
Ref<Texture2D> icon = p_editor->get_icon();
if (icon.is_valid()) {
tb->set_icon(icon);
} else if (theme->has_icon(p_editor->get_name(), EditorStringName(EditorIcons))) {
tb->set_icon(theme->get_icon(p_editor->get_name(), EditorStringName(EditorIcons)));
}
}
}
void EditorNode::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_PROCESS: {
@ -487,7 +567,7 @@ void EditorNode::_notification(int p_what) {
// Update the icon itself only when the spinner is visible.
if (EDITOR_GET("interface/editor/show_update_spinner")) {
update_spinner->set_icon(gui_base->get_editor_theme_icon("Progress" + itos(update_spinner_step + 1)));
update_spinner->set_icon(theme->get_icon("Progress" + itos(update_spinner_step + 1), EditorStringName(EditorIcons)));
}
}
@ -507,9 +587,11 @@ void EditorNode::_notification(int p_what) {
if (window) {
// Handle macOS fullscreen and extend-to-title changes.
window->connect("titlebar_changed", callable_mp(this, &EditorNode::_titlebar_resized));
window->set_theme(theme);
}
// Theme has already been created in the constructor, so we can skip that step.
_update_theme(true);
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec")));
get_tree()->get_root()->set_as_audio_listener_3d(false);
get_tree()->get_root()->set_as_audio_listener_2d(false);
@ -524,6 +606,7 @@ void EditorNode::_notification(int p_what) {
command_palette->register_shortcuts_as_command();
MessageQueue::get_singleton()->push_callable(callable_mp(this, &EditorNode::_begin_first_scan));
/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
} break;
@ -585,6 +668,12 @@ void EditorNode::_notification(int p_what) {
_titlebar_resized();
// Set up a theme context for the 2D preview viewport using the project theme.
List<Ref<Theme>> preview_themes;
preview_themes.push_back(ThemeDB::get_singleton()->get_project_theme());
preview_themes.push_back(ThemeDB::get_singleton()->get_default_theme());
ThemeDB::get_singleton()->create_theme_context(scene_root, preview_themes);
/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
} break;
@ -632,73 +721,14 @@ void EditorNode::_notification(int p_what) {
EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/scale_gizmo_handles");
if (theme_changed) {
theme = create_custom_theme(theme_base->get_theme());
DisplayServer::set_early_window_clear_color_override(true, theme->get_color(SNAME("background"), EditorStringName(Editor)));
theme_base->set_theme(theme);
gui_base->set_theme(theme);
get_window()->set_theme(theme);
gui_base->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Background"), EditorStringName(EditorStyles)));
main_vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, gui_base->get_theme_constant(SNAME("window_border_margin"), EditorStringName(Editor)));
main_vbox->add_theme_constant_override("separation", gui_base->get_theme_constant(SNAME("top_bar_separation"), EditorStringName(Editor)));
scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Content"), EditorStringName(EditorStyles)));
bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles)));
main_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), EditorStringName(EditorStyles)));
_update_theme();
}
scene_tabs->update_scene_tabs();
recent_scenes->reset_size();
// Update debugger area.
if (EditorDebuggerNode::get_singleton()->is_visible()) {
bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles)));
}
// Update icons.
for (int i = 0; i < singleton->main_editor_buttons.size(); i++) {
Button *tb = singleton->main_editor_buttons[i];
EditorPlugin *p_editor = singleton->editor_table[i];
Ref<Texture2D> icon = p_editor->get_icon();
if (icon.is_valid()) {
tb->set_icon(icon);
} else if (singleton->gui_base->has_theme_icon(p_editor->get_name(), EditorStringName(EditorIcons))) {
tb->set_icon(singleton->gui_base->get_editor_theme_icon(p_editor->get_name()));
}
}
_build_icon_type_cache();
prev_scene->set_icon(gui_base->get_editor_theme_icon(SNAME("PrevScene")));
distraction_free->set_icon(gui_base->get_editor_theme_icon(SNAME("DistractionFree")));
bottom_panel_raise->set_icon(gui_base->get_editor_theme_icon(SNAME("ExpandBottomDock")));
if (gui_base->is_layout_rtl()) {
dock_tab_move_left->set_icon(theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
dock_tab_move_right->set_icon(theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
} else {
dock_tab_move_left->set_icon(theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
dock_tab_move_right->set_icon(theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
}
help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), gui_base->get_editor_theme_icon(SNAME("HelpSearch")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_DOCS), gui_base->get_editor_theme_icon(SNAME("ExternalLink")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_QA), gui_base->get_editor_theme_icon(SNAME("ExternalLink")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_REPORT_A_BUG), gui_base->get_editor_theme_icon(SNAME("ExternalLink")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_COPY_SYSTEM_INFO), gui_base->get_editor_theme_icon(SNAME("ActionCopy")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_SUGGEST_A_FEATURE), gui_base->get_editor_theme_icon(SNAME("ExternalLink")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_SEND_DOCS_FEEDBACK), gui_base->get_editor_theme_icon(SNAME("ExternalLink")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_COMMUNITY), gui_base->get_editor_theme_icon(SNAME("ExternalLink")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_ABOUT), gui_base->get_editor_theme_icon(SNAME("Godot")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), gui_base->get_editor_theme_icon(SNAME("Heart")));
for (int i = 0; i < main_editor_buttons.size(); i++) {
main_editor_buttons.write[i]->add_theme_font_override("font", gui_base->get_theme_font(SNAME("main_button_font"), EditorStringName(EditorFonts)));
main_editor_buttons.write[i]->add_theme_font_size_override("font_size", gui_base->get_theme_font_size(SNAME("main_button_font_size"), EditorStringName(EditorFonts)));
}
HashSet<String> updated_textfile_extensions;
bool extensions_match = true;
const Vector<String> textfile_ext = ((String)(EDITOR_GET("docks/filesystem/textfile_extensions"))).split(",", false);
@ -735,8 +765,7 @@ void EditorNode::_update_update_spinner() {
// Make the icon modulate color overbright because icons are not completely white on a dark theme.
// On a light theme, icons are dark, so we need to modulate them with an even brighter color.
const bool dark_theme = EditorSettings::get_singleton()->is_dark_theme();
update_spinner->set_self_modulate(
gui_base->get_theme_color(SNAME("error_color"), EditorStringName(Editor)) * (dark_theme ? Color(1.1, 1.1, 1.1) : Color(4.25, 4.25, 4.25)));
update_spinner->set_self_modulate(theme->get_color(SNAME("error_color"), EditorStringName(Editor)) * (dark_theme ? Color(1.1, 1.1, 1.1) : Color(4.25, 4.25, 4.25)));
} else {
update_spinner->set_tooltip_text(TTR("Spins when the editor window redraws."));
update_spinner->set_self_modulate(Color(1, 1, 1));
@ -3131,12 +3160,12 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed
tb->set_icon(icon);
// Make sure the control is updated if the icon is reimported.
icon->connect_changed(callable_mp((Control *)tb, &Control::update_minimum_size));
} else if (singleton->gui_base->has_theme_icon(p_editor->get_name(), EditorStringName(EditorIcons))) {
tb->set_icon(singleton->gui_base->get_editor_theme_icon(p_editor->get_name()));
} else if (singleton->theme->has_icon(p_editor->get_name(), EditorStringName(EditorIcons))) {
tb->set_icon(singleton->theme->get_icon(p_editor->get_name(), EditorStringName(EditorIcons)));
}
tb->add_theme_font_override("font", singleton->gui_base->get_theme_font(SNAME("main_button_font"), EditorStringName(EditorFonts)));
tb->add_theme_font_size_override("font_size", singleton->gui_base->get_theme_font_size(SNAME("main_button_font_size"), EditorStringName(EditorFonts)));
tb->add_theme_font_override("font", singleton->theme->get_font(SNAME("main_button_font"), EditorStringName(EditorFonts)));
tb->add_theme_font_size_override("font_size", singleton->theme->get_font_size(SNAME("main_button_font_size"), EditorStringName(EditorFonts)));
singleton->main_editor_buttons.push_back(tb);
singleton->main_editor_button_hb->add_child(tb);
@ -4067,14 +4096,14 @@ void EditorNode::notify_all_debug_sessions_exited() {
void EditorNode::add_io_error(const String &p_error) {
DEV_ASSERT(Thread::get_caller_id() == Thread::get_main_id());
singleton->load_errors->add_image(singleton->gui_base->get_editor_theme_icon(SNAME("Error")));
singleton->load_errors->add_image(singleton->theme->get_icon(SNAME("Error"), EditorStringName(EditorIcons)));
singleton->load_errors->add_text(p_error + "\n");
EditorInterface::get_singleton()->popup_dialog_centered_ratio(singleton->load_error_dialog, 0.5);
}
void EditorNode::add_io_warning(const String &p_warning) {
DEV_ASSERT(Thread::get_caller_id() == Thread::get_main_id());
singleton->load_errors->add_image(singleton->gui_base->get_editor_theme_icon(SNAME("Warning")));
singleton->load_errors->add_image(singleton->theme->get_icon(SNAME("Warning"), EditorStringName(EditorIcons)));
singleton->load_errors->add_text(p_warning + "\n");
EditorInterface::get_singleton()->popup_dialog_centered_ratio(singleton->load_error_dialog, 0.5);
}
@ -4212,8 +4241,8 @@ Ref<Texture2D> EditorNode::_get_class_or_script_icon(const String &p_class, cons
// scripts extending other scripts and for built-in classes.
String script_class_name = p_script->get_language()->get_global_class_name(p_script->get_path());
String base_type = ScriptServer::get_global_class_native_base(script_class_name);
if (gui_base && gui_base->has_theme_icon(base_type, EditorStringName(EditorIcons))) {
return gui_base->get_editor_theme_icon(base_type);
if (theme.is_valid() && theme->has_icon(base_type, EditorStringName(EditorIcons))) {
return theme->get_icon(base_type, EditorStringName(EditorIcons));
}
}
}
@ -4236,22 +4265,22 @@ Ref<Texture2D> EditorNode::_get_class_or_script_icon(const String &p_class, cons
// Look up the class name or the fallback name in the editor theme.
// This is only relevant for built-in classes.
if (gui_base) {
if (gui_base->has_theme_icon(p_class, EditorStringName(EditorIcons))) {
return gui_base->get_editor_theme_icon(p_class);
if (theme.is_valid()) {
if (theme->has_icon(p_class, EditorStringName(EditorIcons))) {
return theme->get_icon(p_class, EditorStringName(EditorIcons));
}
if (!p_fallback.is_empty() && gui_base->has_theme_icon(p_fallback, EditorStringName(EditorIcons))) {
return gui_base->get_editor_theme_icon(p_fallback);
if (!p_fallback.is_empty() && theme->has_icon(p_fallback, EditorStringName(EditorIcons))) {
return theme->get_icon(p_fallback, EditorStringName(EditorIcons));
}
// If the fallback is empty or wasn't found, use the default fallback.
if (ClassDB::class_exists(p_class)) {
bool instantiable = !ClassDB::is_virtual(p_class) && ClassDB::can_instantiate(p_class);
if (ClassDB::is_parent_class(p_class, SNAME("Node"))) {
return gui_base->get_editor_theme_icon(instantiable ? "Node" : "NodeDisabled");
return theme->get_icon(instantiable ? "Node" : "NodeDisabled", EditorStringName(EditorIcons));
} else {
return gui_base->get_editor_theme_icon(instantiable ? "Object" : "ObjectDisabled");
return theme->get_icon(instantiable ? "Object" : "ObjectDisabled", EditorStringName(EditorIcons));
}
}
}
@ -4464,12 +4493,12 @@ Ref<Texture2D> EditorNode::_file_dialog_get_icon(const String &p_path) {
void EditorNode::_build_icon_type_cache() {
List<StringName> tl;
theme_base->get_theme()->get_icon_list(EditorStringName(EditorIcons), &tl);
theme->get_icon_list(EditorStringName(EditorIcons), &tl);
for (const StringName &E : tl) {
if (!ClassDB::class_exists(E)) {
continue;
}
icon_type_cache[E] = theme_base->get_theme()->get_icon(E, EditorStringName(EditorIcons));
icon_type_cache[E] = theme->get_icon(E, EditorStringName(EditorIcons));
}
}
@ -4728,7 +4757,7 @@ void EditorNode::_dock_select_draw() {
Color used = Color(0.6, 0.6, 0.6, 0.8);
Color used_selected = Color(0.8, 0.8, 0.8, 0.8);
Color tab_selected = theme_base->get_theme_color(SNAME("mono_color"), EditorStringName(Editor));
Color tab_selected = theme->get_color(SNAME("mono_color"), EditorStringName(Editor));
Color unused = used;
unused.a = 0.4;
Color unusable = unused;
@ -5666,9 +5695,9 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) {
}
if (EditorDebuggerNode::get_singleton() == bottom_panel_items[p_idx].control) {
// This is the debug panel which uses tabs, so the top section should be smaller.
bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles)));
bottom_panel->add_theme_style_override("panel", theme->get_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles)));
} else {
bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles)));
bottom_panel->add_theme_style_override("panel", theme->get_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles)));
}
center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE);
center_split->set_collapsed(false);
@ -5677,7 +5706,7 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) {
}
bottom_panel_raise->show();
} else {
bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles)));
bottom_panel->add_theme_style_override("panel", theme->get_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles)));
bottom_panel_items[p_idx].button->set_pressed(false);
bottom_panel_items[p_idx].control->set_visible(false);
center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);
@ -5766,7 +5795,7 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) {
{
// TODO: make proper previews
Ref<ImageTexture> texture = gui_base->get_editor_theme_icon(SNAME("FileBigThumb"));
Ref<ImageTexture> texture = theme->get_icon(SNAME("FileBigThumb"), EditorStringName(EditorIcons));
Ref<Image> img = texture->get_image();
img = img->duplicate();
img->resize(48, 48); // meh
@ -5816,10 +5845,10 @@ Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control *
if (p_paths[i].ends_with("/")) {
label->set_text(p_paths[i].substr(0, p_paths[i].length() - 1).get_file());
icon->set_texture(gui_base->get_editor_theme_icon(SNAME("Folder")));
icon->set_texture(theme->get_icon(SNAME("Folder"), EditorStringName(EditorIcons)));
} else {
label->set_text(p_paths[i].get_file());
icon->set_texture(gui_base->get_editor_theme_icon(SNAME("File")));
icon->set_texture(theme->get_icon(SNAME("File"), EditorStringName(EditorIcons)));
}
icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
icon->set_size(Size2(16, 16));
@ -6875,32 +6904,22 @@ EditorNode::EditorNode() {
textfile_extensions.insert(E);
}
theme_base = memnew(Control);
add_child(theme_base);
theme_base->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
gui_base = memnew(Panel);
theme_base->add_child(gui_base);
gui_base->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
theme_base->set_theme(theme);
gui_base->set_theme(theme);
gui_base->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Background"), EditorStringName(EditorStyles)));
resource_preview = memnew(EditorResourcePreview);
add_child(resource_preview);
progress_dialog = memnew(ProgressDialog);
progress_dialog->set_unparent_when_invisible(true);
gui_base = memnew(Panel);
add_child(gui_base);
// Take up all screen.
gui_base->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
gui_base->set_anchor(SIDE_RIGHT, Control::ANCHOR_END);
gui_base->set_anchor(SIDE_BOTTOM, Control::ANCHOR_END);
gui_base->set_end(Point2(0, 0));
main_vbox = memnew(VBoxContainer);
gui_base->add_child(main_vbox);
main_vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, gui_base->get_theme_constant(SNAME("window_border_margin"), EditorStringName(Editor)));
main_vbox->add_theme_constant_override("separation", gui_base->get_theme_constant(SNAME("top_bar_separation"), EditorStringName(Editor)));
title_bar = memnew(EditorTitleBar);
main_vbox->add_child(title_bar);
@ -6978,11 +6997,6 @@ EditorNode::EditorNode() {
HBoxContainer *dock_hb = memnew(HBoxContainer);
dock_tab_move_left = memnew(Button);
dock_tab_move_left->set_flat(true);
if (gui_base->is_layout_rtl()) {
dock_tab_move_left->set_icon(theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
} else {
dock_tab_move_left->set_icon(theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
}
dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE);
dock_tab_move_left->connect("pressed", callable_mp(this, &EditorNode::_dock_move_left));
dock_hb->add_child(dock_tab_move_left);
@ -6995,11 +7009,6 @@ EditorNode::EditorNode() {
dock_tab_move_right = memnew(Button);
dock_tab_move_right->set_flat(true);
if (gui_base->is_layout_rtl()) {
dock_tab_move_right->set_icon(theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
} else {
dock_tab_move_right->set_icon(theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
}
dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE);
dock_tab_move_right->connect("pressed", callable_mp(this, &EditorNode::_dock_move_right));
@ -7065,14 +7074,13 @@ EditorNode::EditorNode() {
ED_SHORTCUT_OVERRIDE("editor/distraction_free_mode", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::D);
distraction_free->set_shortcut(ED_GET_SHORTCUT("editor/distraction_free_mode"));
distraction_free->set_tooltip_text(TTR("Toggle distraction-free mode."));
distraction_free->set_icon(gui_base->get_editor_theme_icon(SNAME("DistractionFree")));
distraction_free->set_toggle_mode(true);
scene_tabs->add_extra_button(distraction_free);
distraction_free->connect("pressed", callable_mp(this, &EditorNode::_toggle_distraction_free_mode));
scene_root_parent = memnew(PanelContainer);
scene_root_parent->set_custom_minimum_size(Size2(0, 80) * EDSCALE);
scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Content"), EditorStringName(EditorStyles)));
scene_root_parent->add_theme_style_override("panel", theme->get_stylebox(SNAME("Content"), EditorStringName(EditorStyles)));
scene_root_parent->set_draw_behind_parent(true);
srt->add_child(scene_root_parent);
scene_root_parent->set_v_size_flags(Control::SIZE_EXPAND_FILL);
@ -7080,7 +7088,6 @@ EditorNode::EditorNode() {
scene_root = memnew(SubViewport);
scene_root->set_embedding_subwindows(true);
scene_root->set_disable_3d(true);
scene_root->set_disable_input(true);
scene_root->set_as_audio_listener_2d(true);
@ -7103,7 +7110,7 @@ EditorNode::EditorNode() {
main_menu = memnew(MenuBar);
title_bar->add_child(main_menu);
main_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), EditorStringName(EditorStyles)));
main_menu->add_theme_style_override("hover", theme->get_stylebox(SNAME("MenuHover"), EditorStringName(EditorStyles)));
main_menu->set_flat(true);
main_menu->set_start_index(0); // Main menu, add to the start of global menu.
main_menu->set_prefer_global_menu(global_menu);
@ -7116,7 +7123,6 @@ EditorNode::EditorNode() {
prev_scene = memnew(Button);
prev_scene->set_flat(true);
prev_scene->set_icon(gui_base->get_editor_theme_icon(SNAME("PrevScene")));
prev_scene->set_tooltip_text(TTR("Go to previously opened scene."));
prev_scene->set_disabled(true);
prev_scene->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(FILE_OPEN_PREV));
@ -7277,8 +7283,8 @@ EditorNode::EditorNode() {
if (can_expand && global_menu) {
project_title = memnew(Label);
project_title->add_theme_font_override("font", gui_base->get_theme_font(SNAME("bold"), EditorStringName(EditorFonts)));
project_title->add_theme_font_size_override("font_size", gui_base->get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts)));
project_title->add_theme_font_override("font", theme->get_font(SNAME("bold"), EditorStringName(EditorFonts)));
project_title->add_theme_font_size_override("font_size", theme->get_font_size(SNAME("bold_size"), EditorStringName(EditorFonts)));
project_title->set_focus_mode(Control::FOCUS_NONE);
project_title->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS);
project_title->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
@ -7354,22 +7360,22 @@ EditorNode::EditorNode() {
ED_SHORTCUT_AND_COMMAND("editor/editor_help", TTR("Search Help"), Key::F1);
ED_SHORTCUT_OVERRIDE("editor/editor_help", "macos", KeyModifierMask::ALT | Key::SPACE);
help_menu->add_icon_shortcut(gui_base->get_editor_theme_icon(SNAME("HelpSearch")), ED_GET_SHORTCUT("editor/editor_help"), HELP_SEARCH);
help_menu->add_icon_shortcut(theme->get_icon(SNAME("HelpSearch"), EditorStringName(EditorIcons)), ED_GET_SHORTCUT("editor/editor_help"), HELP_SEARCH);
help_menu->add_separator();
help_menu->add_icon_shortcut(gui_base->get_editor_theme_icon(SNAME("ExternalLink")), ED_SHORTCUT_AND_COMMAND("editor/online_docs", TTR("Online Documentation")), HELP_DOCS);
help_menu->add_icon_shortcut(gui_base->get_editor_theme_icon(SNAME("ExternalLink")), ED_SHORTCUT_AND_COMMAND("editor/q&a", TTR("Questions & Answers")), HELP_QA);
help_menu->add_icon_shortcut(gui_base->get_editor_theme_icon(SNAME("ExternalLink")), ED_SHORTCUT_AND_COMMAND("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG);
help_menu->add_icon_shortcut(gui_base->get_editor_theme_icon(SNAME("ActionCopy")), ED_SHORTCUT_AND_COMMAND("editor/copy_system_info", TTR("Copy System Info")), HELP_COPY_SYSTEM_INFO);
help_menu->add_icon_shortcut(theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)), ED_SHORTCUT_AND_COMMAND("editor/online_docs", TTR("Online Documentation")), HELP_DOCS);
help_menu->add_icon_shortcut(theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)), ED_SHORTCUT_AND_COMMAND("editor/q&a", TTR("Questions & Answers")), HELP_QA);
help_menu->add_icon_shortcut(theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)), ED_SHORTCUT_AND_COMMAND("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG);
help_menu->add_icon_shortcut(theme->get_icon(SNAME("ActionCopy"), EditorStringName(EditorIcons)), ED_SHORTCUT_AND_COMMAND("editor/copy_system_info", TTR("Copy System Info")), HELP_COPY_SYSTEM_INFO);
help_menu->set_item_tooltip(-1, TTR("Copies the system info as a single-line text into the clipboard."));
help_menu->add_icon_shortcut(gui_base->get_editor_theme_icon(SNAME("ExternalLink")), ED_SHORTCUT_AND_COMMAND("editor/suggest_a_feature", TTR("Suggest a Feature")), HELP_SUGGEST_A_FEATURE);
help_menu->add_icon_shortcut(gui_base->get_editor_theme_icon(SNAME("ExternalLink")), ED_SHORTCUT_AND_COMMAND("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK);
help_menu->add_icon_shortcut(gui_base->get_editor_theme_icon(SNAME("ExternalLink")), ED_SHORTCUT_AND_COMMAND("editor/community", TTR("Community")), HELP_COMMUNITY);
help_menu->add_icon_shortcut(theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)), ED_SHORTCUT_AND_COMMAND("editor/suggest_a_feature", TTR("Suggest a Feature")), HELP_SUGGEST_A_FEATURE);
help_menu->add_icon_shortcut(theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)), ED_SHORTCUT_AND_COMMAND("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK);
help_menu->add_icon_shortcut(theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)), ED_SHORTCUT_AND_COMMAND("editor/community", TTR("Community")), HELP_COMMUNITY);
help_menu->add_separator();
if (!global_menu || !OS::get_singleton()->has_feature("macos")) {
// On macOS "Quit" and "About" options are in the "app" menu.
help_menu->add_icon_shortcut(gui_base->get_editor_theme_icon(SNAME("Godot")), ED_SHORTCUT_AND_COMMAND("editor/about", TTR("About Godot")), HELP_ABOUT);
help_menu->add_icon_shortcut(theme->get_icon(SNAME("Godot"), EditorStringName(EditorIcons)), ED_SHORTCUT_AND_COMMAND("editor/about", TTR("About Godot")), HELP_ABOUT);
}
help_menu->add_icon_shortcut(gui_base->get_editor_theme_icon(SNAME("Heart")), ED_SHORTCUT_AND_COMMAND("editor/support_development", TTR("Support Godot Development")), HELP_SUPPORT_GODOT_DEVELOPMENT);
help_menu->add_icon_shortcut(theme->get_icon(SNAME("Heart"), EditorStringName(EditorIcons)), ED_SHORTCUT_AND_COMMAND("editor/support_development", TTR("Support Godot Development")), HELP_SUPPORT_GODOT_DEVELOPMENT);
// Spacer to center 2D / 3D / Script buttons.
Control *right_spacer = memnew(Control);
@ -7391,8 +7397,8 @@ EditorNode::EditorNode() {
renderer->set_fit_to_longest_item(false);
renderer->set_focus_mode(Control::FOCUS_NONE);
renderer->connect("item_selected", callable_mp(this, &EditorNode::_renderer_selected));
renderer->add_theme_font_override("font", gui_base->get_theme_font(SNAME("bold"), EditorStringName(EditorFonts)));
renderer->add_theme_font_size_override("font_size", gui_base->get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts)));
renderer->add_theme_font_override("font", theme->get_font(SNAME("bold"), EditorStringName(EditorFonts)));
renderer->add_theme_font_size_override("font_size", theme->get_font_size(SNAME("bold_size"), EditorStringName(EditorFonts)));
renderer->set_tooltip_text(TTR("Choose a renderer."));
right_menu_hb->add_child(renderer);
@ -7453,7 +7459,7 @@ EditorNode::EditorNode() {
update_spinner = memnew(MenuButton);
right_menu_hb->add_child(update_spinner);
update_spinner->set_icon(gui_base->get_editor_theme_icon(SNAME("Progress1")));
update_spinner->set_icon(theme->get_icon(SNAME("Progress1"), EditorStringName(EditorIcons)));
update_spinner->get_popup()->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option));
PopupMenu *p = update_spinner->get_popup();
p->add_radio_check_item(TTR("Update Continuously"), SETTINGS_UPDATE_CONTINUOUSLY);
@ -7536,7 +7542,7 @@ EditorNode::EditorNode() {
// Bottom panels.
bottom_panel = memnew(PanelContainer);
bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles)));
bottom_panel->add_theme_style_override("panel", theme->get_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles)));
center_split->add_child(bottom_panel);
center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);
@ -7581,14 +7587,11 @@ EditorNode::EditorNode() {
bottom_panel_hb->add_child(h_spacer);
bottom_panel_raise = memnew(Button);
bottom_panel_raise->set_flat(true);
bottom_panel_raise->set_icon(gui_base->get_editor_theme_icon(SNAME("ExpandBottomDock")));
bottom_panel_raise->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KeyModifierMask::SHIFT | Key::F12));
bottom_panel_hb->add_child(bottom_panel_raise);
bottom_panel_raise->hide();
bottom_panel_raise->set_flat(true);
bottom_panel_raise->set_toggle_mode(true);
bottom_panel_raise->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KeyModifierMask::SHIFT | Key::F12));
bottom_panel_raise->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_raise_toggled));
log = memnew(EditorLog);

View file

@ -295,7 +295,6 @@ private:
bool is_main_screen_editing = false;
PanelContainer *scene_root_parent = nullptr;
Control *theme_base = nullptr;
Control *gui_base = nullptr;
VBoxContainer *main_vbox = nullptr;
OptionButton *renderer = nullptr;
@ -525,6 +524,7 @@ private:
static void _resource_saved(Ref<Resource> p_resource, const String &p_path);
static void _resource_loaded(Ref<Resource> p_resource, const String &p_path);
void _update_theme(bool p_skip_creation = false);
void _build_icon_type_cache();
void _enable_pending_addons();
@ -867,7 +867,6 @@ public:
Error export_preset(const String &p_preset, const String &p_path, bool p_debug, bool p_pack_only);
Control *get_gui_base() { return gui_base; }
Control *get_theme_base() { return gui_base->get_parent_control(); }
void save_scene_to_path(String p_file, bool p_with_preview = true) {
if (p_with_preview) {

View file

@ -40,6 +40,7 @@
#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "scene/resources/image_texture.h"
bool EditorResourcePreviewGenerator::handles(const String &p_type) const {
@ -341,7 +342,8 @@ void EditorResourcePreview::_thread() {
void EditorResourcePreview::_update_thumbnail_sizes() {
if (small_thumbnail_size == -1) {
small_thumbnail_size = EditorNode::get_singleton()->get_theme_base()->get_editor_theme_icon(SNAME("Object"))->get_width(); // Kind of a workaround to retrieve the default icon size
// Kind of a workaround to retrieve the default icon size.
small_thumbnail_size = EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Object"), EditorStringName(EditorIcons))->get_width();
}
}

View file

@ -1612,6 +1612,8 @@ void ScriptEditor::_notification(int p_what) {
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
tab_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("ScriptEditor"), EditorStringName(EditorStyles)));
help_search->set_icon(get_editor_theme_icon(SNAME("HelpSearch")));
site_search->set_icon(get_editor_theme_icon(SNAME("ExternalLink")));
@ -1628,7 +1630,7 @@ void ScriptEditor::_notification(int p_what) {
filter_scripts->set_right_icon(get_editor_theme_icon(SNAME("Search")));
filter_methods->set_right_icon(get_editor_theme_icon(SNAME("Search")));
filename->add_theme_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit")));
filename->add_theme_style_override("normal", get_theme_stylebox(SNAME("normal"), SNAME("LineEdit")));
recent_scripts->reset_size();
@ -1639,6 +1641,9 @@ void ScriptEditor::_notification(int p_what) {
} break;
case NOTIFICATION_READY: {
// Can't set own styles in NOTIFICATION_THEME_CHANGED, so for now this will do.
add_theme_style_override("panel", get_theme_stylebox(SNAME("ScriptEditorPanel"), SNAME("EditorStyles")));
get_tree()->connect("tree_changed", callable_mp(this, &ScriptEditor::_tree_changed));
InspectorDock::get_singleton()->connect("request_help", callable_mp(this, &ScriptEditor::_help_class_open));
EditorNode::get_singleton()->connect("request_help_search", callable_mp(this, &ScriptEditor::_help_search));
@ -4139,9 +4144,6 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) {
ScriptServer::edit_request_func = _open_script_request;
add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("ScriptEditorPanel"), EditorStringName(EditorStyles)));
tab_container->add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("ScriptEditor"), EditorStringName(EditorStyles)));
Ref<EditorJSONSyntaxHighlighter> json_syntax_highlighter;
json_syntax_highlighter.instantiate();
register_syntax_highlighter(json_syntax_highlighter);

View file

@ -1217,7 +1217,7 @@ void ThemeItemEditorDialog::_dialog_about_to_show() {
import_default_theme_items->reset_item_tree();
import_editor_theme_items->set_edited_theme(edited_theme);
import_editor_theme_items->set_base_theme(EditorNode::get_singleton()->get_theme_base()->get_theme());
import_editor_theme_items->set_base_theme(EditorNode::get_singleton()->get_editor_theme());
import_editor_theme_items->reset_item_tree();
import_other_theme_items->set_edited_theme(edited_theme);

View file

@ -202,8 +202,14 @@ void ThemeEditorPreview::_notification(int p_what) {
}
connect("visibility_changed", callable_mp(this, &ThemeEditorPreview::_preview_visibility_changed));
[[fallthrough]];
}
} break;
case NOTIFICATION_READY: {
List<Ref<Theme>> preview_themes;
preview_themes.push_back(ThemeDB::get_singleton()->get_default_theme());
ThemeDB::get_singleton()->create_theme_context(preview_root, preview_themes);
} break;
case NOTIFICATION_THEME_CHANGED: {
picker_button->set_icon(get_editor_theme_icon(SNAME("ColorPick")));
@ -247,9 +253,8 @@ ThemeEditorPreview::ThemeEditorPreview() {
preview_container = memnew(ScrollContainer);
preview_body->add_child(preview_container);
MarginContainer *preview_root = memnew(MarginContainer);
preview_root = memnew(MarginContainer);
preview_container->add_child(preview_root);
preview_root->set_theme(ThemeDB::get_singleton()->get_default_theme());
preview_root->set_clip_contents(true);
preview_root->set_custom_minimum_size(Size2(450, 0) * EDSCALE);
preview_root->set_v_size_flags(SIZE_EXPAND_FILL);

View file

@ -44,6 +44,7 @@ class ThemeEditorPreview : public VBoxContainer {
GDCLASS(ThemeEditorPreview, VBoxContainer);
ScrollContainer *preview_container = nullptr;
MarginContainer *preview_root = nullptr;
ColorRect *preview_bg = nullptr;
MarginContainer *preview_overlay = nullptr;
Control *picker_overlay = nullptr;

View file

@ -272,7 +272,17 @@ void ThemeDB::_init_default_theme_context() {
default_theme_context = memnew(ThemeContext);
List<Ref<Theme>> themes;
// Only add the project theme to the default context when running projects.
#ifdef TOOLS_ENABLED
if (!Engine::get_singleton()->is_editor_hint()) {
themes.push_back(project_theme);
}
#else
themes.push_back(project_theme);
#endif
themes.push_back(default_theme);
default_theme_context->set_themes(themes);
}
@ -289,6 +299,14 @@ void ThemeDB::_finalize_theme_contexts() {
}
}
ThemeContext *ThemeDB::get_theme_context(Node *p_node) const {
if (!theme_contexts.has(p_node)) {
return nullptr;
}
return theme_contexts[p_node];
}
ThemeContext *ThemeDB::get_default_theme_context() const {
return default_theme_context;
}

View file

@ -108,6 +108,7 @@ public:
ThemeContext *create_theme_context(Node *p_node, List<Ref<Theme>> &p_themes);
void destroy_theme_context(Node *p_node);
ThemeContext *get_theme_context(Node *p_node) const;
ThemeContext *get_default_theme_context() const;
ThemeContext *get_nearest_theme_context(Node *p_for_node) const;