Optimize the editor icon generation
Icons are no longer upsampled when using an integer editor scale. This makes some icons slightly less crisp, but the icons themselves can be adjusted to mitigate this. When using a non-integer editor scale setting, upsampling is kept as it improves crispness in a far more visible manner. When upsampling is disabled, this speeds up the theme generation by about 100 ms on average, making the project manager and editor start slightly faster. This also speeds up switching between themes.
This commit is contained in:
parent
62d656ea06
commit
9e3393a624
2 changed files with 64 additions and 48 deletions
|
@ -89,7 +89,11 @@ Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color, float
|
|||
// dumb gizmo check
|
||||
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)
|
||||
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) {
|
||||
|
||||
#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;
|
||||
|
||||
// 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) {
|
||||
// convert color: FROM TO
|
||||
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, "#79f3e8", "#12d5c3"); // VS object
|
||||
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 success_color = p_theme->get_color("success_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("#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);
|
||||
|
||||
// generate icons
|
||||
if (!p_only_thumbs)
|
||||
// Generate icons.
|
||||
if (!p_only_thumbs) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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++) {
|
||||
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);
|
||||
}
|
||||
} 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++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
ImageLoaderSVG::set_convert_colors(NULL);
|
||||
#else
|
||||
print_line("SVG support disabled, editor icons won't be rendered.");
|
||||
WARN_PRINT("SVG support disabled, editor icons won't be rendered.");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -103,15 +103,17 @@ Error ImageLoaderSVG::_create_image(Ref<Image> p_image, const PoolVector<uint8_t
|
|||
ERR_PRINT("SVG Corrupted");
|
||||
return ERR_FILE_CORRUPT;
|
||||
}
|
||||
if (convert_colors)
|
||||
|
||||
if (convert_colors) {
|
||||
_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)));
|
||||
|
||||
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)));
|
||||
|
||||
PoolVector<uint8_t> dst_image;
|
||||
|
@ -123,8 +125,9 @@ Error ImageLoaderSVG::_create_image(Ref<Image> p_image, const PoolVector<uint8_t
|
|||
|
||||
dw.release();
|
||||
p_image->create(w, h, false, Image::FORMAT_RGBA8, dst_image);
|
||||
if (upsample)
|
||||
if (upsample) {
|
||||
p_image->shrink_x2();
|
||||
}
|
||||
|
||||
nsvgDelete(svg_image);
|
||||
|
||||
|
|
Loading…
Reference in a new issue