mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-13 20:25:59 +08:00
Multiple beds (part 7):
This is where it really gets nasty: - Switch background_process.m_temp_output_path is now updated when beds are switched, so each Print writes to a different file. - When switching beds in Preview, there is a cache in GCodeViewer which would mistakenly not load the other preview (happens in case when switching to a bed which is not sliced and back). Bypass this cache when beds are being switched. - Added a CallAfter logic into GLCanvas3D::select_bed (the central function where beds are switched). It now does the following: 1. Stops the background process 2. Schedules a callafter which then 3. wxYields the event queue (so all events generated as a result of (1) are consumed before active bed is switched. 4. switches active bed 5. fires couple of update functions and events, schedules background process - When BSProcess is switched to the new bed, it now calls on_slicing_update (in sync). This is to regenerate all slicing error/warning notifications. The on_slicing_update function was updated to be able to process all print(object)steps and objects. - Sliced info in sidebar did not properly show when switching beds in 3D scene. Added explicit refresh into update_background_process.
This commit is contained in:
parent
87a1fe8c65
commit
cc73ff8f4f
@ -9,6 +9,7 @@ namespace Slic3r {
|
||||
|
||||
MultipleBeds s_multiple_beds;
|
||||
bool s_reload_preview_after_switching_beds = false;
|
||||
bool s_beds_just_switched = false;
|
||||
|
||||
|
||||
|
||||
|
@ -14,6 +14,7 @@ class BuildVolume;
|
||||
class PrintBase;
|
||||
|
||||
extern bool s_reload_preview_after_switching_beds;
|
||||
extern bool s_beds_just_switched;
|
||||
|
||||
class MultipleBeds {
|
||||
public:
|
||||
|
@ -102,10 +102,10 @@ std::pair<std::string, bool> SlicingProcessCompletedEvent::format_error_message(
|
||||
return std::make_pair(std::move(error), monospace);
|
||||
}
|
||||
|
||||
BackgroundSlicingProcess::BackgroundSlicingProcess()
|
||||
void BackgroundSlicingProcess::set_temp_output_path(int bed_idx)
|
||||
{
|
||||
boost::filesystem::path temp_path(wxStandardPaths::Get().GetTempDir().utf8_str().data());
|
||||
temp_path /= (boost::format(".%1%.gcode") % get_current_pid()).str();
|
||||
temp_path /= (boost::format(".%1%_%2%.gcode") % get_current_pid() % bed_idx).str();
|
||||
m_temp_output_path = temp_path.string();
|
||||
}
|
||||
|
||||
@ -113,7 +113,19 @@ BackgroundSlicingProcess::~BackgroundSlicingProcess()
|
||||
{
|
||||
this->stop();
|
||||
this->join_background_thread();
|
||||
boost::nowide::remove(m_temp_output_path.c_str());
|
||||
|
||||
// Current m_temp_output_path corresponds to the last selected bed. Remove everything
|
||||
// in the same directory that starts the same (see set_temp_output_path).
|
||||
const auto temp_dir = boost::filesystem::path(m_temp_output_path).parent_path();
|
||||
std::string prefix = boost::filesystem::path(m_temp_output_path).filename().string();
|
||||
prefix = prefix.substr(0, prefix.find('_'));
|
||||
for (const auto& entry : boost::filesystem::directory_iterator(temp_dir)) {
|
||||
if (entry.is_regular_file()) {
|
||||
const std::string filename = entry.path().filename().string();
|
||||
if (boost::starts_with(filename, prefix) && boost::ends_with(filename, ".gcode"))
|
||||
boost::filesystem::remove(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BackgroundSlicingProcess::select_technology(PrinterTechnology tech)
|
||||
|
@ -83,10 +83,10 @@ enum BackgroundSlicingProcessStep {
|
||||
class BackgroundSlicingProcess
|
||||
{
|
||||
public:
|
||||
BackgroundSlicingProcess();
|
||||
// Stop the background processing and finalize the bacgkround processing thread, remove temp files.
|
||||
~BackgroundSlicingProcess();
|
||||
|
||||
void set_temp_output_path(int bed_idx);
|
||||
void set_fff_print(Print* print) { if (m_fff_print != print) stop(); m_fff_print = print; }
|
||||
void set_sla_print(SLAPrint *print) { if (m_sla_print != print) stop(); m_sla_print = print; }
|
||||
void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; }
|
||||
|
@ -870,7 +870,7 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const
|
||||
m_viewer.toggle_top_layer_only_view_range();
|
||||
|
||||
// avoid processing if called with the same gcode_result
|
||||
if (m_last_result_id == gcode_result.id && wxGetApp().is_editor()) {
|
||||
if (m_last_result_id == gcode_result.id && wxGetApp().is_editor() && ! s_reload_preview_after_switching_beds) {
|
||||
// collect tool colors
|
||||
libvgcode::Palette tools_colors;
|
||||
tools_colors.reserve(str_tool_colors.size());
|
||||
|
@ -102,19 +102,28 @@ static bool show_imgui_demo_window = false;
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
static void select_bed(int i)
|
||||
void GLCanvas3D::select_bed(int i)
|
||||
{
|
||||
int old_bed = s_multiple_beds.get_active_bed();
|
||||
if (i == old_bed || i == -1)
|
||||
return;
|
||||
wxGetApp().plater()->canvas3D()->m_process->stop();
|
||||
|
||||
s_multiple_beds.set_active_bed(i);
|
||||
if (wxGetApp().plater()->is_preview_shown()) {
|
||||
s_reload_preview_after_switching_beds = true;
|
||||
wxPostEvent(wxGetApp().plater(), SimpleEvent(EVT_GLVIEWTOOLBAR_PREVIEW));
|
||||
wxGetApp().plater()->get_camera().translate_world(s_multiple_beds.get_bed_translation(i) - s_multiple_beds.get_bed_translation(old_bed));
|
||||
}
|
||||
wxGetApp().plater()->sidebar().update_sliced_info_sizer();
|
||||
// The stop call above schedules some events that would be processed after the switch.
|
||||
// Among else, on_process_completed would be called, which would stop slicing of
|
||||
// the new bed. We need to stop the process, pump all the events out of the queue
|
||||
// and then switch the beds.
|
||||
wxGetApp().CallAfter([i, old_bed]() {
|
||||
wxYield();
|
||||
s_multiple_beds.set_active_bed(i);
|
||||
s_beds_just_switched = true;
|
||||
if (wxGetApp().plater()->is_preview_shown()) {
|
||||
s_reload_preview_after_switching_beds = true;
|
||||
wxPostEvent(wxGetApp().plater(), SimpleEvent(EVT_GLVIEWTOOLBAR_PREVIEW));
|
||||
wxGetApp().plater()->get_camera().translate_world(s_multiple_beds.get_bed_translation(i) - s_multiple_beds.get_bed_translation(old_bed));
|
||||
}
|
||||
wxGetApp().plater()->schedule_background_process();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -732,6 +732,8 @@ private:
|
||||
// returns the containment state in the given out_state, if non-null
|
||||
bool check_volumes_outside_state(GLVolumeCollection& volumes, ModelInstanceEPrintVolumeState* out_state, bool selection_only = true) const;
|
||||
|
||||
void select_bed(int i);
|
||||
|
||||
public:
|
||||
void init_gcode_viewer() { m_gcode_viewer.init(); }
|
||||
void reset_gcode_toolpaths() { m_gcode_viewer.reset(); }
|
||||
|
@ -2119,11 +2119,23 @@ void Plater::priv::process_validation_warning(const std::vector<std::string>& wa
|
||||
// Returns a bitmask of UpdateBackgroundProcessReturnState.
|
||||
unsigned int Plater::priv::update_background_process(bool force_validation, bool postpone_error_messages)
|
||||
{
|
||||
assert(! s_beds_just_switched || background_process.idle());
|
||||
|
||||
int active_bed = s_multiple_beds.get_active_bed();
|
||||
background_process.set_temp_output_path(active_bed);
|
||||
background_process.set_fff_print(fff_prints[active_bed].get());
|
||||
background_process.set_sla_print(sla_prints[active_bed].get());
|
||||
background_process.set_gcode_result(&gcode_results[active_bed]);
|
||||
background_process.select_technology(this->printer_technology);
|
||||
|
||||
if (s_beds_just_switched) {
|
||||
PrintBase::SlicingStatus status(q->active_fff_print(), -1);
|
||||
SlicingStatusEvent evt(EVT_SLICING_UPDATE, 0, status);
|
||||
on_slicing_update(evt);
|
||||
s_beds_just_switched = false;
|
||||
notification_manager->close_notification_of_type(NotificationType::ExportOngoing);
|
||||
q->sidebar().show_sliced_info_sizer(background_process.finished());
|
||||
}
|
||||
|
||||
|
||||
// bitmap of enum UpdateBackgroundProcessReturnState
|
||||
@ -2884,11 +2896,12 @@ void Plater::priv::set_current_panel(wxPanel* panel)
|
||||
bool force_render = (current_panel != nullptr);
|
||||
#endif // __WXMAC__
|
||||
|
||||
ScopeGuard guard([]() { s_reload_preview_after_switching_beds = false; });
|
||||
if (current_panel == panel) {
|
||||
if (! s_reload_preview_after_switching_beds)
|
||||
return;
|
||||
else
|
||||
s_reload_preview_after_switching_beds = false;
|
||||
update_background_process();
|
||||
}
|
||||
|
||||
wxPanel* old_panel = current_panel;
|
||||
@ -3036,36 +3049,71 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
|
||||
this->preview->reload_print();
|
||||
}
|
||||
|
||||
if ((evt.status.flags & PrintBase::SlicingStatus::UPDATE_PRINT_STEP_WARNINGS) &&
|
||||
static_cast<PrintStep>(evt.status.warning_step) == psAlertWhenSupportsNeeded &&
|
||||
!get_app_config()->get_bool("alert_when_supports_needed")) {
|
||||
// This alerts are from psAlertWhenSupportsNeeded and the respective app settings is not Enabled, so discard the alerts.
|
||||
} else if (evt.status.flags &
|
||||
(PrintBase::SlicingStatus::UPDATE_PRINT_STEP_WARNINGS | PrintBase::SlicingStatus::UPDATE_PRINT_OBJECT_STEP_WARNINGS)) {
|
||||
// Update notification center with warnings of object_id and its warning_step.
|
||||
ObjectID object_id = evt.status.warning_object_id;
|
||||
int warning_step = evt.status.warning_step;
|
||||
PrintStateBase::StateWithWarnings state;
|
||||
if (evt.status.flags & PrintBase::SlicingStatus::UPDATE_PRINT_STEP_WARNINGS) {
|
||||
// LUKAS state = this->printer_technology == ptFFF ?
|
||||
//this->fff_print.step_state_with_warnings(static_cast<PrintStep>(warning_step)) :
|
||||
//this->sla_print.step_state_with_warnings(static_cast<SLAPrintStep>(warning_step));
|
||||
} else if (this->printer_technology == ptFFF) {
|
||||
//LUKAS const PrintObject *print_object = this->fff_print.get_object(object_id);
|
||||
//if (print_object)
|
||||
// state = print_object->step_state_with_warnings(static_cast<PrintObjectStep>(warning_step));
|
||||
} else {
|
||||
// LUKAS const SLAPrintObject *print_object = this->sla_print.get_object(object_id);
|
||||
// if (print_object)
|
||||
// state = print_object->step_state_with_warnings(static_cast<SLAPrintObjectStep>(warning_step));
|
||||
|
||||
std::vector<ObjectID> object_ids = { evt.status.warning_object_id };
|
||||
std::vector<int> warning_steps = { evt.status.warning_step };
|
||||
std::vector<int> flagss = { int(evt.status.flags) };
|
||||
|
||||
if (warning_steps.front() == -1) {
|
||||
flagss = { PrintBase::SlicingStatus::UPDATE_PRINT_STEP_WARNINGS, PrintBase::SlicingStatus::UPDATE_PRINT_OBJECT_STEP_WARNINGS };
|
||||
notification_manager->close_slicing_errors_and_warnings();
|
||||
}
|
||||
|
||||
for (int flags : flagss ) {
|
||||
if (warning_steps.front() == -1) {
|
||||
warning_steps.clear();
|
||||
if (flags == PrintBase::SlicingStatus::UPDATE_PRINT_STEP_WARNINGS) {
|
||||
int i = 0;
|
||||
while (i < int(psCount)) { warning_steps.push_back(i); ++i; }
|
||||
} else {
|
||||
int i = 0;
|
||||
while (i < int(posCount)) { warning_steps.push_back(i); ++i; }
|
||||
for (const PrintObject* po : wxGetApp().plater()->active_fff_print().objects())
|
||||
object_ids.push_back(po->id());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for (int warning_step : warning_steps) {
|
||||
for (ObjectID object_id : object_ids) {
|
||||
if ((flags & PrintBase::SlicingStatus::UPDATE_PRINT_STEP_WARNINGS) &&
|
||||
static_cast<PrintStep>(warning_step) == psAlertWhenSupportsNeeded &&
|
||||
!get_app_config()->get_bool("alert_when_supports_needed")) {
|
||||
// This alerts are from psAlertWhenSupportsNeeded and the respective app settings is not Enabled, so discard the alerts.
|
||||
}
|
||||
else if (flags &
|
||||
(PrintBase::SlicingStatus::UPDATE_PRINT_STEP_WARNINGS | PrintBase::SlicingStatus::UPDATE_PRINT_OBJECT_STEP_WARNINGS)) {
|
||||
// Update notification center with warnings of object_id and its warning_step.
|
||||
|
||||
PrintStateBase::StateWithWarnings state;
|
||||
if (flags & PrintBase::SlicingStatus::UPDATE_PRINT_STEP_WARNINGS) {
|
||||
state = this->printer_technology == ptFFF ?
|
||||
q->active_fff_print().step_state_with_warnings(static_cast<PrintStep>(warning_step)) :
|
||||
q->active_sla_print().step_state_with_warnings(static_cast<SLAPrintStep>(warning_step));
|
||||
}
|
||||
else if (this->printer_technology == ptFFF) {
|
||||
const PrintObject* print_object = q->active_fff_print().get_object(object_id);
|
||||
if (print_object)
|
||||
state = print_object->step_state_with_warnings(static_cast<PrintObjectStep>(warning_step));
|
||||
}
|
||||
else {
|
||||
const SLAPrintObject* print_object = q->active_sla_print().get_object(object_id);
|
||||
if (print_object)
|
||||
state = print_object->step_state_with_warnings(static_cast<SLAPrintObjectStep>(warning_step));
|
||||
}
|
||||
// Now process state.warnings.
|
||||
for (auto const& warning : state.warnings) {
|
||||
if (warning.current) {
|
||||
notification_manager->push_slicing_warning_notification(warning.message, false, object_id, warning_step);
|
||||
add_warning(warning, object_id.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Now process state.warnings.
|
||||
for (auto const& warning : state.warnings) {
|
||||
if (warning.current) {
|
||||
notification_manager->push_slicing_warning_notification(warning.message, false, object_id, warning_step);
|
||||
add_warning(warning, object_id.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user