Browse Source

Merge pull request #35340 from Calinou/optimize-editor-icon-generation

Optimize the editor icon generation
Rémi Verschelde 5 years ago
parent
commit
43f84445ba
2 changed files with 64 additions and 48 deletions
  1. 56 43
      editor/editor_themes.cpp
  2. 8 5
      modules/svg/image_loader_svg.cpp

+ 56 - 43
editor/editor_themes.cpp

@@ -89,7 +89,11 @@ Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color, float
 	// dumb gizmo check
 	// dumb gizmo check
 	bool is_gizmo = String(editor_icons_names[p_index]).begins_with("Gizmo");
 	bool is_gizmo = String(editor_icons_names[p_index]).begins_with("Gizmo");
 
 
-	ImageLoaderSVG::create_image_from_string(img, editor_icons_sources[p_index], p_scale, true, p_convert_color);
+	// Upsample icon generation only if the editor scale isn't an integer multiplier.
+	// Generating upsampled icons is slower, and the benefit is hardly visible
+	// with integer editor scales.
+	const bool upsample = !Math::is_equal_approx(Math::round(p_scale), p_scale);
+	ImageLoaderSVG::create_image_from_string(img, editor_icons_sources[p_index], p_scale, upsample, p_convert_color);
 
 
 	if ((p_scale - (float)((int)p_scale)) > 0.0 || is_gizmo || p_force_filter)
 	if ((p_scale - (float)((int)p_scale)) > 0.0 || is_gizmo || p_force_filter)
 		icon->create_from_image(img); // in this case filter really helps
 		icon->create_from_image(img); // in this case filter really helps
@@ -106,7 +110,15 @@ Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color, float
 void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = true, int p_thumb_size = 32, bool p_only_thumbs = false) {
 void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = true, int p_thumb_size = 32, bool p_only_thumbs = false) {
 
 
 #ifdef SVG_ENABLED
 #ifdef SVG_ENABLED
+	// The default icon theme is designed to be used for a dark theme.
+	// This dictionary stores color codes to convert to other colors
+	// for better readability on a light theme.
 	Dictionary dark_icon_color_dictionary;
 	Dictionary dark_icon_color_dictionary;
+
+	// The names of the icons to never convert, even if one of their colors
+	// are contained in the dictionary above.
+	Set<StringName> exceptions;
+
 	if (!p_dark_theme) {
 	if (!p_dark_theme) {
 		// convert color:                             FROM       TO
 		// convert color:                             FROM       TO
 		ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e0e0e0", "#5a5a5a"); // common icon color
 		ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e0e0e0", "#5a5a5a"); // common icon color
@@ -172,9 +184,31 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =
 		ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#69ec9a", "#2ce573"); // VS rid
 		ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#69ec9a", "#2ce573"); // VS rid
 		ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#79f3e8", "#12d5c3"); // VS object
 		ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#79f3e8", "#12d5c3"); // VS object
 		ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#77edb1", "#57e99f"); // VS dict
 		ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#77edb1", "#57e99f"); // VS dict
+
+		exceptions.insert("EditorPivot");
+		exceptions.insert("EditorHandle");
+		exceptions.insert("Editor3DHandle");
+		exceptions.insert("Godot");
+		exceptions.insert("PanoramaSky");
+		exceptions.insert("ProceduralSky");
+		exceptions.insert("EditorControlAnchor");
+		exceptions.insert("DefaultProjectIcon");
+		exceptions.insert("GuiCloseCustomizable");
+		exceptions.insert("GuiGraphNodePort");
+		exceptions.insert("GuiResizer");
+		exceptions.insert("ZoomMore");
+		exceptions.insert("ZoomLess");
+		exceptions.insert("ZoomReset");
+		exceptions.insert("LockViewport");
+		exceptions.insert("GroupViewport");
+		exceptions.insert("StatusError");
+		exceptions.insert("StatusSuccess");
+		exceptions.insert("StatusWarning");
+		exceptions.insert("NodeWarning");
+		exceptions.insert("OverbrightIndicator");
 	}
 	}
 
 
-	// these ones should be converted even if we are using a dark theme
+	// These ones should be converted even if we are using a dark theme.
 	const Color error_color = p_theme->get_color("error_color", "Editor");
 	const Color error_color = p_theme->get_color("error_color", "Editor");
 	const Color success_color = p_theme->get_color("success_color", "Editor");
 	const Color success_color = p_theme->get_color("success_color", "Editor");
 	const Color warning_color = p_theme->get_color("warning_color", "Editor");
 	const Color warning_color = p_theme->get_color("warning_color", "Editor");
@@ -182,65 +216,44 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =
 	dark_icon_color_dictionary[Color::html("#45ff8b")] = success_color;
 	dark_icon_color_dictionary[Color::html("#45ff8b")] = success_color;
 	dark_icon_color_dictionary[Color::html("#dbab09")] = warning_color;
 	dark_icon_color_dictionary[Color::html("#dbab09")] = warning_color;
 
 
-	List<String> exceptions;
-	exceptions.push_back("EditorPivot");
-	exceptions.push_back("EditorHandle");
-	exceptions.push_back("Editor3DHandle");
-	exceptions.push_back("Godot");
-	exceptions.push_back("PanoramaSky");
-	exceptions.push_back("ProceduralSky");
-	exceptions.push_back("EditorControlAnchor");
-	exceptions.push_back("DefaultProjectIcon");
-	exceptions.push_back("GuiCloseCustomizable");
-	exceptions.push_back("GuiGraphNodePort");
-	exceptions.push_back("GuiResizer");
-	exceptions.push_back("ZoomMore");
-	exceptions.push_back("ZoomLess");
-	exceptions.push_back("ZoomReset");
-	exceptions.push_back("LockViewport");
-	exceptions.push_back("GroupViewport");
-	exceptions.push_back("StatusError");
-	exceptions.push_back("StatusSuccess");
-	exceptions.push_back("StatusWarning");
-	exceptions.push_back("NodeWarning");
-	exceptions.push_back("OverbrightIndicator");
-
 	ImageLoaderSVG::set_convert_colors(&dark_icon_color_dictionary);
 	ImageLoaderSVG::set_convert_colors(&dark_icon_color_dictionary);
 
 
-	// generate icons
-	if (!p_only_thumbs)
+	// Generate icons.
+	if (!p_only_thumbs) {
 		for (int i = 0; i < editor_icons_count; i++) {
 		for (int i = 0; i < editor_icons_count; i++) {
-			List<String>::Element *is_exception = exceptions.find(editor_icons_names[i]);
-			if (is_exception) exceptions.erase(is_exception);
-			Ref<ImageTexture> icon = editor_generate_icon(i, !is_exception);
+			const int is_exception = exceptions.has(editor_icons_names[i]);
+			const Ref<ImageTexture> icon = editor_generate_icon(i, !is_exception);
+
 			p_theme->set_icon(editor_icons_names[i], "EditorIcons", icon);
 			p_theme->set_icon(editor_icons_names[i], "EditorIcons", icon);
 		}
 		}
+	}
 
 
-	// generate thumb files with the given thumb size
-	bool force_filter = p_thumb_size != 64 && p_thumb_size != 32; // we don't need filter with original resolution
+	// Generate thumbnail icons with the given thumbnail size.
+	// We don't need filtering when generating at one of the default resolutions.
+	const bool force_filter = p_thumb_size != 64 && p_thumb_size != 32;
 	if (p_thumb_size >= 64) {
 	if (p_thumb_size >= 64) {
-		float scale = (float)p_thumb_size / 64.0 * EDSCALE;
+		const float scale = (float)p_thumb_size / 64.0 * EDSCALE;
 		for (int i = 0; i < editor_bg_thumbs_count; i++) {
 		for (int i = 0; i < editor_bg_thumbs_count; i++) {
-			int index = editor_bg_thumbs_indices[i];
-			List<String>::Element *is_exception = exceptions.find(editor_icons_names[index]);
-			if (is_exception) exceptions.erase(is_exception);
-			Ref<ImageTexture> icon = editor_generate_icon(index, !p_dark_theme && !is_exception, scale, force_filter);
+			const int index = editor_bg_thumbs_indices[i];
+			const int is_exception = exceptions.has(editor_icons_names[index]);
+			const Ref<ImageTexture> icon = editor_generate_icon(index, !p_dark_theme && !is_exception, scale, force_filter);
+
 			p_theme->set_icon(editor_icons_names[index], "EditorIcons", icon);
 			p_theme->set_icon(editor_icons_names[index], "EditorIcons", icon);
 		}
 		}
 	} else {
 	} else {
-		float scale = (float)p_thumb_size / 32.0 * EDSCALE;
+		const float scale = (float)p_thumb_size / 32.0 * EDSCALE;
 		for (int i = 0; i < editor_md_thumbs_count; i++) {
 		for (int i = 0; i < editor_md_thumbs_count; i++) {
-			int index = editor_md_thumbs_indices[i];
-			List<String>::Element *is_exception = exceptions.find(editor_icons_names[index]);
-			if (is_exception) exceptions.erase(is_exception);
-			Ref<ImageTexture> icon = editor_generate_icon(index, !p_dark_theme && !is_exception, scale, force_filter);
+			const int index = editor_md_thumbs_indices[i];
+			const bool is_exception = exceptions.has(editor_icons_names[index]);
+			const Ref<ImageTexture> icon = editor_generate_icon(index, !p_dark_theme && !is_exception, scale, force_filter);
+
 			p_theme->set_icon(editor_icons_names[index], "EditorIcons", icon);
 			p_theme->set_icon(editor_icons_names[index], "EditorIcons", icon);
 		}
 		}
 	}
 	}
 
 
 	ImageLoaderSVG::set_convert_colors(NULL);
 	ImageLoaderSVG::set_convert_colors(NULL);
 #else
 #else
-	print_line("SVG support disabled, editor icons won't be rendered.");
+	WARN_PRINT("SVG support disabled, editor icons won't be rendered.");
 #endif
 #endif
 }
 }
 
 

+ 8 - 5
modules/svg/image_loader_svg.cpp

@@ -103,15 +103,17 @@ Error ImageLoaderSVG::_create_image(Ref<Image> p_image, const PoolVector<uint8_t
 		ERR_PRINT("SVG Corrupted");
 		ERR_PRINT("SVG Corrupted");
 		return ERR_FILE_CORRUPT;
 		return ERR_FILE_CORRUPT;
 	}
 	}
-	if (convert_colors)
+
+	if (convert_colors) {
 		_convert_colors(svg_image);
 		_convert_colors(svg_image);
+	}
 
 
-	float upscale = upsample ? 2.0 : 1.0;
+	const float upscale = upsample ? 2.0 : 1.0;
 
 
-	int w = (int)(svg_image->width * p_scale * upscale);
+	const int w = (int)(svg_image->width * p_scale * upscale);
 	ERR_FAIL_COND_V_MSG(w > Image::MAX_WIDTH, ERR_PARAMETER_RANGE_ERROR, vformat("Can't create image from SVG with scale %s, the resulting image size exceeds max width.", rtos(p_scale)));
 	ERR_FAIL_COND_V_MSG(w > Image::MAX_WIDTH, ERR_PARAMETER_RANGE_ERROR, vformat("Can't create image from SVG with scale %s, the resulting image size exceeds max width.", rtos(p_scale)));
 
 
-	int h = (int)(svg_image->height * p_scale * upscale);
+	const int h = (int)(svg_image->height * p_scale * upscale);
 	ERR_FAIL_COND_V_MSG(h > Image::MAX_HEIGHT, ERR_PARAMETER_RANGE_ERROR, vformat("Can't create image from SVG with scale %s, the resulting image size exceeds max height.", rtos(p_scale)));
 	ERR_FAIL_COND_V_MSG(h > Image::MAX_HEIGHT, ERR_PARAMETER_RANGE_ERROR, vformat("Can't create image from SVG with scale %s, the resulting image size exceeds max height.", rtos(p_scale)));
 
 
 	PoolVector<uint8_t> dst_image;
 	PoolVector<uint8_t> dst_image;
@@ -123,8 +125,9 @@ Error ImageLoaderSVG::_create_image(Ref<Image> p_image, const PoolVector<uint8_t
 
 
 	dw.release();
 	dw.release();
 	p_image->create(w, h, false, Image::FORMAT_RGBA8, dst_image);
 	p_image->create(w, h, false, Image::FORMAT_RGBA8, dst_image);
-	if (upsample)
+	if (upsample) {
 		p_image->shrink_x2();
 		p_image->shrink_x2();
+	}
 
 
 	nsvgDelete(svg_image);
 	nsvgDelete(svg_image);