diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 2944ffccd8..562a939fb5 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1636,6 +1636,10 @@ void GLCanvas3D::render() m_camera.debug_render(); #endif // ENABLE_CAMERA_STATISTICS +#if ENABLE_3DCONNEXION_DEVICES + wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog(); +#endif // ENABLE_3DCONNEXION_DEVICES + wxGetApp().imgui()->render(); m_canvas->SwapBuffers(); @@ -2374,6 +2378,21 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) #endif /* __APPLE__ */ post_event(SimpleEvent(EVT_GLTOOLBAR_COPY)); break; + +#if ENABLE_3DCONNEXION_DEVICES +#ifdef __APPLE__ + case 'm': + case 'M': +#else /* __APPLE__ */ + case WXK_CONTROL_M: +#endif /* __APPLE__ */ + { + Mouse3DController& controller = wxGetApp().plater()->get_mouse3d_controller(); + controller.show_settings_dialog(!controller.is_settings_dialog_shown()); + break; + } +#endif // ENABLE_3DCONNEXION_DEVICES + #ifdef __APPLE__ case 'v': case 'V': diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index 8e4d9eebfa..7d7e826850 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -528,6 +528,11 @@ void ImGuiWrapper::init_style() // Slider set_color(ImGuiCol_SliderGrab, COL_ORANGE_DARK); set_color(ImGuiCol_SliderGrabActive, COL_ORANGE_LIGHT); + +#if ENABLE_3DCONNEXION_DEVICES + // Separator + set_color(ImGuiCol_Separator, COL_ORANGE_LIGHT); +#endif // ENABLE_3DCONNEXION_DEVICES } void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index e3ef335e68..4bd56ee764 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -157,6 +157,9 @@ void KBShortcutsDialog::fill_shortcuts() plater_shortcuts.push_back(Shortcut("Z", L("Zoom to selected object"))); plater_shortcuts.push_back(Shortcut("I", L("Zoom in"))); plater_shortcuts.push_back(Shortcut("O", L("Zoom out"))); +#if ENABLE_3DCONNEXION_DEVICES + plater_shortcuts.push_back(Shortcut(ctrl+"M", L("Show/Hide 3Dconnexion devices settings dialog"))); +#endif // ENABLE_3DCONNEXION_DEVICES plater_shortcuts.push_back(Shortcut("ESC", L("Unselect gizmo / Clear selection"))); #if ENABLE_RENDER_PICKING_PASS // Don't localize debugging texts. diff --git a/src/slic3r/GUI/Mouse3DController.cpp b/src/slic3r/GUI/Mouse3DController.cpp index 10022915a7..18c17f7c2f 100644 --- a/src/slic3r/GUI/Mouse3DController.cpp +++ b/src/slic3r/GUI/Mouse3DController.cpp @@ -9,6 +9,10 @@ #include +#include + +#include "I18N.hpp" + // WARN: If updating these lists, please also update resources/udev/90-3dconnexion.rules static const std::vector _3DCONNEXION_VENDORS = @@ -64,6 +68,30 @@ void Mouse3DController::State::set_button(unsigned int id) m_buttons.push_back(id); } +void Mouse3DController::State::reset_buttons() +{ + std::lock_guard lock(m_mutex); + return m_buttons.clear(); +} + +const Vec3d& Mouse3DController::State::get_translation() const +{ + std::lock_guard lock(m_mutex); + return m_translation; +} + +const Vec3f& Mouse3DController::State::get_rotation() const +{ + std::lock_guard lock(m_mutex); + return m_rotation; +} + +const std::vector& Mouse3DController::State::get_buttons() const +{ + std::lock_guard lock(m_mutex); + return m_buttons; +} + bool Mouse3DController::State::has_translation() const { std::lock_guard lock(m_mutex); @@ -98,25 +126,28 @@ bool Mouse3DController::State::apply(GLCanvas3D& canvas) if (has_translation()) { - camera.set_target(camera.get_target() + m_translation_scale * (m_translation(0) * camera.get_dir_right() + m_translation(1) * camera.get_dir_forward() + m_translation(2) * camera.get_dir_up())); - m_translation = Vec3d::Zero(); + Vec3d translation = get_translation(); + camera.set_target(camera.get_target() + m_translation_scale * (translation(0) * camera.get_dir_right() + translation(1) * camera.get_dir_forward() + translation(2) * camera.get_dir_up())); + set_translation(Vec3d::Zero()); ret = true; } if (has_rotation()) { - float theta = m_rotation_scale * m_rotation(0); - float phi = m_rotation_scale * m_rotation(2); + Vec3f rotation = get_rotation(); + float theta = m_rotation_scale * rotation(0); + float phi = m_rotation_scale * rotation(2); float sign = camera.inverted_phi ? -1.0f : 1.0f; camera.phi += sign * phi; camera.set_theta(camera.get_theta() + theta, wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA); - m_rotation = Vec3f::Zero(); + set_rotation(Vec3f::Zero()); ret = true; } if (has_any_button()) { - for (unsigned int i : m_buttons) + std::vector buttons = get_buttons(); + for (unsigned int i : buttons) { switch (i) { @@ -126,7 +157,7 @@ bool Mouse3DController::State::apply(GLCanvas3D& canvas) } } - m_buttons.clear(); + reset_buttons(); ret = true; } @@ -138,6 +169,7 @@ Mouse3DController::Mouse3DController() , m_canvas(nullptr) , m_device(nullptr) , m_running(false) + , m_settings_dialog(false) { } @@ -174,6 +206,51 @@ void Mouse3DController::shutdown() m_initialized = false; } +void Mouse3DController::render_settings_dialog() const +{ + if ((m_canvas == nullptr) || !m_running || !m_settings_dialog) + return; + + ImGuiWrapper& imgui = *wxGetApp().imgui(); + + std::lock_guard lock(m_mutex); + Size cnv_size = m_canvas->get_canvas_size(); + + imgui.set_next_window_pos(0.5f * (float)cnv_size.get_width(), 0.5f * (float)cnv_size.get_height(), ImGuiCond_Always, 0.5f, 0.5f); + imgui.set_next_window_bg_alpha(0.5f); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + + imgui.begin(_(L("3Dconnexion settings")), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse); + + std::vector product(1024, 0); + hid_get_product_string(m_device, product.data(), 1024); + + const ImVec4& color = ImGui::GetStyleColorVec4(ImGuiCol_Separator); + ImGui::PushStyleColor(ImGuiCol_Text, color); + imgui.text(_(L("Device:"))); + ImGui::PopStyleColor(); + ImGui::SameLine(); + imgui.text(boost::nowide::narrow(product.data())); + ImGui::Separator(); + + ImGui::PushStyleColor(ImGuiCol_Text, color); + imgui.text(_(L("Speed:"))); + ImGui::PopStyleColor(); + + float translation = (float)m_state.get_translation_scale() / State::DefaultTranslationScale; + if (ImGui::SliderFloat(_(L("Translation")), &translation, 0.5f, 2.0f, "%.1f")) + m_state.set_translation_scale(State::DefaultTranslationScale * (double)translation); + + float rotation = (float)m_state.get_rotation_scale() / State::DefaultRotationScale; + if (ImGui::SliderFloat(_(L("Rotation")), &rotation, 0.5f, 2.0f, "%.1f")) + m_state.set_rotation_scale(State::DefaultRotationScale * rotation); + + imgui.end(); + + ImGui::PopStyleVar(); +} + void Mouse3DController::connect_device() { if (m_device != nullptr) diff --git a/src/slic3r/GUI/Mouse3DController.hpp b/src/slic3r/GUI/Mouse3DController.hpp index 64fa34a44c..778a3efede 100644 --- a/src/slic3r/GUI/Mouse3DController.hpp +++ b/src/slic3r/GUI/Mouse3DController.hpp @@ -19,9 +19,11 @@ class Mouse3DController { class State { + public: static const double DefaultTranslationScale; static const float DefaultRotationScale; + private: mutable std::mutex m_mutex; Vec3d m_translation; @@ -37,6 +39,11 @@ class Mouse3DController void set_translation(const Vec3d& translation); void set_rotation(const Vec3f& rotation); void set_button(unsigned int id); + void reset_buttons(); + + const Vec3d& get_translation() const; + const Vec3f& get_rotation() const; + const std::vector& get_buttons() const; bool has_translation() const; bool has_rotation() const; @@ -54,12 +61,13 @@ class Mouse3DController }; bool m_initialized; - State m_state; + mutable State m_state; std::thread m_thread; GLCanvas3D* m_canvas; - std::mutex m_mutex; + mutable std::mutex m_mutex; hid_device* m_device; bool m_running; + bool m_settings_dialog; public: Mouse3DController(); @@ -87,6 +95,10 @@ public: return (m_canvas != nullptr) ? m_state.apply(*m_canvas) : false; } + bool is_settings_dialog_shown() const { return m_settings_dialog; } + void show_settings_dialog(bool show) { m_settings_dialog = show; } + void render_settings_dialog() const; + private: void connect_device(); void disconnect_device();