mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-13 03:49:00 +08:00
Forbid seq arrange for a single bed in cases where it would reorder objects unexpectedly
This commit is contained in:
parent
f2d0bc1f4f
commit
8180bea835
@ -18,6 +18,29 @@
|
||||
namespace Slic3r {
|
||||
|
||||
|
||||
static bool can_arrange_selected_bed(const Model& model, int bed_idx)
|
||||
{
|
||||
// When arranging a single bed, all instances of each object present must be on the same bed.
|
||||
// Otherwise, the resulting order may not be possible to apply without messing up order
|
||||
// on the other beds.
|
||||
const auto map = s_multiple_beds.get_inst_map();
|
||||
for (const ModelObject* mo : model.objects) {
|
||||
std::map<int, bool> used_beds;
|
||||
bool mo_on_this_bed = false;
|
||||
for (const ModelInstance* mi : mo->instances) {
|
||||
int id = -1;
|
||||
if (auto it = map.find(mi->id()); it != map.end())
|
||||
id = it->second;
|
||||
if (id == bed_idx)
|
||||
mo_on_this_bed = true;
|
||||
used_beds[id] = true;
|
||||
}
|
||||
if (mo_on_this_bed && used_beds.size() != 1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static Sequential::PrinterGeometry get_printer_geometry(const ConfigBase& config)
|
||||
{
|
||||
enum ShapeType {
|
||||
@ -187,6 +210,9 @@ void arrange_model_sequential(Model& model, const ConfigBase& config, bool curre
|
||||
SeqArrange::SeqArrange(const Model& model, const ConfigBase& config, bool current_bed_only)
|
||||
{
|
||||
m_selected_bed = current_bed_only ? s_multiple_beds.get_active_bed() : -1;
|
||||
if (m_selected_bed != -1 && ! can_arrange_selected_bed(model, m_selected_bed))
|
||||
throw ExceptionCannotAttemptSeqArrange();
|
||||
|
||||
m_printer_geometry = get_printer_geometry(config);
|
||||
m_solver_configuration = get_solver_config(m_printer_geometry);
|
||||
m_objects = get_objects_to_print(model, m_printer_geometry, m_selected_bed);
|
||||
@ -201,6 +227,25 @@ void SeqArrange::process_seq_arrange(std::function<void(int)> progress_fn)
|
||||
m_solver_configuration,
|
||||
m_printer_geometry,
|
||||
m_objects, progress_fn);
|
||||
|
||||
// If this was arrangement of a single bed, check that all instances of a single object
|
||||
// ended up on the same bed. Otherwise we cannot apply the result (instances of a single
|
||||
// object always follow one another in the object list and therefore the print).
|
||||
if (m_selected_bed != -1 && s_multiple_beds.get_number_of_beds() > 1) {
|
||||
int expected_plate = -1;
|
||||
for (const Sequential::ObjectToPrint& otp : m_objects) {
|
||||
auto it = std::find_if(m_plates.begin(), m_plates.end(), [&otp](const auto& plate)
|
||||
{ return std::any_of(plate.scheduled_objects.begin(), plate.scheduled_objects.end(),
|
||||
[&otp](const auto& obj) { return otp.id == obj.id;
|
||||
});
|
||||
});
|
||||
assert(it != m_plates.end());
|
||||
size_t plate_id = it - m_plates.begin();
|
||||
if (expected_plate != -1 && expected_plate != plate_id)
|
||||
throw ExceptionCannotApplySeqArrange();
|
||||
expected_plate = otp.glued_to_next ? plate_id : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,10 +10,12 @@ namespace Slic3r {
|
||||
class Model;
|
||||
class ConfigBase;
|
||||
|
||||
class ExceptionCannotAttemptSeqArrange : public std::exception {};
|
||||
class ExceptionCannotApplySeqArrange : public std::exception {};
|
||||
|
||||
void arrange_model_sequential(Model& model, const ConfigBase& config);
|
||||
bool check_seq_printability(const Model& model, const ConfigBase& config);
|
||||
|
||||
|
||||
// This is just a helper class to collect data for seq. arrangement, running the arrangement
|
||||
// and applying the results to model. It is here so the processing itself can be offloaded
|
||||
// into a separate thread without copying the Model or sharing it with UI thread.
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/MsgDialog.hpp"
|
||||
|
||||
|
||||
|
||||
@ -39,11 +40,24 @@ void SeqArrangeJob::process(Ctl& ctl)
|
||||
|
||||
|
||||
|
||||
void SeqArrangeJob::finalize(bool canceled, std::exception_ptr&)
|
||||
void SeqArrangeJob::finalize(bool canceled, std::exception_ptr& eptr)
|
||||
{
|
||||
// If the task was cancelled, the stopping exception was already caught
|
||||
// in 'process' function. Let any other exception propagate further.
|
||||
if (! canceled) {
|
||||
// in 'process' function. Any other exception propagates through here.
|
||||
bool error = false;
|
||||
if (eptr) {
|
||||
try {
|
||||
std::rethrow_exception(eptr);
|
||||
} catch (const ExceptionCannotApplySeqArrange&) {
|
||||
ErrorDialog dlg(wxGetApp().plater(), _L("The result of the single-bed arrange would scatter instances of a single object between several beds, "
|
||||
"possibly affecting order of printing of the non-selected beds. Consider using global arrange across all beds."), false);
|
||||
dlg.ShowModal();
|
||||
error = true;
|
||||
eptr = nullptr; // The exception is handled.
|
||||
}
|
||||
}
|
||||
|
||||
if (! canceled && ! error) {
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _u8L("Arrange for sequential print"));
|
||||
m_seq_arrange->apply_seq_arrange(wxGetApp().model());
|
||||
wxGetApp().plater()->canvas3D()->reload_scene(true, true);
|
||||
|
@ -7122,8 +7122,14 @@ void Plater::arrange(bool current_bed_only)
|
||||
const bool sequential = p->config->has("complete_objects") && p->config->opt_bool("complete_objects");
|
||||
|
||||
if (p->can_arrange()) {
|
||||
if (sequential)
|
||||
replace_job(this->get_ui_job_worker(), std::make_unique<SeqArrangeJob>(this->model(), *p->config, current_bed_only));
|
||||
if (sequential) {
|
||||
try {
|
||||
replace_job(this->get_ui_job_worker(), std::make_unique<SeqArrangeJob>(this->model(), *p->config, current_bed_only));
|
||||
} catch (const ExceptionCannotAttemptSeqArrange&) {
|
||||
ErrorDialog dlg(this, _L("Sequential arrange for a single bed is only allowed when all instances of the affected objects are on the same bed."), false);
|
||||
dlg.ShowModal();
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto& w = get_ui_job_worker();
|
||||
arrange(w, mode);
|
||||
|
Loading…
x
Reference in New Issue
Block a user