2
0
Эх сурвалжийг харах

Add theme cache to the inspector

kobewi 5 сар өмнө
parent
commit
d3c34c4f38

+ 151 - 78
editor/editor_inspector.cpp

@@ -1580,6 +1580,7 @@ void EditorInspectorCategory::_notification(int p_what) {
 		} break;
 
 		case NOTIFICATION_THEME_CHANGED: {
+			EditorInspector::initialize_category_theme(theme_cache, this);
 			menu_icon_dirty = true;
 			_update_icon();
 		} break;
@@ -1592,15 +1593,15 @@ void EditorInspectorCategory::_notification(int p_what) {
 		} break;
 
 		case NOTIFICATION_DRAW: {
-			Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
+			const Ref<StyleBox> &sb = theme_cache.background;
 
 			draw_style_box(sb, Rect2(Vector2(), get_size()));
 
-			Ref<Font> font = get_theme_font(SNAME("bold"), EditorStringName(EditorFonts));
-			int font_size = get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts));
+			const Ref<Font> &font = theme_cache.bold_font;
+			int font_size = theme_cache.bold_font_size;
 
-			int hs = get_theme_constant(SNAME("h_separation"), SNAME("Tree"));
-			int icon_size = get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor));
+			int hs = theme_cache.horizontal_separation;
+			int icon_size = theme_cache.class_icon_size;
 
 			int w = font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
 			if (icon.is_valid()) {
@@ -1624,13 +1625,12 @@ void EditorInspectorCategory::_notification(int p_what) {
 				w -= hs + icon_size;
 			}
 
-			Color color = get_theme_color(SceneStringName(font_color), SNAME("Tree"));
 			if (is_layout_rtl()) {
 				ofs = get_size().width - ofs - w;
 			}
 			float text_pos_y = font->get_ascent(font_size) + (get_size().height - font->get_height(font_size)) / 2 + v_margin_offset;
 			Point2 text_pos = Point2(ofs, text_pos_y).round();
-			draw_string(font, text_pos, label, HORIZONTAL_ALIGNMENT_LEFT, w, font_size, color);
+			draw_string(font, text_pos, label, HORIZONTAL_ALIGNMENT_LEFT, w, font_size, theme_cache.font_color);
 		} break;
 	}
 }
@@ -1674,19 +1674,18 @@ void EditorInspectorCategory::set_doc_class_name(const String &p_name) {
 }
 
 Size2 EditorInspectorCategory::get_minimum_size() const {
-	Ref<Font> font = get_theme_font(SNAME("bold"), EditorStringName(EditorFonts));
-	int font_size = get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts));
-
 	Size2 ms;
-	ms.height = font->get_height(font_size);
+	if (theme_cache.bold_font.is_valid()) {
+		ms.height = theme_cache.bold_font->get_height(theme_cache.bold_font_size);
+	}
 	if (icon.is_valid()) {
-		int icon_size = get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor));
-		ms.height = MAX(icon_size, ms.height);
+		ms.height = MAX(theme_cache.class_icon_size, ms.height);
 	}
-	ms.height += get_theme_constant(SNAME("v_separation"), SNAME("Tree"));
+	ms.height += theme_cache.vertical_separation;
 
-	const Ref<StyleBox> &bg_style = get_theme_stylebox(SNAME("bg"));
-	ms.height += bg_style->get_content_margin(SIDE_TOP) + bg_style->get_content_margin(SIDE_BOTTOM);
+	if (theme_cache.background.is_valid()) {
+		ms.height += theme_cache.background->get_content_margin(SIDE_TOP) + theme_cache.background->get_content_margin(SIDE_BOTTOM);
+	}
 
 	return ms;
 }
@@ -1725,9 +1724,9 @@ void EditorInspectorCategory::_popup_context_menu(const Point2i &p_position) {
 
 	if (menu_icon_dirty) {
 		if (is_favorite) {
-			menu->set_item_icon(menu->get_item_index(MENU_UNFAVORITE_ALL), get_editor_theme_icon(SNAME("Unfavorite")));
+			menu->set_item_icon(menu->get_item_index(MENU_UNFAVORITE_ALL), theme_cache.icon_unfavorite);
 		} else {
-			menu->set_item_icon(menu->get_item_index(MENU_OPEN_DOCS), get_editor_theme_icon(SNAME("Help")));
+			menu->set_item_icon(menu->get_item_index(MENU_OPEN_DOCS), theme_cache.icon_help);
 		}
 		menu_icon_dirty = false;
 	}
@@ -1739,7 +1738,7 @@ void EditorInspectorCategory::_popup_context_menu(const Point2i &p_position) {
 
 void EditorInspectorCategory::_update_icon() {
 	if (is_favorite) {
-		icon = get_editor_theme_icon(SNAME("Favorites"));
+		icon = theme_cache.icon_favorites;
 		return;
 	}
 
@@ -1785,12 +1784,12 @@ Ref<Texture2D> EditorInspectorSection::_get_arrow() {
 	Ref<Texture2D> arrow;
 	if (foldable) {
 		if (object->editor_is_section_unfolded(section)) {
-			arrow = get_theme_icon(SNAME("arrow"), SNAME("Tree"));
+			arrow = theme_cache.arrow;
 		} else {
 			if (is_layout_rtl()) {
-				arrow = get_theme_icon(SNAME("arrow_collapsed_mirrored"), SNAME("Tree"));
+				arrow = theme_cache.arrow_collapsed_mirrored;
 			} else {
-				arrow = get_theme_icon(SNAME("arrow_collapsed"), SNAME("Tree"));
+				arrow = theme_cache.arrow_collapsed;
 			}
 		}
 	}
@@ -1802,9 +1801,9 @@ Ref<Texture2D> EditorInspectorSection::_get_checkbox() {
 
 	if (checkable) {
 		if (checked) {
-			checkbox = get_editor_theme_icon(SNAME("GuiChecked"));
+			checkbox = theme_cache.icon_gui_checked;
 		} else {
-			checkbox = get_editor_theme_icon(SNAME("GuiUnchecked"));
+			checkbox = theme_cache.icon_gui_unchecked;
 		}
 	}
 
@@ -1812,15 +1811,12 @@ Ref<Texture2D> EditorInspectorSection::_get_checkbox() {
 }
 
 int EditorInspectorSection::_get_header_height() {
-	Ref<Font> font = get_theme_font(SNAME("bold"), EditorStringName(EditorFonts));
-	int font_size = get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts));
-
-	int header_height = font->get_height(font_size);
+	int header_height = theme_cache.bold_font->get_height(theme_cache.bold_font_size);
 	Ref<Texture2D> arrow = _get_arrow();
 	if (arrow.is_valid()) {
 		header_height = MAX(header_height, arrow->get_height());
 	}
-	header_height += get_theme_constant(SNAME("v_separation"), SNAME("Tree"));
+	header_height += theme_cache.vertical_separation;
 
 	return header_height;
 }
@@ -1840,11 +1836,11 @@ void EditorInspectorSection::_notification(int p_what) {
 		} break;
 
 		case NOTIFICATION_THEME_CHANGED: {
-			update_minimum_size();
-			bg_color = get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor));
+			EditorInspector::initialize_section_theme(theme_cache, this);
+
+			bg_color = theme_cache.prop_subsection;
 			bg_color.a /= level;
-			int separation = get_theme_constant(SNAME("v_separation"), SNAME("EditorInspector"));
-			vbox->add_theme_constant_override(SNAME("separation"), separation);
+			vbox->add_theme_constant_override(SNAME("separation"), theme_cache.vertical_separation);
 		} break;
 
 		case NOTIFICATION_SORT_CHILDREN: {
@@ -1852,14 +1848,12 @@ void EditorInspectorSection::_notification(int p_what) {
 				return;
 			}
 
-			int inspector_margin = get_theme_constant(SNAME("inspector_margin"), EditorStringName(Editor));
-			int section_indent_size = get_theme_constant(SNAME("indent_size"), SNAME("EditorInspectorSection"));
-			if (indent_depth > 0 && section_indent_size > 0) {
-				inspector_margin += indent_depth * section_indent_size;
+			int inspector_margin = theme_cache.inspector_margin;
+			if (indent_depth > 0 && theme_cache.indent_size > 0) {
+				inspector_margin += indent_depth * theme_cache.indent_size;
 			}
-			Ref<StyleBoxFlat> section_indent_style = get_theme_stylebox(SNAME("indent_box"), SNAME("EditorInspectorSection"));
-			if (indent_depth > 0 && section_indent_style.is_valid()) {
-				inspector_margin += section_indent_style->get_margin(SIDE_LEFT) + section_indent_style->get_margin(SIDE_RIGHT);
+			if (indent_depth > 0 && theme_cache.indent_box.is_valid()) {
+				inspector_margin += theme_cache.indent_box->get_margin(SIDE_LEFT) + theme_cache.indent_box->get_margin(SIDE_RIGHT);
 			}
 
 			Size2 size = get_size() - Vector2(inspector_margin, 0);
@@ -1876,11 +1870,11 @@ void EditorInspectorSection::_notification(int p_what) {
 
 		case NOTIFICATION_DRAW: {
 			int section_indent = 0;
-			int section_indent_size = get_theme_constant(SNAME("indent_size"), SNAME("EditorInspectorSection"));
+			int section_indent_size = theme_cache.indent_size;
 			if (indent_depth > 0 && section_indent_size > 0) {
 				section_indent = indent_depth * section_indent_size;
 			}
-			Ref<StyleBoxFlat> section_indent_style = get_theme_stylebox(SNAME("indent_box"), SNAME("EditorInspectorSection"));
+			Ref<StyleBoxFlat> section_indent_style = theme_cache.indent_box;
 			if (indent_depth > 0 && section_indent_style.is_valid()) {
 				section_indent += section_indent_style->get_margin(SIDE_LEFT) + section_indent_style->get_margin(SIDE_RIGHT);
 			}
@@ -1907,7 +1901,6 @@ void EditorInspectorSection::_notification(int p_what) {
 			// Draw header title, folding arrow and count of revertable properties.
 			{
 				int outer_margin = Math::round(2 * EDSCALE);
-				int separation = get_theme_constant(SNAME("h_separation"), SNAME("EditorInspectorSection"));
 
 				int margin_start = section_indent + outer_margin;
 				int margin_end = outer_margin;
@@ -1925,15 +1918,15 @@ void EditorInspectorSection::_notification(int p_what) {
 					if (can_click_unfold) {
 						draw_texture(arrow, arrow_position);
 					}
-					margin_start += arrow->get_width() + separation;
+					margin_start += arrow->get_width() + theme_cache.horizontal_separation;
 				}
 
-				Ref<Font> font = get_theme_font(SNAME("bold"), EditorStringName(EditorFonts));
-				int font_size = get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts));
-				Color font_color = get_theme_color(SceneStringName(font_color), EditorStringName(Editor));
+				Ref<Font> font = theme_cache.bold_font;
+				int font_size = theme_cache.bold_font_size;
+				Color font_color = theme_cache.font_color;
 
-				Ref<Font> light_font = get_theme_font(SNAME("main"), EditorStringName(EditorFonts));
-				int light_font_size = get_theme_font_size(SNAME("main_size"), EditorStringName(EditorFonts));
+				Ref<Font> light_font = theme_cache.light_font;
+				int light_font_size = theme_cache.light_font_size;
 
 				// - Checkbox.
 				Ref<Texture2D> checkbox = _get_checkbox();
@@ -1960,9 +1953,9 @@ void EditorInspectorSection::_notification(int p_what) {
 						checkbox_color.r *= 1.2;
 						checkbox_color.g *= 1.2;
 						checkbox_color.b *= 1.2;
-						check_font_color = checked ? get_theme_color(SNAME("font_hover_pressed_color"), EditorStringName(Editor)) : get_theme_color(SNAME("font_hover_color"), EditorStringName(Editor));
+						check_font_color = checked ? theme_cache.font_hover_pressed_color : theme_cache.font_hover_color;
 					} else if (checked) {
-						check_font_color = get_theme_color(SNAME("font_pressed_color"), EditorStringName(Editor));
+						check_font_color = theme_cache.font_pressed_color;
 					}
 
 					draw_texture(checkbox, checkbox_position, checkbox_color);
@@ -1977,10 +1970,9 @@ void EditorInspectorSection::_notification(int p_what) {
 				int num_revertable_width = 0;
 
 				bool folded = (foldable || hide_feature) && !object->editor_is_section_unfolded(section);
-				if (folded && revertable_properties.size()) {
-					int label_width = font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, available, font_size, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS).x;
 
-					Color light_font_color = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor));
+				if (folded && revertable_properties.size()) {
+					int label_width = theme_cache.bold_font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, available, theme_cache.bold_font_size, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS).x;
 
 					// Can we fit the long version of the revertable count text?
 					num_revertable_str = vformat(TTRN("(%d change)", "(%d changes)", revertable_properties.size()), revertable_properties.size());
@@ -1996,7 +1988,7 @@ void EditorInspectorSection::_notification(int p_what) {
 					if (!rtl) {
 						text_offset.x = get_size().width - (text_offset.x + num_revertable_width);
 					}
-					draw_string(light_font, text_offset, num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, light_font_color, TextServer::JUSTIFICATION_NONE);
+					draw_string(light_font, text_offset, num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, theme_cache.font_disabled_color, TextServer::JUSTIFICATION_NONE);
 					margin_end += num_revertable_width + outer_margin;
 					available -= num_revertable_width + outer_margin;
 				}
@@ -2008,10 +2000,10 @@ void EditorInspectorSection::_notification(int p_what) {
 					text_offset.x = margin_end;
 				}
 				if (object->has_method("_get_property_warning") && !String(object->call("_get_property_warning", related_enable_property)).is_empty()) {
-					font_color = get_theme_color(SNAME("warning_color"), EditorStringName(Editor));
+					font_color = theme_cache.warning_color;
 				}
 				HorizontalAlignment text_align = rtl ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT;
-				draw_string(font, text_offset, label, text_align, available, font_size, font_color, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
+				draw_string(font, text_offset, label, text_align, available, font_size, theme_cache.font_color, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
 			}
 
 			// Draw section indentation.
@@ -2061,18 +2053,16 @@ Size2 EditorInspectorSection::get_minimum_size() const {
 		ms = ms.max(minsize);
 	}
 
-	Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Tree"));
-	int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Tree"));
-	ms.height += font->get_height(font_size) + get_theme_constant(SNAME("v_separation"), SNAME("Tree"));
-	ms.width += get_theme_constant(SNAME("inspector_margin"), EditorStringName(Editor));
+	if (theme_cache.font.is_valid()) {
+		ms.height += theme_cache.font->get_height(theme_cache.font_size) + theme_cache.vertical_separation;
+		ms.width += theme_cache.inspector_margin;
+	}
 
-	int section_indent_size = get_theme_constant(SNAME("indent_size"), SNAME("EditorInspectorSection"));
-	if (indent_depth > 0 && section_indent_size > 0) {
-		ms.width += indent_depth * section_indent_size;
+	if (indent_depth > 0 && theme_cache.indent_size > 0) {
+		ms.width += indent_depth * theme_cache.indent_size;
 	}
-	Ref<StyleBoxFlat> section_indent_style = get_theme_stylebox(SNAME("indent_box"), SNAME("EditorInspectorSection"));
-	if (indent_depth > 0 && section_indent_style.is_valid()) {
-		ms.width += section_indent_style->get_margin(SIDE_LEFT) + section_indent_style->get_margin(SIDE_RIGHT);
+	if (indent_depth > 0 && theme_cache.indent_box.is_valid()) {
+		ms.width += theme_cache.indent_box->get_margin(SIDE_LEFT) + theme_cache.indent_box->get_margin(SIDE_RIGHT);
 	}
 
 	return ms;
@@ -2101,7 +2091,7 @@ Control *EditorInspectorSection::make_custom_tooltip(const String &p_text) const
 	if (object->has_method("_get_property_warning")) {
 		const String custom_warning = object->call("_get_property_warning", related_enable_property);
 		if (!custom_warning.is_empty()) {
-			prologue = "[b][color=" + get_theme_color(SNAME("warning_color"), EditorStringName(Editor)).to_html(false) + "]" + custom_warning + "[/color][/b]";
+			prologue = "[b][color=" + theme_cache.warning_color.to_html(false) + "]" + custom_warning + "[/color][/b]";
 		}
 	}
 
@@ -3340,6 +3330,65 @@ EditorProperty *EditorInspector::instantiate_property_editor(Object *p_object, c
 	return nullptr;
 }
 
+void EditorInspector::initialize_section_theme(EditorInspectorSection::ThemeCache &p_cache, Control *p_control) {
+	EditorInspector *parent_inspector = _get_control_parent_inspector(p_control);
+	if (parent_inspector && parent_inspector != p_control) {
+		p_cache = parent_inspector->section_theme_cache;
+		return;
+	}
+
+	p_cache.horizontal_separation = p_control->get_theme_constant(SNAME("h_separation"), SNAME("EditorInspectorSection"));
+	p_cache.vertical_separation = p_control->get_theme_constant(SNAME("v_separation"), SNAME("Tree"));
+	p_cache.inspector_margin = p_control->get_theme_constant(SNAME("inspector_margin"), EditorStringName(Editor));
+	p_cache.indent_size = p_control->get_theme_constant(SNAME("indent_size"), SNAME("EditorInspectorSection"));
+
+	p_cache.warning_color = p_control->get_theme_color(SNAME("warning_color"), EditorStringName(Editor));
+	p_cache.prop_subsection = p_control->get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor));
+	p_cache.font_color = p_control->get_theme_color(SceneStringName(font_color), EditorStringName(Editor));
+	p_cache.font_disabled_color = p_control->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor));
+	p_cache.font_hover_color = p_control->get_theme_color(SNAME("font_hover_color"), EditorStringName(Editor));
+	p_cache.font_pressed_color = p_control->get_theme_color(SNAME("font_pressed_color"), EditorStringName(Editor));
+	p_cache.font_hover_pressed_color = p_control->get_theme_color(SNAME("font_hover_pressed_color"), EditorStringName(Editor));
+
+	p_cache.font = p_control->get_theme_font(SceneStringName(font), SNAME("Tree"));
+	p_cache.font_size = p_control->get_theme_font_size(SceneStringName(font_size), SNAME("Tree"));
+	p_cache.bold_font = p_control->get_theme_font(SNAME("bold"), EditorStringName(EditorFonts));
+	p_cache.bold_font_size = p_control->get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts));
+	p_cache.light_font = p_control->get_theme_font(SNAME("main"), EditorStringName(EditorFonts));
+	p_cache.light_font_size = p_control->get_theme_font_size(SNAME("main_size"), EditorStringName(EditorFonts));
+
+	p_cache.arrow = p_control->get_theme_icon(SNAME("arrow"), SNAME("Tree"));
+	p_cache.arrow_collapsed = p_control->get_theme_icon(SNAME("arrow_collapsed"), SNAME("Tree"));
+	p_cache.arrow_collapsed_mirrored = p_control->get_theme_icon(SNAME("arrow_collapsed_mirrored"), SNAME("Tree"));
+	p_cache.icon_gui_checked = p_control->get_editor_theme_icon(SNAME("GuiChecked"));
+	p_cache.icon_gui_unchecked = p_control->get_editor_theme_icon(SNAME("GuiUnchecked"));
+
+	p_cache.indent_box = p_control->get_theme_stylebox(SNAME("indent_box"), SNAME("EditorInspectorSection"));
+}
+
+void EditorInspector::initialize_category_theme(EditorInspectorCategory::ThemeCache &p_cache, Control *p_control) {
+	EditorInspector *parent_inspector = _get_control_parent_inspector(p_control);
+	if (parent_inspector && parent_inspector != p_control) {
+		p_cache = parent_inspector->category_theme_cache;
+		return;
+	}
+
+	p_cache.horizontal_separation = p_control->get_theme_constant(SNAME("h_separation"), SNAME("Tree"));
+	p_cache.vertical_separation = p_control->get_theme_constant(SNAME("v_separation"), SNAME("Tree"));
+	p_cache.class_icon_size = p_control->get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor));
+
+	p_cache.font_color = p_control->get_theme_color(SceneStringName(font_color), SNAME("Tree"));
+
+	p_cache.bold_font = p_control->get_theme_font(SNAME("bold"), EditorStringName(EditorFonts));
+	p_cache.bold_font_size = p_control->get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts));
+
+	p_cache.icon_favorites = p_control->get_editor_theme_icon(SNAME("Favorites"));
+	p_cache.icon_unfavorite = p_control->get_editor_theme_icon(SNAME("Unfavorite"));
+	p_cache.icon_help = p_control->get_editor_theme_icon(SNAME("Help"));
+
+	p_cache.background = p_control->get_theme_stylebox(SNAME("bg"), SNAME("EditorInspectorCategory"));
+}
+
 void EditorInspector::add_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin) {
 	ERR_FAIL_COND(inspector_plugin_count == MAX_PLUGINS);
 
@@ -3581,7 +3630,7 @@ void EditorInspector::update_tree() {
 	HashMap<String, HashMap<String, LocalVector<EditorProperty *>>> favorites_to_add;
 	HashMap<String, EditorInspectorSection *> togglable_editor_inspector_sections;
 
-	Color sscolor = get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor));
+	const Color sscolor = theme_cache.prop_subsection;
 	bool sub_inspectors_enabled = EDITOR_GET("interface/inspector/open_resources_in_current_inspector");
 
 	if (!valid_plugins.is_empty()) {
@@ -3884,8 +3933,7 @@ void EditorInspector::update_tree() {
 		// Recreate the category vbox if it was reset.
 		if (category_vbox == nullptr) {
 			category_vbox = memnew(VBoxContainer);
-			int separation = get_theme_constant(SNAME("v_separation"), SNAME("EditorInspector"));
-			category_vbox->add_theme_constant_override(SNAME("separation"), separation);
+			category_vbox->add_theme_constant_override(SNAME("separation"), theme_cache.vertical_separation);
 			category_vbox->hide();
 			main_vbox->add_child(category_vbox);
 		}
@@ -4472,7 +4520,7 @@ void EditorInspector::update_tree() {
 		main_vbox->add_child(spacer);
 
 		Button *add_md = EditorInspector::create_inspector_action_button(TTR("Add Metadata"));
-		add_md->set_button_icon(get_editor_theme_icon(SNAME("Add")));
+		add_md->set_button_icon(theme_cache.icon_add);
 		add_md->connect(SceneStringName(pressed), callable_mp(this, &EditorInspector::_show_add_meta_dialog));
 		main_vbox->add_child(add_md);
 		if (all_read_only) {
@@ -5280,12 +5328,18 @@ void EditorInspector::_notification(int p_what) {
 				break;
 			}
 
-			int separation = get_theme_constant(SNAME("v_separation"), SNAME("EditorInspector"));
-			base_vbox->add_theme_constant_override("separation", separation);
-			begin_vbox->add_theme_constant_override("separation", separation);
-			favorites_section->add_theme_constant_override("separation", separation);
-			favorites_groups_vbox->add_theme_constant_override("separation", separation);
-			main_vbox->add_theme_constant_override("separation", separation);
+			theme_cache.vertical_separation = get_theme_constant(SNAME("v_separation"), SNAME("EditorInspector"));
+			theme_cache.prop_subsection = get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor));
+			theme_cache.icon_add = get_editor_theme_icon(SNAME("Add"));
+
+			initialize_section_theme(section_theme_cache, this);
+			initialize_category_theme(category_theme_cache, this);
+
+			base_vbox->add_theme_constant_override("separation", theme_cache.vertical_separation);
+			begin_vbox->add_theme_constant_override("separation", theme_cache.vertical_separation);
+			favorites_section->add_theme_constant_override("separation", theme_cache.vertical_separation);
+			favorites_groups_vbox->add_theme_constant_override("separation", theme_cache.vertical_separation);
+			main_vbox->add_theme_constant_override("separation", theme_cache.vertical_separation);
 		} break;
 
 		case NOTIFICATION_READY: {
@@ -5464,6 +5518,25 @@ void EditorInspector::_add_meta_confirm() {
 	undo_redo->commit_action();
 }
 
+EditorInspector *EditorInspector::_get_control_parent_inspector(Control *p_control) {
+	{
+		EditorInspector *inspector = Object::cast_to<EditorInspector>(p_control);
+		if (inspector) {
+			return inspector;
+		}
+	}
+
+	Control *parent = p_control->get_parent_control();
+	while (parent) {
+		EditorInspector *inspector = Object::cast_to<EditorInspector>(parent);
+		if (inspector) {
+			return inspector;
+		}
+		parent = parent->get_parent_control();
+	}
+	return nullptr;
+}
+
 void EditorInspector::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("edit", "object"), &EditorInspector::edit);
 	ClassDB::bind_method("_edit_request_change", &EditorInspector::_edit_request_change);

+ 64 - 0
editor/editor_inspector.h

@@ -303,13 +303,33 @@ public:
 class EditorInspectorCategory : public Control {
 	GDCLASS(EditorInspectorCategory, Control);
 
+	friend class EditorInspector;
+
 	// Right-click context menu options.
 	enum ClassMenuOption {
 		MENU_OPEN_DOCS,
 		MENU_UNFAVORITE_ALL,
 	};
 
+	struct ThemeCache {
+		int horizontal_separation = 0;
+		int vertical_separation = 0;
+		int class_icon_size = 0;
+
+		Color font_color;
+
+		Ref<Font> bold_font;
+		int bold_font_size = 0;
+
+		Ref<Texture2D> icon_favorites;
+		Ref<Texture2D> icon_unfavorite;
+		Ref<Texture2D> icon_help;
+
+		Ref<StyleBox> background;
+	} theme_cache;
+
 	PropertyInfo info;
+
 	Ref<Texture2D> icon;
 	String label;
 	String doc_class_name;
@@ -373,6 +393,36 @@ class EditorInspectorSection : public Container {
 
 	EditorInspector *_get_parent_inspector() const;
 
+	struct ThemeCache {
+		int horizontal_separation = 0;
+		int vertical_separation = 0;
+		int inspector_margin = 0;
+		int indent_size = 0;
+
+		Color warning_color;
+		Color prop_subsection;
+		Color font_color;
+		Color font_disabled_color;
+		Color font_hover_color;
+		Color font_pressed_color;
+		Color font_hover_pressed_color;
+
+		Ref<Font> font;
+		int font_size = 0;
+		Ref<Font> bold_font;
+		int bold_font_size = 0;
+		Ref<Font> light_font;
+		int light_font_size = 0;
+
+		Ref<Texture2D> arrow;
+		Ref<Texture2D> arrow_collapsed;
+		Ref<Texture2D> arrow_collapsed_mirrored;
+		Ref<Texture2D> icon_gui_checked;
+		Ref<Texture2D> icon_gui_unchecked;
+
+		Ref<StyleBoxFlat> indent_box;
+	} theme_cache;
+
 protected:
 	Object *object = nullptr;
 	VBoxContainer *vbox = nullptr;
@@ -570,6 +620,15 @@ class EditorInspector : public ScrollContainer {
 	static Ref<EditorInspectorPlugin> inspector_plugins[MAX_PLUGINS];
 	static int inspector_plugin_count;
 
+	struct ThemeCache {
+		int vertical_separation = 0;
+		Color prop_subsection;
+		Ref<Texture2D> icon_add;
+	} theme_cache;
+
+	EditorInspectorSection::ThemeCache section_theme_cache;
+	EditorInspectorCategory::ThemeCache category_theme_cache;
+
 	bool can_favorite = false;
 	PackedStringArray current_favorites;
 	VBoxContainer *favorites_section = nullptr;
@@ -687,6 +746,8 @@ class EditorInspector : public ScrollContainer {
 	void _add_meta_confirm();
 	void _show_add_meta_dialog();
 
+	static EditorInspector *_get_control_parent_inspector(Control *p_control);
+
 protected:
 	static void _bind_methods();
 	void _notification(int p_what);
@@ -699,6 +760,9 @@ public:
 
 	static EditorProperty *instantiate_property_editor(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false);
 
+	static void initialize_section_theme(EditorInspectorSection::ThemeCache &p_cache, Control *p_control);
+	static void initialize_category_theme(EditorInspectorCategory::ThemeCache &p_cache, Control *p_control);
+
 	bool is_main_editor_inspector() const;
 	String get_selected_path() const;