Przeglądaj źródła

Fix premature theme item access in editor tools

Yuri Sizov 2 lat temu
rodzic
commit
9b500ab53c

+ 13 - 1
editor/debugger/editor_performance_profiler.cpp

@@ -234,7 +234,9 @@ TreeItem *EditorPerformanceProfiler::_get_monitor_base(const StringName &p_base_
 	base->set_editable(0, false);
 	base->set_selectable(0, false);
 	base->set_expand_right(0, true);
-	base->set_custom_font(0, get_theme_font(SNAME("bold"), SNAME("EditorFonts")));
+	if (is_inside_tree()) {
+		base->set_custom_font(0, get_theme_font(SNAME("bold"), SNAME("EditorFonts")));
+	}
 	base_map.insert(p_base_name, base);
 	return base;
 }
@@ -368,6 +370,16 @@ List<float> *EditorPerformanceProfiler::get_monitor_data(const StringName &p_nam
 	return nullptr;
 }
 
+void EditorPerformanceProfiler::_notification(int p_what) {
+	switch (p_what) {
+		case NOTIFICATION_THEME_CHANGED: {
+			for (KeyValue<StringName, TreeItem *> &E : base_map) {
+				E.value->set_custom_font(0, get_theme_font(SNAME("bold"), SNAME("EditorFonts")));
+			}
+		} break;
+	}
+}
+
 EditorPerformanceProfiler::EditorPerformanceProfiler() {
 	set_name(TTR("Monitors"));
 	set_split_offset(340 * EDSCALE);

+ 3 - 0
editor/debugger/editor_performance_profiler.h

@@ -79,6 +79,9 @@ private:
 	TreeItem *_create_monitor_item(const StringName &p_monitor_name, TreeItem *p_base);
 	void _marker_input(const Ref<InputEvent> &p_event);
 
+protected:
+	void _notification(int p_what);
+
 public:
 	void reset();
 	void update_monitors(const Vector<StringName> &p_names);

+ 14 - 15
editor/editor_audio_buses.cpp

@@ -1436,6 +1436,15 @@ Size2 EditorAudioMeterNotches::get_minimum_size() const {
 	return Size2(width, height);
 }
 
+void EditorAudioMeterNotches::_update_theme_item_cache() {
+	Control::_update_theme_item_cache();
+
+	theme_cache.notch_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
+
+	theme_cache.font = get_theme_font(SNAME("font"), SNAME("Label"));
+	theme_cache.font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+}
+
 void EditorAudioMeterNotches::_bind_methods() {
 	ClassDB::bind_method("add_notch", &EditorAudioMeterNotches::add_notch);
 	ClassDB::bind_method("_draw_audio_notches", &EditorAudioMeterNotches::_draw_audio_notches);
@@ -1443,10 +1452,6 @@ void EditorAudioMeterNotches::_bind_methods() {
 
 void EditorAudioMeterNotches::_notification(int p_what) {
 	switch (p_what) {
-		case NOTIFICATION_THEME_CHANGED: {
-			notch_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
-		} break;
-
 		case NOTIFICATION_DRAW: {
 			_draw_audio_notches();
 		} break;
@@ -1454,28 +1459,22 @@ void EditorAudioMeterNotches::_notification(int p_what) {
 }
 
 void EditorAudioMeterNotches::_draw_audio_notches() {
-	Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
-	int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
-	float font_height = font->get_height(font_size);
+	float font_height = theme_cache.font->get_height(theme_cache.font_size);
 
 	for (int i = 0; i < notches.size(); i++) {
 		AudioNotch n = notches[i];
 		draw_line(Vector2(0, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
 				Vector2(line_length * EDSCALE, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
-				notch_color,
+				theme_cache.notch_color,
 				Math::round(EDSCALE));
 
 		if (n.render_db_value) {
-			draw_string(font,
+			draw_string(theme_cache.font,
 					Vector2((line_length + label_space) * EDSCALE,
 							(1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + (font_height / 4) + top_padding),
 					String::num(Math::abs(n.db_value)) + "dB",
-					HORIZONTAL_ALIGNMENT_LEFT, -1, font_size,
-					notch_color);
+					HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size,
+					theme_cache.notch_color);
 		}
 	}
 }
-
-EditorAudioMeterNotches::EditorAudioMeterNotches() {
-	notch_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
-}

+ 10 - 2
editor/editor_audio_buses.h

@@ -244,23 +244,31 @@ private:
 
 	List<AudioNotch> notches;
 
+	struct ThemeCache {
+		Color notch_color;
+
+		Ref<Font> font;
+		int font_size = 0;
+	} theme_cache;
+
 public:
 	const float line_length = 5.0f;
 	const float label_space = 2.0f;
 	const float btm_padding = 9.0f;
 	const float top_padding = 5.0f;
-	Color notch_color;
 
 	void add_notch(float p_normalized_offset, float p_db_value, bool p_render_value = false);
 	Size2 get_minimum_size() const override;
 
 private:
+	virtual void _update_theme_item_cache() override;
+
 	static void _bind_methods();
 	void _notification(int p_what);
 	void _draw_audio_notches();
 
 public:
-	EditorAudioMeterNotches();
+	EditorAudioMeterNotches() {}
 };
 
 class AudioBusesEditorPlugin : public EditorPlugin {

+ 1 - 1
editor/editor_run_native.cpp

@@ -40,6 +40,7 @@ void EditorRunNative::_notification(int p_what) {
 		case NOTIFICATION_THEME_CHANGED: {
 			remote_debug->set_icon(get_theme_icon(SNAME("PlayRemote"), SNAME("EditorIcons")));
 		} break;
+
 		case NOTIFICATION_PROCESS: {
 			bool changed = EditorExport::get_singleton()->poll_export_platforms() || first;
 
@@ -155,7 +156,6 @@ bool EditorRunNative::is_deploy_debug_remote_enabled() const {
 EditorRunNative::EditorRunNative() {
 	remote_debug = memnew(MenuButton);
 	remote_debug->get_popup()->connect("id_pressed", callable_mp(this, &EditorRunNative::run_native));
-	remote_debug->set_icon(get_theme_icon(SNAME("PlayRemote"), SNAME("EditorIcons")));
 	remote_debug->set_tooltip_text(TTR("Remote Debug"));
 	remote_debug->set_disabled(true);
 

+ 1 - 5
editor/import/dynamic_font_import_settings.cpp

@@ -924,9 +924,9 @@ void DynamicFontImportSettings::_notification(int p_what) {
 			connect("confirmed", callable_mp(this, &DynamicFontImportSettings::_re_import));
 		} break;
 
-		case NOTIFICATION_ENTER_TREE:
 		case NOTIFICATION_THEME_CHANGED: {
 			add_var->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+			label_warn->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor")));
 		} break;
 
 		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
@@ -1284,8 +1284,6 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
 	options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "variation_face_index"), 0));
 	options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::TRANSFORM2D, "variation_transform"), Transform2D()));
 
-	Color warn_color = (EditorNode::get_singleton()) ? EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("warning_color"), SNAME("Editor")) : Color(1, 1, 0);
-
 	// Root layout
 
 	VBoxContainer *root_vb = memnew(VBoxContainer);
@@ -1302,7 +1300,6 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
 	label_warn->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
 	label_warn->set_text("");
 	root_vb->add_child(label_warn);
-	label_warn->add_theme_color_override("font_color", warn_color);
 	label_warn->hide();
 
 	// Page 1 layout: Rendering Options
@@ -1379,7 +1376,6 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
 	add_var = memnew(Button);
 	page2_hb_vars->add_child(add_var);
 	add_var->set_tooltip_text(TTR("Add configuration"));
-	add_var->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
 	add_var->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_variation_add));
 
 	vars_list = memnew(Tree);

+ 6 - 3
editor/import/scene_import_settings.cpp

@@ -1001,6 +1001,12 @@ void SceneImportSettings::_notification(int p_what) {
 			connect("confirmed", callable_mp(this, &SceneImportSettings::_re_import));
 		} break;
 
+		case NOTIFICATION_THEME_CHANGED: {
+			action_menu->add_theme_style_override("normal", get_theme_stylebox("normal", "Button"));
+			action_menu->add_theme_style_override("hover", get_theme_stylebox("hover", "Button"));
+			action_menu->add_theme_style_override("pressed", get_theme_stylebox("pressed", "Button"));
+		} break;
+
 		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
 			inspector->set_property_name_style(EditorPropertyNameProcessor::get_settings_style());
 		} break;
@@ -1288,9 +1294,6 @@ SceneImportSettings::SceneImportSettings() {
 	action_menu->set_text(TTR("Actions..."));
 	// Style the MenuButton like a regular Button to make it more noticeable.
 	action_menu->set_flat(false);
-	action_menu->add_theme_style_override("normal", get_theme_stylebox("normal", "Button"));
-	action_menu->add_theme_style_override("hover", get_theme_stylebox("hover", "Button"));
-	action_menu->add_theme_style_override("pressed", get_theme_stylebox("pressed", "Button"));
 	action_menu->set_focus_mode(Control::FOCUS_ALL);
 	menu_hb->add_child(action_menu);
 

+ 4 - 7
editor/inspector_dock.cpp

@@ -420,12 +420,9 @@ Container *InspectorDock::get_addon_area() {
 
 void InspectorDock::_notification(int p_what) {
 	switch (p_what) {
-		case NOTIFICATION_ENTER_TREE:
+		case NOTIFICATION_THEME_CHANGED:
 		case NOTIFICATION_TRANSLATION_CHANGED:
-		case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
-		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
-			set_theme(EditorNode::get_singleton()->get_gui_base()->get_theme());
-
+		case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
 			resource_new_button->set_icon(get_theme_icon(SNAME("New"), SNAME("EditorIcons")));
 			resource_load_button->set_icon(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")));
 			resource_save_button->set_icon(get_theme_icon(SNAME("Save"), SNAME("EditorIcons")));
@@ -659,8 +656,8 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) {
 	resource_extra_button->set_tooltip_text(TTR("Extra resource options."));
 	general_options_hb->add_child(resource_extra_button);
 	resource_extra_button->connect("about_to_popup", callable_mp(this, &InspectorDock::_prepare_resource_extra_popup));
-	resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource from Clipboard")), RESOURCE_EDIT_CLIPBOARD);
-	resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
+	resource_extra_button->get_popup()->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource from Clipboard")), RESOURCE_EDIT_CLIPBOARD);
+	resource_extra_button->get_popup()->add_shortcut(ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
 	resource_extra_button->get_popup()->set_item_disabled(1, true);
 	resource_extra_button->get_popup()->add_separator();
 	resource_extra_button->get_popup()->add_shortcut(ED_SHORTCUT("property_editor/show_in_filesystem", TTR("Show in FileSystem")), RESOURCE_SHOW_IN_FILESYSTEM);

+ 11 - 7
editor/plugins/tiles/tile_atlas_view.cpp

@@ -394,13 +394,11 @@ void TileAtlasView::_draw_alternatives() {
 }
 
 void TileAtlasView::_draw_background_left() {
-	Ref<Texture2D> texture = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons"));
-	background_left->draw_texture_rect(texture, Rect2(Vector2(), background_left->get_size()), true);
+	background_left->draw_texture_rect(theme_cache.checkerboard, Rect2(Vector2(), background_left->get_size()), true);
 }
 
 void TileAtlasView::_draw_background_right() {
-	Ref<Texture2D> texture = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons"));
-	background_right->draw_texture_rect(texture, Rect2(Vector2(), background_right->get_size()), true);
+	background_right->draw_texture_rect(theme_cache.checkerboard, Rect2(Vector2(), background_right->get_size()), true);
 }
 
 void TileAtlasView::set_atlas_source(TileSet *p_tile_set, TileSetAtlasSource *p_tile_set_atlas_source, int p_source_id) {
@@ -539,6 +537,13 @@ void TileAtlasView::queue_redraw() {
 	background_right->queue_redraw();
 }
 
+void TileAtlasView::_update_theme_item_cache() {
+	Control::_update_theme_item_cache();
+
+	theme_cache.center_view_icon = get_theme_icon(SNAME("CenterView"), SNAME("EditorIcons"));
+	theme_cache.checkerboard = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons"));
+}
+
 void TileAtlasView::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_ENTER_TREE:
@@ -546,8 +551,8 @@ void TileAtlasView::_notification(int p_what) {
 			panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EDITOR_GET("editors/panning/simple_panning")));
 		} break;
 
-		case NOTIFICATION_READY: {
-			button_center_view->set_icon(get_theme_icon(SNAME("CenterView"), SNAME("EditorIcons")));
+		case NOTIFICATION_THEME_CHANGED: {
+			button_center_view->set_icon(theme_cache.center_view_icon);
 		} break;
 	}
 }
@@ -574,7 +579,6 @@ TileAtlasView::TileAtlasView() {
 	zoom_widget->set_shortcut_context(this);
 
 	button_center_view = memnew(Button);
-	button_center_view->set_icon(get_theme_icon(SNAME("CenterView"), SNAME("EditorIcons")));
 	button_center_view->set_anchors_and_offsets_preset(Control::PRESET_TOP_RIGHT, Control::PRESET_MODE_MINSIZE, 5);
 	button_center_view->connect("pressed", callable_mp(this, &TileAtlasView::_center_view));
 	button_center_view->set_flat(true);

+ 7 - 0
editor/plugins/tiles/tile_atlas_view.h

@@ -110,7 +110,14 @@ private:
 
 	Size2i _compute_alternative_tiles_control_size();
 
+	struct ThemeCache {
+		Ref<Texture2D> center_view_icon;
+		Ref<Texture2D> checkerboard;
+	} theme_cache;
+
 protected:
+	virtual void _update_theme_item_cache() override;
+
 	void _notification(int p_what);
 	static void _bind_methods();
 

+ 33 - 16
modules/multiplayer/editor/editor_network_profiler.cpp

@@ -41,25 +41,42 @@ void EditorNetworkProfiler::_bind_methods() {
 
 void EditorNetworkProfiler::_notification(int p_what) {
 	switch (p_what) {
-		case NOTIFICATION_ENTER_TREE:
 		case NOTIFICATION_THEME_CHANGED: {
-			node_icon = get_theme_icon(SNAME("Node"), SNAME("EditorIcons"));
 			if (activate->is_pressed()) {
-				activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
+				activate->set_icon(theme_cache.stop_icon);
 			} else {
-				activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
+				activate->set_icon(theme_cache.play_icon);
 			}
-			clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")));
-			incoming_bandwidth_text->set_right_icon(get_theme_icon(SNAME("ArrowDown"), SNAME("EditorIcons")));
-			outgoing_bandwidth_text->set_right_icon(get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons")));
+			clear_button->set_icon(theme_cache.clear_icon);
+
+			incoming_bandwidth_text->set_right_icon(theme_cache.incoming_bandwidth_icon);
+			outgoing_bandwidth_text->set_right_icon(theme_cache.outgoing_bandwidth_icon);
 
 			// This needs to be done here to set the faded color when the profiler is first opened
-			incoming_bandwidth_text->add_theme_color_override("font_uneditable_color", get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, 0.5));
-			outgoing_bandwidth_text->add_theme_color_override("font_uneditable_color", get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, 0.5));
+			incoming_bandwidth_text->add_theme_color_override("font_uneditable_color", theme_cache.incoming_bandwidth_color * Color(1, 1, 1, 0.5));
+			outgoing_bandwidth_text->add_theme_color_override("font_uneditable_color", theme_cache.outgoing_bandwidth_color * Color(1, 1, 1, 0.5));
 		} break;
 	}
 }
 
+void EditorNetworkProfiler::_update_theme_item_cache() {
+	VBoxContainer::_update_theme_item_cache();
+
+	theme_cache.node_icon = get_theme_icon(SNAME("Node"), SNAME("EditorIcons"));
+	theme_cache.stop_icon = get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"));
+	theme_cache.play_icon = get_theme_icon(SNAME("Play"), SNAME("EditorIcons"));
+	theme_cache.clear_icon = get_theme_icon(SNAME("Clear"), SNAME("EditorIcons"));
+
+	theme_cache.multiplayer_synchronizer_icon = get_theme_icon("MultiplayerSynchronizer", SNAME("EditorIcons"));
+	theme_cache.instance_options_icon = get_theme_icon(SNAME("InstanceOptions"), SNAME("EditorIcons"));
+
+	theme_cache.incoming_bandwidth_icon = get_theme_icon(SNAME("ArrowDown"), SNAME("EditorIcons"));
+	theme_cache.outgoing_bandwidth_icon = get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons"));
+
+	theme_cache.incoming_bandwidth_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
+	theme_cache.outgoing_bandwidth_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
+}
+
 void EditorNetworkProfiler::_refresh() {
 	if (!dirty) {
 		return;
@@ -111,11 +128,11 @@ void EditorNetworkProfiler::refresh_replication_data() {
 		const NodeInfo &cfg_info = node_data[E.value.config];
 
 		node->set_text(0, root_info.path.get_file());
-		node->set_icon(0, has_theme_icon(root_info.type, SNAME("EditorIcons")) ? get_theme_icon(root_info.type, SNAME("EditorIcons")) : node_icon);
+		node->set_icon(0, has_theme_icon(root_info.type, SNAME("EditorIcons")) ? get_theme_icon(root_info.type, SNAME("EditorIcons")) : theme_cache.node_icon);
 		node->set_tooltip_text(0, root_info.path);
 
 		node->set_text(1, sync_info.path.get_file());
-		node->set_icon(1, get_theme_icon("MultiplayerSynchronizer", SNAME("EditorIcons")));
+		node->set_icon(1, theme_cache.multiplayer_synchronizer_icon);
 		node->set_tooltip_text(1, sync_info.path);
 
 		int cfg_idx = cfg_info.path.find("::");
@@ -123,7 +140,7 @@ void EditorNetworkProfiler::refresh_replication_data() {
 			String res_idstr = cfg_info.path.substr(cfg_idx + 2).replace("SceneReplicationConfig_", "");
 			String scene_path = cfg_info.path.substr(0, cfg_idx);
 			node->set_text(2, vformat("%s (%s)", res_idstr, scene_path.get_file()));
-			node->add_button(2, get_theme_icon(SNAME("InstanceOptions"), SNAME("EditorIcons")));
+			node->add_button(2, theme_cache.instance_options_icon);
 			node->set_tooltip_text(2, cfg_info.path);
 			node->set_metadata(2, scene_path);
 		} else {
@@ -154,11 +171,11 @@ void EditorNetworkProfiler::add_node_data(const NodeInfo &p_info) {
 void EditorNetworkProfiler::_activate_pressed() {
 	if (activate->is_pressed()) {
 		refresh_timer->start();
-		activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
+		activate->set_icon(theme_cache.stop_icon);
 		activate->set_text(TTR("Stop"));
 	} else {
 		refresh_timer->stop();
-		activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
+		activate->set_icon(theme_cache.play_icon);
 		activate->set_text(TTR("Start"));
 	}
 	emit_signal(SNAME("enable_profiling"), activate->is_pressed());
@@ -224,10 +241,10 @@ void EditorNetworkProfiler::set_bandwidth(int p_incoming, int p_outgoing) {
 	// Make labels more prominent when the bandwidth is greater than 0 to attract user attention
 	incoming_bandwidth_text->add_theme_color_override(
 			"font_uneditable_color",
-			get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, p_incoming > 0 ? 1 : 0.5));
+			theme_cache.incoming_bandwidth_color * Color(1, 1, 1, p_incoming > 0 ? 1 : 0.5));
 	outgoing_bandwidth_text->add_theme_color_override(
 			"font_uneditable_color",
-			get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, p_outgoing > 0 ? 1 : 0.5));
+			theme_cache.outgoing_bandwidth_color * Color(1, 1, 1, p_outgoing > 0 ? 1 : 0.5));
 }
 
 bool EditorNetworkProfiler::is_profiling() {

+ 18 - 1
modules/multiplayer/editor/editor_network_profiler.h

@@ -73,7 +73,22 @@ private:
 	HashMap<ObjectID, SyncInfo> sync_data;
 	HashMap<ObjectID, NodeInfo> node_data;
 	HashSet<ObjectID> missing_node_data;
-	Ref<Texture2D> node_icon;
+
+	struct ThemeCache {
+		Ref<Texture2D> node_icon;
+		Ref<Texture2D> stop_icon;
+		Ref<Texture2D> play_icon;
+		Ref<Texture2D> clear_icon;
+
+		Ref<Texture2D> multiplayer_synchronizer_icon;
+		Ref<Texture2D> instance_options_icon;
+
+		Ref<Texture2D> incoming_bandwidth_icon;
+		Ref<Texture2D> outgoing_bandwidth_icon;
+
+		Color incoming_bandwidth_color;
+		Color outgoing_bandwidth_color;
+	} theme_cache;
 
 	void _activate_pressed();
 	void _clear_pressed();
@@ -81,6 +96,8 @@ private:
 	void _replication_button_clicked(TreeItem *p_item, int p_column, int p_idx, MouseButton p_button);
 
 protected:
+	virtual void _update_theme_item_cache() override;
+
 	void _notification(int p_what);
 	static void _bind_methods();