Refactor Theme item management in the theme editor

Backport of #46593, #46808, #49227
This commit is contained in:
Yuri Sizov 2021-06-11 00:44:42 +03:00
parent 03f275e66f
commit 014cb0c33a
12 changed files with 2175 additions and 722 deletions

View file

@ -0,0 +1 @@
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="nonzero"><path d="m8 9.669-3.536 2.583h2.536v2.537h2v-2.537h2.536z"/><path d="m8 6.355-3.536-2.583h2.536v-2.537h2v2.537h2.536z"/><path d="m.704 7.085h14.591v1.831h-14.591z"/></g></svg>

After

Width:  |  Height:  |  Size: 360 B

View file

@ -0,0 +1 @@
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="nonzero"><path d="m8 16-3.536-2.597h2.536v-2.523h2v2.523h2.536z"/><path d="m8 0-3.536 2.583h2.536v2.537h2v-2.537h2.536z"/><path d="m.704 7.085h14.591v1.831h-14.591z"/></g></svg>

After

Width:  |  Height:  |  Size: 353 B

View file

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6 6 6 0 0 0 -6-6zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4z" fill="#999"/></svg>

After

Width:  |  Height:  |  Size: 240 B

View file

@ -0,0 +1 @@
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m5.952 6.976h8.063v2.005h-8.063z" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.01h-4.011zm.968.968h2.075v2.074h-2.075z"/><path d="m5.952 1.956h8.063v2.005h-8.063z" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z"/><path d="m5.952 11.996h8.063v2.005h-8.063z" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z"/></g></svg>

After

Width:  |  Height:  |  Size: 582 B

View file

@ -0,0 +1 @@
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1.745c-.595 0-1.084.489-1.084 1.084v3.699l-3.851-1.927c-.163-.08-.343-.119-.525-.112-.395.015-.752.244-.929.597-.076.151-.115.317-.115.485 0 .41.233.786.599.97l3.481 1.74-3.481 1.74c-.366.184-.599.56-.599.97 0 .168.039.334.115.485.183.367.559.599.969.599.168 0 .334-.039.485-.114l3.851-1.927v3.111c0 .594.489 1.084 1.084 1.084s1.084-.49 1.084-1.084v-3.111l3.851 1.927c.151.075.317.114.485.114.41 0 .786-.232.969-.599.076-.151.115-.317.115-.485 0-.41-.233-.786-.599-.97l-3.481-1.74 3.481-1.74c.366-.184.599-.56.599-.97 0-.168-.039-.334-.115-.485-.182-.364-.554-.596-.961-.599-.171-.001-.34.038-.493.114l-3.851 1.927v-3.699c0-.595-.489-1.084-1.084-1.084z" fill="#8eef97"/><g fill-rule="nonzero"><path d="m8 1.745v1.783h-1.084v-.699c0-.595.489-1.084 1.084-1.084z" fill="#ff4545"/><path d="m1.528 5.312h2.957l-1.42-.711c-.163-.08-.343-.119-.525-.112-.395.015-.752.244-.929.597-.036.072-.064.148-.083.226zm5.388-1.784h1.084v1.784h-1.084z" fill="#ffe345"/><path d="m6.916 5.312h1.084v1.783h-4.796l-1.109-.554c-.366-.184-.599-.56-.599-.97 0-.088.011-.175.032-.259h2.957l2.431 1.216z" fill="#80ff45"/><path d="m3.204 7.095h4.796v1.783h-3.619l1.195-.597z" fill="#45ffa2"/><path d="m4.381 8.878h3.619v1.784h-1.084v-.628l-1.255.628h-4.114c.088-.274.283-.508.548-.641z" fill="#45d7ff"/><path d="m6.916 12.445h1.084v1.784c-.595-.001-1.084-.49-1.084-1.084z" fill="#ff4596"/><path d="m6.916 10.662h1.084v1.783h-1.084zm-1.255 0h-4.114c-.033.105-.051.216-.051.329 0 .168.039.334.115.485.183.367.559.599.969.599.168 0 .334-.039.485-.114z" fill="#8045ff"/></g></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1 @@
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m11.299 3c.772.513 1.42 1.199 1.888 2h-2.553c-.706-.621-1.629-1-2.634-1s-1.928.379-2.634 1h-2.553c.468-.801 1.116-1.487 1.888-2z" fill="#ffe345"/><path d="m5.366 5c-.593.522-1.033 1.216-1.238 2h-2.043c.122-.717.373-1.392.728-2zm7.821 0c.355.608.606 1.283.728 2h-2.043c-.205-.784-.645-1.478-1.238-2z" fill="#80ff45"/><path d="m13.915 7c.056.326.085.66.085 1s-.029.674-.085 1h-2.043c.083-.32.128-.655.128-1s-.045-.68-.128-1zm-9.787 0c-.083.32-.128.655-.128 1s.045.68.128 1h-2.043c-.056-.326-.085-.66-.085-1s.029-.674.085-1z" fill="#45ffa2"/><path d="m4.128 9c.205.784.645 1.478 1.238 2h-2.553c-.355-.608-.606-1.283-.728-2zm9.787 0c-.122.717-.373 1.392-.728 2h-2.553c.593-.522 1.033-1.216 1.238-2z" fill="#45d7ff"/><path d="m11.299 13h-6.598c.949.631 2.084 1 3.299 1s2.35-.369 3.299-1z" fill="#ff4596"/><path d="m13.187 11c-.468.801-1.116 1.487-1.888 2h-6.598c-.772-.513-1.42-1.199-1.888-2h2.553c.706.621 1.629 1 2.634 1s1.928-.379 2.634-1z" fill="#8045ff"/><path d="m4.701 3h6.598c-.949-.631-2.084-1-3.299-1s-2.35.369-3.299 1z" fill="#ff4545"/></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1 @@
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m5.952 6.976h8.049v2.005h-8.049z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.01h-4.011zm.968.968h2.075v2.074h-2.075z" fill="#e0e0e0"/><path d="m5.952 1.956h8.049v2.005h-8.049z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/><path d="m5.952 11.996h8.049v2.005h-8.049z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/></svg>

After

Width:  |  Height:  |  Size: 874 B

View file

@ -0,0 +1 @@
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m11 6.976h3.015v2.005h-3.015z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.01h-4.011zm.968.968h2.075v2.074h-2.075z" fill="#e0e0e0"/><path d="m11 1.956h3.015v2.005h-3.015z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/><path d="m11 11.996h3.015v2.005h-3.015z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/><path d="m5.995 5.995h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m5.995 5.995h4.01v4.01h-4.01zm.968.968h2.074v2.074h-2.074z" fill="#e0e0e0"/><path d="m5.995.974h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m5.995.974h4.01v4.011h-4.01zm.968.968h2.074v2.075h-2.074z" fill="#e0e0e0"/><path d="m5.995 11.015h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m5.995 11.015h4.01v4.011h-4.01zm.968.968h2.074v2.075h-2.074z" fill="#e0e0e0"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

File diff suppressed because it is too large Load diff

View file

@ -31,8 +31,6 @@
#ifndef THEME_EDITOR_PLUGIN_H #ifndef THEME_EDITOR_PLUGIN_H
#define THEME_EDITOR_PLUGIN_H #define THEME_EDITOR_PLUGIN_H
#include "scene/gui/check_box.h"
#include "scene/gui/file_dialog.h"
#include "scene/gui/margin_container.h" #include "scene/gui/margin_container.h"
#include "scene/gui/option_button.h" #include "scene/gui/option_button.h"
#include "scene/gui/scroll_container.h" #include "scene/gui/scroll_container.h"
@ -41,49 +39,233 @@
#include "editor/editor_node.h" #include "editor/editor_node.h"
class ThemeItemImportTree : public VBoxContainer {
GDCLASS(ThemeItemImportTree, VBoxContainer);
Ref<Theme> edited_theme;
Ref<Theme> base_theme;
struct ThemeItem {
String type_name;
Theme::DataType data_type;
String item_name;
bool operator<(const ThemeItem &p_item) const {
if (type_name == p_item.type_name && data_type == p_item.data_type) {
return item_name < p_item.item_name;
}
if (type_name == p_item.type_name) {
return data_type < p_item.data_type;
}
return type_name < p_item.type_name;
}
};
enum ItemCheckedState {
SELECT_IMPORT_DEFINITION,
SELECT_IMPORT_FULL,
};
Map<ThemeItem, ItemCheckedState> selected_items;
LineEdit *import_items_filter;
Tree *import_items_tree;
List<TreeItem *> tree_color_items;
List<TreeItem *> tree_constant_items;
List<TreeItem *> tree_font_items;
List<TreeItem *> tree_icon_items;
List<TreeItem *> tree_stylebox_items;
bool updating_tree = false;
enum ItemActionFlag {
IMPORT_ITEM = 1,
IMPORT_ITEM_DATA = 2,
};
TextureRect *select_colors_icon;
Label *select_colors_label;
Button *select_all_colors_button;
Button *select_full_colors_button;
Button *deselect_all_colors_button;
Label *total_selected_colors_label;
TextureRect *select_constants_icon;
Label *select_constants_label;
Button *select_all_constants_button;
Button *select_full_constants_button;
Button *deselect_all_constants_button;
Label *total_selected_constants_label;
TextureRect *select_fonts_icon;
Label *select_fonts_label;
Button *select_all_fonts_button;
Button *select_full_fonts_button;
Button *deselect_all_fonts_button;
Label *total_selected_fonts_label;
TextureRect *select_icons_icon;
Label *select_icons_label;
Button *select_all_icons_button;
Button *select_full_icons_button;
Button *deselect_all_icons_button;
Label *total_selected_icons_label;
TextureRect *select_styleboxes_icon;
Label *select_styleboxes_label;
Button *select_all_styleboxes_button;
Button *select_full_styleboxes_button;
Button *deselect_all_styleboxes_button;
Label *total_selected_styleboxes_label;
HBoxContainer *select_icons_warning_hb;
TextureRect *select_icons_warning_icon;
Label *select_icons_warning;
Button *import_collapse_types_button;
Button *import_expand_types_button;
Button *import_select_all_button;
Button *import_select_full_button;
Button *import_deselect_all_button;
void _update_items_tree();
void _toggle_type_items(bool p_collapse);
void _filter_text_changed(const String &p_value);
void _store_selected_item(TreeItem *p_tree_item);
void _restore_selected_item(TreeItem *p_tree_item);
void _update_total_selected(Theme::DataType p_data_type);
void _tree_item_edited();
void _select_all_subitems(TreeItem *p_root_item, bool p_select_with_data);
void _deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely);
void _update_parent_items(TreeItem *p_root_item);
void _select_all_items_pressed();
void _select_full_items_pressed();
void _deselect_all_items_pressed();
void _select_all_data_type_pressed(int p_data_type);
void _select_full_data_type_pressed(int p_data_type);
void _deselect_all_data_type_pressed(int p_data_type);
void _import_selected();
protected:
void _notification(int p_what);
static void _bind_methods();
public:
void set_edited_theme(const Ref<Theme> &p_theme);
void set_base_theme(const Ref<Theme> &p_theme);
void reset_item_tree();
bool has_selected_items() const;
ThemeItemImportTree();
};
class ThemeItemEditorDialog : public AcceptDialog {
GDCLASS(ThemeItemEditorDialog, AcceptDialog);
Ref<Theme> edited_theme;
TabContainer *tc;
ItemList *edit_type_list;
LineEdit *edit_add_type_value;
String edited_item_type;
Button *edit_items_add_color;
Button *edit_items_add_constant;
Button *edit_items_add_font;
Button *edit_items_add_icon;
Button *edit_items_add_stylebox;
Button *edit_items_remove_class;
Button *edit_items_remove_custom;
Button *edit_items_remove_all;
Tree *edit_items_tree;
enum ItemsTreeAction {
ITEMS_TREE_RENAME_ITEM,
ITEMS_TREE_REMOVE_ITEM,
ITEMS_TREE_REMOVE_DATA_TYPE,
};
ConfirmationDialog *edit_theme_item_dialog;
VBoxContainer *edit_theme_item_old_vb;
Label *theme_item_old_name;
LineEdit *theme_item_name;
enum ItemPopupMode {
CREATE_THEME_ITEM,
RENAME_THEME_ITEM,
ITEM_POPUP_MODE_MAX
};
ItemPopupMode item_popup_mode = ITEM_POPUP_MODE_MAX;
String edit_item_old_name;
Theme::DataType edit_item_data_type = Theme::DATA_TYPE_MAX;
ThemeItemImportTree *import_default_theme_items;
ThemeItemImportTree *import_editor_theme_items;
ThemeItemImportTree *import_other_theme_items;
LineEdit *import_another_theme_value;
Button *import_another_theme_button;
EditorFileDialog *import_another_theme_dialog;
ConfirmationDialog *confirm_closing_dialog;
void ok_pressed();
void _close_dialog();
void _dialog_about_to_show();
void _update_edit_types();
void _edited_type_selected(int p_item_idx);
void _update_edit_item_tree(String p_item_type);
void _item_tree_button_pressed(Object *p_item, int p_column, int p_id);
void _add_theme_type();
void _add_theme_item(Theme::DataType p_data_type, String p_item_name, String p_item_type);
void _remove_data_type_items(Theme::DataType p_data_type, String p_item_type);
void _remove_class_items();
void _remove_custom_items();
void _remove_all_items();
void _open_add_theme_item_dialog(int p_data_type);
void _open_rename_theme_item_dialog(Theme::DataType p_data_type, String p_item_name);
void _confirm_edit_theme_item();
void _edit_theme_item_gui_input(const Ref<InputEvent> &p_event);
void _open_select_another_theme();
void _select_another_theme_cbk(const String &p_path);
protected:
void _notification(int p_what);
static void _bind_methods();
public:
void set_edited_theme(const Ref<Theme> &p_theme);
ThemeItemEditorDialog();
};
class ThemeEditor : public VBoxContainer { class ThemeEditor : public VBoxContainer {
GDCLASS(ThemeEditor, VBoxContainer); GDCLASS(ThemeEditor, VBoxContainer);
Ref<Theme> theme;
double time_left = 0;
ThemeItemEditorDialog *theme_edit_dialog;
void _theme_edit_button_cbk();
Panel *main_panel; Panel *main_panel;
MarginContainer *main_container; MarginContainer *main_container;
Ref<Theme> theme;
EditorFileDialog *file_dialog;
double time_left;
MenuButton *theme_menu;
ConfirmationDialog *add_del_dialog;
HBoxContainer *type_hbc;
MenuButton *type_menu;
LineEdit *type_edit;
HBoxContainer *name_hbc;
MenuButton *name_menu;
LineEdit *name_edit;
OptionButton *type_select;
Label *type_select_label;
Label *name_select_label;
enum PopupMode {
POPUP_ADD,
POPUP_CLASS_ADD,
POPUP_REMOVE,
POPUP_CLASS_REMOVE,
POPUP_CREATE_EMPTY,
POPUP_CREATE_EDITOR_EMPTY,
POPUP_IMPORT_EDITOR_THEME
};
int popup_mode;
Tree *test_tree;
void _save_template_cbk(String fname);
void _dialog_cbk();
void _type_menu_cbk(int p_option);
void _name_menu_about_to_show();
void _name_menu_cbk(int p_option);
void _theme_menu_cbk(int p_option);
void _propagate_redraw(Control *p_at); void _propagate_redraw(Control *p_at);
void _refresh_interval(); void _refresh_interval();

View file

@ -33,6 +33,11 @@
#include "core/print_string.h" #include "core/print_string.h"
void Theme::_emit_theme_changed() { void Theme::_emit_theme_changed() {
if (no_change_propagation) {
return;
}
_change_notify();
emit_changed(); emit_changed();
} }
@ -381,8 +386,7 @@ void Theme::set_default_theme_font(const Ref<Font> &p_default_font) {
default_theme_font->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED); default_theme_font->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED);
} }
_change_notify(); _emit_theme_changed();
emit_changed();
} }
Ref<Font> Theme::get_default_theme_font() const { Ref<Font> Theme::get_default_theme_font() const {
@ -424,8 +428,6 @@ void Theme::set_default_font(const Ref<Font> &p_font) {
} }
void Theme::set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture> &p_icon) { void Theme::set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture> &p_icon) {
bool new_value = !icon_map.has(p_node_type) || !icon_map[p_node_type].has(p_name);
if (icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()) { if (icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()) {
icon_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed"); icon_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed");
} }
@ -436,10 +438,7 @@ void Theme::set_icon(const StringName &p_name, const StringName &p_node_type, co
icon_map[p_node_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED); icon_map[p_node_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED);
} }
if (new_value) { _emit_theme_changed();
_change_notify();
emit_changed();
}
} }
Ref<Texture> Theme::get_icon(const StringName &p_name, const StringName &p_node_type) const { Ref<Texture> Theme::get_icon(const StringName &p_name, const StringName &p_node_type) const {
@ -454,6 +453,10 @@ bool Theme::has_icon(const StringName &p_name, const StringName &p_node_type) co
return (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()); return (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid());
} }
bool Theme::has_icon_nocheck(const StringName &p_name, const StringName &p_node_type) const {
return (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name));
}
void Theme::rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { void Theme::rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
ERR_FAIL_COND_MSG(!icon_map.has(p_node_type), "Cannot rename the icon '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); ERR_FAIL_COND_MSG(!icon_map.has(p_node_type), "Cannot rename the icon '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
ERR_FAIL_COND_MSG(icon_map[p_node_type].has(p_name), "Cannot rename the icon '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); ERR_FAIL_COND_MSG(icon_map[p_node_type].has(p_name), "Cannot rename the icon '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
@ -462,8 +465,7 @@ void Theme::rename_icon(const StringName &p_old_name, const StringName &p_name,
icon_map[p_node_type][p_name] = icon_map[p_node_type][p_old_name]; icon_map[p_node_type][p_name] = icon_map[p_node_type][p_old_name];
icon_map[p_node_type].erase(p_old_name); icon_map[p_node_type].erase(p_old_name);
_change_notify(); _emit_theme_changed();
emit_changed();
} }
void Theme::clear_icon(const StringName &p_name, const StringName &p_node_type) { void Theme::clear_icon(const StringName &p_name, const StringName &p_node_type) {
@ -476,8 +478,7 @@ void Theme::clear_icon(const StringName &p_name, const StringName &p_node_type)
icon_map[p_node_type].erase(p_name); icon_map[p_node_type].erase(p_name);
_change_notify(); _emit_theme_changed();
emit_changed();
} }
void Theme::get_icon_list(StringName p_node_type, List<StringName> *p_list) const { void Theme::get_icon_list(StringName p_node_type, List<StringName> *p_list) const {
@ -511,14 +512,9 @@ void Theme::get_icon_types(List<StringName> *p_list) const {
} }
void Theme::set_shader(const StringName &p_name, const StringName &p_node_type, const Ref<Shader> &p_shader) { void Theme::set_shader(const StringName &p_name, const StringName &p_node_type, const Ref<Shader> &p_shader) {
bool new_value = !shader_map.has(p_node_type) || !shader_map[p_node_type].has(p_name);
shader_map[p_node_type][p_name] = p_shader; shader_map[p_node_type][p_name] = p_shader;
if (new_value) { _emit_theme_changed();
_change_notify();
emit_changed();
}
} }
Ref<Shader> Theme::get_shader(const StringName &p_name, const StringName &p_node_type) const { Ref<Shader> Theme::get_shader(const StringName &p_name, const StringName &p_node_type) const {
@ -538,8 +534,8 @@ void Theme::clear_shader(const StringName &p_name, const StringName &p_node_type
ERR_FAIL_COND(!shader_map[p_node_type].has(p_name)); ERR_FAIL_COND(!shader_map[p_node_type].has(p_name));
shader_map[p_node_type].erase(p_name); shader_map[p_node_type].erase(p_name);
_change_notify();
emit_changed(); _emit_theme_changed();
} }
void Theme::get_shader_list(const StringName &p_node_type, List<StringName> *p_list) const { void Theme::get_shader_list(const StringName &p_node_type, List<StringName> *p_list) const {
@ -557,8 +553,6 @@ void Theme::get_shader_list(const StringName &p_node_type, List<StringName> *p_l
} }
void Theme::set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style) { void Theme::set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style) {
bool new_value = !style_map.has(p_node_type) || !style_map[p_node_type].has(p_name);
if (style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()) { if (style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()) {
style_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed"); style_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed");
} }
@ -569,10 +563,7 @@ void Theme::set_stylebox(const StringName &p_name, const StringName &p_node_type
style_map[p_node_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED); style_map[p_node_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED);
} }
if (new_value) { _emit_theme_changed();
_change_notify();
}
emit_changed();
} }
Ref<StyleBox> Theme::get_stylebox(const StringName &p_name, const StringName &p_node_type) const { Ref<StyleBox> Theme::get_stylebox(const StringName &p_name, const StringName &p_node_type) const {
@ -587,6 +578,10 @@ bool Theme::has_stylebox(const StringName &p_name, const StringName &p_node_type
return (style_map.has(p_node_type) && style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()); return (style_map.has(p_node_type) && style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid());
} }
bool Theme::has_stylebox_nocheck(const StringName &p_name, const StringName &p_node_type) const {
return (style_map.has(p_node_type) && style_map[p_node_type].has(p_name));
}
void Theme::rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { void Theme::rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
ERR_FAIL_COND_MSG(!style_map.has(p_node_type), "Cannot rename the stylebox '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); ERR_FAIL_COND_MSG(!style_map.has(p_node_type), "Cannot rename the stylebox '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
ERR_FAIL_COND_MSG(style_map[p_node_type].has(p_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); ERR_FAIL_COND_MSG(style_map[p_node_type].has(p_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
@ -595,8 +590,7 @@ void Theme::rename_stylebox(const StringName &p_old_name, const StringName &p_na
style_map[p_node_type][p_name] = style_map[p_node_type][p_old_name]; style_map[p_node_type][p_name] = style_map[p_node_type][p_old_name];
style_map[p_node_type].erase(p_old_name); style_map[p_node_type].erase(p_old_name);
_change_notify(); _emit_theme_changed();
emit_changed();
} }
void Theme::clear_stylebox(const StringName &p_name, const StringName &p_node_type) { void Theme::clear_stylebox(const StringName &p_name, const StringName &p_node_type) {
@ -609,8 +603,7 @@ void Theme::clear_stylebox(const StringName &p_name, const StringName &p_node_ty
style_map[p_node_type].erase(p_name); style_map[p_node_type].erase(p_name);
_change_notify(); _emit_theme_changed();
emit_changed();
} }
void Theme::get_stylebox_list(StringName p_node_type, List<StringName> *p_list) const { void Theme::get_stylebox_list(StringName p_node_type, List<StringName> *p_list) const {
@ -644,8 +637,6 @@ void Theme::get_stylebox_types(List<StringName> *p_list) const {
} }
void Theme::set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font) { void Theme::set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font) {
bool new_value = !font_map.has(p_node_type) || !font_map[p_node_type].has(p_name);
if (font_map[p_node_type][p_name].is_valid()) { if (font_map[p_node_type][p_name].is_valid()) {
font_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed"); font_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed");
} }
@ -656,10 +647,7 @@ void Theme::set_font(const StringName &p_name, const StringName &p_node_type, co
font_map[p_node_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED); font_map[p_node_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED);
} }
if (new_value) { _emit_theme_changed();
_change_notify();
emit_changed();
}
} }
Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_node_type) const { Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_node_type) const {
@ -676,6 +664,10 @@ bool Theme::has_font(const StringName &p_name, const StringName &p_node_type) co
return (font_map.has(p_node_type) && font_map[p_node_type].has(p_name) && font_map[p_node_type][p_name].is_valid()); return (font_map.has(p_node_type) && font_map[p_node_type].has(p_name) && font_map[p_node_type][p_name].is_valid());
} }
bool Theme::has_font_nocheck(const StringName &p_name, const StringName &p_node_type) const {
return (font_map.has(p_node_type) && font_map[p_node_type].has(p_name));
}
void Theme::rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { void Theme::rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
ERR_FAIL_COND_MSG(!font_map.has(p_node_type), "Cannot rename the font '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); ERR_FAIL_COND_MSG(!font_map.has(p_node_type), "Cannot rename the font '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
ERR_FAIL_COND_MSG(font_map[p_node_type].has(p_name), "Cannot rename the font '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); ERR_FAIL_COND_MSG(font_map[p_node_type].has(p_name), "Cannot rename the font '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
@ -684,8 +676,7 @@ void Theme::rename_font(const StringName &p_old_name, const StringName &p_name,
font_map[p_node_type][p_name] = font_map[p_node_type][p_old_name]; font_map[p_node_type][p_name] = font_map[p_node_type][p_old_name];
font_map[p_node_type].erase(p_old_name); font_map[p_node_type].erase(p_old_name);
_change_notify(); _emit_theme_changed();
emit_changed();
} }
void Theme::clear_font(const StringName &p_name, const StringName &p_node_type) { void Theme::clear_font(const StringName &p_name, const StringName &p_node_type) {
@ -697,8 +688,8 @@ void Theme::clear_font(const StringName &p_name, const StringName &p_node_type)
} }
font_map[p_node_type].erase(p_name); font_map[p_node_type].erase(p_name);
_change_notify();
emit_changed(); _emit_theme_changed();
} }
void Theme::get_font_list(StringName p_node_type, List<StringName> *p_list) const { void Theme::get_font_list(StringName p_node_type, List<StringName> *p_list) const {
@ -732,14 +723,9 @@ void Theme::get_font_types(List<StringName> *p_list) const {
} }
void Theme::set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color) { void Theme::set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color) {
bool new_value = !color_map.has(p_node_type) || !color_map[p_node_type].has(p_name);
color_map[p_node_type][p_name] = p_color; color_map[p_node_type][p_name] = p_color;
if (new_value) { _emit_theme_changed();
_change_notify();
emit_changed();
}
} }
Color Theme::get_color(const StringName &p_name, const StringName &p_node_type) const { Color Theme::get_color(const StringName &p_name, const StringName &p_node_type) const {
@ -754,6 +740,10 @@ bool Theme::has_color(const StringName &p_name, const StringName &p_node_type) c
return (color_map.has(p_node_type) && color_map[p_node_type].has(p_name)); return (color_map.has(p_node_type) && color_map[p_node_type].has(p_name));
} }
bool Theme::has_color_nocheck(const StringName &p_name, const StringName &p_node_type) const {
return (color_map.has(p_node_type) && color_map[p_node_type].has(p_name));
}
void Theme::rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { void Theme::rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
ERR_FAIL_COND_MSG(!color_map.has(p_node_type), "Cannot rename the color '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); ERR_FAIL_COND_MSG(!color_map.has(p_node_type), "Cannot rename the color '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
ERR_FAIL_COND_MSG(color_map[p_node_type].has(p_name), "Cannot rename the color '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); ERR_FAIL_COND_MSG(color_map[p_node_type].has(p_name), "Cannot rename the color '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
@ -762,8 +752,7 @@ void Theme::rename_color(const StringName &p_old_name, const StringName &p_name,
color_map[p_node_type][p_name] = color_map[p_node_type][p_old_name]; color_map[p_node_type][p_name] = color_map[p_node_type][p_old_name];
color_map[p_node_type].erase(p_old_name); color_map[p_node_type].erase(p_old_name);
_change_notify(); _emit_theme_changed();
emit_changed();
} }
void Theme::clear_color(const StringName &p_name, const StringName &p_node_type) { void Theme::clear_color(const StringName &p_name, const StringName &p_node_type) {
@ -771,8 +760,8 @@ void Theme::clear_color(const StringName &p_name, const StringName &p_node_type)
ERR_FAIL_COND_MSG(!color_map[p_node_type].has(p_name), "Cannot clear the color '" + String(p_name) + "' because it does not exist."); ERR_FAIL_COND_MSG(!color_map[p_node_type].has(p_name), "Cannot clear the color '" + String(p_name) + "' because it does not exist.");
color_map[p_node_type].erase(p_name); color_map[p_node_type].erase(p_name);
_change_notify();
emit_changed(); _emit_theme_changed();
} }
void Theme::get_color_list(StringName p_node_type, List<StringName> *p_list) const { void Theme::get_color_list(StringName p_node_type, List<StringName> *p_list) const {
@ -806,13 +795,9 @@ void Theme::get_color_types(List<StringName> *p_list) const {
} }
void Theme::set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant) { void Theme::set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant) {
bool new_value = !constant_map.has(p_node_type) || !constant_map[p_node_type].has(p_name);
constant_map[p_node_type][p_name] = p_constant; constant_map[p_node_type][p_name] = p_constant;
if (new_value) { _emit_theme_changed();
_change_notify();
emit_changed();
}
} }
int Theme::get_constant(const StringName &p_name, const StringName &p_node_type) const { int Theme::get_constant(const StringName &p_name, const StringName &p_node_type) const {
@ -827,6 +812,10 @@ bool Theme::has_constant(const StringName &p_name, const StringName &p_node_type
return (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name)); return (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name));
} }
bool Theme::has_constant_nocheck(const StringName &p_name, const StringName &p_node_type) const {
return (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name));
}
void Theme::rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { void Theme::rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
ERR_FAIL_COND_MSG(!constant_map.has(p_node_type), "Cannot rename the constant '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); ERR_FAIL_COND_MSG(!constant_map.has(p_node_type), "Cannot rename the constant '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
ERR_FAIL_COND_MSG(constant_map[p_node_type].has(p_name), "Cannot rename the constant '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); ERR_FAIL_COND_MSG(constant_map[p_node_type].has(p_name), "Cannot rename the constant '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
@ -835,8 +824,7 @@ void Theme::rename_constant(const StringName &p_old_name, const StringName &p_na
constant_map[p_node_type][p_name] = constant_map[p_node_type][p_old_name]; constant_map[p_node_type][p_name] = constant_map[p_node_type][p_old_name];
constant_map[p_node_type].erase(p_old_name); constant_map[p_node_type].erase(p_old_name);
_change_notify(); _emit_theme_changed();
emit_changed();
} }
void Theme::clear_constant(const StringName &p_name, const StringName &p_node_type) { void Theme::clear_constant(const StringName &p_name, const StringName &p_node_type) {
@ -844,8 +832,8 @@ void Theme::clear_constant(const StringName &p_name, const StringName &p_node_ty
ERR_FAIL_COND_MSG(!constant_map[p_node_type].has(p_name), "Cannot clear the constant '" + String(p_name) + "' because it does not exist."); ERR_FAIL_COND_MSG(!constant_map[p_node_type].has(p_name), "Cannot clear the constant '" + String(p_name) + "' because it does not exist.");
constant_map[p_node_type].erase(p_name); constant_map[p_node_type].erase(p_name);
_change_notify();
emit_changed(); _emit_theme_changed();
} }
void Theme::get_constant_list(StringName p_node_type, List<StringName> *p_list) const { void Theme::get_constant_list(StringName p_node_type, List<StringName> *p_list) const {
@ -953,6 +941,25 @@ bool Theme::has_theme_item(DataType p_data_type, const StringName &p_name, const
return false; return false;
} }
bool Theme::has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const {
switch (p_data_type) {
case DATA_TYPE_COLOR:
return has_color_nocheck(p_name, p_node_type);
case DATA_TYPE_CONSTANT:
return has_constant_nocheck(p_name, p_node_type);
case DATA_TYPE_FONT:
return has_font_nocheck(p_name, p_node_type);
case DATA_TYPE_ICON:
return has_icon_nocheck(p_name, p_node_type);
case DATA_TYPE_STYLEBOX:
return has_stylebox_nocheck(p_name, p_node_type);
case DATA_TYPE_MAX:
break; // Can't happen, but silences warning.
}
return false;
}
void Theme::rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { void Theme::rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
switch (p_data_type) { switch (p_data_type) {
case DATA_TYPE_COLOR: case DATA_TYPE_COLOR:
@ -1063,6 +1070,15 @@ void Theme::get_theme_item_types(DataType p_data_type, List<StringName> *p_list)
} }
} }
void Theme::_freeze_change_propagation() {
no_change_propagation = true;
}
void Theme::_unfreeze_and_propagate_changes() {
no_change_propagation = false;
_emit_theme_changed();
}
void Theme::clear() { void Theme::clear() {
//these need disconnecting //these need disconnecting
{ {
@ -1111,8 +1127,7 @@ void Theme::clear() {
color_map.clear(); color_map.clear();
constant_map.clear(); constant_map.clear();
_change_notify(); _emit_theme_changed();
emit_changed();
} }
void Theme::copy_default_theme() { void Theme::copy_default_theme() {
@ -1126,6 +1141,8 @@ void Theme::copy_theme(const Ref<Theme> &p_other) {
return; return;
} }
_freeze_change_propagation();
// These items need reconnecting, so add them normally. // These items need reconnecting, so add them normally.
{ {
const StringName *K = nullptr; const StringName *K = nullptr;
@ -1162,8 +1179,7 @@ void Theme::copy_theme(const Ref<Theme> &p_other) {
constant_map = p_other->constant_map; constant_map = p_other->constant_map;
shader_map = p_other->shader_map; shader_map = p_other->shader_map;
_change_notify(); _unfreeze_and_propagate_changes();
emit_changed();
} }
void Theme::get_type_list(List<StringName> *p_list) const { void Theme::get_type_list(List<StringName> *p_list) const {

View file

@ -42,6 +42,11 @@ class Theme : public Resource {
GDCLASS(Theme, Resource); GDCLASS(Theme, Resource);
RES_BASE_EXTENSION("theme"); RES_BASE_EXTENSION("theme");
#ifdef TOOLS_ENABLED
friend class ThemeItemImportTree;
friend class ThemeItemEditorDialog;
#endif
public: public:
enum DataType { enum DataType {
DATA_TYPE_COLOR, DATA_TYPE_COLOR,
@ -53,6 +58,8 @@ public:
}; };
private: private:
bool no_change_propagation = false;
void _emit_theme_changed(); void _emit_theme_changed();
HashMap<StringName, HashMap<StringName, Ref<Texture>>> icon_map; HashMap<StringName, HashMap<StringName, Ref<Texture>>> icon_map;
@ -92,6 +99,9 @@ protected:
static void _bind_methods(); static void _bind_methods();
void _freeze_change_propagation();
void _unfreeze_and_propagate_changes();
public: public:
static Ref<Theme> get_default(); static Ref<Theme> get_default();
static void set_default(const Ref<Theme> &p_default); static void set_default(const Ref<Theme> &p_default);
@ -109,6 +119,7 @@ public:
void set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture> &p_icon); void set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture> &p_icon);
Ref<Texture> get_icon(const StringName &p_name, const StringName &p_node_type) const; Ref<Texture> get_icon(const StringName &p_name, const StringName &p_node_type) const;
bool has_icon(const StringName &p_name, const StringName &p_node_type) const; bool has_icon(const StringName &p_name, const StringName &p_node_type) const;
bool has_icon_nocheck(const StringName &p_name, const StringName &p_node_type) const;
void rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_icon(const StringName &p_name, const StringName &p_node_type); void clear_icon(const StringName &p_name, const StringName &p_node_type);
void get_icon_list(StringName p_node_type, List<StringName> *p_list) const; void get_icon_list(StringName p_node_type, List<StringName> *p_list) const;
@ -124,6 +135,7 @@ public:
void set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style); void set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style);
Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_node_type) const; Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_node_type) const;
bool has_stylebox(const StringName &p_name, const StringName &p_node_type) const; bool has_stylebox(const StringName &p_name, const StringName &p_node_type) const;
bool has_stylebox_nocheck(const StringName &p_name, const StringName &p_node_type) const;
void rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_stylebox(const StringName &p_name, const StringName &p_node_type); void clear_stylebox(const StringName &p_name, const StringName &p_node_type);
void get_stylebox_list(StringName p_node_type, List<StringName> *p_list) const; void get_stylebox_list(StringName p_node_type, List<StringName> *p_list) const;
@ -133,6 +145,7 @@ public:
void set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font); void set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font);
Ref<Font> get_font(const StringName &p_name, const StringName &p_node_type) const; Ref<Font> get_font(const StringName &p_name, const StringName &p_node_type) const;
bool has_font(const StringName &p_name, const StringName &p_node_type) const; bool has_font(const StringName &p_name, const StringName &p_node_type) const;
bool has_font_nocheck(const StringName &p_name, const StringName &p_node_type) const;
void rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_font(const StringName &p_name, const StringName &p_node_type); void clear_font(const StringName &p_name, const StringName &p_node_type);
void get_font_list(StringName p_node_type, List<StringName> *p_list) const; void get_font_list(StringName p_node_type, List<StringName> *p_list) const;
@ -142,6 +155,7 @@ public:
void set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color); void set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color);
Color get_color(const StringName &p_name, const StringName &p_node_type) const; Color get_color(const StringName &p_name, const StringName &p_node_type) const;
bool has_color(const StringName &p_name, const StringName &p_node_type) const; bool has_color(const StringName &p_name, const StringName &p_node_type) const;
bool has_color_nocheck(const StringName &p_name, const StringName &p_node_type) const;
void rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_color(const StringName &p_name, const StringName &p_node_type); void clear_color(const StringName &p_name, const StringName &p_node_type);
void get_color_list(StringName p_node_type, List<StringName> *p_list) const; void get_color_list(StringName p_node_type, List<StringName> *p_list) const;
@ -151,6 +165,7 @@ public:
void set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant); void set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant);
int get_constant(const StringName &p_name, const StringName &p_node_type) const; int get_constant(const StringName &p_name, const StringName &p_node_type) const;
bool has_constant(const StringName &p_name, const StringName &p_node_type) const; bool has_constant(const StringName &p_name, const StringName &p_node_type) const;
bool has_constant_nocheck(const StringName &p_name, const StringName &p_node_type) const;
void rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_constant(const StringName &p_name, const StringName &p_node_type); void clear_constant(const StringName &p_name, const StringName &p_node_type);
void get_constant_list(StringName p_node_type, List<StringName> *p_list) const; void get_constant_list(StringName p_node_type, List<StringName> *p_list) const;
@ -160,6 +175,7 @@ public:
void set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type, const Variant &p_value); void set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type, const Variant &p_value);
Variant get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const; Variant get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const;
bool has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const; bool has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const;
bool has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const;
void rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type); void clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type);
void get_theme_item_list(DataType p_data_type, StringName p_node_type, List<StringName> *p_list) const; void get_theme_item_list(DataType p_data_type, StringName p_node_type, List<StringName> *p_list) const;