This commit is contained in:
Enrico Turri 2020-03-09 15:23:38 +01:00
commit 56fa84c9d9
6 changed files with 80 additions and 42 deletions

View file

@ -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)

View file

@ -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;
}

View file

@ -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();
}
@ -2846,16 +2876,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! "

View file

@ -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);
}
}
@ -348,7 +351,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,16 +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) {
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 {
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);
}

View file

@ -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 {
@ -99,10 +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
DriveData m_drive_data_last_eject;
mutable tbb::mutex m_drives_mutex;
// Returns drive path (same as path in DriveData) if exists otherwise empty string.

View file

@ -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(