From ec75b760b8e7277ed90f0e4cd7113190db4607bf Mon Sep 17 00:00:00 2001 From: bubnikv <bubnikv@gmail.com> Date: Mon, 9 Mar 2020 10:36:55 +0100 Subject: [PATCH 1/5] Fix of saving the 3DConnexion status on OSX. Fixes 2.2.0 RC2 - 3Dconnexion settings not saved / Zoom digital (#3791) --- src/slic3r/GUI/Mouse3DController.cpp | 10 ++++++---- src/slic3r/GUI/Mouse3DHandlerMac.mm | 4 ++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/Mouse3DController.cpp b/src/slic3r/GUI/Mouse3DController.cpp index 8bc9744f1..0cd39b092 100644 --- a/src/slic3r/GUI/Mouse3DController.cpp +++ b/src/slic3r/GUI/Mouse3DController.cpp @@ -368,6 +368,8 @@ void Mouse3DController::render_settings_dialog(GLCanvas3D& canvas) const void Mouse3DController::connected(std::string device_name) { + assert(! m_connected); + assert(m_device_str.empty()); m_device_str = device_name; // Copy the parameters for m_device_str into the current parameters. if (auto it_params = m_params_by_device.find(m_device_str); it_params != m_params_by_device.end()) { @@ -380,13 +382,13 @@ void Mouse3DController::connected(std::string device_name) void Mouse3DController::disconnected() { // Copy the current parameters for m_device_str into the parameter database. - assert(! m_device_str.empty()); - if (! m_device_str.empty()) { + assert(m_connected == ! m_device_str.empty()); + if (m_connected) { tbb::mutex::scoped_lock lock(m_params_ui_mutex); m_params_by_device[m_device_str] = m_params_ui; + m_device_str.clear(); + m_connected = false; } - m_device_str.clear(); - m_connected = false; } bool Mouse3DController::handle_input(const DataPacketAxis& packet) diff --git a/src/slic3r/GUI/Mouse3DHandlerMac.mm b/src/slic3r/GUI/Mouse3DHandlerMac.mm index d40948cd1..eaf580908 100644 --- a/src/slic3r/GUI/Mouse3DHandlerMac.mm +++ b/src/slic3r/GUI/Mouse3DHandlerMac.mm @@ -152,6 +152,8 @@ static void DeviceAdded(uint32_t unused) static void DeviceRemoved(uint32_t unused) { BOOST_LOG_TRIVIAL(info) << "3dx device removed\n"; + assert(m_connected); + assert(! m_device_str.empty()); mouse_3d_controller->disconnected(); } @@ -214,6 +216,8 @@ void Mouse3DController::shutdown() CleanupConnexionHandlers(); unload_driver(); } + // Copy the current parameters to parameter database, mark the device as disconnected. + this->disconnected(); mouse_3d_controller = nullptr; } From e83fb4582c1de8477fd10d8675e3b0a1e5ef9767 Mon Sep 17 00:00:00 2001 From: bubnikv <bubnikv@gmail.com> Date: Mon, 9 Mar 2020 10:56:51 +0100 Subject: [PATCH 2/5] Reworked the eject on unix systems to wait for the return of the system call to the command line utility and send out the unmount wxWidgets event immediately. Hopefully improves 2.2.0-RC Eject is very slow in Linux (#3795) --- src/slic3r/GUI/RemovableDriveManager.cpp | 10 ++++++++-- src/slic3r/GUI/RemovableDriveManager.hpp | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/RemovableDriveManager.cpp b/src/slic3r/GUI/RemovableDriveManager.cpp index 2264cc954..5054d061e 100644 --- a/src/slic3r/GUI/RemovableDriveManager.cpp +++ b/src/slic3r/GUI/RemovableDriveManager.cpp @@ -348,7 +348,10 @@ void RemovableDriveManager::eject_drive() return; } - m_drive_data_last_eject = *it_drive_data; + assert(m_callback_evt_handler); + if (m_callback_evt_handler) + wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::move(*it_drive_data))); + m_current_drives.erase(it_drive_data); } } @@ -473,12 +476,15 @@ void RemovableDriveManager::update() tbb::mutex::scoped_lock lock(m_drives_mutex); std::sort(current_drives.begin(), current_drives.end()); if (current_drives != m_current_drives) { +#ifdef WIN32 if (! m_drive_data_last_eject.empty() && std::find(current_drives.begin(), current_drives.end(), m_drive_data_last_eject) == current_drives.end()) { assert(m_callback_evt_handler); if (m_callback_evt_handler) wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::move(m_drive_data_last_eject))); m_drive_data_last_eject.clear(); - } else { + } else +#endif // WIN32 + { assert(m_callback_evt_handler); if (m_callback_evt_handler) wxPostEvent(m_callback_evt_handler, RemovableDrivesChangedEvent(EVT_REMOVABLE_DRIVES_CHANGED)); diff --git a/src/slic3r/GUI/RemovableDriveManager.hpp b/src/slic3r/GUI/RemovableDriveManager.hpp index 3b808d9d7..7ada13e5a 100644 --- a/src/slic3r/GUI/RemovableDriveManager.hpp +++ b/src/slic3r/GUI/RemovableDriveManager.hpp @@ -65,6 +65,8 @@ public: // Verify whether the path provided is on removable media. If so, save the path for further eject and return true, otherwise return false. bool set_and_verify_last_save_path(const std::string &path); // Eject drive of a file set by set_and_verify_last_save_path(). + // On Unix / OSX, the function blocks and sends out the EVT_REMOVABLE_DRIVE_EJECTED event on success. + // On Windows, the function does not block, and the eject is detected in the background thread. void eject_drive(); struct RemovableDrivesStatus { @@ -102,7 +104,9 @@ private: // When user requested an eject, the drive to be forcefuly ejected is stored here, so the next update will // recognize that the eject was finished with success and an eject event is sent out. // guarded with m_drives_mutex +#ifdef WIN32 DriveData m_drive_data_last_eject; +#endif // WIN32 mutable tbb::mutex m_drives_mutex; // Returns drive path (same as path in DriveData) if exists otherwise empty string. From aac691c0e7aa19e697d00ac0e92bf4bdb8d121f5 Mon Sep 17 00:00:00 2001 From: bubnikv <bubnikv@gmail.com> Date: Mon, 9 Mar 2020 11:47:20 +0100 Subject: [PATCH 3/5] Forced SD card / USB drive eject now sends out the event immediately on Windows as well as on Unix platforms including OSX. --- src/slic3r/GUI/RemovableDriveManager.cpp | 21 +++++++-------------- src/slic3r/GUI/RemovableDriveManager.hpp | 6 ------ 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/slic3r/GUI/RemovableDriveManager.cpp b/src/slic3r/GUI/RemovableDriveManager.cpp index 5054d061e..0c4c417b2 100644 --- a/src/slic3r/GUI/RemovableDriveManager.cpp +++ b/src/slic3r/GUI/RemovableDriveManager.cpp @@ -103,7 +103,10 @@ void RemovableDriveManager::eject_drive() return; } CloseHandle(handle); - m_drive_data_last_eject = *it_drive_data; + assert(m_callback_evt_handler); + if (m_callback_evt_handler) + wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::move(*it_drive_data))); + m_current_drives.erase(it_drive_data); } } @@ -476,19 +479,9 @@ void RemovableDriveManager::update() tbb::mutex::scoped_lock lock(m_drives_mutex); std::sort(current_drives.begin(), current_drives.end()); if (current_drives != m_current_drives) { -#ifdef WIN32 - if (! m_drive_data_last_eject.empty() && std::find(current_drives.begin(), current_drives.end(), m_drive_data_last_eject) == current_drives.end()) { - assert(m_callback_evt_handler); - if (m_callback_evt_handler) - wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::move(m_drive_data_last_eject))); - m_drive_data_last_eject.clear(); - } else -#endif // WIN32 - { - assert(m_callback_evt_handler); - if (m_callback_evt_handler) - wxPostEvent(m_callback_evt_handler, RemovableDrivesChangedEvent(EVT_REMOVABLE_DRIVES_CHANGED)); - } + assert(m_callback_evt_handler); + if (m_callback_evt_handler) + wxPostEvent(m_callback_evt_handler, RemovableDrivesChangedEvent(EVT_REMOVABLE_DRIVES_CHANGED)); } m_current_drives = std::move(current_drives); } diff --git a/src/slic3r/GUI/RemovableDriveManager.hpp b/src/slic3r/GUI/RemovableDriveManager.hpp index 7ada13e5a..8b661d19c 100644 --- a/src/slic3r/GUI/RemovableDriveManager.hpp +++ b/src/slic3r/GUI/RemovableDriveManager.hpp @@ -101,12 +101,6 @@ private: // m_current_drives is guarded by m_drives_mutex // sorted ascending by path std::vector<DriveData> m_current_drives; - // When user requested an eject, the drive to be forcefuly ejected is stored here, so the next update will - // recognize that the eject was finished with success and an eject event is sent out. - // guarded with m_drives_mutex -#ifdef WIN32 - DriveData m_drive_data_last_eject; -#endif // WIN32 mutable tbb::mutex m_drives_mutex; // Returns drive path (same as path in DriveData) if exists otherwise empty string. From cbd80685c28398d0f8174f6c3a707ba1d5b7aa08 Mon Sep 17 00:00:00 2001 From: bubnikv <bubnikv@gmail.com> Date: Mon, 9 Mar 2020 12:29:40 +0100 Subject: [PATCH 4/5] Fix of Print settings dropdown list messed up after deleting an entry (#3800) --- src/slic3r/GUI/Tab.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 9a6313e70..9e49dc5bd 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2861,10 +2861,10 @@ void Tab::select_preset(std::string preset_name, bool delete_current) // Mark the print & filament enabled if they are compatible with the currently selected preset. // The following method should not discard changes of current print or filament presets on change of a printer profile, // if they are compatible with the current printer. - auto update_compatible_type = [](bool technology_changed, bool on_page, bool show_incompatible_presets) { - return technology_changed ? PresetSelectCompatibleType::Always : - on_page ? PresetSelectCompatibleType::Never : - (show_incompatible_presets ? PresetSelectCompatibleType::OnlyIfWasCompatible : PresetSelectCompatibleType::Always); + auto update_compatible_type = [delete_current](bool technology_changed, bool on_page, bool show_incompatible_presets) { + return (delete_current || technology_changed) ? PresetSelectCompatibleType::Always : + on_page ? PresetSelectCompatibleType::Never : + show_incompatible_presets ? PresetSelectCompatibleType::OnlyIfWasCompatible : PresetSelectCompatibleType::Always; }; if (current_dirty || delete_current || print_tab || printer_tab) m_preset_bundle->update_compatible( From c489663126828fde0d27ac405aad9f3c82f135d8 Mon Sep 17 00:00:00 2001 From: tamasmeszaros <meszaros.q@gmail.com> Date: Mon, 9 Mar 2020 14:05:54 +0100 Subject: [PATCH 5/5] Add arrange support for unprintable items --- src/slic3r/GUI/Plater.cpp | 71 +++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 48eb86743..e1f75d07d 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1509,6 +1509,7 @@ struct Plater::priv ret.poly.contour = std::move(p); ret.translation = scaled(m_pos); ret.rotation = m_rotation; + ret.priority++; return ret; } } wipetower; @@ -1572,18 +1573,23 @@ struct Plater::priv // the current bed width. static const constexpr double LOGICAL_BED_GAP = 1. / 5.; - ArrangePolygons m_selected, m_unselected; + ArrangePolygons m_selected, m_unselected, m_unprintable; // clear m_selected and m_unselected, reserve space for next usage void clear_input() { const Model &model = plater().model; - size_t count = 0; // To know how much space to reserve - for (auto obj : model.objects) count += obj->instances.size(); + size_t count = 0, cunprint = 0; // To know how much space to reserve + for (auto obj : model.objects) + for (auto mi : obj->instances) + mi->printable ? count++ : cunprint++; + m_selected.clear(); m_unselected.clear(); + m_unprintable.clear(); m_selected.reserve(count + 1 /* for optional wti */); m_unselected.reserve(count + 1 /* for optional wti */); + m_unprintable.reserve(cunprint /* for optional wti */); } // Stride between logical beds @@ -1612,8 +1618,10 @@ struct Plater::priv clear_input(); for (ModelObject *obj: plater().model.objects) - for (ModelInstance *mi : obj->instances) - m_selected.emplace_back(get_arrange_poly(mi)); + for (ModelInstance *mi : obj->instances) { + ArrangePolygons & cont = mi->printable ? m_selected : m_unprintable; + cont.emplace_back(get_arrange_poly(mi)); + } auto& wti = plater().updated_wipe_tower(); if (wti) m_selected.emplace_back(get_arrange_poly(&wti)); @@ -1648,9 +1656,12 @@ struct Plater::priv for (size_t i = 0; i < inst_sel.size(); ++i) { ArrangePolygon &&ap = get_arrange_poly(mo->instances[i]); - inst_sel[i] ? - m_selected.emplace_back(std::move(ap)) : - m_unselected.emplace_back(std::move(ap)); + ArrangePolygons &cont = mo->instances[i]->printable ? + (inst_sel[i] ? m_selected : + m_unselected) : + m_unprintable; + + cont.emplace_back(std::move(ap)); } } @@ -1682,16 +1693,35 @@ struct Plater::priv public: using PlaterJob::PlaterJob; - int status_range() const override { return int(m_selected.size()); } + int status_range() const override + { + return int(m_selected.size() + m_unprintable.size()); + } void process() override; void finalize() override { // Ignore the arrange result if aborted. if (was_canceled()) return; - + + // Unprintable items go to the last virtual bed + int beds = 0; + // Apply the arrange result to all selected objects - for (ArrangePolygon &ap : m_selected) ap.apply(); + for (ArrangePolygon &ap : m_selected) { + beds = std::max(ap.bed_idx, beds); + ap.apply(); + } + + // Get the virtual beds from the unselected items + for (ArrangePolygon &ap : m_unselected) + beds = std::max(ap.bed_idx, beds); + + // Move the unprintable items to the last virtual bed. + for (ArrangePolygon &ap : m_unprintable) { + ap.bed_idx += beds + 1; + ap.apply(); + } plater().update(); } @@ -2838,16 +2868,21 @@ void Plater::priv::ArrangeJob::process() { } coord_t min_d = scaled(dist); - auto count = unsigned(m_selected.size()); + auto count = unsigned(m_selected.size() + m_unprintable.size()); arrangement::BedShapeHint bedshape = plater().get_bed_shape_hint(); - + + auto stopfn = [this]() { return was_canceled(); }; + try { arrangement::arrange(m_selected, m_unselected, min_d, bedshape, - [this, count](unsigned st) { - if (st > 0) // will not finalize after last one - update_status(int(count - st), arrangestr); - }, - [this]() { return was_canceled(); }); + [this, count](unsigned st) { + st += m_unprintable.size(); + if (st > 0) update_status(int(count - st), arrangestr); + }, stopfn); + arrangement::arrange(m_unprintable, {}, min_d, bedshape, + [this, count](unsigned st) { + if (st > 0) update_status(int(count - st), arrangestr); + }, stopfn); } catch (std::exception & /*e*/) { GUI::show_error(plater().q, _(L("Could not arrange model objects! "