Prechádzať zdrojové kódy

Register theme properties with ThemeDB

Yuri Sizov 1 rok pred
rodič
commit
2924bfd4d3
71 zmenil súbory, kde vykonal 837 pridanie a 802 odobranie
  1. 5 8
      scene/gui/box_container.cpp
  2. 0 2
      scene/gui/box_container.h
  3. 37 40
      scene/gui/button.cpp
  4. 1 1
      scene/gui/button.h
  5. 16 17
      scene/gui/check_box.cpp
  6. 1 1
      scene/gui/check_box.h
  7. 16 18
      scene/gui/check_button.cpp
  8. 1 1
      scene/gui/check_button.h
  9. 47 49
      scene/gui/code_edit.cpp
  10. 0 2
      scene/gui/code_edit.h
  11. 39 46
      scene/gui/color_picker.cpp
  12. 1 4
      scene/gui/color_picker.h
  13. 22 0
      scene/gui/control.cpp
  14. 1 0
      scene/gui/control.h
  15. 4 7
      scene/gui/dialogs.cpp
  16. 1 1
      scene/gui/dialogs.h
  17. 19 22
      scene/gui/file_dialog.cpp
  18. 1 3
      scene/gui/file_dialog.h
  19. 5 7
      scene/gui/flow_container.cpp
  20. 0 2
      scene/gui/flow_container.h
  21. 5 7
      scene/gui/grid_container.cpp
  22. 0 2
      scene/gui/grid_container.h
  23. 24 27
      scene/gui/item_list.cpp
  24. 0 2
      scene/gui/item_list.h
  25. 14 17
      scene/gui/label.cpp
  26. 0 2
      scene/gui/label.h
  27. 25 23
      scene/gui/line_edit.cpp
  28. 4 2
      scene/gui/line_edit.h
  29. 17 20
      scene/gui/link_button.cpp
  30. 1 1
      scene/gui/link_button.h
  31. 8 8
      scene/gui/margin_container.cpp
  32. 1 2
      scene/gui/margin_container.h
  33. 26 29
      scene/gui/menu_bar.cpp
  34. 0 1
      scene/gui/menu_bar.h
  35. 17 19
      scene/gui/option_button.cpp
  36. 2 1
      scene/gui/option_button.h
  37. 5 6
      scene/gui/panel.cpp
  38. 1 2
      scene/gui/panel.h
  39. 6 6
      scene/gui/panel_container.cpp
  40. 1 1
      scene/gui/panel_container.h
  41. 11 16
      scene/gui/popup.cpp
  42. 2 3
      scene/gui/popup.h
  43. 43 46
      scene/gui/popup_menu.cpp
  44. 1 2
      scene/gui/popup_menu.h
  45. 10 13
      scene/gui/progress_bar.cpp
  46. 0 2
      scene/gui/progress_bar.h
  47. 37 36
      scene/gui/rich_text_label.cpp
  48. 1 0
      scene/gui/rich_text_label.h
  49. 15 18
      scene/gui/scroll_bar.cpp
  50. 0 2
      scene/gui/scroll_bar.h
  51. 3 6
      scene/gui/scroll_container.cpp
  52. 2 3
      scene/gui/scroll_container.h
  53. 7 7
      scene/gui/separator.cpp
  54. 1 2
      scene/gui/separator.h
  55. 13 16
      scene/gui/slider.cpp
  56. 0 1
      scene/gui/slider.h
  57. 3 6
      scene/gui/spin_box.cpp
  58. 0 2
      scene/gui/spin_box.h
  59. 10 13
      scene/gui/split_container.cpp
  60. 0 2
      scene/gui/split_container.h
  61. 30 33
      scene/gui/tab_bar.cpp
  62. 1 1
      scene/gui/tab_bar.h
  63. 41 47
      scene/gui/tab_container.cpp
  64. 0 1
      scene/gui/tab_container.h
  65. 45 43
      scene/gui/text_edit.cpp
  66. 71 70
      scene/gui/tree.cpp
  67. 1 2
      scene/gui/tree.h
  68. 23 0
      scene/main/window.cpp
  69. 1 0
      scene/main/window.h
  70. 44 0
      scene/theme/theme_db.cpp
  71. 47 0
      scene/theme/theme_db.h

+ 5 - 8
scene/gui/box_container.cpp

@@ -30,8 +30,9 @@
 
 #include "box_container.h"
 
-#include "label.h"
-#include "margin_container.h"
+#include "scene/gui/label.h"
+#include "scene/gui/margin_container.h"
+#include "scene/theme/theme_db.h"
 
 struct _MinSizeCache {
 	int min_size = 0;
@@ -288,12 +289,6 @@ Size2 BoxContainer::get_minimum_size() const {
 	return minimum;
 }
 
-void BoxContainer::_update_theme_item_cache() {
-	Container::_update_theme_item_cache();
-
-	theme_cache.separation = get_theme_constant(SNAME("separation"));
-}
-
 void BoxContainer::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_SORT_CHILDREN: {
@@ -399,6 +394,8 @@ void BoxContainer::_bind_methods() {
 
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment", "get_alignment");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vertical"), "set_vertical", "is_vertical");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, BoxContainer, separation);
 }
 
 MarginContainer *VBoxContainer::add_margin_child(const String &p_label, Control *p_control, bool p_expand) {

+ 0 - 2
scene/gui/box_container.h

@@ -56,8 +56,6 @@ private:
 protected:
 	bool is_fixed = false;
 
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int p_what);
 	void _validate_property(PropertyInfo &p_property) const;
 	static void _bind_methods();

+ 37 - 40
scene/gui/button.cpp

@@ -31,6 +31,7 @@
 #include "button.h"
 
 #include "core/string/translation.h"
+#include "scene/theme/theme_db.h"
 #include "servers/rendering_server.h"
 
 Size2 Button::get_minimum_size() const {
@@ -49,46 +50,6 @@ void Button::_set_internal_margin(Side p_side, float p_value) {
 void Button::_queue_update_size_cache() {
 }
 
-void Button::_update_theme_item_cache() {
-	BaseButton::_update_theme_item_cache();
-
-	theme_cache.normal = get_theme_stylebox(SNAME("normal"));
-	theme_cache.normal_mirrored = get_theme_stylebox(SNAME("normal_mirrored"));
-	theme_cache.pressed = get_theme_stylebox(SNAME("pressed"));
-	theme_cache.pressed_mirrored = get_theme_stylebox(SNAME("pressed_mirrored"));
-	theme_cache.hover = get_theme_stylebox(SNAME("hover"));
-	theme_cache.hover_mirrored = get_theme_stylebox(SNAME("hover_mirrored"));
-	theme_cache.hover_pressed = get_theme_stylebox(SNAME("hover_pressed"));
-	theme_cache.hover_pressed_mirrored = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
-	theme_cache.disabled = get_theme_stylebox(SNAME("disabled"));
-	theme_cache.disabled_mirrored = get_theme_stylebox(SNAME("disabled_mirrored"));
-	theme_cache.focus = get_theme_stylebox(SNAME("focus"));
-
-	theme_cache.font_color = get_theme_color(SNAME("font_color"));
-	theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
-	theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
-	theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
-	theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
-	theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
-
-	theme_cache.font = get_theme_font(SNAME("font"));
-	theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
-	theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
-	theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
-
-	theme_cache.icon_normal_color = get_theme_color(SNAME("icon_normal_color"));
-	theme_cache.icon_focus_color = get_theme_color(SNAME("icon_focus_color"));
-	theme_cache.icon_pressed_color = get_theme_color(SNAME("icon_pressed_color"));
-	theme_cache.icon_hover_color = get_theme_color(SNAME("icon_hover_color"));
-	theme_cache.icon_hover_pressed_color = get_theme_color(SNAME("icon_hover_pressed_color"));
-	theme_cache.icon_disabled_color = get_theme_color(SNAME("icon_disabled_color"));
-
-	theme_cache.icon = get_theme_icon(SNAME("icon"));
-
-	theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
-	theme_cache.icon_max_width = get_theme_constant(SNAME("icon_max_width"));
-}
-
 void Button::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
@@ -670,6 +631,42 @@ void Button::_bind_methods() {
 	ADD_GROUP("BiDi", "");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Button, normal);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Button, normal_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Button, pressed);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Button, pressed_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Button, hover);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Button, hover_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Button, hover_pressed);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Button, hover_pressed_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Button, disabled);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Button, disabled_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Button, focus);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, font_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, font_focus_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, font_pressed_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, font_hover_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, font_hover_pressed_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, font_disabled_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, Button, font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, Button, font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, outline_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, font_outline_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, icon_normal_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, icon_focus_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, icon_pressed_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, icon_hover_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, icon_hover_pressed_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Button, icon_disabled_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Button, icon);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, h_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, icon_max_width);
 }
 
 Button::Button(const String &p_text) {

+ 1 - 1
scene/gui/button.h

@@ -100,8 +100,8 @@ private:
 
 protected:
 	void _set_internal_margin(Side p_side, float p_value);
-	virtual void _update_theme_item_cache() override;
 	virtual void _queue_update_size_cache();
+
 	void _notification(int p_what);
 	static void _bind_methods();
 

+ 16 - 17
scene/gui/check_box.cpp

@@ -30,6 +30,7 @@
 
 #include "check_box.h"
 
+#include "scene/theme/theme_db.h"
 #include "servers/rendering_server.h"
 
 Size2 CheckBox::get_icon_size() const {
@@ -73,23 +74,6 @@ Size2 CheckBox::get_minimum_size() const {
 	return minsize;
 }
 
-void CheckBox::_update_theme_item_cache() {
-	Button::_update_theme_item_cache();
-
-	theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
-	theme_cache.check_v_offset = get_theme_constant(SNAME("check_v_offset"));
-	theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
-
-	theme_cache.checked = get_theme_icon(SNAME("checked"));
-	theme_cache.unchecked = get_theme_icon(SNAME("unchecked"));
-	theme_cache.radio_checked = get_theme_icon(SNAME("radio_checked"));
-	theme_cache.radio_unchecked = get_theme_icon(SNAME("radio_unchecked"));
-	theme_cache.checked_disabled = get_theme_icon(SNAME("checked_disabled"));
-	theme_cache.unchecked_disabled = get_theme_icon(SNAME("unchecked_disabled"));
-	theme_cache.radio_checked_disabled = get_theme_icon(SNAME("radio_checked_disabled"));
-	theme_cache.radio_unchecked_disabled = get_theme_icon(SNAME("radio_unchecked_disabled"));
-}
-
 void CheckBox::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_THEME_CHANGED:
@@ -149,6 +133,21 @@ bool CheckBox::is_radio() {
 	return get_button_group().is_valid();
 }
 
+void CheckBox::_bind_methods() {
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, CheckBox, h_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, CheckBox, check_v_offset);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, CheckBox, normal_style, "normal");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckBox, checked);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckBox, unchecked);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckBox, radio_checked);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckBox, radio_unchecked);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckBox, checked_disabled);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckBox, unchecked_disabled);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckBox, radio_checked_disabled);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckBox, radio_unchecked_disabled);
+}
+
 CheckBox::CheckBox(const String &p_text) :
 		Button(p_text) {
 	set_toggle_mode(true);

+ 1 - 1
scene/gui/check_box.h

@@ -55,8 +55,8 @@ protected:
 	Size2 get_icon_size() const;
 	Size2 get_minimum_size() const override;
 
-	virtual void _update_theme_item_cache() override;
 	void _notification(int p_what);
+	static void _bind_methods();
 
 	bool is_radio();
 

+ 16 - 18
scene/gui/check_button.cpp

@@ -30,7 +30,7 @@
 
 #include "check_button.h"
 
-#include "core/string/print_string.h"
+#include "scene/theme/theme_db.h"
 #include "servers/rendering_server.h"
 
 Size2 CheckButton::get_icon_size() const {
@@ -78,23 +78,6 @@ Size2 CheckButton::get_minimum_size() const {
 	return minsize;
 }
 
-void CheckButton::_update_theme_item_cache() {
-	Button::_update_theme_item_cache();
-
-	theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
-	theme_cache.check_v_offset = get_theme_constant(SNAME("check_v_offset"));
-	theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
-
-	theme_cache.checked = get_theme_icon(SNAME("checked"));
-	theme_cache.unchecked = get_theme_icon(SNAME("unchecked"));
-	theme_cache.checked_disabled = get_theme_icon(SNAME("checked_disabled"));
-	theme_cache.unchecked_disabled = get_theme_icon(SNAME("unchecked_disabled"));
-	theme_cache.checked_mirrored = get_theme_icon(SNAME("checked_mirrored"));
-	theme_cache.unchecked_mirrored = get_theme_icon(SNAME("unchecked_mirrored"));
-	theme_cache.checked_disabled_mirrored = get_theme_icon(SNAME("checked_disabled_mirrored"));
-	theme_cache.unchecked_disabled_mirrored = get_theme_icon(SNAME("unchecked_disabled_mirrored"));
-}
-
 void CheckButton::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_THEME_CHANGED:
@@ -153,6 +136,21 @@ void CheckButton::_notification(int p_what) {
 	}
 }
 
+void CheckButton::_bind_methods() {
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, CheckButton, h_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, CheckButton, check_v_offset);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, CheckButton, normal_style, "normal");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckButton, checked);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckButton, unchecked);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckButton, checked_disabled);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckButton, unchecked_disabled);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckButton, checked_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckButton, unchecked_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckButton, checked_disabled_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CheckButton, unchecked_disabled_mirrored);
+}
+
 CheckButton::CheckButton(const String &p_text) :
 		Button(p_text) {
 	set_toggle_mode(true);

+ 1 - 1
scene/gui/check_button.h

@@ -55,8 +55,8 @@ protected:
 	Size2 get_icon_size() const;
 	virtual Size2 get_minimum_size() const override;
 
-	virtual void _update_theme_item_cache() override;
 	void _notification(int p_what);
+	static void _bind_methods();
 
 public:
 	CheckButton(const String &p_text = String());

+ 47 - 49
scene/gui/code_edit.cpp

@@ -34,6 +34,7 @@
 #include "core/os/keyboard.h"
 #include "core/string/string_builder.h"
 #include "core/string/ustring.h"
+#include "scene/theme/theme_db.h"
 
 void CodeEdit::_notification(int p_what) {
 	switch (p_what) {
@@ -228,55 +229,6 @@ void CodeEdit::_notification(int p_what) {
 	}
 }
 
-void CodeEdit::_update_theme_item_cache() {
-	TextEdit::_update_theme_item_cache();
-
-	/* Gutters */
-	theme_cache.code_folding_color = get_theme_color(SNAME("code_folding_color"));
-	theme_cache.can_fold_icon = get_theme_icon(SNAME("can_fold"));
-	theme_cache.folded_icon = get_theme_icon(SNAME("folded"));
-	theme_cache.folded_eol_icon = get_theme_icon(SNAME("folded_eol_icon"));
-
-	theme_cache.breakpoint_color = get_theme_color(SNAME("breakpoint_color"));
-	theme_cache.breakpoint_icon = get_theme_icon(SNAME("breakpoint"));
-
-	theme_cache.bookmark_color = get_theme_color(SNAME("bookmark_color"));
-	theme_cache.bookmark_icon = get_theme_icon(SNAME("bookmark"));
-
-	theme_cache.executing_line_color = get_theme_color(SNAME("executing_line_color"));
-	theme_cache.executing_line_icon = get_theme_icon(SNAME("executing_line"));
-
-	theme_cache.line_number_color = get_theme_color(SNAME("line_number_color"));
-
-	/* Code Completion */
-	theme_cache.code_completion_style = get_theme_stylebox(SNAME("completion"));
-	theme_cache.code_completion_icon_separation = get_theme_constant(SNAME("h_separation"), SNAME("ItemList"));
-
-	theme_cache.code_completion_max_width = get_theme_constant(SNAME("completion_max_width"));
-	theme_cache.code_completion_max_lines = get_theme_constant(SNAME("completion_lines"));
-	theme_cache.code_completion_scroll_width = get_theme_constant(SNAME("completion_scroll_width"));
-	theme_cache.code_completion_scroll_color = get_theme_color(SNAME("completion_scroll_color"));
-	theme_cache.code_completion_scroll_hovered_color = get_theme_color(SNAME("completion_scroll_hovered_color"));
-	theme_cache.code_completion_background_color = get_theme_color(SNAME("completion_background_color"));
-	theme_cache.code_completion_selected_color = get_theme_color(SNAME("completion_selected_color"));
-	theme_cache.code_completion_existing_color = get_theme_color(SNAME("completion_existing_color"));
-
-	/* Code hint */
-	theme_cache.code_hint_style = get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel"));
-	theme_cache.code_hint_color = get_theme_color(SNAME("font_color"), SNAME("TooltipLabel"));
-
-	/* Line length guideline */
-	theme_cache.line_length_guideline_color = get_theme_color(SNAME("line_length_guideline_color"));
-
-	/* Other visuals */
-	theme_cache.style_normal = get_theme_stylebox(SNAME("normal"));
-
-	theme_cache.font = get_theme_font(SNAME("font"));
-	theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
-
-	theme_cache.line_spacing = get_theme_constant(SNAME("line_spacing"));
-}
-
 void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
 	Ref<InputEventMouseButton> mb = p_gui_input;
 	if (mb.is_valid()) {
@@ -2527,6 +2479,52 @@ void CodeEdit::_bind_methods() {
 	/* Symbol lookup */
 	ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::INT, "column")));
 	ADD_SIGNAL(MethodInfo("symbol_validate", PropertyInfo(Variant::STRING, "symbol")));
+
+	/* Theme items */
+	/* Gutters */
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, CodeEdit, code_folding_color);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, CodeEdit, can_fold_icon, "can_fold");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, CodeEdit, folded_icon, "folded");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CodeEdit, folded_eol_icon);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, CodeEdit, breakpoint_color);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_COLOR, CodeEdit, breakpoint_icon, "breakpoint");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, CodeEdit, bookmark_color);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, CodeEdit, bookmark_icon, "bookmark");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, CodeEdit, executing_line_color);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, CodeEdit, executing_line_icon, "executing_line");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, CodeEdit, line_number_color);
+
+	/* Code Completion */
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, CodeEdit, code_completion_style, "completion");
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_CONSTANT, CodeEdit, code_completion_icon_separation, "h_separation", "ItemList");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, CodeEdit, code_completion_max_width, "completion_max_width");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, CodeEdit, code_completion_max_lines, "completion_lines");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, CodeEdit, code_completion_scroll_width, "completion_scroll_width");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_COLOR, CodeEdit, code_completion_scroll_color, "completion_scroll_color");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_COLOR, CodeEdit, code_completion_scroll_hovered_color, "completion_scroll_hovered_color");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_COLOR, CodeEdit, code_completion_background_color, "completion_background_color");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_COLOR, CodeEdit, code_completion_selected_color, "completion_selected_color");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_COLOR, CodeEdit, code_completion_existing_color, "completion_existing_color");
+
+	/* Code hint */
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, CodeEdit, code_hint_style, "panel", "TooltipPanel");
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, CodeEdit, code_hint_color, "font_color", "TooltipLabel");
+
+	/* Line length guideline */
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, CodeEdit, line_length_guideline_color);
+
+	/* Other visuals */
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, CodeEdit, style_normal, "normal");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, CodeEdit, font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, CodeEdit, font_size);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, CodeEdit, line_spacing);
 }
 
 /* Auto brace completion */

+ 0 - 2
scene/gui/code_edit.h

@@ -293,8 +293,6 @@ protected:
 	static void _bind_compatibility_methods();
 #endif
 
-	virtual void _update_theme_item_cache() override;
-
 	/* Text manipulation */
 
 	// Overridable actions

+ 39 - 46
scene/gui/color_picker.cpp

@@ -39,6 +39,7 @@
 #include "scene/resources/image_texture.h"
 #include "scene/resources/style_box_flat.h"
 #include "scene/resources/style_box_texture.h"
+#include "scene/theme/theme_db.h"
 #include "servers/display_server.h"
 #include "thirdparty/misc/ok_color.h"
 #include "thirdparty/misc/ok_color_shader.h"
@@ -122,34 +123,6 @@ void ColorPicker::_update_theme_item_cache() {
 	VBoxContainer::_update_theme_item_cache();
 
 	theme_cache.base_scale = get_theme_default_base_scale();
-
-	theme_cache.content_margin = get_theme_constant(SNAME("margin"));
-	theme_cache.label_width = get_theme_constant(SNAME("label_width"));
-
-	theme_cache.sv_width = get_theme_constant(SNAME("sv_width"));
-	theme_cache.sv_height = get_theme_constant(SNAME("sv_height"));
-	theme_cache.h_width = get_theme_constant(SNAME("h_width"));
-
-	theme_cache.center_slider_grabbers = get_theme_constant(SNAME("center_slider_grabbers"));
-
-	theme_cache.screen_picker = get_theme_icon(SNAME("screen_picker"));
-	theme_cache.expanded_arrow = get_theme_icon(SNAME("expanded_arrow"));
-	theme_cache.folded_arrow = get_theme_icon(SNAME("folded_arrow"));
-	theme_cache.add_preset = get_theme_icon(SNAME("add_preset"));
-
-	theme_cache.shape_rect = get_theme_icon(SNAME("shape_rect"));
-	theme_cache.shape_rect_wheel = get_theme_icon(SNAME("shape_rect_wheel"));
-	theme_cache.shape_circle = get_theme_icon(SNAME("shape_circle"));
-
-	theme_cache.bar_arrow = get_theme_icon(SNAME("bar_arrow"));
-	theme_cache.sample_background_icon = get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker"));
-	theme_cache.overbright_indicator = get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker"));
-	theme_cache.picker_cursor = get_theme_icon(SNAME("picker_cursor"));
-	theme_cache.color_hue_icon = get_theme_icon(SNAME("color_hue"));
-
-	theme_cache.mode_button_normal = get_theme_stylebox("tab_unselected", "TabContainer");
-	theme_cache.mode_button_pressed = get_theme_stylebox("tab_selected", "TabContainer");
-	theme_cache.mode_button_hover = get_theme_stylebox("tab_selected", "TabContainer");
 }
 
 Ref<Shader> ColorPicker::wheel_shader;
@@ -1710,6 +1683,34 @@ void ColorPicker::_bind_methods() {
 	BIND_ENUM_CONSTANT(SHAPE_VHS_CIRCLE);
 	BIND_ENUM_CONSTANT(SHAPE_OKHSL_CIRCLE);
 	BIND_ENUM_CONSTANT(SHAPE_NONE);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, ColorPicker, content_margin, "margin");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, label_width);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, sv_width);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, sv_height);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, h_width);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, center_slider_grabbers);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, screen_picker);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, expanded_arrow);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, folded_arrow);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, add_preset);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, shape_rect);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, shape_rect_wheel);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, shape_circle);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, bar_arrow);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ColorPicker, sample_background_icon, "sample_bg");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, overbright_indicator);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, picker_cursor);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ColorPicker, color_hue_icon, "color_hue");
+
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, ColorPicker, mode_button_normal, "tab_unselected", "TabContainer");
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, ColorPicker, mode_button_pressed, "tab_selected", "TabContainer");
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, ColorPicker, mode_button_hover, "tab_selected", "TabContainer");
 }
 
 ColorPicker::ColorPicker() {
@@ -2011,15 +2012,6 @@ void ColorPickerButton::_notification(int p_what) {
 	}
 }
 
-void ColorPickerButton::_update_theme_item_cache() {
-	Button::_update_theme_item_cache();
-
-	theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
-	theme_cache.background_icon = get_theme_icon(SNAME("bg"));
-
-	theme_cache.overbright_indicator = get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker"));
-}
-
 void ColorPickerButton::set_pick_color(const Color &p_color) {
 	if (color == p_color) {
 		return;
@@ -2093,6 +2085,10 @@ void ColorPickerButton::_bind_methods() {
 	ADD_SIGNAL(MethodInfo("picker_created"));
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_pick_color", "get_pick_color");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ColorPickerButton, normal_style, "normal");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ColorPickerButton, background_icon, "bg");
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_ICON, ColorPickerButton, overbright_indicator, "overbright_indicator", "ColorPicker");
 }
 
 ColorPickerButton::ColorPickerButton(const String &p_text) :
@@ -2153,15 +2149,6 @@ void ColorPresetButton::_notification(int p_what) {
 	}
 }
 
-void ColorPresetButton::_update_theme_item_cache() {
-	BaseButton::_update_theme_item_cache();
-
-	theme_cache.foreground_style = get_theme_stylebox(SNAME("preset_fg"));
-
-	theme_cache.background_icon = get_theme_icon(SNAME("preset_bg"));
-	theme_cache.overbright_indicator = get_theme_icon(SNAME("overbright_indicator"));
-}
-
 void ColorPresetButton::set_preset_color(const Color &p_color) {
 	preset_color = p_color;
 }
@@ -2170,6 +2157,12 @@ Color ColorPresetButton::get_preset_color() const {
 	return preset_color;
 }
 
+void ColorPresetButton::_bind_methods() {
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ColorPresetButton, foreground_style, "preset_fg");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ColorPresetButton, background_icon, "preset_bg");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPresetButton, overbright_indicator);
+}
+
 ColorPresetButton::ColorPresetButton(Color p_color, int p_size) {
 	preset_color = p_color;
 	set_toggle_mode(true);

+ 1 - 4
scene/gui/color_picker.h

@@ -67,9 +67,8 @@ class ColorPresetButton : public BaseButton {
 	} theme_cache;
 
 protected:
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int);
+	static void _bind_methods();
 
 public:
 	void set_preset_color(const Color &p_color);
@@ -393,8 +392,6 @@ class ColorPickerButton : public Button {
 	void _update_picker();
 
 protected:
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int);
 	static void _bind_methods();
 

+ 22 - 0
scene/gui/control.cpp

@@ -2448,6 +2448,7 @@ void Control::_invalidate_theme_cache() {
 }
 
 void Control::_update_theme_item_cache() {
+	ThemeDB::get_singleton()->update_class_instance_items(this);
 }
 
 void Control::set_theme_owner_node(Node *p_node) {
@@ -2669,6 +2670,27 @@ int Control::get_theme_constant(const StringName &p_name, const StringName &p_th
 	return constant;
 }
 
+Variant Control::get_theme_item(Theme::DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const {
+	switch (p_data_type) {
+		case Theme::DATA_TYPE_COLOR:
+			return get_theme_color(p_name, p_theme_type);
+		case Theme::DATA_TYPE_CONSTANT:
+			return get_theme_constant(p_name, p_theme_type);
+		case Theme::DATA_TYPE_FONT:
+			return get_theme_font(p_name, p_theme_type);
+		case Theme::DATA_TYPE_FONT_SIZE:
+			return get_theme_font_size(p_name, p_theme_type);
+		case Theme::DATA_TYPE_ICON:
+			return get_theme_icon(p_name, p_theme_type);
+		case Theme::DATA_TYPE_STYLEBOX:
+			return get_theme_stylebox(p_name, p_theme_type);
+		case Theme::DATA_TYPE_MAX:
+			break; // Can't happen, but silences warning.
+	}
+
+	return Variant();
+}
+
 #ifdef TOOLS_ENABLED
 Ref<Texture2D> Control::get_editor_theme_icon(const StringName &p_name) const {
 	return get_theme_icon(p_name, SNAME("EditorIcons"));

+ 1 - 0
scene/gui/control.h

@@ -585,6 +585,7 @@ public:
 	int get_theme_font_size(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
 	Color get_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
 	int get_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+	Variant get_theme_item(Theme::DataType p_data_type, const StringName &p_name, const StringName &p_theme_type = StringName()) const;
 #ifdef TOOLS_ENABLED
 	Ref<Texture2D> get_editor_theme_icon(const StringName &p_name) const;
 #endif

+ 4 - 7
scene/gui/dialogs.cpp

@@ -34,6 +34,7 @@
 #include "core/string/print_string.h"
 #include "core/string/translation.h"
 #include "scene/gui/line_edit.h"
+#include "scene/theme/theme_db.h"
 
 // AcceptDialog
 
@@ -49,13 +50,6 @@ void AcceptDialog::_parent_focused() {
 	}
 }
 
-void AcceptDialog::_update_theme_item_cache() {
-	Window::_update_theme_item_cache();
-
-	theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
-	theme_cache.buttons_separation = get_theme_constant(SNAME("buttons_separation"));
-}
-
 void AcceptDialog::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_POST_ENTER_TREE: {
@@ -395,6 +389,9 @@ void AcceptDialog::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dialog_hide_on_ok"), "set_hide_on_ok", "get_hide_on_ok");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dialog_close_on_escape"), "set_close_on_escape", "get_close_on_escape");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dialog_autowrap"), "set_autowrap", "has_autowrap");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, AcceptDialog, panel_style, "panel");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, AcceptDialog, buttons_separation);
 }
 
 bool AcceptDialog::swap_cancel_ok = false;

+ 1 - 1
scene/gui/dialogs.h

@@ -70,10 +70,10 @@ class AcceptDialog : public Window {
 
 protected:
 	virtual Size2 _get_contents_minimum_size() const override;
-	virtual void _update_theme_item_cache() override;
 
 	void _notification(int p_what);
 	static void _bind_methods();
+
 	virtual void ok_pressed() {}
 	virtual void cancel_pressed() {}
 	virtual void custom_action(const String &) {}

+ 19 - 22
scene/gui/file_dialog.cpp

@@ -33,6 +33,7 @@
 #include "core/os/keyboard.h"
 #include "core/string/print_string.h"
 #include "scene/gui/label.h"
+#include "scene/theme/theme_db.h"
 
 FileDialog::GetIconFunc FileDialog::get_icon_func = nullptr;
 
@@ -90,28 +91,6 @@ VBoxContainer *FileDialog::get_vbox() {
 	return vbox;
 }
 
-void FileDialog::_update_theme_item_cache() {
-	ConfirmationDialog::_update_theme_item_cache();
-
-	theme_cache.parent_folder = get_theme_icon(SNAME("parent_folder"));
-	theme_cache.forward_folder = get_theme_icon(SNAME("forward_folder"));
-	theme_cache.back_folder = get_theme_icon(SNAME("back_folder"));
-	theme_cache.reload = get_theme_icon(SNAME("reload"));
-	theme_cache.toggle_hidden = get_theme_icon(SNAME("toggle_hidden"));
-	theme_cache.folder = get_theme_icon(SNAME("folder"));
-	theme_cache.file = get_theme_icon(SNAME("file"));
-
-	theme_cache.folder_icon_color = get_theme_color(SNAME("folder_icon_color"));
-	theme_cache.file_icon_color = get_theme_color(SNAME("file_icon_color"));
-	theme_cache.file_disabled_color = get_theme_color(SNAME("file_disabled_color"));
-
-	// TODO: Define own colors?
-	theme_cache.icon_normal_color = get_theme_color(SNAME("font_color"), SNAME("Button"));
-	theme_cache.icon_hover_color = get_theme_color(SNAME("font_hover_color"), SNAME("Button"));
-	theme_cache.icon_focus_color = get_theme_color(SNAME("font_focus_color"), SNAME("Button"));
-	theme_cache.icon_pressed_color = get_theme_color(SNAME("font_pressed_color"), SNAME("Button"));
-}
-
 void FileDialog::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -1042,6 +1021,24 @@ void FileDialog::_bind_methods() {
 	BIND_ENUM_CONSTANT(ACCESS_RESOURCES);
 	BIND_ENUM_CONSTANT(ACCESS_USERDATA);
 	BIND_ENUM_CONSTANT(ACCESS_FILESYSTEM);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, parent_folder);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, forward_folder);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, back_folder);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, reload);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, toggle_hidden);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, folder);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, file);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, FileDialog, folder_icon_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, FileDialog, file_icon_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, FileDialog, file_disabled_color);
+
+	// TODO: Define own colors?
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, FileDialog, icon_normal_color, "font_color", "Button");
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, FileDialog, icon_hover_color, "font_hover_color", "Button");
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, FileDialog, icon_focus_color, "font_focus_color", "Button");
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, FileDialog, icon_pressed_color, "font_pressed_color", "Button");
 }
 
 void FileDialog::set_show_hidden_files(bool p_show) {

+ 1 - 3
scene/gui/file_dialog.h

@@ -166,11 +166,9 @@ private:
 	virtual void _post_popup() override;
 
 protected:
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int p_what);
 	static void _bind_methods();
-	//bind helpers
+
 public:
 	virtual void popup(const Rect2i &p_rect = Rect2i()) override;
 

+ 5 - 7
scene/gui/flow_container.cpp

@@ -30,6 +30,8 @@
 
 #include "flow_container.h"
 
+#include "scene/theme/theme_db.h"
+
 struct _LineData {
 	int child_count = 0;
 	int min_line_height = 0;
@@ -269,13 +271,6 @@ Vector<int> FlowContainer::get_allowed_size_flags_vertical() const {
 	return flags;
 }
 
-void FlowContainer::_update_theme_item_cache() {
-	Container::_update_theme_item_cache();
-
-	theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
-	theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
-}
-
 void FlowContainer::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_SORT_CHILDREN: {
@@ -345,4 +340,7 @@ void FlowContainer::_bind_methods() {
 
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment", "get_alignment");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vertical"), "set_vertical", "is_vertical");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, FlowContainer, h_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, FlowContainer, v_separation);
 }

+ 0 - 2
scene/gui/flow_container.h

@@ -60,8 +60,6 @@ private:
 protected:
 	bool is_fixed = false;
 
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int p_what);
 	void _validate_property(PropertyInfo &p_property) const;
 	static void _bind_methods();

+ 5 - 7
scene/gui/grid_container.cpp

@@ -29,14 +29,9 @@
 /**************************************************************************/
 
 #include "grid_container.h"
-#include "core/templates/rb_set.h"
-
-void GridContainer::_update_theme_item_cache() {
-	Container::_update_theme_item_cache();
 
-	theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
-	theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
-}
+#include "core/templates/rb_set.h"
+#include "scene/theme/theme_db.h"
 
 void GridContainer::_notification(int p_what) {
 	switch (p_what) {
@@ -269,6 +264,9 @@ void GridContainer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_columns"), &GridContainer::get_columns);
 
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "columns", PROPERTY_HINT_RANGE, "1,1024,1"), "set_columns", "get_columns");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, GridContainer, h_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, GridContainer, v_separation);
 }
 
 Size2 GridContainer::get_minimum_size() const {

+ 0 - 2
scene/gui/grid_container.h

@@ -44,8 +44,6 @@ class GridContainer : public Container {
 	} theme_cache;
 
 protected:
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int p_what);
 	static void _bind_methods();
 

+ 24 - 27
scene/gui/item_list.cpp

@@ -33,6 +33,7 @@
 #include "core/config/project_settings.h"
 #include "core/os/os.h"
 #include "core/string/translation.h"
+#include "scene/theme/theme_db.h"
 
 void ItemList::_shape_text(int p_idx) {
 	Item &item = items.write[p_idx];
@@ -992,33 +993,6 @@ static Rect2 _adjust_to_max_size(Size2 p_size, Size2 p_max_size) {
 	return Rect2(ofs_x, ofs_y, tex_width, tex_height);
 }
 
-void ItemList::_update_theme_item_cache() {
-	Control::_update_theme_item_cache();
-
-	theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
-	theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
-
-	theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
-	theme_cache.focus_style = get_theme_stylebox(SNAME("focus"));
-
-	theme_cache.font = get_theme_font(SNAME("font"));
-	theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
-	theme_cache.font_color = get_theme_color(SNAME("font_color"));
-	theme_cache.font_hovered_color = get_theme_color(SNAME("font_hovered_color"));
-	theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
-	theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
-	theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
-
-	theme_cache.line_separation = get_theme_constant(SNAME("line_separation"));
-	theme_cache.icon_margin = get_theme_constant(SNAME("icon_margin"));
-	theme_cache.hovered_style = get_theme_stylebox(SNAME("hovered"));
-	theme_cache.selected_style = get_theme_stylebox(SNAME("selected"));
-	theme_cache.selected_focus_style = get_theme_stylebox(SNAME("selected_focus"));
-	theme_cache.cursor_style = get_theme_stylebox(SNAME("cursor_unfocused"));
-	theme_cache.cursor_focus_style = get_theme_stylebox(SNAME("cursor"));
-	theme_cache.guide_color = get_theme_color(SNAME("guide_color"));
-}
-
 void ItemList::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_RESIZED: {
@@ -1909,6 +1883,29 @@ void ItemList::_bind_methods() {
 	ADD_SIGNAL(MethodInfo("item_clicked", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::VECTOR2, "at_position"), PropertyInfo(Variant::INT, "mouse_button_index")));
 	ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "selected")));
 	ADD_SIGNAL(MethodInfo("item_activated", PropertyInfo(Variant::INT, "index")));
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ItemList, h_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ItemList, v_separation);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ItemList, panel_style, "panel");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ItemList, focus_style, "focus");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, ItemList, font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, ItemList, font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, font_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, font_hovered_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, font_selected_color);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, ItemList, font_outline_size, "outline_size");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, font_outline_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ItemList, line_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ItemList, icon_margin);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ItemList, hovered_style, "hovered");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ItemList, selected_style, "selected");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ItemList, selected_focus_style, "selected_focus");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ItemList, cursor_style, "cursor_unfocused");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ItemList, cursor_focus_style, "cursor");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, guide_color);
 }
 
 ItemList::ItemList() {

+ 0 - 2
scene/gui/item_list.h

@@ -153,8 +153,6 @@ private:
 	void _mouse_exited();
 
 protected:
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int p_what);
 	bool _set(const StringName &p_name, const Variant &p_value);
 	bool _get(const StringName &p_name, Variant &r_ret) const;

+ 14 - 17
scene/gui/label.cpp

@@ -33,7 +33,7 @@
 #include "core/config/project_settings.h"
 #include "core/string/print_string.h"
 #include "core/string/translation.h"
-
+#include "scene/theme/theme_db.h"
 #include "servers/text_server.h"
 
 void Label::set_autowrap_mode(TextServer::AutowrapMode p_mode) {
@@ -324,22 +324,6 @@ inline void draw_glyph_outline(const Glyph &p_gl, const RID &p_canvas, const Col
 	}
 }
 
-void Label::_update_theme_item_cache() {
-	Control::_update_theme_item_cache();
-
-	theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
-	theme_cache.font = get_theme_font(SNAME("font"));
-
-	theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
-	theme_cache.line_spacing = get_theme_constant(SNAME("line_spacing"));
-	theme_cache.font_color = get_theme_color(SNAME("font_color"));
-	theme_cache.font_shadow_color = get_theme_color(SNAME("font_shadow_color"));
-	theme_cache.font_shadow_offset = Point2(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
-	theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
-	theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
-	theme_cache.font_shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size"));
-}
-
 PackedStringArray Label::get_configuration_warnings() const {
 	PackedStringArray warnings = Control::get_configuration_warnings();
 
@@ -1054,6 +1038,19 @@ void Label::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Label, normal_style, "normal");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Label, line_spacing);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, Label, font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, Label, font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Label, font_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Label, font_shadow_color);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, Label, font_shadow_offset.x, "shadow_offset_x");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, Label, font_shadow_offset.y, "shadow_offset_y");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Label, font_outline_color);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, Label, font_outline_size, "outline_size");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, Label, font_shadow_outline_size, "shadow_outline_size");
 }
 
 Label::Label(const String &p_text) {

+ 0 - 2
scene/gui/label.h

@@ -88,8 +88,6 @@ private:
 	void _invalidate();
 
 protected:
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int p_what);
 	static void _bind_methods();
 

+ 25 - 23
scene/gui/line_edit.cpp

@@ -36,13 +36,15 @@
 #include "core/os/os.h"
 #include "core/string/print_string.h"
 #include "core/string/translation.h"
-#include "label.h"
+#include "scene/gui/label.h"
+#include "scene/main/window.h"
+#include "scene/theme/theme_db.h"
 #include "servers/display_server.h"
 #include "servers/text_server.h"
+
 #ifdef TOOLS_ENABLED
 #include "editor/editor_settings.h"
 #endif
-#include "scene/main/window.h"
 
 void LineEdit::_swap_current_input_direction() {
 	if (input_direction == TEXT_DIRECTION_LTR) {
@@ -733,27 +735,6 @@ bool LineEdit::_is_over_clear_button(const Point2 &p_pos) const {
 void LineEdit::_update_theme_item_cache() {
 	Control::_update_theme_item_cache();
 
-	theme_cache.normal = get_theme_stylebox(SNAME("normal"));
-	theme_cache.read_only = get_theme_stylebox(SNAME("read_only"));
-	theme_cache.focus = get_theme_stylebox(SNAME("focus"));
-
-	theme_cache.font = get_theme_font(SNAME("font"));
-	theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
-	theme_cache.font_color = get_theme_color(SNAME("font_color"));
-	theme_cache.font_uneditable_color = get_theme_color(SNAME("font_uneditable_color"));
-	theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
-	theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
-	theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
-	theme_cache.font_placeholder_color = get_theme_color(SNAME("font_placeholder_color"));
-	theme_cache.caret_width = get_theme_constant(SNAME("caret_width"));
-	theme_cache.caret_color = get_theme_color(SNAME("caret_color"));
-	theme_cache.minimum_character_width = get_theme_constant(SNAME("minimum_character_width"));
-	theme_cache.selection_color = get_theme_color(SNAME("selection_color"));
-
-	theme_cache.clear_icon = get_theme_icon(SNAME("clear"));
-	theme_cache.clear_button_color = get_theme_color(SNAME("clear_button_color"));
-	theme_cache.clear_button_color_pressed = get_theme_color(SNAME("clear_button_color_pressed"));
-
 	theme_cache.base_scale = get_theme_default_base_scale();
 }
 
@@ -2669,6 +2650,27 @@ void LineEdit::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, LineEdit, normal);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, LineEdit, read_only);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, LineEdit, focus);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, LineEdit, font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, LineEdit, font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LineEdit, font_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LineEdit, font_uneditable_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LineEdit, font_selected_color);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, LineEdit, font_outline_size, "outline_size");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LineEdit, font_outline_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LineEdit, font_placeholder_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, LineEdit, caret_width);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LineEdit, caret_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, LineEdit, minimum_character_width);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LineEdit, selection_color);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, LineEdit, clear_icon, "clear");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LineEdit, clear_button_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LineEdit, clear_button_color_pressed);
 }
 
 LineEdit::LineEdit(const String &p_placeholder) {

+ 4 - 2
scene/gui/line_edit.h

@@ -246,14 +246,16 @@ private:
 
 protected:
 	bool _is_over_clear_button(const Point2 &p_pos) const;
+
 	virtual void _update_theme_item_cache() override;
+
 	void _notification(int p_what);
+	void _validate_property(PropertyInfo &p_property) const;
 	static void _bind_methods();
+
 	virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
 	virtual void gui_input(const Ref<InputEvent> &p_event) override;
 
-	void _validate_property(PropertyInfo &p_property) const;
-
 public:
 	void set_horizontal_alignment(HorizontalAlignment p_alignment);
 	HorizontalAlignment get_horizontal_alignment() const;

+ 17 - 20
scene/gui/link_button.cpp

@@ -31,6 +31,7 @@
 #include "link_button.h"
 
 #include "core/string/translation.h"
+#include "scene/theme/theme_db.h"
 
 void LinkButton::_shape() {
 	Ref<Font> font = theme_cache.font;
@@ -141,26 +142,6 @@ Size2 LinkButton::get_minimum_size() const {
 	return text_buf->get_size();
 }
 
-void LinkButton::_update_theme_item_cache() {
-	BaseButton::_update_theme_item_cache();
-
-	theme_cache.focus = get_theme_stylebox(SNAME("focus"));
-
-	theme_cache.font_color = get_theme_color(SNAME("font_color"));
-	theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
-	theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
-	theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
-	theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
-	theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
-
-	theme_cache.font = get_theme_font(SNAME("font"));
-	theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
-	theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
-	theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
-
-	theme_cache.underline_spacing = get_theme_constant(SNAME("underline_spacing"));
-}
-
 void LinkButton::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_TRANSLATION_CHANGED: {
@@ -284,6 +265,22 @@ void LinkButton::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, LinkButton, focus);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LinkButton, font_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LinkButton, font_focus_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LinkButton, font_pressed_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LinkButton, font_hover_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LinkButton, font_hover_pressed_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LinkButton, font_disabled_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, LinkButton, font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, LinkButton, font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, LinkButton, outline_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LinkButton, font_outline_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, LinkButton, underline_spacing);
 }
 
 LinkButton::LinkButton(const String &p_text) {

+ 1 - 1
scene/gui/link_button.h

@@ -79,7 +79,7 @@ private:
 protected:
 	virtual void pressed() override;
 	virtual Size2 get_minimum_size() const override;
-	virtual void _update_theme_item_cache() override;
+
 	void _notification(int p_what);
 	static void _bind_methods();
 

+ 8 - 8
scene/gui/margin_container.cpp

@@ -30,14 +30,7 @@
 
 #include "margin_container.h"
 
-void MarginContainer::_update_theme_item_cache() {
-	Container::_update_theme_item_cache();
-
-	theme_cache.margin_left = get_theme_constant(SNAME("margin_left"));
-	theme_cache.margin_top = get_theme_constant(SNAME("margin_top"));
-	theme_cache.margin_right = get_theme_constant(SNAME("margin_right"));
-	theme_cache.margin_bottom = get_theme_constant(SNAME("margin_bottom"));
-}
+#include "scene/theme/theme_db.h"
 
 Size2 MarginContainer::get_minimum_size() const {
 	Size2 max;
@@ -113,5 +106,12 @@ void MarginContainer::_notification(int p_what) {
 	}
 }
 
+void MarginContainer::_bind_methods() {
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, MarginContainer, margin_left);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, MarginContainer, margin_top);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, MarginContainer, margin_right);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, MarginContainer, margin_bottom);
+}
+
 MarginContainer::MarginContainer() {
 }

+ 1 - 2
scene/gui/margin_container.h

@@ -44,9 +44,8 @@ class MarginContainer : public Container {
 	} theme_cache;
 
 protected:
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int p_what);
+	static void _bind_methods();
 
 public:
 	virtual Size2 get_minimum_size() const override;

+ 26 - 29
scene/gui/menu_bar.cpp

@@ -32,6 +32,7 @@
 
 #include "core/os/keyboard.h"
 #include "scene/main/window.h"
+#include "scene/theme/theme_db.h"
 
 void MenuBar::gui_input(const Ref<InputEvent> &p_event) {
 	ERR_FAIL_COND(p_event.is_null());
@@ -305,35 +306,6 @@ void MenuBar::_update_menu() {
 	queue_redraw();
 }
 
-void MenuBar::_update_theme_item_cache() {
-	Control::_update_theme_item_cache();
-
-	theme_cache.normal = get_theme_stylebox(SNAME("normal"));
-	theme_cache.normal_mirrored = get_theme_stylebox(SNAME("normal_mirrored"));
-	theme_cache.disabled = get_theme_stylebox(SNAME("disabled"));
-	theme_cache.disabled_mirrored = get_theme_stylebox(SNAME("disabled_mirrored"));
-	theme_cache.pressed = get_theme_stylebox(SNAME("pressed"));
-	theme_cache.pressed_mirrored = get_theme_stylebox(SNAME("pressed_mirrored"));
-	theme_cache.hover = get_theme_stylebox(SNAME("hover"));
-	theme_cache.hover_mirrored = get_theme_stylebox(SNAME("hover_mirrored"));
-	theme_cache.hover_pressed = get_theme_stylebox(SNAME("hover_pressed"));
-	theme_cache.hover_pressed_mirrored = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
-
-	theme_cache.font = get_theme_font(SNAME("font"));
-	theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
-	theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
-	theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
-
-	theme_cache.font_color = get_theme_color(SNAME("font_color"));
-	theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
-	theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
-	theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
-	theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
-	theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
-
-	theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
-}
-
 void MenuBar::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_ENTER_TREE: {
@@ -684,6 +656,31 @@ void MenuBar::_bind_methods() {
 	ADD_GROUP("BiDi", "");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, MenuBar, normal);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, MenuBar, normal_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, MenuBar, disabled);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, MenuBar, disabled_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, MenuBar, pressed);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, MenuBar, pressed_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, MenuBar, hover);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, MenuBar, hover_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, MenuBar, hover_pressed);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, MenuBar, hover_pressed_mirrored);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, MenuBar, font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, MenuBar, font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, MenuBar, outline_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, MenuBar, font_outline_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, MenuBar, font_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, MenuBar, font_disabled_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, MenuBar, font_pressed_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, MenuBar, font_hover_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, MenuBar, font_hover_pressed_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, MenuBar, font_focus_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, MenuBar, h_separation);
 }
 
 void MenuBar::set_switch_on_hover(bool p_enabled) {

+ 0 - 1
scene/gui/menu_bar.h

@@ -121,7 +121,6 @@ class MenuBar : public Control {
 protected:
 	virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
 
-	virtual void _update_theme_item_cache() override;
 	void _notification(int p_what);
 	virtual void add_child_notify(Node *p_child) override;
 	virtual void move_child_notify(Node *p_child) override;

+ 17 - 19
scene/gui/option_button.cpp

@@ -32,6 +32,7 @@
 
 #include "core/os/keyboard.h"
 #include "core/string/print_string.h"
+#include "scene/theme/theme_db.h"
 
 static const int NONE_SELECTED = -1;
 
@@ -72,25 +73,6 @@ Size2 OptionButton::get_minimum_size() const {
 	return minsize;
 }
 
-void OptionButton::_update_theme_item_cache() {
-	Button::_update_theme_item_cache();
-
-	theme_cache.normal = get_theme_stylebox(SNAME("normal"));
-
-	theme_cache.font_color = get_theme_color(SNAME("font_color"));
-	theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
-	theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
-	theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
-	theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
-	theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
-
-	theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
-
-	theme_cache.arrow_icon = get_theme_icon(SNAME("arrow"));
-	theme_cache.arrow_margin = get_theme_constant(SNAME("arrow_margin"));
-	theme_cache.modulate_arrow = get_theme_constant(SNAME("modulate_arrow"));
-}
-
 void OptionButton::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_POSTINITIALIZE: {
@@ -597,8 +579,24 @@ void OptionButton::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "selected"), "_select_int", "get_selected");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fit_to_longest_item"), "set_fit_to_longest_item", "is_fit_to_longest_item");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_reselect"), "set_allow_reselect", "get_allow_reselect");
+
 	ADD_SIGNAL(MethodInfo("item_selected", PropertyInfo(Variant::INT, "index")));
 	ADD_SIGNAL(MethodInfo("item_focused", PropertyInfo(Variant::INT, "index")));
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, OptionButton, normal);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, OptionButton, font_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, OptionButton, font_focus_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, OptionButton, font_pressed_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, OptionButton, font_hover_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, OptionButton, font_hover_pressed_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, OptionButton, font_disabled_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, OptionButton, h_separation);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, OptionButton, arrow_icon, "arrow");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, OptionButton, arrow_margin);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, OptionButton, modulate_arrow);
 }
 
 void OptionButton::set_disable_shortcuts(bool p_disabled) {

+ 2 - 1
scene/gui/option_button.h

@@ -72,14 +72,15 @@ class OptionButton : public Button {
 
 protected:
 	Size2 get_minimum_size() const override;
-	virtual void _update_theme_item_cache() override;
 	virtual void _queue_update_size_cache() override;
+
 	void _notification(int p_what);
 	bool _set(const StringName &p_name, const Variant &p_value);
 	bool _get(const StringName &p_name, Variant &r_ret) const;
 	void _get_property_list(List<PropertyInfo> *p_list) const;
 	void _validate_property(PropertyInfo &p_property) const;
 	static void _bind_methods();
+
 	virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
 
 public:

+ 5 - 6
scene/gui/panel.cpp

@@ -29,12 +29,7 @@
 /**************************************************************************/
 
 #include "panel.h"
-
-void Panel::_update_theme_item_cache() {
-	Control::_update_theme_item_cache();
-
-	theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
-}
+#include "scene/theme/theme_db.h"
 
 void Panel::_notification(int p_what) {
 	switch (p_what) {
@@ -45,6 +40,10 @@ void Panel::_notification(int p_what) {
 	}
 }
 
+void Panel::_bind_methods() {
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Panel, panel_style, "panel");
+}
+
 Panel::Panel() {
 	// Has visible stylebox, so stop by default.
 	set_mouse_filter(MOUSE_FILTER_STOP);

+ 1 - 2
scene/gui/panel.h

@@ -41,9 +41,8 @@ class Panel : public Control {
 	} theme_cache;
 
 protected:
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int p_what);
+	static void _bind_methods();
 
 public:
 	Panel();

+ 6 - 6
scene/gui/panel_container.cpp

@@ -30,6 +30,8 @@
 
 #include "panel_container.h"
 
+#include "scene/theme/theme_db.h"
+
 Size2 PanelContainer::get_minimum_size() const {
 	Size2 ms;
 	for (int i = 0; i < get_child_count(); i++) {
@@ -70,12 +72,6 @@ Vector<int> PanelContainer::get_allowed_size_flags_vertical() const {
 	return flags;
 }
 
-void PanelContainer::_update_theme_item_cache() {
-	Container::_update_theme_item_cache();
-
-	theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
-}
-
 void PanelContainer::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_DRAW: {
@@ -106,6 +102,10 @@ void PanelContainer::_notification(int p_what) {
 	}
 }
 
+void PanelContainer::_bind_methods() {
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, PanelContainer, panel_style, "panel");
+}
+
 PanelContainer::PanelContainer() {
 	// Has visible stylebox, so stop by default.
 	set_mouse_filter(MOUSE_FILTER_STOP);

+ 1 - 1
scene/gui/panel_container.h

@@ -41,8 +41,8 @@ class PanelContainer : public Container {
 	} theme_cache;
 
 protected:
-	virtual void _update_theme_item_cache() override;
 	void _notification(int p_what);
+	static void _bind_methods();
 
 public:
 	virtual Size2 get_minimum_size() const override;

+ 11 - 16
scene/gui/popup.cpp

@@ -33,6 +33,7 @@
 #include "core/config/engine.h"
 #include "core/os/keyboard.h"
 #include "scene/gui/panel.h"
+#include "scene/theme/theme_db.h"
 
 void Popup::_input_from_window(const Ref<InputEvent> &p_event) {
 	if (get_flag(FLAG_POPUP) && p_event->is_action_pressed(SNAME("ui_cancel"), false, true)) {
@@ -67,12 +68,6 @@ void Popup::_deinitialize_visible_parents() {
 	}
 }
 
-void Popup::_update_theme_item_cache() {
-	Window::_update_theme_item_cache();
-
-	theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
-}
-
 void Popup::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -135,10 +130,6 @@ void Popup::_post_popup() {
 	popped_up = true;
 }
 
-void Popup::_bind_methods() {
-	ADD_SIGNAL(MethodInfo("popup_hide"));
-}
-
 void Popup::_validate_property(PropertyInfo &p_property) const {
 	if (
 			p_property.name == "transient" ||
@@ -200,6 +191,12 @@ Rect2i Popup::_popup_adjust_rect() const {
 	return current;
 }
 
+void Popup::_bind_methods() {
+	ADD_SIGNAL(MethodInfo("popup_hide"));
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Popup, panel_style, "panel");
+}
+
 Popup::Popup() {
 	set_wrap_controls(true);
 	set_visible(false);
@@ -259,12 +256,6 @@ void PopupPanel::_update_child_rects() {
 	}
 }
 
-void PopupPanel::_update_theme_item_cache() {
-	Popup::_update_theme_item_cache();
-
-	theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
-}
-
 void PopupPanel::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_READY:
@@ -279,6 +270,10 @@ void PopupPanel::_notification(int p_what) {
 	}
 }
 
+void PopupPanel::_bind_methods() {
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, PopupPanel, panel_style, "panel");
+}
+
 PopupPanel::PopupPanel() {
 	panel = memnew(Panel);
 	add_child(panel, false, INTERNAL_MODE_FRONT);

+ 2 - 3
scene/gui/popup.h

@@ -56,10 +56,9 @@ protected:
 	void _close_pressed();
 	virtual Rect2i _popup_adjust_rect() const override;
 
-	virtual void _update_theme_item_cache() override;
 	void _notification(int p_what);
-	static void _bind_methods();
 	void _validate_property(PropertyInfo &p_property) const;
+	static void _bind_methods();
 
 	virtual void _parent_focused();
 
@@ -82,8 +81,8 @@ class PopupPanel : public Popup {
 protected:
 	void _update_child_rects();
 
-	virtual void _update_theme_item_cache() override;
 	void _notification(int p_what);
+	static void _bind_methods();
 
 	virtual Size2 _get_contents_minimum_size() const override;
 

+ 43 - 46
scene/gui/popup_menu.cpp

@@ -38,6 +38,7 @@
 #include "core/string/print_string.h"
 #include "core/string/translation.h"
 #include "scene/gui/menu_bar.h"
+#include "scene/theme/theme_db.h"
 
 String PopupMenu::_get_accel_text(const Item &p_item) const {
 	if (p_item.shortcut.is_valid()) {
@@ -839,52 +840,6 @@ void PopupMenu::remove_child_notify(Node *p_child) {
 	_menu_changed();
 }
 
-void PopupMenu::_update_theme_item_cache() {
-	Popup::_update_theme_item_cache();
-
-	theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
-	theme_cache.hover_style = get_theme_stylebox(SNAME("hover"));
-
-	theme_cache.separator_style = get_theme_stylebox(SNAME("separator"));
-	theme_cache.labeled_separator_left = get_theme_stylebox(SNAME("labeled_separator_left"));
-	theme_cache.labeled_separator_right = get_theme_stylebox(SNAME("labeled_separator_right"));
-
-	theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
-	theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
-	theme_cache.indent = get_theme_constant(SNAME("indent"));
-	theme_cache.item_start_padding = get_theme_constant(SNAME("item_start_padding"));
-	theme_cache.item_end_padding = get_theme_constant(SNAME("item_end_padding"));
-	theme_cache.icon_max_width = get_theme_constant(SNAME("icon_max_width"));
-
-	theme_cache.checked = get_theme_icon(SNAME("checked"));
-	theme_cache.checked_disabled = get_theme_icon(SNAME("checked_disabled"));
-	theme_cache.unchecked = get_theme_icon(SNAME("unchecked"));
-	theme_cache.unchecked_disabled = get_theme_icon(SNAME("unchecked_disabled"));
-	theme_cache.radio_checked = get_theme_icon(SNAME("radio_checked"));
-	theme_cache.radio_checked_disabled = get_theme_icon(SNAME("radio_checked_disabled"));
-	theme_cache.radio_unchecked = get_theme_icon(SNAME("radio_unchecked"));
-	theme_cache.radio_unchecked_disabled = get_theme_icon(SNAME("radio_unchecked_disabled"));
-
-	theme_cache.submenu = get_theme_icon(SNAME("submenu"));
-	theme_cache.submenu_mirrored = get_theme_icon(SNAME("submenu_mirrored"));
-
-	theme_cache.font = get_theme_font(SNAME("font"));
-	theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
-	theme_cache.font_separator = get_theme_font(SNAME("font_separator"));
-	theme_cache.font_separator_size = get_theme_font_size(SNAME("font_separator_size"));
-
-	theme_cache.font_color = get_theme_color(SNAME("font_color"));
-	theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
-	theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
-	theme_cache.font_accelerator_color = get_theme_color(SNAME("font_accelerator_color"));
-	theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
-	theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
-
-	theme_cache.font_separator_color = get_theme_color(SNAME("font_separator_color"));
-	theme_cache.font_separator_outline_size = get_theme_constant(SNAME("separator_outline_size"));
-	theme_cache.font_separator_outline_color = get_theme_color(SNAME("font_separator_outline_color"));
-}
-
 void PopupMenu::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_ENTER_TREE: {
@@ -2308,6 +2263,48 @@ void PopupMenu::_bind_methods() {
 	ADD_SIGNAL(MethodInfo("id_focused", PropertyInfo(Variant::INT, "id")));
 	ADD_SIGNAL(MethodInfo("index_pressed", PropertyInfo(Variant::INT, "index")));
 	ADD_SIGNAL(MethodInfo("menu_changed"));
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, PopupMenu, panel_style, "panel");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, PopupMenu, hover_style, "hover");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, PopupMenu, separator_style, "separator");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, PopupMenu, labeled_separator_left);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, PopupMenu, labeled_separator_right);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, PopupMenu, v_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, PopupMenu, h_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, PopupMenu, indent);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, PopupMenu, item_start_padding);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, PopupMenu, item_end_padding);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, PopupMenu, icon_max_width);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, PopupMenu, checked);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, PopupMenu, checked_disabled);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, PopupMenu, unchecked);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, PopupMenu, unchecked_disabled);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, PopupMenu, radio_checked);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, PopupMenu, radio_checked_disabled);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, PopupMenu, radio_unchecked);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, PopupMenu, radio_unchecked_disabled);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, PopupMenu, submenu);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, PopupMenu, submenu_mirrored);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, PopupMenu, font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, PopupMenu, font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, PopupMenu, font_separator);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, PopupMenu, font_separator_size);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, PopupMenu, font_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, PopupMenu, font_hover_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, PopupMenu, font_disabled_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, PopupMenu, font_accelerator_color);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, PopupMenu, font_outline_size, "outline_size");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, PopupMenu, font_outline_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, PopupMenu, font_separator_color);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, PopupMenu, font_separator_outline_size, "separator_outline_size");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, PopupMenu, font_separator_outline_color);
 }
 
 void PopupMenu::popup(const Rect2i &p_bounds) {

+ 1 - 2
scene/gui/popup_menu.h

@@ -190,10 +190,9 @@ class PopupMenu : public Popup {
 	void _menu_changed();
 
 protected:
-	virtual void _update_theme_item_cache() override;
-
 	virtual void add_child_notify(Node *p_child) override;
 	virtual void remove_child_notify(Node *p_child) override;
+
 	void _notification(int p_what);
 	bool _set(const StringName &p_name, const Variant &p_value);
 	bool _get(const StringName &p_name, Variant &r_ret) const;

+ 10 - 13
scene/gui/progress_bar.cpp

@@ -31,6 +31,7 @@
 #include "progress_bar.h"
 
 #include "scene/resources/text_line.h"
+#include "scene/theme/theme_db.h"
 
 Size2 ProgressBar::get_minimum_size() const {
 	Size2 minimum_size = theme_cache.background_style->get_minimum_size();
@@ -47,19 +48,6 @@ Size2 ProgressBar::get_minimum_size() const {
 	return minimum_size;
 }
 
-void ProgressBar::_update_theme_item_cache() {
-	Range::_update_theme_item_cache();
-
-	theme_cache.background_style = get_theme_stylebox(SNAME("background"));
-	theme_cache.fill_style = get_theme_stylebox(SNAME("fill"));
-
-	theme_cache.font = get_theme_font(SNAME("font"));
-	theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
-	theme_cache.font_color = get_theme_color(SNAME("font_color"));
-	theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
-	theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
-}
-
 void ProgressBar::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_DRAW: {
@@ -158,6 +146,15 @@ void ProgressBar::_bind_methods() {
 	BIND_ENUM_CONSTANT(FILL_END_TO_BEGIN);
 	BIND_ENUM_CONSTANT(FILL_TOP_TO_BOTTOM);
 	BIND_ENUM_CONSTANT(FILL_BOTTOM_TO_TOP);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ProgressBar, background_style, "background");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ProgressBar, fill_style, "fill");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, ProgressBar, font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, ProgressBar, font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ProgressBar, font_color);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, ProgressBar, font_outline_size, "outline_size");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ProgressBar, font_outline_color);
 }
 
 ProgressBar::ProgressBar() {

+ 0 - 2
scene/gui/progress_bar.h

@@ -50,8 +50,6 @@ class ProgressBar : public Range {
 	} theme_cache;
 
 protected:
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int p_what);
 	static void _bind_methods();
 

+ 37 - 36
scene/gui/rich_text_label.cpp

@@ -38,6 +38,7 @@
 #include "scene/gui/label.h"
 #include "scene/resources/atlas_texture.h"
 #include "scene/scene_string_names.h"
+#include "scene/theme/theme_db.h"
 #include "servers/display_server.h"
 
 #include "modules/modules_enabled.gen.h" // For regex.
@@ -1744,43 +1745,8 @@ _FORCE_INLINE_ float RichTextLabel::_calculate_line_vertical_offset(const RichTe
 void RichTextLabel::_update_theme_item_cache() {
 	Control::_update_theme_item_cache();
 
-	theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
-	theme_cache.focus_style = get_theme_stylebox(SNAME("focus"));
-	theme_cache.progress_bg_style = get_theme_stylebox(SNAME("background"), SNAME("ProgressBar"));
-	theme_cache.progress_fg_style = get_theme_stylebox(SNAME("fill"), SNAME("ProgressBar"));
-
-	theme_cache.line_separation = get_theme_constant(SNAME("line_separation"));
-
-	theme_cache.normal_font = get_theme_font(SNAME("normal_font"));
-	theme_cache.normal_font_size = get_theme_font_size(SNAME("normal_font_size"));
-
-	theme_cache.default_color = get_theme_color(SNAME("default_color"));
-	theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
-	use_selected_font_color = theme_cache.font_selected_color != Color(0, 0, 0, 0);
-	theme_cache.selection_color = get_theme_color(SNAME("selection_color"));
-	theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
-	theme_cache.font_shadow_color = get_theme_color(SNAME("font_shadow_color"));
-	theme_cache.shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size"));
-	theme_cache.shadow_offset_x = get_theme_constant(SNAME("shadow_offset_x"));
-	theme_cache.shadow_offset_y = get_theme_constant(SNAME("shadow_offset_y"));
-	theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
-
-	theme_cache.bold_font = get_theme_font(SNAME("bold_font"));
-	theme_cache.bold_font_size = get_theme_font_size(SNAME("bold_font_size"));
-	theme_cache.bold_italics_font = get_theme_font(SNAME("bold_italics_font"));
-	theme_cache.bold_italics_font_size = get_theme_font_size(SNAME("bold_italics_font_size"));
-	theme_cache.italics_font = get_theme_font(SNAME("italics_font"));
-	theme_cache.italics_font_size = get_theme_font_size(SNAME("italics_font_size"));
-	theme_cache.mono_font = get_theme_font(SNAME("mono_font"));
-	theme_cache.mono_font_size = get_theme_font_size(SNAME("mono_font_size"));
-
-	theme_cache.table_h_separation = get_theme_constant(SNAME("table_h_separation"));
-	theme_cache.table_v_separation = get_theme_constant(SNAME("table_v_separation"));
-	theme_cache.table_odd_row_bg = get_theme_color(SNAME("table_odd_row_bg"));
-	theme_cache.table_even_row_bg = get_theme_color(SNAME("table_even_row_bg"));
-	theme_cache.table_border = get_theme_color(SNAME("table_border"));
-
 	theme_cache.base_scale = get_theme_default_base_scale();
+	use_selected_font_color = theme_cache.font_selected_color != Color(0, 0, 0, 0);
 }
 
 void RichTextLabel::_notification(int p_what) {
@@ -5821,6 +5787,41 @@ void RichTextLabel::_bind_methods() {
 	BIND_ENUM_CONSTANT(MENU_COPY);
 	BIND_ENUM_CONSTANT(MENU_SELECT_ALL);
 	BIND_ENUM_CONSTANT(MENU_MAX);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, RichTextLabel, normal_style, "normal");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, RichTextLabel, focus_style, "focus");
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, RichTextLabel, progress_bg_style, "background", "ProgressBar");
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, RichTextLabel, progress_fg_style, "fill", "ProgressBar");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, line_separation);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, RichTextLabel, normal_font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, RichTextLabel, normal_font_size);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, RichTextLabel, default_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, RichTextLabel, font_selected_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, RichTextLabel, selection_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, RichTextLabel, font_outline_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, RichTextLabel, font_shadow_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, shadow_outline_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, shadow_offset_x);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, shadow_offset_y);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, outline_size);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, RichTextLabel, bold_font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, RichTextLabel, bold_font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, RichTextLabel, bold_italics_font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, RichTextLabel, bold_italics_font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, RichTextLabel, italics_font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, RichTextLabel, italics_font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, RichTextLabel, mono_font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, RichTextLabel, mono_font_size);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, table_h_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, table_v_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, RichTextLabel, table_odd_row_bg);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, RichTextLabel, table_even_row_bg);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, RichTextLabel, table_border);
 }
 
 TextServer::VisibleCharactersBehavior RichTextLabel::get_visible_characters_behavior() const {

+ 1 - 0
scene/gui/rich_text_label.h

@@ -98,6 +98,7 @@ public:
 
 protected:
 	virtual void _update_theme_item_cache() override;
+
 	void _notification(int p_what);
 	static void _bind_methods();
 

+ 15 - 18
scene/gui/scroll_bar.cpp

@@ -34,6 +34,7 @@
 #include "core/os/os.h"
 #include "core/string/print_string.h"
 #include "scene/main/window.h"
+#include "scene/theme/theme_db.h"
 
 bool ScrollBar::focus_by_default = false;
 
@@ -221,24 +222,6 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
 	}
 }
 
-void ScrollBar::_update_theme_item_cache() {
-	Range::_update_theme_item_cache();
-
-	theme_cache.scroll_style = get_theme_stylebox(SNAME("scroll"));
-	theme_cache.scroll_focus_style = get_theme_stylebox(SNAME("scroll_focus"));
-	theme_cache.scroll_offset_style = get_theme_stylebox(SNAME("hscroll"));
-	theme_cache.grabber_style = get_theme_stylebox(SNAME("grabber"));
-	theme_cache.grabber_hl_style = get_theme_stylebox(SNAME("grabber_highlight"));
-	theme_cache.grabber_pressed_style = get_theme_stylebox(SNAME("grabber_pressed"));
-
-	theme_cache.increment_icon = get_theme_icon(SNAME("increment"));
-	theme_cache.increment_hl_icon = get_theme_icon(SNAME("increment_highlight"));
-	theme_cache.increment_pressed_icon = get_theme_icon(SNAME("increment_pressed"));
-	theme_cache.decrement_icon = get_theme_icon(SNAME("decrement"));
-	theme_cache.decrement_hl_icon = get_theme_icon(SNAME("decrement_highlight"));
-	theme_cache.decrement_pressed_icon = get_theme_icon(SNAME("decrement_pressed"));
-}
-
 void ScrollBar::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_DRAW: {
@@ -653,6 +636,20 @@ void ScrollBar::_bind_methods() {
 	ADD_SIGNAL(MethodInfo("scrolling"));
 
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_step", PROPERTY_HINT_RANGE, "-1,4096,suffix:px"), "set_custom_step", "get_custom_step");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollBar, scroll_style, "scroll");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollBar, scroll_focus_style, "scroll_focus");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollBar, scroll_offset_style, "hscroll");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollBar, grabber_style, "grabber");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollBar, grabber_hl_style, "grabber_highlight");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollBar, grabber_pressed_style, "grabber_pressed");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ScrollBar, increment_icon, "increment");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ScrollBar, increment_hl_icon, "increment_highlight");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ScrollBar, increment_pressed_icon, "increment_pressed");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ScrollBar, decrement_icon, "decrement");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ScrollBar, decrement_hl_icon, "decrement_highlight");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ScrollBar, decrement_pressed_icon, "decrement_pressed");
 }
 
 ScrollBar::ScrollBar(Orientation p_orientation) {

+ 0 - 2
scene/gui/scroll_bar.h

@@ -108,8 +108,6 @@ class ScrollBar : public Range {
 	virtual void gui_input(const Ref<InputEvent> &p_event) override;
 
 protected:
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int p_what);
 	static void _bind_methods();
 

+ 3 - 6
scene/gui/scroll_container.cpp

@@ -33,6 +33,7 @@
 #include "core/config/project_settings.h"
 #include "core/os/os.h"
 #include "scene/main/window.h"
+#include "scene/theme/theme_db.h"
 
 Size2 ScrollContainer::get_minimum_size() const {
 	Size2 min_size;
@@ -80,12 +81,6 @@ Size2 ScrollContainer::get_minimum_size() const {
 	return min_size;
 }
 
-void ScrollContainer::_update_theme_item_cache() {
-	Container::_update_theme_item_cache();
-
-	theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
-}
-
 void ScrollContainer::_cancel_drag() {
 	set_physics_process_internal(false);
 	drag_touching_deaccel = false;
@@ -627,6 +622,8 @@ void ScrollContainer::_bind_methods() {
 	BIND_ENUM_CONSTANT(SCROLL_MODE_SHOW_ALWAYS);
 	BIND_ENUM_CONSTANT(SCROLL_MODE_SHOW_NEVER);
 
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollContainer, panel_style, "panel");
+
 	GLOBAL_DEF("gui/common/default_scroll_deadzone", 0);
 };
 

+ 2 - 3
scene/gui/scroll_container.h

@@ -76,18 +76,17 @@ private:
 	void _cancel_drag();
 
 protected:
-	virtual void _update_theme_item_cache() override;
 	Size2 get_minimum_size() const override;
 
 	void _gui_focus_changed(Control *p_control);
 	void _reposition_children();
-	void _notification(int p_what);
 
-	void _scroll_moved(float);
+	void _notification(int p_what);
 	static void _bind_methods();
 
 	bool _updating_scrollbars = false;
 	void _update_scrollbar_position();
+	void _scroll_moved(float);
 
 public:
 	virtual void gui_input(const Ref<InputEvent> &p_gui_input) override;

+ 7 - 7
scene/gui/separator.cpp

@@ -30,6 +30,8 @@
 
 #include "separator.h"
 
+#include "scene/theme/theme_db.h"
+
 Size2 Separator::get_minimum_size() const {
 	Size2 ms(3, 3);
 	if (orientation == VERTICAL) {
@@ -40,13 +42,6 @@ Size2 Separator::get_minimum_size() const {
 	return ms;
 }
 
-void Separator::_update_theme_item_cache() {
-	Control::_update_theme_item_cache();
-
-	theme_cache.separation = get_theme_constant(SNAME("separation"));
-	theme_cache.separator_style = get_theme_stylebox(SNAME("separator"));
-}
-
 void Separator::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_DRAW: {
@@ -62,6 +57,11 @@ void Separator::_notification(int p_what) {
 	}
 }
 
+void Separator::_bind_methods() {
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Separator, separation);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Separator, separator_style, "separator");
+}
+
 Separator::Separator() {
 }
 

+ 1 - 2
scene/gui/separator.h

@@ -43,9 +43,8 @@ class Separator : public Control {
 protected:
 	Orientation orientation = Orientation::HORIZONTAL;
 
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int p_what);
+	static void _bind_methods();
 
 public:
 	virtual Size2 get_minimum_size() const override;

+ 13 - 16
scene/gui/slider.cpp

@@ -31,6 +31,7 @@
 #include "slider.h"
 
 #include "core/os/keyboard.h"
+#include "scene/theme/theme_db.h"
 
 Size2 Slider::get_minimum_size() const {
 	Size2i ss = theme_cache.slider_style->get_minimum_size();
@@ -176,22 +177,6 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
 	}
 }
 
-void Slider::_update_theme_item_cache() {
-	Range::_update_theme_item_cache();
-
-	theme_cache.slider_style = get_theme_stylebox(SNAME("slider"));
-	theme_cache.grabber_area_style = get_theme_stylebox(SNAME("grabber_area"));
-	theme_cache.grabber_area_hl_style = get_theme_stylebox(SNAME("grabber_area_highlight"));
-
-	theme_cache.grabber_icon = get_theme_icon(SNAME("grabber"));
-	theme_cache.grabber_hl_icon = get_theme_icon(SNAME("grabber_highlight"));
-	theme_cache.grabber_disabled_icon = get_theme_icon(SNAME("grabber_disabled"));
-	theme_cache.tick_icon = get_theme_icon(SNAME("tick"));
-
-	theme_cache.center_grabber = get_theme_constant(SNAME("center_grabber"));
-	theme_cache.grabber_offset = get_theme_constant(SNAME("grabber_offset"));
-}
-
 void Slider::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_INTERNAL_PROCESS: {
@@ -392,6 +377,18 @@ void Slider::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrollable"), "set_scrollable", "is_scrollable");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "tick_count", PROPERTY_HINT_RANGE, "0,4096,1"), "set_ticks", "get_ticks");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ticks_on_borders"), "set_ticks_on_borders", "get_ticks_on_borders");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Slider, slider_style, "slider");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Slider, grabber_area_style, "grabber_area");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Slider, grabber_area_hl_style, "grabber_area_highlight");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, Slider, grabber_icon, "grabber");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, Slider, grabber_hl_icon, "grabber_highlight");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, Slider, grabber_disabled_icon, "grabber_disabled");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, Slider, tick_icon, "tick");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Slider, center_grabber);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Slider, grabber_offset);
 }
 
 Slider::Slider(Orientation p_orientation) {

+ 0 - 1
scene/gui/slider.h

@@ -71,7 +71,6 @@ protected:
 	bool ticks_on_borders = false;
 
 	virtual void gui_input(const Ref<InputEvent> &p_event) override;
-	virtual void _update_theme_item_cache() override;
 	void _notification(int p_what);
 	static void _bind_methods();
 

+ 3 - 6
scene/gui/spin_box.cpp

@@ -32,6 +32,7 @@
 
 #include "core/input/input.h"
 #include "core/math/expression.h"
+#include "scene/theme/theme_db.h"
 
 Size2 SpinBox::get_minimum_size() const {
 	Size2 ms = line_edit->get_combined_minimum_size();
@@ -228,12 +229,6 @@ inline void SpinBox::_adjust_width_for_icon(const Ref<Texture2D> &icon) {
 	}
 }
 
-void SpinBox::_update_theme_item_cache() {
-	Range::_update_theme_item_cache();
-
-	theme_cache.updown_icon = get_theme_icon(SNAME("updown"));
-}
-
 void SpinBox::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_DRAW: {
@@ -379,6 +374,8 @@ void SpinBox::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "suffix"), "set_suffix", "get_suffix");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_arrow_step", PROPERTY_HINT_RANGE, "0,10000,0.0001,or_greater"), "set_custom_arrow_step", "get_custom_arrow_step");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "select_all_on_focus"), "set_select_all_on_focus", "is_select_all_on_focus");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, SpinBox, updown_icon, "updown");
 }
 
 SpinBox::SpinBox() {

+ 0 - 2
scene/gui/spin_box.h

@@ -76,9 +76,7 @@ class SpinBox : public Range {
 protected:
 	virtual void gui_input(const Ref<InputEvent> &p_event) override;
 
-	virtual void _update_theme_item_cache() override;
 	void _notification(int p_what);
-
 	static void _bind_methods();
 
 public:

+ 10 - 13
scene/gui/split_container.cpp

@@ -30,8 +30,9 @@
 
 #include "split_container.h"
 
-#include "label.h"
-#include "margin_container.h"
+#include "scene/gui/label.h"
+#include "scene/gui/margin_container.h"
+#include "scene/theme/theme_db.h"
 
 void SplitContainerDragger::gui_input(const Ref<InputEvent> &p_event) {
 	ERR_FAIL_COND(p_event.is_null());
@@ -292,17 +293,6 @@ void SplitContainer::_validate_property(PropertyInfo &p_property) const {
 	}
 }
 
-void SplitContainer::_update_theme_item_cache() {
-	Container::_update_theme_item_cache();
-
-	theme_cache.separation = get_theme_constant(SNAME("separation"));
-	theme_cache.minimum_grab_thickness = get_theme_constant(SNAME("minimum_grab_thickness"));
-	theme_cache.autohide = get_theme_constant(SNAME("autohide"));
-	theme_cache.grabber_icon = get_theme_icon(SNAME("grabber"));
-	theme_cache.grabber_icon_h = get_theme_icon(SNAME("h_grabber"));
-	theme_cache.grabber_icon_v = get_theme_icon(SNAME("v_grabber"));
-}
-
 void SplitContainer::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_TRANSLATION_CHANGED:
@@ -428,6 +418,13 @@ void SplitContainer::_bind_methods() {
 	BIND_ENUM_CONSTANT(DRAGGER_VISIBLE);
 	BIND_ENUM_CONSTANT(DRAGGER_HIDDEN);
 	BIND_ENUM_CONSTANT(DRAGGER_HIDDEN_COLLAPSED);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, SplitContainer, separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, SplitContainer, minimum_grab_thickness);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, SplitContainer, autohide);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, SplitContainer, grabber_icon, "grabber");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, SplitContainer, grabber_icon_h, "h_grabber");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, SplitContainer, grabber_icon_v, "v_grabber");
 }
 
 SplitContainer::SplitContainer(bool p_vertical) {

+ 0 - 2
scene/gui/split_container.h

@@ -90,8 +90,6 @@ private:
 protected:
 	bool is_fixed = false;
 
-	virtual void _update_theme_item_cache() override;
-
 	void _notification(int p_what);
 	void _validate_property(PropertyInfo &p_property) const;
 	static void _bind_methods();

+ 30 - 33
scene/gui/tab_bar.cpp

@@ -36,6 +36,7 @@
 #include "scene/gui/label.h"
 #include "scene/gui/texture_rect.h"
 #include "scene/main/viewport.h"
+#include "scene/theme/theme_db.h"
 
 Size2 TabBar::get_minimum_size() const {
 	Size2 ms;
@@ -304,39 +305,6 @@ void TabBar::_shape(int p_tab) {
 	tabs.write[p_tab].text_buf->add_string(tabs[p_tab].xl_text, theme_cache.font, theme_cache.font_size, tabs[p_tab].language);
 }
 
-void TabBar::_update_theme_item_cache() {
-	Control::_update_theme_item_cache();
-
-	theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
-	theme_cache.icon_max_width = get_theme_constant(SNAME("icon_max_width"));
-
-	theme_cache.tab_unselected_style = get_theme_stylebox(SNAME("tab_unselected"));
-	theme_cache.tab_hovered_style = get_theme_stylebox(SNAME("tab_hovered"));
-	theme_cache.tab_selected_style = get_theme_stylebox(SNAME("tab_selected"));
-	theme_cache.tab_disabled_style = get_theme_stylebox(SNAME("tab_disabled"));
-
-	theme_cache.increment_icon = get_theme_icon(SNAME("increment"));
-	theme_cache.increment_hl_icon = get_theme_icon(SNAME("increment_highlight"));
-	theme_cache.decrement_icon = get_theme_icon(SNAME("decrement"));
-	theme_cache.decrement_hl_icon = get_theme_icon(SNAME("decrement_highlight"));
-	theme_cache.drop_mark_icon = get_theme_icon(SNAME("drop_mark"));
-	theme_cache.drop_mark_color = get_theme_color(SNAME("drop_mark_color"));
-
-	theme_cache.font = get_theme_font(SNAME("font"));
-	theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
-	theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
-
-	theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
-	theme_cache.font_hovered_color = get_theme_color(SNAME("font_hovered_color"));
-	theme_cache.font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
-	theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
-	theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
-
-	theme_cache.close_icon = get_theme_icon(SNAME("close"));
-	theme_cache.button_pressed_style = get_theme_stylebox(SNAME("button_pressed"));
-	theme_cache.button_hl_style = get_theme_stylebox(SNAME("button_highlight"));
-}
-
 void TabBar::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
@@ -1698,6 +1666,35 @@ void TabBar::_bind_methods() {
 	BIND_ENUM_CONSTANT(CLOSE_BUTTON_SHOW_ACTIVE_ONLY);
 	BIND_ENUM_CONSTANT(CLOSE_BUTTON_SHOW_ALWAYS);
 	BIND_ENUM_CONSTANT(CLOSE_BUTTON_MAX);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabBar, h_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabBar, icon_max_width);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, tab_unselected_style, "tab_unselected");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, tab_hovered_style, "tab_hovered");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, tab_selected_style, "tab_selected");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, tab_disabled_style, "tab_disabled");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabBar, increment_icon, "increment");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabBar, increment_hl_icon, "increment_highlight");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabBar, decrement_icon, "decrement");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabBar, decrement_hl_icon, "decrement_highlight");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabBar, drop_mark_icon, "drop_mark");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, drop_mark_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, font_selected_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, font_hovered_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, font_unselected_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, font_disabled_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, font_outline_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, TabBar, font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, TabBar, font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabBar, outline_size);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabBar, close_icon, "close");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, button_pressed_style, "button_pressed");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, button_hl_style, "button_highlight");
 }
 
 TabBar::TabBar() {

+ 1 - 1
scene/gui/tab_bar.h

@@ -152,7 +152,7 @@ private:
 
 protected:
 	virtual void gui_input(const Ref<InputEvent> &p_event) override;
-	virtual void _update_theme_item_cache() override;
+
 	bool _set(const StringName &p_name, const Variant &p_value);
 	bool _get(const StringName &p_name, Variant &r_ret) const;
 	void _get_property_list(List<PropertyInfo> *p_list) const;

+ 41 - 47
scene/gui/tab_container.cpp

@@ -33,6 +33,7 @@
 #include "scene/gui/box_container.h"
 #include "scene/gui/label.h"
 #include "scene/gui/texture_rect.h"
+#include "scene/theme/theme_db.h"
 
 int TabContainer::_get_top_margin() const {
 	int height = 0;
@@ -133,44 +134,6 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
 	}
 }
 
-void TabContainer::_update_theme_item_cache() {
-	Container::_update_theme_item_cache();
-
-	theme_cache.side_margin = get_theme_constant(SNAME("side_margin"));
-
-	theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
-	theme_cache.tabbar_style = get_theme_stylebox(SNAME("tabbar_background"));
-
-	theme_cache.menu_icon = get_theme_icon(SNAME("menu"));
-	theme_cache.menu_hl_icon = get_theme_icon(SNAME("menu_highlight"));
-
-	// TabBar overrides.
-	theme_cache.icon_separation = get_theme_constant(SNAME("icon_separation"));
-	theme_cache.icon_max_width = get_theme_constant(SNAME("icon_max_width"));
-	theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
-
-	theme_cache.tab_unselected_style = get_theme_stylebox(SNAME("tab_unselected"));
-	theme_cache.tab_hovered_style = get_theme_stylebox(SNAME("tab_hovered"));
-	theme_cache.tab_selected_style = get_theme_stylebox(SNAME("tab_selected"));
-	theme_cache.tab_disabled_style = get_theme_stylebox(SNAME("tab_disabled"));
-
-	theme_cache.increment_icon = get_theme_icon(SNAME("increment"));
-	theme_cache.increment_hl_icon = get_theme_icon(SNAME("increment_highlight"));
-	theme_cache.decrement_icon = get_theme_icon(SNAME("decrement"));
-	theme_cache.decrement_hl_icon = get_theme_icon(SNAME("decrement_highlight"));
-	theme_cache.drop_mark_icon = get_theme_icon(SNAME("drop_mark"));
-	theme_cache.drop_mark_color = get_theme_color(SNAME("drop_mark_color"));
-
-	theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
-	theme_cache.font_hovered_color = get_theme_color(SNAME("font_hovered_color"));
-	theme_cache.font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
-	theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
-	theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
-
-	theme_cache.tab_font = get_theme_font(SNAME("font"));
-	theme_cache.tab_font_size = get_theme_font_size(SNAME("font_size"));
-}
-
 void TabContainer::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_ENTER_TREE: {
@@ -218,7 +181,7 @@ void TabContainer::_notification(int p_what) {
 		case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
 		case NOTIFICATION_THEME_CHANGED: {
 			theme_changing = true;
-			call_deferred(SNAME("_on_theme_changed")); // Wait until all changed theme.
+			callable_mp(this, &TabContainer::_on_theme_changed).call_deferred(); // Wait until all changed theme.
 		} break;
 	}
 }
@@ -511,14 +474,14 @@ void TabContainer::_on_tab_hovered(int p_tab) {
 }
 
 void TabContainer::_on_tab_changed(int p_tab) {
-	call_deferred(SNAME("_repaint"));
+	callable_mp(this, &TabContainer::_repaint).call_deferred();
 
 	emit_signal(SNAME("tab_changed"), p_tab);
 }
 
 void TabContainer::_on_tab_selected(int p_tab) {
 	if (p_tab != get_previous_tab()) {
-		call_deferred(SNAME("_repaint"));
+		callable_mp(this, &TabContainer::_repaint).call_deferred();
 	}
 
 	emit_signal(SNAME("tab_selected"), p_tab);
@@ -561,7 +524,7 @@ void TabContainer::add_child_notify(Node *p_child) {
 
 	// TabBar won't emit the "tab_changed" signal when not inside the tree.
 	if (!is_inside_tree()) {
-		call_deferred("_repaint");
+		callable_mp(this, &TabContainer::_repaint).call_deferred();
 	}
 }
 
@@ -618,7 +581,7 @@ void TabContainer::remove_child_notify(Node *p_child) {
 
 	// TabBar won't emit the "tab_changed" signal when not inside the tree.
 	if (!is_inside_tree()) {
-		call_deferred("_repaint");
+		callable_mp(this, &TabContainer::_repaint).call_deferred();
 	}
 }
 
@@ -804,7 +767,7 @@ void TabContainer::set_tab_hidden(int p_tab, bool p_hidden) {
 	if (!get_clip_tabs()) {
 		update_minimum_size();
 	}
-	call_deferred(SNAME("_repaint"));
+	callable_mp(this, &TabContainer::_repaint).call_deferred();
 }
 
 bool TabContainer::is_tab_hidden(int p_tab) const {
@@ -981,9 +944,6 @@ void TabContainer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_use_hidden_tabs_for_min_size", "enabled"), &TabContainer::set_use_hidden_tabs_for_min_size);
 	ClassDB::bind_method(D_METHOD("get_use_hidden_tabs_for_min_size"), &TabContainer::get_use_hidden_tabs_for_min_size);
 
-	ClassDB::bind_method(D_METHOD("_repaint"), &TabContainer::_repaint);
-	ClassDB::bind_method(D_METHOD("_on_theme_changed"), &TabContainer::_on_theme_changed);
-
 	ADD_SIGNAL(MethodInfo("active_tab_rearranged", PropertyInfo(Variant::INT, "idx_to")));
 	ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab")));
 	ADD_SIGNAL(MethodInfo("tab_clicked", PropertyInfo(Variant::INT, "tab")));
@@ -1000,6 +960,40 @@ void TabContainer::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "tabs_rearrange_group"), "set_tabs_rearrange_group", "get_tabs_rearrange_group");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hidden_tabs_for_min_size"), "set_use_hidden_tabs_for_min_size", "get_use_hidden_tabs_for_min_size");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabContainer, side_margin);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabContainer, panel_style, "panel");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabContainer, tabbar_style, "tabbar_background");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabContainer, menu_icon, "menu");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabContainer, menu_hl_icon, "menu_highlight");
+
+	// TabBar overrides.
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabContainer, icon_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabContainer, icon_max_width);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabContainer, tab_unselected_style, "tab_unselected");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabContainer, tab_hovered_style, "tab_hovered");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabContainer, tab_selected_style, "tab_selected");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabContainer, tab_disabled_style, "tab_disabled");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabContainer, increment_icon, "increment");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabContainer, increment_hl_icon, "increment_highlight");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabContainer, decrement_icon, "decrement");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabContainer, decrement_hl_icon, "decrement_highlight");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabContainer, drop_mark_icon, "drop_mark");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, drop_mark_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, font_selected_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, font_hovered_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, font_unselected_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, font_disabled_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, font_outline_color);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT, TabContainer, tab_font, "font");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT_SIZE, TabContainer, tab_font_size, "font_size");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabContainer, outline_size);
 }
 
 TabContainer::TabContainer() {

+ 0 - 1
scene/gui/tab_container.h

@@ -103,7 +103,6 @@ class TabContainer : public Container {
 
 protected:
 	virtual void gui_input(const Ref<InputEvent> &p_event) override;
-	virtual void _update_theme_item_cache() override;
 
 	void _notification(int p_what);
 	virtual void add_child_notify(Node *p_child) override;

+ 45 - 43
scene/gui/text_edit.cpp

@@ -39,9 +39,9 @@
 #include "core/os/os.h"
 #include "core/string/string_builder.h"
 #include "core/string/translation.h"
-#include "label.h"
-
+#include "scene/gui/label.h"
 #include "scene/main/window.h"
+#include "scene/theme/theme_db.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 ///                            TEXT                                         ///
@@ -2984,51 +2984,11 @@ void TextEdit::_update_theme_item_cache() {
 	Control::_update_theme_item_cache();
 
 	theme_cache.base_scale = get_theme_default_base_scale();
-
-	/* Internal API for CodeEdit */
-	theme_cache.brace_mismatch_color = get_theme_color(SNAME("brace_mismatch_color"), SNAME("CodeEdit"));
-	theme_cache.code_folding_color = get_theme_color(SNAME("code_folding_color"), SNAME("CodeEdit"));
-	theme_cache.folded_eol_icon = get_theme_icon(SNAME("folded_eol_icon"), SNAME("CodeEdit"));
-
-	/* Search */
-	theme_cache.search_result_color = get_theme_color(SNAME("search_result_color"));
-	theme_cache.search_result_border_color = get_theme_color(SNAME("search_result_border_color"));
-
-	/* Caret */
-	theme_cache.caret_width = get_theme_constant(SNAME("caret_width"));
-	theme_cache.caret_color = get_theme_color(SNAME("caret_color"));
-	theme_cache.caret_background_color = get_theme_color(SNAME("caret_background_color"));
-
-	/* Selection */
-	theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
-	theme_cache.selection_color = get_theme_color(SNAME("selection_color"));
 	use_selected_font_color = theme_cache.font_selected_color != Color(0, 0, 0, 0);
 
-	/* Other visuals */
-	theme_cache.style_normal = get_theme_stylebox(SNAME("normal"));
-	theme_cache.style_focus = get_theme_stylebox(SNAME("focus"));
-	theme_cache.style_readonly = get_theme_stylebox(SNAME("read_only"));
-
-	theme_cache.tab_icon = get_theme_icon(SNAME("tab"));
-	theme_cache.space_icon = get_theme_icon(SNAME("space"));
-
-	theme_cache.font = get_theme_font(SNAME("font"));
-	theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
-	theme_cache.font_color = get_theme_color(SNAME("font_color"));
-	theme_cache.font_readonly_color = get_theme_color(SNAME("font_readonly_color"));
-	theme_cache.font_placeholder_color = get_theme_color(SNAME("font_placeholder_color"));
-
-	theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
-	theme_cache.outline_color = get_theme_color(SNAME("font_outline_color"));
-
-	theme_cache.line_spacing = get_theme_constant(SNAME("line_spacing"));
 	if (text.get_line_height() + theme_cache.line_spacing < 1) {
 		WARN_PRINT("Line height is too small, please increase font_size and/or line_spacing");
 	}
-
-	theme_cache.background_color = get_theme_color(SNAME("background_color"));
-	theme_cache.current_line_color = get_theme_color(SNAME("current_line_color"));
-	theme_cache.word_highlighted_color = get_theme_color(SNAME("word_highlighted_color"));
 }
 
 void TextEdit::_update_caches() {
@@ -6037,7 +5997,7 @@ bool TextEdit::is_drawing_spaces() const {
 }
 
 void TextEdit::_bind_methods() {
-	/*Internal. */
+	/* Internal. */
 
 	ClassDB::bind_method(D_METHOD("_text_changed_emit"), &TextEdit::_text_changed_emit);
 
@@ -6496,6 +6456,48 @@ void TextEdit::_bind_methods() {
 	ADD_SIGNAL(MethodInfo("gutter_added"));
 	ADD_SIGNAL(MethodInfo("gutter_removed"));
 
+	/* Theme items */
+	/* Internal API for CodeEdit */
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, TextEdit, brace_mismatch_color, "brace_mismatch_color", "CodeEdit");
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, TextEdit, code_folding_color, "code_folding_color", "CodeEdit");
+	BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_ICON, TextEdit, folded_eol_icon, "folded_eol_icon", "CodeEdit");
+
+	/* Search */
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, search_result_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, search_result_border_color);
+
+	/* Caret */
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TextEdit, caret_width);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, caret_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, caret_background_color);
+
+	/* Selection */
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, font_selected_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, selection_color);
+
+	/* Other visuals */
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TextEdit, style_normal, "normal");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TextEdit, style_focus, "focus");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TextEdit, style_readonly, "read_only");
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TextEdit, tab_icon, "tab");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TextEdit, space_icon, "space");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, TextEdit, font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, TextEdit, font_size);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, font_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, font_readonly_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, font_placeholder_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TextEdit, outline_size);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_COLOR, TextEdit, outline_color, "font_outline_color");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TextEdit, line_spacing);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, background_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, current_line_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, word_highlighted_color);
+
 	/* Settings. */
 	GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "gui/timers/text_edit_idle_detect_sec", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 3);
 	GLOBAL_DEF(PropertyInfo(Variant::INT, "gui/common/text_edit_undo_stack_max_size", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"), 1024);

+ 71 - 70
scene/gui/tree.cpp

@@ -40,6 +40,7 @@
 #include "scene/gui/box_container.h"
 #include "scene/gui/text_edit.h"
 #include "scene/main/window.h"
+#include "scene/theme/theme_db.h"
 
 #include <limits.h>
 
@@ -1700,76 +1701,6 @@ TreeItem::~TreeItem() {
 void Tree::_update_theme_item_cache() {
 	Control::_update_theme_item_cache();
 
-	theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
-	theme_cache.focus_style = get_theme_stylebox(SNAME("focus"));
-
-	theme_cache.font = get_theme_font(SNAME("font"));
-	theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
-	theme_cache.tb_font = get_theme_font(SNAME("title_button_font"));
-	theme_cache.tb_font_size = get_theme_font_size(SNAME("title_button_font_size"));
-
-	theme_cache.selected = get_theme_stylebox(SNAME("selected"));
-	theme_cache.selected_focus = get_theme_stylebox(SNAME("selected_focus"));
-	theme_cache.cursor = get_theme_stylebox(SNAME("cursor"));
-	theme_cache.cursor_unfocus = get_theme_stylebox(SNAME("cursor_unfocused"));
-	theme_cache.button_pressed = get_theme_stylebox(SNAME("button_pressed"));
-
-	theme_cache.checked = get_theme_icon(SNAME("checked"));
-	theme_cache.unchecked = get_theme_icon(SNAME("unchecked"));
-	theme_cache.indeterminate = get_theme_icon(SNAME("indeterminate"));
-	theme_cache.arrow = get_theme_icon(SNAME("arrow"));
-	theme_cache.arrow_collapsed = get_theme_icon(SNAME("arrow_collapsed"));
-	theme_cache.arrow_collapsed_mirrored = get_theme_icon(SNAME("arrow_collapsed_mirrored"));
-	theme_cache.select_arrow = get_theme_icon(SNAME("select_arrow"));
-	theme_cache.updown = get_theme_icon(SNAME("updown"));
-
-	theme_cache.custom_button = get_theme_stylebox(SNAME("custom_button"));
-	theme_cache.custom_button_hover = get_theme_stylebox(SNAME("custom_button_hover"));
-	theme_cache.custom_button_pressed = get_theme_stylebox(SNAME("custom_button_pressed"));
-	theme_cache.custom_button_font_highlight = get_theme_color(SNAME("custom_button_font_highlight"));
-
-	theme_cache.font_color = get_theme_color(SNAME("font_color"));
-	theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
-	theme_cache.drop_position_color = get_theme_color(SNAME("drop_position_color"));
-	theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
-	theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
-	theme_cache.inner_item_margin_bottom = get_theme_constant(SNAME("inner_item_margin_bottom"));
-	theme_cache.inner_item_margin_left = get_theme_constant(SNAME("inner_item_margin_left"));
-	theme_cache.inner_item_margin_right = get_theme_constant(SNAME("inner_item_margin_right"));
-	theme_cache.inner_item_margin_top = get_theme_constant(SNAME("inner_item_margin_top"));
-	theme_cache.item_margin = get_theme_constant(SNAME("item_margin"));
-	theme_cache.button_margin = get_theme_constant(SNAME("button_margin"));
-	theme_cache.icon_max_width = get_theme_constant(SNAME("icon_max_width"));
-
-	theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
-	theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
-
-	theme_cache.draw_guides = get_theme_constant(SNAME("draw_guides"));
-	theme_cache.guide_color = get_theme_color(SNAME("guide_color"));
-	theme_cache.draw_relationship_lines = get_theme_constant(SNAME("draw_relationship_lines"));
-	theme_cache.relationship_line_width = get_theme_constant(SNAME("relationship_line_width"));
-	theme_cache.parent_hl_line_width = get_theme_constant(SNAME("parent_hl_line_width"));
-	theme_cache.children_hl_line_width = get_theme_constant(SNAME("children_hl_line_width"));
-	theme_cache.parent_hl_line_margin = get_theme_constant(SNAME("parent_hl_line_margin"));
-	theme_cache.relationship_line_color = get_theme_color(SNAME("relationship_line_color"));
-	theme_cache.parent_hl_line_color = get_theme_color(SNAME("parent_hl_line_color"));
-	theme_cache.children_hl_line_color = get_theme_color(SNAME("children_hl_line_color"));
-
-	theme_cache.scroll_border = get_theme_constant(SNAME("scroll_border"));
-	theme_cache.scroll_speed = get_theme_constant(SNAME("scroll_speed"));
-
-	theme_cache.scrollbar_margin_top = get_theme_constant(SNAME("scrollbar_margin_top"));
-	theme_cache.scrollbar_margin_right = get_theme_constant(SNAME("scrollbar_margin_right"));
-	theme_cache.scrollbar_margin_bottom = get_theme_constant(SNAME("scrollbar_margin_bottom"));
-	theme_cache.scrollbar_margin_left = get_theme_constant(SNAME("scrollbar_margin_left"));
-	theme_cache.scrollbar_h_separation = get_theme_constant(SNAME("scrollbar_h_separation"));
-	theme_cache.scrollbar_v_separation = get_theme_constant(SNAME("scrollbar_v_separation"));
-
-	theme_cache.title_button = get_theme_stylebox(SNAME("title_button_normal"));
-	theme_cache.title_button_pressed = get_theme_stylebox(SNAME("title_button_pressed"));
-	theme_cache.title_button_hover = get_theme_stylebox(SNAME("title_button_hover"));
-	theme_cache.title_button_color = get_theme_color(SNAME("title_button_color"));
-
 	theme_cache.base_scale = get_theme_default_base_scale();
 }
 
@@ -5577,6 +5508,76 @@ void Tree::_bind_methods() {
 	BIND_ENUM_CONSTANT(DROP_MODE_DISABLED);
 	BIND_ENUM_CONSTANT(DROP_MODE_ON_ITEM);
 	BIND_ENUM_CONSTANT(DROP_MODE_INBETWEEN);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Tree, panel_style, "panel");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Tree, focus_style, "focus");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, Tree, font);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, Tree, font_size);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT, Tree, tb_font, "title_button_font");
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT_SIZE, Tree, tb_font_size, "title_button_font_size");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, selected);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, selected_focus);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, cursor);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Tree, cursor_unfocus, "cursor_unfocused");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, button_pressed);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, checked);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, unchecked);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, indeterminate);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, arrow);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, arrow_collapsed);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, arrow_collapsed_mirrored);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, select_arrow);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, updown);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, custom_button);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, custom_button_hover);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, custom_button_pressed);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, custom_button_font_highlight);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, font_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, font_selected_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, drop_position_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, h_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, v_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, inner_item_margin_bottom);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, inner_item_margin_left);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, inner_item_margin_right);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, inner_item_margin_top);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, item_margin);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, button_margin);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, icon_max_width);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, font_outline_color);
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, Tree, font_outline_size, "outline_size");
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, draw_guides);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, guide_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, draw_relationship_lines);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, relationship_line_width);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, parent_hl_line_width);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, children_hl_line_width);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, parent_hl_line_margin);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, relationship_line_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, parent_hl_line_color);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, children_hl_line_color);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, scroll_border);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, scroll_speed);
+
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, scrollbar_margin_top);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, scrollbar_margin_right);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, scrollbar_margin_bottom);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, scrollbar_margin_left);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, scrollbar_h_separation);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, scrollbar_v_separation);
+
+	BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Tree, title_button, "title_button_normal");
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, title_button_pressed);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, title_button_hover);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, title_button_color);
 }
 
 Tree::Tree() {

+ 1 - 2
scene/gui/tree.h

@@ -504,8 +504,6 @@ private:
 
 	void popup_select(int p_option);
 
-	void _notification(int p_what);
-
 	void item_edited(int p_column, TreeItem *p_item, MouseButton p_custom_mouse_index = MouseButton::NONE);
 	void item_changed(int p_column, TreeItem *p_item);
 	void item_selected(int p_column, TreeItem *p_item);
@@ -676,6 +674,7 @@ private:
 protected:
 	virtual void _update_theme_item_cache() override;
 
+	void _notification(int p_what);
 	static void _bind_methods();
 
 public:

+ 23 - 0
scene/main/window.cpp

@@ -1965,6 +1965,8 @@ void Window::_update_theme_item_cache() {
 	} else {
 		child_controls_changed();
 	}
+
+	ThemeDB::get_singleton()->update_class_instance_items(this);
 }
 
 void Window::_update_embedded_window() {
@@ -2138,6 +2140,27 @@ int Window::get_theme_constant(const StringName &p_name, const StringName &p_the
 	return constant;
 }
 
+Variant Window::get_theme_item(Theme::DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const {
+	switch (p_data_type) {
+		case Theme::DATA_TYPE_COLOR:
+			return get_theme_color(p_name, p_theme_type);
+		case Theme::DATA_TYPE_CONSTANT:
+			return get_theme_constant(p_name, p_theme_type);
+		case Theme::DATA_TYPE_FONT:
+			return get_theme_font(p_name, p_theme_type);
+		case Theme::DATA_TYPE_FONT_SIZE:
+			return get_theme_font_size(p_name, p_theme_type);
+		case Theme::DATA_TYPE_ICON:
+			return get_theme_icon(p_name, p_theme_type);
+		case Theme::DATA_TYPE_STYLEBOX:
+			return get_theme_stylebox(p_name, p_theme_type);
+		case Theme::DATA_TYPE_MAX:
+			break; // Can't happen, but silences warning.
+	}
+
+	return Variant();
+}
+
 #ifdef TOOLS_ENABLED
 Ref<Texture2D> Window::get_editor_theme_icon(const StringName &p_name) const {
 	return get_theme_icon(p_name, SNAME("EditorIcons"));

+ 1 - 0
scene/main/window.h

@@ -397,6 +397,7 @@ public:
 	int get_theme_font_size(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
 	Color get_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
 	int get_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const;
+	Variant get_theme_item(Theme::DataType p_data_type, const StringName &p_name, const StringName &p_theme_type = StringName()) const;
 #ifdef TOOLS_ENABLED
 	Ref<Texture2D> get_editor_theme_icon(const StringName &p_name) const;
 #endif

+ 44 - 0
scene/theme/theme_db.cpp

@@ -326,6 +326,50 @@ ThemeContext *ThemeDB::get_nearest_theme_context(Node *p_for_node) const {
 	return nullptr;
 }
 
+// Theme item binding.
+
+void ThemeDB::bind_class_item(const StringName &p_class_name, const StringName &p_prop_name, const StringName &p_item_name, ThemeItemSetter p_setter) {
+	ERR_FAIL_COND_MSG(theme_item_binds[p_class_name].has(p_prop_name), vformat("Failed to bind theme item '%s' in class '%s': already bound", p_prop_name, p_class_name));
+
+	ThemeItemBind bind;
+	bind.class_name = p_class_name;
+	bind.item_name = p_item_name;
+	bind.setter = p_setter;
+
+	theme_item_binds[p_class_name][p_prop_name] = bind;
+}
+
+void ThemeDB::bind_class_external_item(const StringName &p_class_name, const StringName &p_prop_name, const StringName &p_item_name, const StringName &p_type_name, ThemeItemSetter p_setter) {
+	ERR_FAIL_COND_MSG(theme_item_binds[p_class_name].has(p_prop_name), vformat("Failed to bind theme item '%s' in class '%s': already bound", p_prop_name, p_class_name));
+
+	ThemeItemBind bind;
+	bind.class_name = p_class_name;
+	bind.item_name = p_item_name;
+	bind.type_name = p_type_name;
+	bind.external = true;
+	bind.setter = p_setter;
+
+	theme_item_binds[p_class_name][p_prop_name] = bind;
+}
+
+void ThemeDB::update_class_instance_items(Node *p_instance) {
+	ERR_FAIL_COND(!p_instance);
+
+	// Use the hierarchy to initialize all inherited theme caches. Setters carry the necessary
+	// context and will set the values appropriately.
+	StringName class_name = p_instance->get_class();
+	while (class_name != StringName()) {
+		HashMap<StringName, HashMap<StringName, ThemeItemBind>>::Iterator E = theme_item_binds.find(class_name);
+		if (E) {
+			for (const KeyValue<StringName, ThemeItemBind> &F : E->value) {
+				F.value.setter(p_instance);
+			}
+		}
+
+		class_name = ClassDB::get_parent_class_nocheck(class_name);
+	}
+}
+
 // Object methods.
 
 void ThemeDB::_bind_methods() {

+ 47 - 0
scene/theme/theme_db.h

@@ -34,6 +34,8 @@
 #include "core/object/class_db.h"
 #include "core/object/ref_counted.h"
 
+#include <functional>
+
 class Font;
 class Node;
 class StyleBox;
@@ -41,6 +43,30 @@ class Texture2D;
 class Theme;
 class ThemeContext;
 
+// Macros for binding theme items of this class. This information is used for the documentation, theme
+// overrides, etc. This is also the basis for theme cache.
+
+#define BIND_THEME_ITEM(m_data_type, m_class, m_prop)                                                      \
+	ThemeDB::get_singleton()->bind_class_item(get_class_static(), #m_prop, #m_prop, [](Node *p_instance) { \
+		m_class *p_cast = Object::cast_to<m_class>(p_instance);                                            \
+		p_cast->theme_cache.m_prop = p_cast->get_theme_item(m_data_type, _scs_create(#m_prop));            \
+	})
+
+#define BIND_THEME_ITEM_CUSTOM(m_data_type, m_class, m_prop, m_item_name)                                      \
+	ThemeDB::get_singleton()->bind_class_item(get_class_static(), #m_prop, m_item_name, [](Node *p_instance) { \
+		m_class *p_cast = Object::cast_to<m_class>(p_instance);                                                \
+		p_cast->theme_cache.m_prop = p_cast->get_theme_item(m_data_type, _scs_create(m_item_name));            \
+	})
+
+// Macro for binding theme items used by this class, but defined/binded by other classes. This is primarily used for
+// the theme cache. Can also be used to list such items in documentation.
+
+#define BIND_THEME_ITEM_EXT(m_data_type, m_class, m_prop, m_item_name, m_type_name)                                                  \
+	ThemeDB::get_singleton()->bind_class_external_item(get_class_static(), #m_prop, m_item_name, m_type_name, [](Node *p_instance) { \
+		m_class *p_cast = Object::cast_to<m_class>(p_instance);                                                                      \
+		p_cast->theme_cache.m_prop = p_cast->get_theme_item(m_data_type, _scs_create(m_item_name), _scs_create(m_type_name));        \
+	})
+
 class ThemeDB : public Object {
 	GDCLASS(ThemeDB, Object);
 
@@ -68,6 +94,21 @@ class ThemeDB : public Object {
 	void _init_default_theme_context();
 	void _finalize_theme_contexts();
 
+	// Binding of theme items to Node classes.
+
+	typedef std::function<void(Node *)> ThemeItemSetter;
+
+	struct ThemeItemBind {
+		StringName class_name;
+		StringName item_name;
+		StringName type_name;
+		bool external = false;
+
+		ThemeItemSetter setter;
+	};
+
+	HashMap<StringName, HashMap<StringName, ThemeItemBind>> theme_item_binds;
+
 protected:
 	static void _bind_methods();
 
@@ -112,6 +153,12 @@ public:
 	ThemeContext *get_default_theme_context() const;
 	ThemeContext *get_nearest_theme_context(Node *p_for_node) const;
 
+	// Theme item binding.
+
+	void bind_class_item(const StringName &p_class_name, const StringName &p_prop_name, const StringName &p_item_name, ThemeItemSetter p_setter);
+	void bind_class_external_item(const StringName &p_class_name, const StringName &p_prop_name, const StringName &p_item_name, const StringName &p_type_name, ThemeItemSetter p_setter);
+	void update_class_instance_items(Node *p_instance);
+
 	// Memory management, reference, and initialization.
 
 	static ThemeDB *get_singleton();