Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a system to contextualize global themes #81130

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
311 changes: 173 additions & 138 deletions editor/editor_node.cpp

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions editor/editor_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,6 @@ class EditorNode : public Node {
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;
Expand Down Expand Up @@ -525,6 +524,7 @@ class EditorNode : public Node {
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();

Expand Down Expand Up @@ -851,6 +851,8 @@ class EditorNode : public Node {
void stop_child_process(OS::ProcessID p_pid);

Ref<Theme> get_editor_theme() const { return theme; }
void update_preview_themes(int p_mode);

Ref<Script> get_object_custom_type_base(const Object *p_object) const;
StringName get_object_custom_type_name(const Object *p_object) const;
Ref<Texture2D> get_object_icon(const Object *p_object, const String &p_fallback = "Object");
Expand All @@ -867,7 +869,6 @@ class EditorNode : public Node {
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) {
Expand Down
4 changes: 3 additions & 1 deletion editor/editor_resource_preview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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();
}
}

Expand Down
30 changes: 30 additions & 0 deletions editor/plugins/canvas_item_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,22 @@ void CanvasItemEditor::_on_grid_menu_id_pressed(int p_id) {
viewport->queue_redraw();
}

void CanvasItemEditor::_switch_theme_preview(int p_mode) {
view_menu->get_popup()->hide();

if (theme_preview == p_mode) {
return;
}
theme_preview = (ThemePreviewMode)p_mode;
EditorSettings::get_singleton()->set_project_metadata("2d_editor", "theme_preview", theme_preview);

for (int i = 0; i < THEME_PREVIEW_MAX; i++) {
theme_menu->set_item_checked(i, i == theme_preview);
}

EditorNode::get_singleton()->update_preview_themes(theme_preview);
}

bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_event) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
Ref<InputEventMouseButton> b = p_event;
Expand Down Expand Up @@ -5322,6 +5338,20 @@ CanvasItemEditor::CanvasItemEditor() {
p->add_separator();
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale")), PREVIEW_CANVAS_SCALE);

theme_menu = memnew(PopupMenu);
theme_menu->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_switch_theme_preview));
theme_menu->set_name("ThemeMenu");
theme_menu->add_radio_check_item(TTR("Project theme"), THEME_PREVIEW_PROJECT);
theme_menu->add_radio_check_item(TTR("Editor theme"), THEME_PREVIEW_EDITOR);
theme_menu->add_radio_check_item(TTR("Default theme"), THEME_PREVIEW_DEFAULT);
p->add_child(theme_menu);
p->add_submenu_item(TTR("Preview Theme"), "ThemeMenu");

theme_preview = (ThemePreviewMode)(int)EditorSettings::get_singleton()->get_project_metadata("2d_editor", "theme_preview", THEME_PREVIEW_PROJECT);
for (int i = 0; i < THEME_PREVIEW_MAX; i++) {
theme_menu->set_item_checked(i, i == theme_preview);
}

main_menu_hbox->add_child(memnew(VSeparator));

// Contextual toolbars.
Expand Down
16 changes: 16 additions & 0 deletions editor/plugins/canvas_item_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ class CanvasItemEditor : public VBoxContainer {
Button *override_camera_button = nullptr;
MenuButton *view_menu = nullptr;
PopupMenu *grid_menu = nullptr;
PopupMenu *theme_menu = nullptr;
HBoxContainer *animation_hb = nullptr;
MenuButton *animation_menu = nullptr;

Expand Down Expand Up @@ -404,6 +405,19 @@ class CanvasItemEditor : public VBoxContainer {
void _prepare_grid_menu();
void _on_grid_menu_id_pressed(int p_id);

public:
enum ThemePreviewMode {
THEME_PREVIEW_PROJECT,
THEME_PREVIEW_EDITOR,
THEME_PREVIEW_DEFAULT,

THEME_PREVIEW_MAX // The number of options for enumerating.
};

private:
ThemePreviewMode theme_preview = THEME_PREVIEW_PROJECT;
void _switch_theme_preview(int p_mode);

List<CanvasItem *> _get_edited_canvas_items(bool retrieve_locked = false, bool remove_canvas_item_if_parent_in_selection = true) const;
Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list);
void _expand_encompassing_rect_using_children(Rect2 &r_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D(), bool include_locked_nodes = true);
Expand Down Expand Up @@ -558,6 +572,8 @@ class CanvasItemEditor : public VBoxContainer {

virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override;

ThemePreviewMode get_theme_preview() const { return theme_preview; }

EditorSelection *editor_selection = nullptr;

CanvasItemEditor();
Expand Down
10 changes: 6 additions & 4 deletions editor/plugins/script_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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")));

Expand All @@ -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();

Expand All @@ -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));
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/theme_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 9 additions & 4 deletions editor/plugins/theme_editor_preview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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")));

Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions editor/plugins/theme_editor_preview.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
45 changes: 17 additions & 28 deletions scene/3d/label_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -780,42 +780,31 @@ Ref<Font> Label3D::_get_font_or_default() const {
return font_override;
}

// Check the project-defined Theme resource.
if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
List<StringName> theme_types;
ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
StringName theme_name = "font";
List<StringName> theme_types;
ThemeDB::get_singleton()->get_native_type_dependencies(get_class_name(), &theme_types);

ThemeContext *global_context = ThemeDB::get_singleton()->get_default_theme_context();
for (const Ref<Theme> &theme : global_context->get_themes()) {
if (theme.is_null()) {
continue;
}

for (const StringName &E : theme_types) {
if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
Ref<Font> f = ThemeDB::get_singleton()->get_project_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
if (f.is_valid()) {
theme_font = f;
theme_font->connect_changed(callable_mp(const_cast<Label3D *>(this), &Label3D::_font_changed));
}
return f;
if (!theme->has_font(theme_name, E)) {
continue;
}
}
}

// Lastly, fall back on the items defined in the default Theme, if they exist.
{
List<StringName> theme_types;
ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);

for (const StringName &E : theme_types) {
if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
Ref<Font> f = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
if (f.is_valid()) {
theme_font = f;
theme_font->connect_changed(callable_mp(const_cast<Label3D *>(this), &Label3D::_font_changed));
}
return f;
Ref<Font> f = theme->get_font(theme_name, E);
if (f.is_valid()) {
theme_font = f;
theme_font->connect_changed(callable_mp(const_cast<Label3D *>(this), &Label3D::_font_changed));
}
return f;
}
}

// If they don't exist, use any type to return the default/empty value.
Ref<Font> f = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName());
Ref<Font> f = global_context->get_fallback_theme()->get_font(theme_name, StringName());
if (f.is_valid()) {
theme_font = f;
theme_font->connect_changed(callable_mp(const_cast<Label3D *>(this), &Label3D::_font_changed));
Expand Down
12 changes: 10 additions & 2 deletions scene/gui/control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2465,6 +2465,11 @@ bool Control::has_theme_owner_node() const {
return data.theme_owner->has_owner_node();
}

void Control::set_theme_context(ThemeContext *p_context, bool p_propagate) {
ERR_MAIN_THREAD_GUARD;
data.theme_owner->set_owner_context(p_context, p_propagate);
}

void Control::set_theme(const Ref<Theme> &p_theme) {
ERR_MAIN_THREAD_GUARD;
if (data.theme == p_theme) {
Expand Down Expand Up @@ -3124,7 +3129,9 @@ void Control::_notification(int p_notification) {
notification(NOTIFICATION_TRANSLATION_CHANGED);
}
#endif
notification(NOTIFICATION_THEME_CHANGED);

// Emits NOTIFICATION_THEME_CHANGED internally.
set_theme_context(ThemeDB::get_singleton()->get_nearest_theme_context(this));
} break;

case NOTIFICATION_POST_ENTER_TREE: {
Expand All @@ -3134,6 +3141,7 @@ void Control::_notification(int p_notification) {
} break;

case NOTIFICATION_EXIT_TREE: {
set_theme_context(nullptr, false);
release_focus();
get_viewport()->_gui_remove_control(this);
} break;
Expand Down Expand Up @@ -3632,7 +3640,7 @@ void Control::_bind_methods() {
}

Control::Control() {
data.theme_owner = memnew(ThemeOwner);
data.theme_owner = memnew(ThemeOwner(this));
}

Control::~Control() {
Expand Down
3 changes: 3 additions & 0 deletions scene/gui/control.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class Viewport;
class Label;
class Panel;
class ThemeOwner;
class ThemeContext;

class Control : public CanvasItem {
GDCLASS(Control, CanvasItem);
Expand Down Expand Up @@ -553,6 +554,8 @@ class Control : public CanvasItem {
Node *get_theme_owner_node() const;
bool has_theme_owner_node() const;

void set_theme_context(ThemeContext *p_context, bool p_propagate = true);

void set_theme(const Ref<Theme> &p_theme);
Ref<Theme> get_theme() const;

Expand Down
13 changes: 11 additions & 2 deletions scene/main/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1269,7 +1269,9 @@ void Window::_notification(int p_what) {
notification(NOTIFICATION_TRANSLATION_CHANGED);
}
#endif
notification(NOTIFICATION_THEME_CHANGED);

// Emits NOTIFICATION_THEME_CHANGED internally.
set_theme_context(ThemeDB::get_singleton()->get_nearest_theme_context(this));
} break;

case NOTIFICATION_READY: {
Expand Down Expand Up @@ -1313,6 +1315,8 @@ void Window::_notification(int p_what) {
} break;

case NOTIFICATION_EXIT_TREE: {
set_theme_context(nullptr, false);

if (transient) {
_clear_transient();
}
Expand Down Expand Up @@ -1889,6 +1893,11 @@ bool Window::has_theme_owner_node() const {
return theme_owner->has_owner_node();
}

void Window::set_theme_context(ThemeContext *p_context, bool p_propagate) {
ERR_MAIN_THREAD_GUARD;
theme_owner->set_owner_context(p_context, p_propagate);
}

void Window::set_theme(const Ref<Theme> &p_theme) {
ERR_MAIN_THREAD_GUARD;
if (theme == p_theme) {
Expand Down Expand Up @@ -2887,7 +2896,7 @@ Window::Window() {
max_size_used = max_size; // Update max_size_used.
}

theme_owner = memnew(ThemeOwner);
theme_owner = memnew(ThemeOwner(this));
RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED);
}

Expand Down
3 changes: 3 additions & 0 deletions scene/main/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Font;
class Shortcut;
class StyleBox;
class ThemeOwner;
class ThemeContext;

class Window : public Viewport {
GDCLASS(Window, Viewport)
Expand Down Expand Up @@ -365,6 +366,8 @@ class Window : public Viewport {
Node *get_theme_owner_node() const;
bool has_theme_owner_node() const;

void set_theme_context(ThemeContext *p_context, bool p_propagate = true);

void set_theme(const Ref<Theme> &p_theme);
Ref<Theme> get_theme() const;

Expand Down
Loading