فهرست منبع

Implement theme item cache in ColorPicker and friends

Yuri Sizov 2 سال پیش
والد
کامیت
e401540264
2فایلهای تغییر یافته به همراه165 افزوده شده و 58 حذف شده
  1. 113 57
      scene/gui/color_picker.cpp
  2. 52 1
      scene/gui/color_picker.h

+ 113 - 57
scene/gui/color_picker.cpp

@@ -47,36 +47,47 @@ void ColorPicker::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_ENTER_TREE: {
 			_update_color();
-			[[fallthrough]];
-		}
+		} break;
+
 		case NOTIFICATION_THEME_CHANGED: {
-			btn_pick->set_icon(get_theme_icon(SNAME("screen_picker"), SNAME("ColorPicker")));
+			btn_pick->set_icon(theme_cache.screen_picker);
 			_update_drop_down_arrow(btn_preset->is_pressed(), btn_preset);
 			_update_drop_down_arrow(btn_recent_preset->is_pressed(), btn_recent_preset);
-			btn_add_preset->set_icon(get_theme_icon(SNAME("add_preset")));
+			btn_add_preset->set_icon(theme_cache.add_preset);
 
-			btn_pick->set_custom_minimum_size(Size2(28 * get_theme_default_base_scale(), 0));
-			btn_shape->set_custom_minimum_size(Size2(28 * get_theme_default_base_scale(), 0));
-			btn_mode->set_custom_minimum_size(Size2(28 * get_theme_default_base_scale(), 0));
+			btn_pick->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0));
+			btn_shape->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0));
+			btn_mode->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0));
 
-			uv_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height"))));
-			w_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("h_width")), 0));
+			uv_edit->set_custom_minimum_size(Size2(theme_cache.sv_width, theme_cache.sv_height));
+			w_edit->set_custom_minimum_size(Size2(theme_cache.h_width, 0));
 
-			wheel_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height"))));
-			wheel_margin->add_theme_constant_override("margin_bottom", 8 * get_theme_default_base_scale());
+			wheel_edit->set_custom_minimum_size(Size2(theme_cache.sv_width, theme_cache.sv_height));
+			wheel_margin->add_theme_constant_override("margin_bottom", 8 * theme_cache.base_scale);
 
 			for (int i = 0; i < SLIDER_COUNT; i++) {
-				labels[i]->set_custom_minimum_size(Size2(get_theme_constant(SNAME("label_width")), 0));
-				set_offset((Side)i, get_offset((Side)i) + get_theme_constant(SNAME("margin")));
+				labels[i]->set_custom_minimum_size(Size2(theme_cache.label_width, 0));
+				set_offset((Side)i, get_offset((Side)i) + theme_cache.content_margin);
 			}
-			alpha_label->set_custom_minimum_size(Size2(get_theme_constant(SNAME("label_width")), 0));
-			set_offset((Side)0, get_offset((Side)0) + get_theme_constant(SNAME("margin")));
+			alpha_label->set_custom_minimum_size(Size2(theme_cache.label_width, 0));
+			set_offset((Side)0, get_offset((Side)0) + theme_cache.content_margin);
+
+			for (int i = 0; i < MODE_BUTTON_COUNT; i++) {
+				mode_btns[i]->add_theme_style_override("pressed", theme_cache.mode_button_pressed);
+				mode_btns[i]->add_theme_style_override("normal", theme_cache.mode_button_normal);
+				mode_btns[i]->add_theme_style_override("hover", theme_cache.mode_button_hover);
+			}
+
+			shape_popup->set_item_icon(shape_popup->get_item_index(SHAPE_HSV_RECTANGLE), theme_cache.shape_rect);
+			shape_popup->set_item_icon(shape_popup->get_item_index(SHAPE_HSV_WHEEL), theme_cache.shape_rect_wheel);
+			shape_popup->set_item_icon(shape_popup->get_item_index(SHAPE_VHS_CIRCLE), theme_cache.shape_circle);
+			shape_popup->set_item_icon(shape_popup->get_item_index(SHAPE_OKHSL_CIRCLE), theme_cache.shape_circle);
 
-			_reset_theme();
+			_reset_sliders_theme();
 
 			if (Engine::get_singleton()->is_editor_hint()) {
 				// Adjust for the width of the "Script" icon.
-				text_type->set_custom_minimum_size(Size2(28 * get_theme_default_base_scale(), 0));
+				text_type->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0));
 			}
 
 			_update_presets();
@@ -87,7 +98,7 @@ void ColorPicker::_notification(int p_what) {
 		case NOTIFICATION_VISIBILITY_CHANGED: {
 			Popup *p = Object::cast_to<Popup>(get_parent());
 			if (p && is_visible_in_tree()) {
-				p->set_size(Size2(get_combined_minimum_size().width + get_theme_constant(SNAME("margin")) * 2, get_combined_minimum_size().height + get_theme_constant(SNAME("margin")) * 2));
+				p->set_size(Size2(get_combined_minimum_size().width + theme_cache.content_margin * 2, get_combined_minimum_size().height + theme_cache.content_margin * 2));
 			}
 		} break;
 
@@ -99,6 +110,38 @@ void ColorPicker::_notification(int p_what) {
 	}
 }
 
+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.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;
 Ref<Shader> ColorPicker::circle_shader;
 Ref<Shader> ColorPicker::circle_ok_color_shader;
@@ -475,21 +518,21 @@ ColorPicker::PickerShapeType ColorPicker::_get_actual_shape() const {
 	return modes[current_mode]->get_shape_override() != SHAPE_MAX ? modes[current_mode]->get_shape_override() : current_shape;
 }
 
-void ColorPicker::_reset_theme() {
+void ColorPicker::_reset_sliders_theme() {
 	Ref<StyleBoxFlat> style_box_flat(memnew(StyleBoxFlat));
-	style_box_flat->set_content_margin(SIDE_TOP, 16 * get_theme_default_base_scale());
+	style_box_flat->set_content_margin(SIDE_TOP, 16 * theme_cache.base_scale);
 	style_box_flat->set_bg_color(Color(0.2, 0.23, 0.31).lerp(Color(0, 0, 0, 1), 0.3).clamp());
 	for (int i = 0; i < SLIDER_COUNT; i++) {
-		sliders[i]->add_theme_icon_override("grabber", get_theme_icon(SNAME("bar_arrow"), SNAME("ColorPicker")));
-		sliders[i]->add_theme_icon_override("grabber_highlight", get_theme_icon(SNAME("bar_arrow"), SNAME("ColorPicker")));
-		sliders[i]->add_theme_constant_override("grabber_offset", 8 * get_theme_default_base_scale());
+		sliders[i]->add_theme_icon_override("grabber", theme_cache.bar_arrow);
+		sliders[i]->add_theme_icon_override("grabber_highlight", theme_cache.bar_arrow);
+		sliders[i]->add_theme_constant_override("grabber_offset", 8 * theme_cache.base_scale);
 		if (!colorize_sliders) {
 			sliders[i]->add_theme_style_override("slider", style_box_flat);
 		}
 	}
-	alpha_slider->add_theme_icon_override("grabber", get_theme_icon(SNAME("bar_arrow"), SNAME("ColorPicker")));
-	alpha_slider->add_theme_icon_override("grabber_highlight", get_theme_icon(SNAME("bar_arrow"), SNAME("ColorPicker")));
-	alpha_slider->add_theme_constant_override("grabber_offset", 8 * get_theme_default_base_scale());
+	alpha_slider->add_theme_icon_override("grabber", theme_cache.bar_arrow);
+	alpha_slider->add_theme_icon_override("grabber_highlight", theme_cache.bar_arrow);
+	alpha_slider->add_theme_constant_override("grabber_offset", 8 * theme_cache.base_scale);
 	if (!colorize_sliders) {
 		alpha_slider->add_theme_style_override("slider", style_box_flat);
 	}
@@ -676,9 +719,9 @@ void ColorPicker::_show_hide_preset(const bool &p_is_btn_pressed, Button *p_btn_
 
 void ColorPicker::_update_drop_down_arrow(const bool &p_is_btn_pressed, Button *p_btn_preset) {
 	if (p_is_btn_pressed) {
-		p_btn_preset->set_icon(get_theme_icon(SNAME("expanded_arrow"), SNAME("ColorPicker")));
+		p_btn_preset->set_icon(theme_cache.expanded_arrow);
 	} else {
-		p_btn_preset->set_icon(get_theme_icon(SNAME("folded_arrow"), SNAME("ColorPicker")));
+		p_btn_preset->set_icon(theme_cache.folded_arrow);
 	}
 }
 
@@ -851,7 +894,7 @@ void ColorPicker::set_color_mode(ColorModeType p_mode) {
 	}
 
 	if (slider_theme_modified) {
-		_reset_theme();
+		_reset_sliders_theme();
 	}
 
 	mode_popup->set_item_checked(current_mode, false);
@@ -896,7 +939,7 @@ void ColorPicker::set_colorize_sliders(bool p_colorize_sliders) {
 		alpha_slider->add_theme_style_override("slider", style_box_empty);
 	} else {
 		Ref<StyleBoxFlat> style_box_flat(memnew(StyleBoxFlat));
-		style_box_flat->set_content_margin(SIDE_TOP, 16 * get_theme_default_base_scale());
+		style_box_flat->set_content_margin(SIDE_TOP, 16 * theme_cache.base_scale);
 		style_box_flat->set_bg_color(Color(0.2, 0.23, 0.31).lerp(Color(0, 0, 0, 1), 0.3).clamp());
 
 		if (!slider_theme_modified) {
@@ -966,28 +1009,28 @@ void ColorPicker::_sample_draw() {
 		const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
 
 		if (old_color.a < 1.0) {
-			sample->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), rect_old, true);
+			sample->draw_texture_rect(theme_cache.sample_background_icon, rect_old, true);
 		}
 
 		sample->draw_rect(rect_old, old_color);
 
 		if (old_color.r > 1 || old_color.g > 1 || old_color.b > 1) {
 			// Draw an indicator to denote that the old color is "overbright" and can't be displayed accurately in the preview.
-			sample->draw_texture(get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")), Point2());
+			sample->draw_texture(theme_cache.overbright_indicator, Point2());
 		}
 	} else {
 		rect_new = Rect2(Point2(), Size2(sample->get_size().width, sample->get_size().height * 0.95));
 	}
 
 	if (color.a < 1.0) {
-		sample->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), rect_new, true);
+		sample->draw_texture_rect(theme_cache.sample_background_icon, rect_new, true);
 	}
 
 	sample->draw_rect(rect_new, color);
 
 	if (color.r > 1 || color.g > 1 || color.b > 1) {
 		// Draw an indicator to denote that the new color is "overbright" and can't be displayed accurately in the preview.
-		sample->draw_texture(get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")), Point2(uv_edit->get_size().width * 0.5, 0));
+		sample->draw_texture(theme_cache.overbright_indicator, Point2(uv_edit->get_size().width * 0.5, 0));
 	}
 }
 
@@ -1063,21 +1106,21 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
 			default: {
 			}
 		}
-		Ref<Texture2D> cursor = get_theme_icon(SNAME("picker_cursor"), SNAME("ColorPicker"));
+
 		int x;
 		int y;
 		if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) {
-			x = center.x + (center.x * Math::cos(h * Math_TAU) * s) - (cursor->get_width() / 2);
-			y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - (cursor->get_height() / 2);
+			x = center.x + (center.x * Math::cos(h * Math_TAU) * s) - (theme_cache.picker_cursor->get_width() / 2);
+			y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - (theme_cache.picker_cursor->get_height() / 2);
 		} else {
 			real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0;
 			real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0;
 
 			Size2 real_size(c->get_size().x - corner_x * 2, c->get_size().y - corner_y * 2);
-			x = CLAMP(real_size.x * s, 0, real_size.x) + corner_x - (cursor->get_width() / 2);
-			y = CLAMP(real_size.y - real_size.y * v, 0, real_size.y) + corner_y - (cursor->get_height() / 2);
+			x = CLAMP(real_size.x * s, 0, real_size.x) + corner_x - (theme_cache.picker_cursor->get_width() / 2);
+			y = CLAMP(real_size.y - real_size.y * v, 0, real_size.y) + corner_y - (theme_cache.picker_cursor->get_height() / 2);
 		}
-		c->draw_texture(cursor, Point2(x, y));
+		c->draw_texture(theme_cache.picker_cursor, Point2(x, y));
 
 		col.set_hsv(h, 1, 1);
 		if (actual_shape == SHAPE_HSV_WHEEL) {
@@ -1093,9 +1136,8 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
 
 	} else if (p_which == 1) {
 		if (actual_shape == SHAPE_HSV_RECTANGLE) {
-			Ref<Texture2D> hue = get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
 			c->draw_set_transform(Point2(), -Math_PI / 2, Size2(c->get_size().x, -c->get_size().y));
-			c->draw_texture_rect(hue, Rect2(Point2(), Size2(1, 1)));
+			c->draw_texture_rect(theme_cache.color_hue_icon, Rect2(Point2(), Size2(1, 1)));
 			c->draw_set_transform(Point2(), 0, Size2(1, 1));
 			int y = c->get_size().y - c->get_size().y * (1.0 - h);
 			Color col;
@@ -1663,10 +1705,10 @@ ColorPicker::ColorPicker() {
 	current_shape = SHAPE_HSV_RECTANGLE;
 
 	shape_popup = btn_shape->get_popup();
-	shape_popup->add_icon_radio_check_item(get_theme_icon(SNAME("shape_rect"), SNAME("ColorPicker")), "HSV Rectangle", SHAPE_HSV_RECTANGLE);
-	shape_popup->add_icon_radio_check_item(get_theme_icon(SNAME("shape_rect_wheel"), SNAME("ColorPicker")), "HSV Wheel", SHAPE_HSV_WHEEL);
-	shape_popup->add_icon_radio_check_item(get_theme_icon(SNAME("shape_circle"), SNAME("ColorPicker")), "VHS Circle", SHAPE_VHS_CIRCLE);
-	shape_popup->add_icon_radio_check_item(get_theme_icon(SNAME("shape_circle"), SNAME("ColorPicker")), "OKHSL Circle", SHAPE_OKHSL_CIRCLE);
+	shape_popup->add_radio_check_item("HSV Rectangle", SHAPE_HSV_RECTANGLE);
+	shape_popup->add_radio_check_item("HSV Wheel", SHAPE_HSV_WHEEL);
+	shape_popup->add_radio_check_item("VHS Circle", SHAPE_VHS_CIRCLE);
+	shape_popup->add_radio_check_item("OKHSL Circle", SHAPE_OKHSL_CIRCLE);
 	shape_popup->set_item_checked(current_shape, true);
 	shape_popup->connect("id_pressed", callable_mp(this, &ColorPicker::set_picker_shape));
 
@@ -1687,9 +1729,6 @@ ColorPicker::ColorPicker() {
 		mode_hbc->add_child(mode_btns[i]);
 		mode_btns[i]->set_focus_mode(FOCUS_NONE);
 		mode_btns[i]->set_h_size_flags(SIZE_EXPAND_FILL);
-		mode_btns[i]->add_theme_style_override("pressed", get_theme_stylebox("tab_selected", "TabContainer"));
-		mode_btns[i]->add_theme_style_override("normal", get_theme_stylebox("tab_unselected", "TabContainer"));
-		mode_btns[i]->add_theme_style_override("hover", get_theme_stylebox("tab_selected", "TabContainer"));
 		mode_btns[i]->set_toggle_mode(true);
 		mode_btns[i]->set_text(modes[i]->get_name());
 		mode_btns[i]->set_button_group(mode_group);
@@ -1901,14 +1940,13 @@ void ColorPickerButton::pressed() {
 void ColorPickerButton::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_DRAW: {
-			const Ref<StyleBox> normal = get_theme_stylebox(SNAME("normal"));
-			const Rect2 r = Rect2(normal->get_offset(), get_size() - normal->get_minimum_size());
-			draw_texture_rect(Control::get_theme_icon(SNAME("bg"), SNAME("ColorPickerButton")), r, true);
+			const Rect2 r = Rect2(theme_cache.normal_style->get_offset(), get_size() - theme_cache.normal_style->get_minimum_size());
+			draw_texture_rect(theme_cache.background_icon, r, true);
 			draw_rect(r, color);
 
 			if (color.r > 1 || color.g > 1 || color.b > 1) {
 				// Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview
-				draw_texture(Control::get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")), normal->get_offset());
+				draw_texture(theme_cache.overbright_indicator, theme_cache.normal_style->get_offset());
 			}
 		} break;
 
@@ -1926,6 +1964,15 @@ 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;
@@ -2012,7 +2059,7 @@ void ColorPresetButton::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_DRAW: {
 			const Rect2 r = Rect2(Point2(0, 0), get_size());
-			Ref<StyleBox> sb_raw = get_theme_stylebox(SNAME("preset_fg"), SNAME("ColorPresetButton"))->duplicate();
+			Ref<StyleBox> sb_raw = theme_cache.foreground_style->duplicate();
 			Ref<StyleBoxFlat> sb_flat = sb_raw;
 			Ref<StyleBoxTexture> sb_texture = sb_raw;
 
@@ -2034,7 +2081,7 @@ void ColorPresetButton::_notification(int p_what) {
 					bg_texture_rect = bg_texture_rect.grow_side(SIDE_TOP, -sb_flat->get_margin(SIDE_TOP));
 					bg_texture_rect = bg_texture_rect.grow_side(SIDE_BOTTOM, -sb_flat->get_margin(SIDE_BOTTOM));
 
-					draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPresetButton")), bg_texture_rect, true);
+					draw_texture_rect(theme_cache.background_icon, bg_texture_rect, true);
 					sb_flat->set_bg_color(preset_color);
 				}
 				sb_flat->set_bg_color(preset_color);
@@ -2043,7 +2090,7 @@ void ColorPresetButton::_notification(int p_what) {
 				if (preset_color.a < 1) {
 					// Draw a background pattern when the color is transparent.
 					bool use_tile_texture = (sb_texture->get_h_axis_stretch_mode() == StyleBoxTexture::AxisStretchMode::AXIS_STRETCH_MODE_TILE) || (sb_texture->get_h_axis_stretch_mode() == StyleBoxTexture::AxisStretchMode::AXIS_STRETCH_MODE_TILE_FIT);
-					draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPresetButton")), r, use_tile_texture);
+					draw_texture_rect(theme_cache.background_icon, r, use_tile_texture);
 				}
 				sb_texture->set_modulate(preset_color);
 				sb_texture->draw(get_canvas_item(), r);
@@ -2052,13 +2099,22 @@ void ColorPresetButton::_notification(int p_what) {
 			}
 			if (preset_color.r > 1 || preset_color.g > 1 || preset_color.b > 1) {
 				// Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview
-				draw_texture(Control::get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPresetButton")), Vector2(0, 0));
+				draw_texture(theme_cache.overbright_indicator, Vector2(0, 0));
 			}
 
 		} break;
 	}
 }
 
+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;
 }

+ 52 - 1
scene/gui/color_picker.h

@@ -58,7 +58,16 @@ class ColorPresetButton : public BaseButton {
 
 	Color preset_color;
 
+	struct ThemeCache {
+		Ref<StyleBox> foreground_style;
+
+		Ref<Texture2D> background_icon;
+		Ref<Texture2D> overbright_indicator;
+	} theme_cache;
+
 protected:
+	virtual void _update_theme_item_cache() override;
+
 	void _notification(int);
 
 public:
@@ -194,12 +203,43 @@ private:
 	float v = 0.0;
 	Color last_color;
 
+	struct ThemeCache {
+		float base_scale = 1.0;
+
+		int content_margin = 0;
+		int label_width = 0;
+
+		int sv_height = 0;
+		int sv_width = 0;
+		int h_width = 0;
+
+		Ref<Texture2D> screen_picker;
+		Ref<Texture2D> expanded_arrow;
+		Ref<Texture2D> folded_arrow;
+		Ref<Texture2D> add_preset;
+
+		Ref<Texture2D> shape_rect;
+		Ref<Texture2D> shape_rect_wheel;
+		Ref<Texture2D> shape_circle;
+
+		Ref<Texture2D> bar_arrow;
+		Ref<Texture2D> sample_background_icon;
+		Ref<Texture2D> overbright_indicator;
+		Ref<Texture2D> picker_cursor;
+		Ref<Texture2D> color_hue_icon;
+
+		/* Mode buttons */
+		Ref<StyleBox> mode_button_normal;
+		Ref<StyleBox> mode_button_pressed;
+		Ref<StyleBox> mode_button_hover;
+	} theme_cache;
+
 	void _copy_color_to_hsv();
 	void _copy_hsv_to_color();
 
 	PickerShapeType _get_actual_shape() const;
 	void create_slider(GridContainer *gc, int idx);
-	void _reset_theme();
+	void _reset_sliders_theme();
 	void _html_submitted(const String &p_html);
 	void _value_changed(double);
 	void _update_controls();
@@ -237,6 +277,8 @@ private:
 	void _drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control);
 
 protected:
+	virtual void _update_theme_item_cache() override;
+
 	void _notification(int);
 	static void _bind_methods();
 
@@ -326,6 +368,13 @@ class ColorPickerButton : public Button {
 	Color color;
 	bool edit_alpha = true;
 
+	struct ThemeCache {
+		Ref<StyleBox> normal_style;
+		Ref<Texture2D> background_icon;
+
+		Ref<Texture2D> overbright_indicator;
+	} theme_cache;
+
 	void _about_to_popup();
 	void _color_changed(const Color &p_color);
 	void _modal_closed();
@@ -335,6 +384,8 @@ class ColorPickerButton : public Button {
 	void _update_picker();
 
 protected:
+	virtual void _update_theme_item_cache() override;
+
 	void _notification(int);
 	static void _bind_methods();