Skip to content

Commit 2cd9046

Browse files
committed
Add svg import conversion tool
1 parent d7cc121 commit 2cd9046

File tree

4 files changed

+280
-0
lines changed

4 files changed

+280
-0
lines changed

editor/editor_node.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@
162162
#include "editor/settings/project_settings_editor.h"
163163
#include "editor/shader/editor_native_shader_source_visualizer.h"
164164
#include "editor/shader/visual_shader_editor_plugin.h"
165+
#include "editor/svg_import_conversion_tool.h"
165166
#include "editor/themes/editor_scale.h"
166167
#include "editor/themes/editor_theme_manager.h"
167168
#include "editor/translations/editor_translation_parser.h"
@@ -1076,6 +1077,10 @@ void EditorNode::_execute_upgrades() {
10761077
// Execute another scan to reimport the modified files.
10771078
project_upgrade_tool->connect(project_upgrade_tool->UPGRADE_FINISHED, callable_mp(EditorFileSystem::get_singleton(), &EditorFileSystem::scan), CONNECT_ONE_SHOT);
10781079
project_upgrade_tool->finish_upgrade();
1080+
} else if (run_svg_import_conversion_tool) {
1081+
run_svg_import_conversion_tool = false;
1082+
svg_import_conversion_tool->connect("conversion_finished", callable_mp(EditorFileSystem::get_singleton(), &EditorFileSystem::scan), CONNECT_ONE_SHOT);
1083+
svg_import_conversion_tool->finish_conversion();
10791084
}
10801085
}
10811086

@@ -3644,6 +3649,9 @@ void EditorNode::_tool_menu_option(int p_idx) {
36443649
case TOOLS_PROJECT_UPGRADE: {
36453650
project_upgrade_tool->popup_dialog();
36463651
} break;
3652+
case TOOLS_SVG_IMPORT_CONVERSION: {
3653+
svg_import_conversion_tool->popup_dialog();
3654+
} break;
36473655
case TOOLS_CUSTOM: {
36483656
if (tool_menu->get_item_submenu(p_idx) == "") {
36493657
Callable callback = tool_menu->get_item_metadata(p_idx);
@@ -7560,6 +7568,13 @@ EditorNode::EditorNode() {
75607568
project_upgrade_tool->begin_upgrade();
75617569
}
75627570

7571+
// Similar warm up for the svg import upgrade tool.
7572+
svg_import_conversion_tool = memnew(SvgImportConversionTool);
7573+
run_svg_import_conversion_tool = EditorSettings::get_singleton()->get_project_metadata(svg_import_conversion_tool->META_SVG_IMPORT_CONVERSION_TOOL, svg_import_conversion_tool->META_RUN_ON_RESTART, false);
7574+
if (run_svg_import_conversion_tool) {
7575+
svg_import_conversion_tool->begin_conversion();
7576+
}
7577+
75637578
{
75647579
bool agile_input_event_flushing = EDITOR_GET("input/buffering/agile_event_flushing");
75657580
bool use_accumulated_input = EDITOR_GET("input/buffering/use_accumulated_input");
@@ -8122,6 +8137,7 @@ EditorNode::EditorNode() {
81228137
tool_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/orphan_resource_explorer", TTRC("Orphan Resource Explorer...")), TOOLS_ORPHAN_RESOURCES);
81238138
tool_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/engine_compilation_configuration_editor", TTRC("Engine Compilation Configuration Editor...")), TOOLS_BUILD_PROFILE_MANAGER);
81248139
tool_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/upgrade_project", TTRC("Upgrade Project Files...")), TOOLS_PROJECT_UPGRADE);
8140+
tool_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/upgrade_svg_imports", TTRC("Convert SVG Import Files from Texture2D to SVGTexture...")), TOOLS_SVG_IMPORT_CONVERSION);
81258141

81268142
project_menu->add_separator();
81278143
project_menu->add_shortcut(ED_SHORTCUT("editor/reload_current_project", TTRC("Reload Current Project")), PROJECT_RELOAD_CURRENT_PROJECT);
@@ -8850,6 +8866,7 @@ EditorNode::~EditorNode() {
88508866
memdelete(editor_plugins_force_input_forwarding);
88518867
memdelete(progress_hb);
88528868
memdelete(project_upgrade_tool);
8869+
memdelete(svg_import_conversion_tool);
88538870
memdelete(editor_dock_manager);
88548871

88558872
EditorSettings::destroy();

editor/editor_node.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class ProjectExportDialog;
100100
class ProjectSettingsEditor;
101101
class SceneImportSettingsDialog;
102102
class ProjectUpgradeTool;
103+
class SvgImportConversionTool;
103104

104105
#ifdef ANDROID_ENABLED
105106
class TouchActionsPanel;
@@ -173,6 +174,7 @@ class EditorNode : public Node {
173174
TOOLS_ORPHAN_RESOURCES,
174175
TOOLS_BUILD_PROFILE_MANAGER,
175176
TOOLS_PROJECT_UPGRADE,
177+
TOOLS_SVG_IMPORT_CONVERSION,
176178
TOOLS_CUSTOM,
177179

178180
VCS_METADATA,
@@ -493,6 +495,8 @@ class EditorNode : public Node {
493495

494496
ProjectUpgradeTool *project_upgrade_tool = nullptr;
495497
bool run_project_upgrade_tool = false;
498+
SvgImportConversionTool *svg_import_conversion_tool = nullptr;
499+
bool run_svg_import_conversion_tool = false;
496500

497501
bool was_window_windowed_last = false;
498502

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/**************************************************************************/
2+
/* svg_import_conversion_tool.cpp */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#include "svg_import_conversion_tool.h"
32+
33+
#include "core/io/config_file.h"
34+
#include "core/io/dir_access.h"
35+
#include "editor/editor_node.h"
36+
#include "editor/file_system/editor_file_system.h"
37+
#include "editor/settings/editor_settings.h"
38+
#include "editor/themes/editor_scale.h"
39+
#include "scene/gui/dialogs.h"
40+
41+
void SvgImportConversionTool::_find_svg_files(EditorFileSystemDirectory *p_dir, Vector<String> &r_svg_paths) {
42+
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
43+
for (int i = 0; i < p_dir->get_file_count(); i++) {
44+
const String path = p_dir->get_file_path(i);
45+
const String ext = path.get_extension();
46+
if (ext == "svg") {
47+
if (da->file_exists(path + ".import")) {
48+
if (_is_texture2d_import(path + ".import")) {
49+
r_svg_paths.append(path);
50+
}
51+
}
52+
}
53+
}
54+
55+
for (int i = 0; i < p_dir->get_subdir_count(); i++) {
56+
_find_svg_files(p_dir->get_subdir(i), r_svg_paths);
57+
}
58+
}
59+
60+
void SvgImportConversionTool::_bind_methods() {
61+
ADD_SIGNAL(MethodInfo("conversion_finished"));
62+
ClassDB::bind_method(D_METHOD("_on_dialog_confirmed"), &SvgImportConversionTool::_on_dialog_confirmed);
63+
}
64+
65+
void SvgImportConversionTool::popup_dialog() {
66+
if (!convert_dialog) {
67+
convert_dialog = memnew(ConfirmationDialog);
68+
convert_dialog->set_autowrap(true);
69+
convert_dialog->set_text(TTRC("This tool will convert all SVG files that are currently imported as Texture2D to use the SVGTexture importer instead.\n\nThe following will be preserved:\n- SVG scale (renamed to base_scale)\n\nDo you want to continue?"));
70+
convert_dialog->get_ok_button()->set_text(TTRC("Convert"));
71+
convert_dialog->get_label()->set_custom_minimum_size(Size2(750 * EDSCALE, 0));
72+
EditorNode::get_singleton()->get_gui_base()->add_child(convert_dialog);
73+
convert_dialog->connect(SceneStringName(confirmed), callable_mp(this, &SvgImportConversionTool::convert_svgs));
74+
}
75+
convert_dialog->popup_centered();
76+
}
77+
78+
void SvgImportConversionTool::prepare_conversion() {
79+
EditorSettings::get_singleton()->set_project_metadata(META_SVG_IMPORT_CONVERSION_TOOL, META_RUN_ON_RESTART, true);
80+
81+
Vector<String> reimport_svg_paths;
82+
_find_svg_files(EditorFileSystem::get_singleton()->get_filesystem(), reimport_svg_paths);
83+
84+
EditorSettings::get_singleton()->set_project_metadata(META_SVG_IMPORT_CONVERSION_TOOL, META_REIMPORT_PATHS, reimport_svg_paths);
85+
86+
// Delay to avoid deadlocks, since this dialog can be triggered by loading a scene.
87+
callable_mp(EditorNode::get_singleton(), &EditorNode::restart_editor).call_deferred(false);
88+
}
89+
90+
void SvgImportConversionTool::begin_conversion() {
91+
EditorSettings::get_singleton()->set_project_metadata(META_SVG_IMPORT_CONVERSION_TOOL, META_RUN_ON_RESTART, false);
92+
}
93+
94+
bool SvgImportConversionTool::_is_texture2d_import(const String &p_import_path) {
95+
Ref<ConfigFile> cf;
96+
cf.instantiate();
97+
Error err = cf->load(p_import_path);
98+
if (err != OK) {
99+
return false;
100+
}
101+
102+
String importer = cf->get_value("remap", "importer", "");
103+
return importer == "texture";
104+
}
105+
106+
void SvgImportConversionTool::_convert_svg_file(const String &p_path) {
107+
String import_path = p_path + ".import";
108+
float svg_scale = 1.0;
109+
ResourceUID::ID uid = ResourceUID::INVALID_ID;
110+
111+
// Read old import settings
112+
Ref<ConfigFile> cf;
113+
cf.instantiate();
114+
if (cf->load(import_path) == OK) {
115+
if (cf->has_section_key("remap", "uid")) {
116+
String uid_text = cf->get_value("remap", "uid", "");
117+
uid = ResourceUID::get_singleton()->text_to_id(uid_text);
118+
}
119+
if (cf->has_section_key("params", "svg/scale")) {
120+
svg_scale = cf->get_value("params", "svg/scale", 1.0);
121+
}
122+
}
123+
124+
String base_path = p_path.get_basename();
125+
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
126+
if (da.is_valid()) {
127+
da->remove(base_path + ".ctex");
128+
129+
const char *variants[] = { "s3tc", "etc2", "bptc", "astc", nullptr };
130+
int i = 0;
131+
while (variants[i]) {
132+
da->remove(base_path + "." + variants[i] + ".ctex");
133+
i++;
134+
}
135+
136+
da->remove(base_path + ".editor.ctex");
137+
da->remove(base_path + ".editor.meta");
138+
}
139+
140+
cf->clear();
141+
142+
cf->set_value("remap", "importer", "svg");
143+
cf->set_value("remap", "type", "SVGTexture");
144+
if (uid != ResourceUID::INVALID_ID) {
145+
cf->set_value("remap", "uid", ResourceUID::get_singleton()->id_to_text(uid));
146+
}
147+
148+
// The path will be set by the importer during reimport
149+
cf->set_value("remap", "path", "");
150+
151+
cf->set_value("params", "base_scale", svg_scale);
152+
153+
cf->save(import_path);
154+
}
155+
156+
void SvgImportConversionTool::_on_dialog_confirmed() {
157+
convert_svgs();
158+
}
159+
160+
void SvgImportConversionTool::convert_svgs() {
161+
if (!EditorFileSystem::get_singleton() || !EditorFileSystem::get_singleton()->get_filesystem()) {
162+
if (EditorNode::get_singleton()) {
163+
EditorNode::get_singleton()->show_warning("Editor file system is not ready. Please try again.");
164+
}
165+
return;
166+
}
167+
168+
Vector<String> svg_paths;
169+
_find_svg_files(EditorFileSystem::get_singleton()->get_filesystem(), svg_paths);
170+
171+
if (svg_paths.is_empty()) {
172+
if (EditorNode::get_singleton()) {
173+
EditorNode::get_singleton()->show_warning("No SVG files found that are imported as Texture2D.");
174+
}
175+
return;
176+
}
177+
178+
print_line(vformat("Found %d SVG files to convert.", svg_paths.size()));
179+
180+
for (int i = 0; i < svg_paths.size(); i++) {
181+
print_line(vformat("Converting: %s", svg_paths[i]));
182+
_convert_svg_file(svg_paths[i]);
183+
}
184+
185+
print_line(vformat("Converted %d SVG files to use SVGTexture importer.", svg_paths.size()));
186+
print_line(vformat("Recommend reloading the project to prevent (non-harmful) cache errors."));
187+
188+
if (!svg_paths.is_empty()) {
189+
EditorFileSystem::get_singleton()->reimport_files(svg_paths);
190+
}
191+
}
192+
193+
void SvgImportConversionTool::finish_conversion() {
194+
emit_signal(CONVERSION_FINISHED);
195+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**************************************************************************/
2+
/* svg_import_conversion_tool.h */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#pragma once
32+
33+
#include "core/object/class_db.h"
34+
35+
class ConfirmationDialog;
36+
class EditorFileSystemDirectory;
37+
38+
class SvgImportConversionTool : public Object {
39+
GDCLASS(SvgImportConversionTool, Object);
40+
41+
ConfirmationDialog *convert_dialog = nullptr;
42+
43+
void _find_svg_files(EditorFileSystemDirectory *p_dir, Vector<String> &r_svg_paths);
44+
bool _is_texture2d_import(const String &p_import_path);
45+
void _convert_svg_file(const String &p_path);
46+
void _on_dialog_confirmed();
47+
48+
const String META_REIMPORT_PATHS = "reimport_paths";
49+
50+
public:
51+
const String META_SVG_IMPORT_CONVERSION_TOOL = "svg_import_conversion_tool";
52+
const String META_RUN_ON_RESTART = "run_on_restart";
53+
const StringName CONVERSION_FINISHED = "conversion_finished";
54+
55+
protected:
56+
static void _bind_methods();
57+
58+
public:
59+
void popup_dialog();
60+
void prepare_conversion();
61+
void begin_conversion();
62+
void finish_conversion();
63+
void convert_svgs();
64+
};

0 commit comments

Comments
 (0)