#include #include #include #include #include #include #include #include #include #include "heading.h" #include "scene.h" Scene::Scene(const std::filesystem::path& path) { std::ifstream input(path.c_str()); std::string line; bool section_started = false; Heading cur_heading; std::ostringstream cur_value; bool value_started = false; auto handle_end_of_section = [&]() { section_started = false; value_started = false; if (cur_heading.type() == "sub_resource") { sub_resources_[std::get(cur_heading.GetKeyval("id"))] = { cur_heading, cur_value.str()}; } else { other_.emplace_back(cur_heading, cur_value.str()); } cur_value = {}; }; while (std::getline(input, line)) { if (section_started && (line.empty() || line[0] == '[')) { handle_end_of_section(); } if (!line.empty() && line[0] == '[') { Heading heading(line); if (heading.type() == "gd_scene") { file_descriptor_ = heading; } else if (heading.type() == "ext_resource") { ext_resources_[std::get(heading.GetKeyval("id"))] = heading; } else { cur_heading = heading; section_started = true; } } else if (!line.empty()) { if (value_started) { cur_value << std::endl; } else { value_started = true; } cur_value << line; } } if (section_started) { handle_end_of_section(); } for (const auto& [id, stuff] : sub_resources_) { if (id >= next_sub_id_) { next_sub_id_ = id + 1; } } } int Scene::AddSubResource(const Script& script) { int new_id = next_sub_id_++; std::ostringstream resource_contents; for (const auto& [variable, value] : script.exports()) { resource_contents << variable << " = SubResource( " << value << " )" << std::endl; } resource_contents << "script/source = " << std::quoted(script.ToString()); Heading heading; heading.set_type("sub_resource"); heading.SetKeyval("type", "GDScript"); heading.SetKeyval("id", new_id); sub_resources_[new_id] = {heading, resource_contents.str()}; return new_id; } void Scene::RemoveExtResource(int id) { ext_resources_.erase(id); } void Scene::ReplaceScriptReferences(int ext_id, int sub_id) { auto replace_refs = [&](std::string& text) { std::ostringstream search_str; search_str << "ExtResource( " << ext_id << " )"; std::string search = search_str.str(); std::ostringstream new_text; std::string_view corpus = text; int location; while ((location = corpus.find(search)) != std::string_view::npos) { new_text << corpus.substr(0, location) << "SubResource( " << sub_id << " )"; corpus.remove_prefix(location + search.size()); } new_text << corpus; text = new_text.str(); }; for (auto& [id, stuff] : sub_resources_) { auto& [heading, text] = stuff; replace_refs(text); } for (auto& [heading, text] : other_) { replace_refs(text); } } std::string Scene::ToString() const { std::ostringstream output; output << file_descriptor_.ToString() << std::endl; for (const auto& [id, heading] : ext_resources_) { output << heading.ToString(); } output << std::endl; for (const auto& [id, resource] : sub_resources_) { const auto& [heading, value] = resource; output << heading.ToString() << value << std::endl << std::endl; } for (const auto& [heading, value] : other_) { output << heading.ToString() << value << std::endl << std::endl; } return output.str(); }