#include #include #include #include #include #include "heading.h" #include "scene.h" #include "script.h" struct EmbeddedScript { Script script; bool internal = false; // true if referred from within another script int id = -1; // if internal is false, ExtResource id std::string path; // if internal is true }; void show_usage() { std::cout << "godot3_tscn_compactor [path to root tscn] [file prefix]" << std::endl; } int main(int argc, char** argv) { if (argc != 3) { show_usage(); return 0; } std::filesystem::path root_tscn_path(argv[1]); std::string file_prefix(argv[2]); Scene root_tscn(root_tscn_path); std::vector sub_scripts; for (const auto& [id, heading] : root_tscn.ext_resources()) { std::string resource_filename = std::get(heading.GetKeyval("path")); if (resource_filename.substr(0, file_prefix.size()) == file_prefix) { std::filesystem::path relative_filename = resource_filename.substr(file_prefix.size()); std::filesystem::path resource_path = root_tscn_path.parent_path() / relative_filename; EmbeddedScript embedded_script; embedded_script.script = Script(resource_path, file_prefix); embedded_script.id = id; sub_scripts.push_back(std::move(embedded_script)); } } std::list all_scripts; std::vector scripts_to_check = sub_scripts; while (!scripts_to_check.empty()) { std::vector cur_scripts; cur_scripts.swap(scripts_to_check); for (const EmbeddedScript& embedded_script : cur_scripts) { all_scripts.push_front(embedded_script); for (const std::string& loaded_script_path : embedded_script.script.loaded_scripts()) { std::filesystem::path resource_path = root_tscn_path.parent_path() / loaded_script_path; EmbeddedScript embedded_script; embedded_script.script = Script(resource_path, file_prefix); embedded_script.internal = true; embedded_script.path = loaded_script_path; scripts_to_check.push_back(std::move(embedded_script)); } } } std::map new_sub_scripts; for (EmbeddedScript embedded_script : all_scripts) { embedded_script.script.ReplaceScriptReferences(new_sub_scripts); int sub_resource_id = root_tscn.AddSubResource(embedded_script.script); if (embedded_script.internal) { new_sub_scripts[embedded_script.path] = sub_resource_id; } else { root_tscn.RemoveExtResource(embedded_script.id); root_tscn.ReplaceScriptReferences(embedded_script.id, sub_resource_id); } } std::filesystem::path output_name = root_tscn_path; output_name.replace_filename(std::string(output_name.stem()) + "_compiled.tscn"); std::ofstream output_stream(output_name); output_stream << root_tscn.ToString(); return 0; }