From 0631f3a2c14cc707873e4c0d8b4a6b0aaa8ef7f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0toura=C4=8D?= <525032@mail.muni.cz> Date: Tue, 21 May 2024 12:42:30 +0200 Subject: [PATCH] add functional import of rofiworld --- src/edit/include/edit/editor.hpp | 5 + src/edit/src/editor.cpp | 34 +++++ .../include/filein/rofiworld_loader.hpp | 2 + src/filein/src/rofiworld_loader.cpp | 121 ++++++++++++------ src/gui/include/gui/ui.hpp | 2 + src/gui/src/ui.cpp | 76 +++++++++-- src/rofi/include/rofi/rofiworld.hpp | 3 + 7 files changed, 193 insertions(+), 50 deletions(-) diff --git a/src/edit/include/edit/editor.hpp b/src/edit/include/edit/editor.hpp index 539793f..7d84ebc 100644 --- a/src/edit/include/edit/editor.hpp +++ b/src/edit/include/edit/editor.hpp @@ -49,6 +49,9 @@ public: bool export_file_prompt = false; bool export_file_visible = false; bool export_file_error = false; + bool import_file_prompt = false; + bool import_file_visible = false; + bool import_file_error = false; bool save_module_prompt = false; bool save_module_visible = false; bool save_module_error = false; @@ -229,6 +232,7 @@ class Editor std::vector<module_ptr> modules = import_saved_configurations_module(); rofiworld_ptr rofiworld = std::make_shared<rofi::RofiWorld>(); + std::map<std::string, rofiworld_ptr> rofiworld_selection; module_ptr selected_add_module; module_ptr prev_selected_add_module; @@ -351,6 +355,7 @@ public: void manageUI(); void manageUISaveModule(); void manageUISaveRofiWorld(); + void manageUIImportRofiWorld(); bool checkModuleExport(const voxel_graph_ptr &voxel_graph, const build_mode_I build_mode); diff --git a/src/edit/src/editor.cpp b/src/edit/src/editor.cpp index 663483d..6f14a98 100644 --- a/src/edit/src/editor.cpp +++ b/src/edit/src/editor.cpp @@ -51,6 +51,8 @@ void Editor::manageUI() manageUISaveModule(); manageUISaveRofiWorld(); + + manageUIImportRofiWorld(); } void Editor::manageUISaveModule() @@ -157,6 +159,38 @@ void Editor::manageUISaveRofiWorld() } } +void Editor::manageUIImportRofiWorld() +{ + if (editor_phase != phase::two) + return; + + if (ui.import_file_prompt) + { + const std::string rofiworlds_directory = "./data/rofi/rofiworlds/"; + auto imported_rofiworld = import_rofiworld(std::filesystem::path(rofiworlds_directory + std::string(ui.name_buffer) + std::string(".json"))); + if (imported_rofiworld) + { + for (const auto &module : imported_rofiworld->getModulesSet()) + setRoFIMesh(module->getParts()); + + setRofiWorldNodeTreeToScene(rofiworld->getNodeTree(), imported_rofiworld->getNodeTree()); + rofiworld = imported_rofiworld; + voxel_graph = imported_rofiworld->getVoxelGraph(); + + ui.import_file_error = false; + ui.name_buffer[0] = '\0'; + } + else + { + setError("Error: Cannot Import Configuration"); + ui.import_file_visible = true; + ui.import_file_error = true; + } + + ui.import_file_prompt = false; + } +} + bool Editor::checkModuleExport(const voxel_graph_ptr &voxel_graph, const build_mode_I build_mode) { using enum build_mode_I; diff --git a/src/filein/include/filein/rofiworld_loader.hpp b/src/filein/include/filein/rofiworld_loader.hpp index be78aa7..bfbb578 100644 --- a/src/filein/include/filein/rofiworld_loader.hpp +++ b/src/filein/include/filein/rofiworld_loader.hpp @@ -52,6 +52,8 @@ void get_rofiworld_data(const boost::json::object &json_object, boost::json::array &moduleJoints_array); bool import_modules(rofiworld_ptr rofiworld, const boost::json::array &modules_array); +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); diff --git a/src/filein/src/rofiworld_loader.cpp b/src/filein/src/rofiworld_loader.cpp index 0cddeee..060e3c8 100644 --- a/src/filein/src/rofiworld_loader.cpp +++ b/src/filein/src/rofiworld_loader.cpp @@ -343,16 +343,16 @@ void get_rofiworld_data(const boost::json::object &json_object, bool import_modules(rofiworld_ptr rofiworld, const boost::json::array &modules_array) { - const std::string modules_directory = "./data/rofi/modules"; - const auto universal = import_module(modules_directory + std::string("UM.json")); - const auto cube = import_module(modules_directory + std::string("cube_full.json")); + const std::string modules_directory = "./data/rofi/modules/"; + // const auto universal = import_module(modules_directory + std::string("UM.json")); + // const auto cube = import_module(modules_directory + std::string("cube_full.json")); for (const auto &module_value : modules_array) { const auto module_object = module_value.as_object(); const auto module_type = module_object.at("type"); const auto module_type_string = module_type.if_string(); - const auto module_id = module_object.at("id").as_uint64(); + const auto module_id = static_cast<uint64_t>(module_object.at("id").as_int64()); module_ptr module_copy = nullptr; @@ -361,49 +361,89 @@ bool import_modules(rofiworld_ptr rofiworld, const boost::json::array &modules_a if (*module_type_string == "universal") { - module_copy = rofi::Module::copy(universal); + module_copy = import_module(modules_directory + std::string("UM.json")); - const auto alpha = module_object.at("alpha").is_int64() ? module_object.at("alpha").as_int64() : module_object.at("alpha").as_double(); - const auto shoe_a = module_copy->getConnectorByDock("A-Z"); - rofiworld->rotateConnector(shoe_a, static_cast<float>(alpha)); + rofi::VoxelGraph::linkImportVoxelGraphToNodes(module_copy->getParts()); + rofi::Module::setModuleNodeHierarchy(module_copy->getParts(), std::string(*module_type_string)); - const auto beta = module_object.at("beta").is_int64() ? module_object.at("beta").as_int64() : module_object.at("beta").as_double(); - const auto shoe_b = module_copy->getConnectorByDock("B-Z"); - rofiworld->rotateConnector(shoe_b, static_cast<float>(beta)); - - const auto gamma = module_object.at("gamma").is_int64() ? module_object.at("gamma").as_int64() : module_object.at("gamma").as_double(); - const auto body_b = module_copy->getParts()->getVoxels().front()->getNode()->getPositionLocal() == glm::vec3(0.0f) - ? module_copy->getParts()->getVoxels().back() - : module_copy->getParts()->getVoxels().front(); - rofiworld->rotateVoxel(body_b, static_cast<float>(gamma)); - - rofiworld->addModule(rofi::Module::copy(universal)); + rotate_universal_joints(module_object, rofiworld, module_copy); } else if (*module_type_string == "cube") { - module_copy = rofi::Module::copy(cube); - rofiworld->addModule(module_copy); + module_copy = import_module(modules_directory + std::string("cube_full.json")); + + rofi::VoxelGraph::linkImportVoxelGraphToNodes(module_copy->getParts()); + rofi::Module::setModuleNodeHierarchy(module_copy->getParts(), std::string(*module_type_string)); } else if (*module_type_string == "pad") { - const auto width = module_object.at("width").as_int64(); - const auto height = module_object.at("height").as_int64(); + const auto width = static_cast<uint64_t>(module_object.at("width").as_int64()); + const auto height = static_cast<uint64_t>(module_object.at("height").as_int64()); + + module_copy = import_pad(width, height); - // TO DO - // module_copy = std::make_shared<rofi::Module>() - // rofiworld->addModule() + rofi::VoxelGraph::linkImportVoxelGraphToNodes(module_copy->getParts()); + rofi::Module::setModuleNodeHierarchy(module_copy->getParts(), std::string(*module_type_string)); } else return false; + rofiworld->addModule(module_copy); rofiworld->changeModuleID(module_copy, module_id); - - rofi::VoxelGraph::linkImportVoxelGraphToNodes(module_copy->getParts()); - rofi::Module::setModuleNodeHierarchy(module_copy->getParts(), std::string(*module_type_string)); } return true; +} + +void rotate_universal_joints(const boost::json::object &module_object, rofiworld_ptr rofiworld, module_ptr um_module) +{ + const auto alpha = module_object.at("alpha").is_int64() ? module_object.at("alpha").as_int64() : module_object.at("alpha").as_double(); + const auto shoe_a = um_module->getConnectorByDock("A-Z"); + rofiworld->rotateConnector(shoe_a, static_cast<float>(alpha)); + + const auto beta = module_object.at("beta").is_int64() ? module_object.at("beta").as_int64() : module_object.at("beta").as_double(); + const auto shoe_b = um_module->getConnectorByDock("B-Z"); + rofiworld->rotateConnector(shoe_b, static_cast<float>(beta)); + + const auto gamma = module_object.at("gamma").is_int64() ? module_object.at("gamma").as_int64() : module_object.at("gamma").as_double(); + const auto body_b = um_module->getParts()->getVoxels().front()->getNode()->getPositionLocal() == glm::vec3(0.0f) + ? um_module->getParts()->getVoxels().back() + : um_module->getParts()->getVoxels().front(); + rofiworld->rotateVoxel(body_b, static_cast<float>(gamma)); +} + +module_ptr import_pad(const uint64_t width, const uint64_t height) +{ + using namespace rofi; + + voxel_graph_ptr vg = std::make_shared<VoxelGraph>(); + std::map<objectbase_ptr, uint64_t> component_ids; + uint64_t id_counter; + + for ( int x = 0; x < width; ++x ) + { + for ( int y = 0; y < height; ++y ) + { + float x_pos = static_cast<float>(x); + float y_pos = static_cast<float>(y); + + auto open_con_node = Node::create(glm::vec3(x_pos, y_pos, 0.0f), get_connector_face_rotation(glm::vec3(0.0f, 0.0f, -1.0f))); + open_con_node->rotateRotationQuat(glm::rotation(open_con_node->getRotationAxisXLocal(), glm::vec3(0.0f, 1.0f, 0.0f))); + auto open_connector = vg->addConnector(open_con_node, connector_type::open); + component_ids.emplace(open_connector, id_counter); + + auto pad_board_node = Node::create(glm::vec3(x_pos, y_pos, 0.5f), glm::angleAxis(glm::radians(90.0f), glm::vec3(-1.0f, 0.0f, 0.0f))); + auto pad_board = vg->addPadBoard(pad_board_node); + + vg->join(open_connector, pad_board, enum_to_vec(side::y_pos)); + + ++id_counter; + } + } + std::string name = std::string("pad") + std::to_string(width) + std::to_string(height); + std::string type = "pad"; + return std::make_shared<Module>(vg, name, type, component_ids); } bool import_spaceJoints(rofiworld_ptr rofiworld, const boost::json::array &spaceJoints_array) @@ -434,10 +474,10 @@ bool import_spaceJoint(rofiworld_ptr rofiworld, const boost::json::object &space module_ptr import_spaceJoint_to(rofiworld_ptr rofiworld, const boost::json::object &to_object) { - if (to_object.at("component").as_uint64() != 0) + if (to_object.at("component").as_int64() != 0) return nullptr; - const auto id = to_object.at("id").as_uint64(); + const auto id = static_cast<uint64_t>(to_object.at("id").as_int64()); ASSUMPTION(rofiworld->containsID(id)); return rofiworld->getModuleByID(id); } @@ -454,7 +494,7 @@ void import_spaceJoint_point(const module_ptr module, const boost::json::array & position[i] = static_cast<float>(value.as_double()); } - module->getNode()->setPosVec(position); + module->getNode()->setPosVec(convert_to_editor_coordinates(position)); } void import_spaceJoint_joint(rofiworld_ptr rofiworld, const module_ptr module, const boost::json::object &joint) @@ -464,6 +504,12 @@ void import_spaceJoint_joint(rofiworld_ptr rofiworld, const module_ptr module, c const auto editor_rotation_mat = convert_to_editor_import_coordinates(rofi_rotation_mat); // TO DO rotate somehow + + // const auto root_connector = std::dynamic_pointer_cast<rofi::Connector>(module->getComponentByID(0)); + // ASSUMPTION(root_connector); + // rofiworld->rebuildNodeTree(module, root_connector->getNode()); + // root_connector->getNode()->setRotationQuat(editor_rotation_mat); + } void import_moduleJoints(rofiworld_ptr rofiworld, const boost::json::array &moduleJoints_array) @@ -487,18 +533,11 @@ void import_moduleJoint(rofiworld_ptr rofiworld, const boost::json::object &modu rofiworld->rebuildNodeTree(from_module, from_connector->getNode()); rofiworld->getVoxelGraph()->joinConnectors(from_connector, to_connector); rofiworld->teleportModulesByConnectors(from_connector, to_connector, mutual_orientation); - - // rebuildRofiWorldNodeTree(rofiworld->getModuleWithNode(source_node), source_node, rofiworld); - - // voxel_graph->joinConnectors(selected_connectors.first, selected_connectors.second); - - // rofiworld->teleportModulesByConnectors(selected_connectors.first, selected_connectors.second, selected_cardinality); - } std::pair<module_ptr, connector_ptr> get_moduleJoint_module_connector(rofiworld_ptr rofiworld, const boost::json::object &where_object) { - const auto id = where_object.at("id").as_uint64(); + const auto id = static_cast<uint64_t>(where_object.at("id").as_int64()); const auto module = rofiworld->getModuleByID(id); const auto dock = where_object.at("connector"); @@ -506,7 +545,7 @@ std::pair<module_ptr, connector_ptr> get_moduleJoint_module_connector(rofiworld_ if (dock.is_string()) return {module, module->getConnectorByDock(std::string(dock.as_string()))}; else // number - return {module, std::dynamic_pointer_cast<rofi::Connector>(module->getComponentByID(dock.as_uint64()))}; + return {module, std::dynamic_pointer_cast<rofi::Connector>(module->getComponentByID(dock.as_int64()))}; } rofi::cardinal get_moduleJoint_orientation(const boost::json::string &orientation_string) diff --git a/src/gui/include/gui/ui.hpp b/src/gui/include/gui/ui.hpp index 193d172..9f83c4e 100644 --- a/src/gui/include/gui/ui.hpp +++ b/src/gui/include/gui/ui.hpp @@ -57,6 +57,8 @@ void save_module_ui(const osi::Window &window, edit::UIData &data); void export_file_ui(const osi::Window &window, edit::UIData &data); void export_module_file_ui(const osi::Window &window, edit::UIData &data); void export_rofiworld_file_ui(const osi::Window &window, edit::UIData &data); +void import_file_ui(const osi::Window &window, edit::UIData &data); +void import_rofiworld_file_ui(const osi::Window &window, edit::UIData &data); void rotation_settings(const osi::Window &window, edit::UIData &data); void experimental_warning(const osi::Window &window, edit::UIData &data); diff --git a/src/gui/src/ui.cpp b/src/gui/src/ui.cpp index 6b61ec4..0ae207b 100644 --- a/src/gui/src/ui.cpp +++ b/src/gui/src/ui.cpp @@ -180,14 +180,21 @@ void rofiworld_menu_ui(const osi::Window &window, edit::UIData &data) void file_menu_ui(const osi::Window &window, edit::UIData &data) { - if (ImGui::MenuItem("Export Configuration", NULL, false, data.editor_mode_I == edit::mode_I::build)) + using namespace edit; + bool available = (data.editor_mode_I == mode_I::build && data.editor_phase == phase::one) + || (data.editor_mode_II == mode_II::build && data.editor_phase == phase::two); + if (ImGui::MenuItem("Export Configuration", NULL, false, available)) { data.export_file_visible = true; } - // if (ImGui::MenuItem("Import Configuration", NULL, false, data.editor_mode_I == edit::mode_I::build)) - // { - // // TO DO - // } + + if (data.editor_phase == phase::one) + return; + + if (ImGui::MenuItem("Import Configuration", NULL, false, available)) + { + data.import_file_visible = true; + } } void help_menu_ui(const osi::Window &window, edit::UIData &data) @@ -238,6 +245,7 @@ void mode_I_build_ui(const osi::Window &window, edit::UIData &data) build_toolbar_ui(window, data); save_module_ui(window, data); export_file_ui(window, data); + import_file_ui(window, data); create_pad_ui(window, data); rotation_settings(window, data); @@ -255,6 +263,7 @@ void mode_II_build_ui(const osi::Window &window, edit::UIData &data) module_rotation_ui(window, data); component_rotation_ui(window, data); export_file_ui(window, data); + import_file_ui(window, data); } int build_mode_I_to_int(edit::build_mode_I mode) @@ -927,7 +936,7 @@ void save_module_ui(const osi::Window &window, edit::UIData &data) ImGui::NewLine(); } - if (ImGui::Button("Submit")) { + if (ImGui::Button("Submit##SaveModuleButton")) { data.save_module_prompt = true; data.export_file_prompt = true; data.save_module_visible = false; @@ -979,7 +988,7 @@ void export_module_file_ui(const osi::Window &window, edit::UIData &data) ImGui::NewLine(); } - if (ImGui::Button("Submit")) { + if (ImGui::Button("Submit##ExportModuleButton")) { data.export_file_prompt = true; data.export_file_visible = false; } @@ -999,14 +1008,21 @@ void export_rofiworld_file_ui(const osi::Window &window, edit::UIData &data) ImGui::Text("Enter Text:"); // InputText takes a pointer to a buffer, a maximum buffer size, and optional flags - ImGui::InputText("File Name##RofiWorldFileNameInput", data.name_buffer, sizeof(data.name_buffer), + ImGui::InputText("File Name##RofiWorldExportFileNameInput", data.name_buffer, sizeof(data.name_buffer), ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_AlwaysOverwrite); + if (data.export_file_error && data.current_second - data.error_start_second < 2) + ImGui::Text(data.error_msg.c_str()); + else + { + data.export_file_error = false; + ImGui::NewLine(); + } ImGui::Checkbox("Selected Module as spaceJoint##spaceJointCheckBox", &data.export_rofiworld_use_selected_space_joint); - if (ImGui::Button("Submit")) { + if (ImGui::Button("Submit##ExportRofiWorldButton")) { data.export_file_prompt = true; data.export_file_visible = false; } @@ -1014,6 +1030,48 @@ void export_rofiworld_file_ui(const osi::Window &window, edit::UIData &data) ImGui::End(); } +void import_file_ui(const osi::Window &window, edit::UIData &data) +{ + if (!data.import_file_visible) + return; + + ImGui::SetNextWindowPos(ImVec2(0, mode_toolbar_height * 3), ImGuiCond_Appearing, ImVec2(0.0f, 0.0f)); + + import_rofiworld_file_ui(window, data); +} + +void import_rofiworld_file_ui(const osi::Window &window, edit::UIData &data) +{ + if (!ImGui::Begin("Import RofiWorld Configuration", &data.import_file_visible, + ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) + { + ImGui::End(); + return; + } + + ImGui::Text("Enter Text:"); + + // InputText takes a pointer to a buffer, a maximum buffer size, and optional flags + ImGui::InputText("File Name##RofiWorldImportFileNameInput", data.name_buffer, sizeof(data.name_buffer), + ImGuiInputTextFlags_AutoSelectAll + | ImGuiInputTextFlags_AlwaysOverwrite); + + if (data.import_file_error && data.current_second - data.error_start_second < 2) + ImGui::Text(data.error_msg.c_str()); + else + { + data.import_file_error = false; + ImGui::NewLine(); + } + + if (ImGui::Button("Submit##ImportRofiWorldButton")) { + data.import_file_prompt = true; + data.import_file_visible = false; + } + + ImGui::End(); +} + void rotation_settings(const osi::Window &window, edit::UIData &data) { if (!data.connector_selected diff --git a/src/rofi/include/rofi/rofiworld.hpp b/src/rofi/include/rofi/rofiworld.hpp index 0c8fb2d..80ab2db 100644 --- a/src/rofi/include/rofi/rofiworld.hpp +++ b/src/rofi/include/rofi/rofiworld.hpp @@ -32,10 +32,13 @@ class RofiWorld public: + bool empty() const { return voxel_graph->empty() && node_tree.empty(); } + const std::vector<node_ptr> &getNodeTree() const { return node_tree; } voxel_graph_ptr getVoxelGraph() const { return voxel_graph; } const std::map<module_ptr, uint64_t> &getModulesMap() const { return modules_map; } + const std::set<module_ptr> &getModulesSet() const { return modules_set; } const uint64_t getModuleID(const module_ptr module) const { return modules_map.at(module); } const module_ptr getModuleByID(const uint64_t id) const; bool containsID(uint64_t id) const { return ids_set.contains(id); } -- GitLab