diff --git a/src/filein/include/filein/rofiworld_loader.hpp b/src/filein/include/filein/rofiworld_loader.hpp index bfbb57840a9a80e48516ea909294a404700af13f..8c9b639216d1bfe8adad36c275f1f01aa705f1cc 100644 --- a/src/filein/include/filein/rofiworld_loader.hpp +++ b/src/filein/include/filein/rofiworld_loader.hpp @@ -55,14 +55,14 @@ bool import_modules(rofiworld_ptr rofiworld, const boost::json::array &modules_a void rotate_universal_joints(const boost::json::object &module_object, rofiworld_ptr rofiworld, module_ptr um_module); module_ptr import_pad(const uint64_t width, const uint64_t height); -bool import_spaceJoints(rofiworld_ptr rofiworld, const boost::json::array &spaceJoints_array); -bool import_spaceJoint(rofiworld_ptr rofiworld, const boost::json::object &spaceJoint_object); +bool import_spaceJoints(rofiworld_ptr rofiworld, const boost::json::array &spaceJoints_array, std::set<module_ptr> &spaceJoint_modules); +bool import_spaceJoint(rofiworld_ptr rofiworld, const boost::json::object &spaceJoint_object, std::set<module_ptr> &spaceJoint_modules); module_ptr import_spaceJoint_to(rofiworld_ptr rofiworld, const boost::json::object &to_object); void import_spaceJoint_point(const module_ptr module, const boost::json::array &point); void import_spaceJoint_joint(rofiworld_ptr rofiworld, const module_ptr module, const boost::json::object &joint); -void import_moduleJoints(rofiworld_ptr rofiworld, const boost::json::array &moduleJoints_array); -void import_moduleJoint(rofiworld_ptr rofiworld, const boost::json::object &moduleJoint_object); +void import_moduleJoints(rofiworld_ptr rofiworld, const boost::json::array &moduleJoints_array, std::set<module_ptr> &spaceJoint_modules); +module_ptr import_moduleJoint(rofiworld_ptr rofiworld, module_ptr module, const std::set<module_ptr> &searched_modules, const boost::json::object &moduleJoint_object); std::pair<module_ptr, connector_ptr> get_moduleJoint_module_connector(rofiworld_ptr rofiworld, const boost::json::object &where_object); rofi::cardinal get_moduleJoint_orientation(const boost::json::string &orientation_string); diff --git a/src/filein/src/rofiworld_loader.cpp b/src/filein/src/rofiworld_loader.cpp index f0b98099ee83a22d5f95fd8eaa2d3230146bba45..279bc40b7aa531369bcf9171237d519e50b42d43 100644 --- a/src/filein/src/rofiworld_loader.cpp +++ b/src/filein/src/rofiworld_loader.cpp @@ -4,6 +4,8 @@ #include <filein/json_loader.hpp> #include <filein/module_loader.hpp> +#include <queue> + void export_rofiworld(const rofiworld_ptr rofiworld, const std::vector<objectbase_ptr> &selected_spaceJoints, const char* file_name) { boost::json::value value; @@ -302,7 +304,13 @@ std::vector<rofiworld_ptr> import_saved_configurations_rofiworld() rofiworld_ptr import_rofiworld(const std::filesystem::path file_path) { - const auto json_object = read_file(file_path).as_object(); + if (!std::filesystem::exists(file_path)) + { + std::cerr << "Cannot import RofiWorld. Invalid file path." << file_path << std::endl; + return nullptr; + } + + const auto json_object = read_file(file_path).as_object(); boost::json::array modules_array; boost::json::array spaceJoints_array; @@ -314,19 +322,18 @@ rofiworld_ptr import_rofiworld(const std::filesystem::path file_path) if (!import_modules(rofiworld, modules_array)) { - { std::cerr << "Cannot import RofiWorld. Invalid module type." << file_path << std::endl; return nullptr; } - } - if (!import_spaceJoints(rofiworld, spaceJoints_array)) + std::set<module_ptr> spaceJoint_modules; + if (!import_spaceJoints(rofiworld, spaceJoints_array, spaceJoint_modules)) { std::cerr << "Cannot import RofiWorld. Specified spaceJoint component is other than 0." << file_path << std::endl; return nullptr; } - import_moduleJoints(rofiworld, moduleJoints_array); + import_moduleJoints(rofiworld, moduleJoints_array, spaceJoint_modules); return rofiworld; } @@ -446,24 +453,29 @@ module_ptr import_pad(const uint64_t width, const uint64_t height) return std::make_shared<Module>(vg, name, type, component_ids); } -bool import_spaceJoints(rofiworld_ptr rofiworld, const boost::json::array &spaceJoints_array) +bool import_spaceJoints(rofiworld_ptr rofiworld, const boost::json::array &spaceJoints_array, std::set<module_ptr> &spaceJoint_modules) { + + for (const auto &spaceJoint_value : spaceJoints_array) { - if (!import_spaceJoint(rofiworld, spaceJoint_value.as_object())) + if (!import_spaceJoint(rofiworld, spaceJoint_value.as_object(), spaceJoint_modules)) return false; } + return true; } -bool import_spaceJoint(rofiworld_ptr rofiworld, const boost::json::object &spaceJoint_object) +bool import_spaceJoint(rofiworld_ptr rofiworld, const boost::json::object &spaceJoint_object, std::set<module_ptr> &spaceJoint_modules) { const auto to = spaceJoint_object.at("to").as_object(); const auto module = import_spaceJoint_to(rofiworld, to); if (!module) return false; + spaceJoint_modules.emplace(module); + const auto point = spaceJoint_object.at("point").as_array(); import_spaceJoint_point(module, point); const auto joint = spaceJoint_object.at("joint").as_object(); @@ -519,27 +531,55 @@ void import_spaceJoint_joint(rofiworld_ptr rofiworld, const module_ptr module, c } -void import_moduleJoints(rofiworld_ptr rofiworld, const boost::json::array &moduleJoints_array) +void import_moduleJoints(rofiworld_ptr rofiworld, const boost::json::array &moduleJoints_array, std::set<module_ptr> &spaceJoint_modules) { - for (const auto &moduleJoint_value : moduleJoints_array) + std::set<module_ptr> searched_modules; + for (const auto &module : spaceJoint_modules) { - import_moduleJoint(rofiworld, moduleJoint_value.as_object()); + std::queue<module_ptr> q; + q.push(module); + + while (!q.empty()) + { + const auto source_module = q.front(); + for (const auto &moduleJoint_value : moduleJoints_array) + { + const auto oppposite_module = import_moduleJoint(rofiworld, source_module, searched_modules, moduleJoint_value.as_object()); + if (oppposite_module && !searched_modules.contains(oppposite_module)) + q.push(oppposite_module); + } + searched_modules.emplace(q.front()); + q.pop(); + } } } -void import_moduleJoint(rofiworld_ptr rofiworld, const boost::json::object &moduleJoint_object) +module_ptr import_moduleJoint(rofiworld_ptr rofiworld, module_ptr module, const std::set<module_ptr> &searched_modules, const boost::json::object &moduleJoint_object) { const auto from_object = moduleJoint_object.at("from").as_object(); - const auto to_object = moduleJoint_object.at("to").as_object(); - const auto orientation_string = moduleJoint_object.at("orientation").as_string(); - const auto [from_module, from_connector] = get_moduleJoint_module_connector(rofiworld, from_object); + + const auto to_object = moduleJoint_object.at("to").as_object(); const auto [to_module, to_connector] = get_moduleJoint_module_connector(rofiworld, to_object); + + if (from_module != module && to_module != module) + return nullptr; + if (searched_modules.contains(from_module) || searched_modules.contains(to_module)) + return nullptr; + + const auto orientation_string = moduleJoint_object.at("orientation").as_string(); const auto mutual_orientation = get_moduleJoint_orientation(orientation_string); rofiworld->rebuildNodeTree(from_module, from_connector->getNode()); rofiworld->getVoxelGraph()->joinConnectors(from_connector, to_connector); - rofiworld->teleportModulesByConnectors(from_connector, to_connector, mutual_orientation); + // NOTE: order of connectors is swapped because we have to build additional modules around the spaceJoint module + // -> we go to "source" + const auto fst_connector = from_module == module ? to_connector : from_connector; + const auto snd_connector = from_module == module ? from_connector : to_connector; + ASSUMPTION(fst_connector != snd_connector); + rofiworld->teleportModulesByConnectors(fst_connector, snd_connector, mutual_orientation); + + return from_module == module ? to_module : from_module; } std::pair<module_ptr, connector_ptr> get_moduleJoint_module_connector(rofiworld_ptr rofiworld, const boost::json::object &where_object) diff --git a/src/rofi/src/connector.cpp b/src/rofi/src/connector.cpp index b863f9f47a265927c8801dc295f35f67c0ca3740..ff599ae206f53b9052d8b6bd387ce7ff2f21fb77 100644 --- a/src/rofi/src/connector.cpp +++ b/src/rofi/src/connector.cpp @@ -401,7 +401,10 @@ glm::vec3 enum_to_vec(side s) cardinal degree_to_cardinal(float degree_angle) { - float epsilon = 0.001f; + // NOTE: This epsilon value is this large, because the editor refused to connect + // connectors at an angle of 89.9989548 degrees, which I believe was a product + // of the floating-point arithmetic + float epsilon = 0.01f; if (glm::epsilonEqual(degree_angle, 0.0f, epsilon)) return North; if (glm::epsilonEqual(degree_angle, 90.0f, epsilon))