diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 949f82c0a..66532e9ea 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1877,6 +1877,31 @@ bool model_volume_list_changed(const ModelObject &model_object_old, const ModelO return false; } +extern bool model_has_multi_part_objects(const Model &model) +{ + for (const ModelObject *model_object : model.objects) + if (model_object->volumes.size() != 1 || ! model_object->volumes.front()->is_model_part()) + return true; + return false; +} + +extern bool model_has_advanced_features(const Model &model) +{ + auto config_is_advanced = [](const DynamicPrintConfig &config) { + return ! (config.empty() || (config.size() == 1 && config.cbegin()->first == "extruder")); + }; + for (const ModelObject *model_object : model.objects) { + // Is there more than one instance or advanced config data? + if (model_object->instances.size() > 1 || config_is_advanced(model_object->config)) + return true; + // Is there any modifier or advanced config data? + for (const ModelVolume* model_volume : model_object->volumes) + if (! model_volume->is_model_part() || config_is_advanced(model_volume->config)) + return true; + } + return false; +} + #ifndef NDEBUG // Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique. void check_model_ids_validity(const Model &model) diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index c026863ec..2b4a6d978 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -761,6 +761,12 @@ extern bool model_object_list_extended(const Model &model_old, const Model &mode // than the old ModelObject. extern bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolumeType type); +// If the model has multi-part objects, then it is currently not supported by the SLA mode. +// Either the model cannot be loaded, or a SLA printer has to be activated. +extern bool model_has_multi_part_objects(const Model &model); +// If the model has advanced features, then it cannot be processed in simple mode. +extern bool model_has_advanced_features(const Model &model); + #ifndef NDEBUG // Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique. void check_model_ids_validity(const Model &model); diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 9a641c7c0..8f41ed5a3 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -135,8 +135,7 @@ void config_wizard(int reason) wxGetApp().load_current_presets(); - if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA && - wxGetApp().obj_list()->has_multi_part_objects()) + if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA && model_has_multi_part_objects(wxGetApp().model())) { show_info(nullptr, _(L("It's impossible to print multi-part object(s) with SLA technology.")) + "\n\n" + diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index b4e7bc2b2..02290e83d 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -854,7 +854,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu) // This is called when closing the application, when loading a config file or when starting the config wizard // to notify the user whether he is aware that some preset changes will be lost. -bool GUI_App::check_unsaved_changes() +bool GUI_App::check_unsaved_changes(const wxString &header) { wxString dirty; PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology(); @@ -868,8 +868,12 @@ bool GUI_App::check_unsaved_changes() // No changes, the application may close or reload presets. return true; // Ask the user. + wxString message; + if (! header.empty()) + message = header + "\n\n"; + message += _(L("The presets on the following tabs were modified")) + ": " + dirty + "\n\n" + _(L("Discard changes and continue anyway?")); wxMessageDialog dialog(mainframe, - _(L("The presets on the following tabs were modified")) + ": " + dirty + "\n\n" + _(L("Discard changes and continue anyway?")), + message, wxString(SLIC3R_APP_NAME) + " - " + _(L("Unsaved Presets")), wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT); return dialog.ShowModal() == wxID_YES; @@ -944,9 +948,9 @@ Plater* GUI_App::plater() return plater_; } -ModelObjectPtrs* GUI_App::model_objects() +Model& GUI_App::model() { - return &plater_->model().objects; + return plater_->model(); } wxNotebook* GUI_App::tab_panel() const diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 2f0e8bcf3..8d0bcfe2f 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -139,7 +139,7 @@ public: void update_mode(); void add_config_menu(wxMenuBar *menu); - bool check_unsaved_changes(); + bool check_unsaved_changes(const wxString &header = wxString()); bool checked_tab(Tab* tab); void load_current_presets(); @@ -158,7 +158,7 @@ public: ObjectList* obj_list(); ObjectLayers* obj_layers(); Plater* plater(); - std::vector *model_objects(); + Model& model(); AppConfig* app_config{ nullptr }; PresetBundle* preset_bundle{ nullptr }; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 3f3256c42..f7abb4128 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2603,7 +2603,7 @@ bool ObjectList::edit_layer_range(const t_layer_height_range& range, const t_lay void ObjectList::init_objects() { - m_objects = wxGetApp().model_objects(); + m_objects = &wxGetApp().model().objects; } bool ObjectList::multiple_selection() const @@ -3080,19 +3080,6 @@ void ObjectList::last_volume_is_deleted(const int obj_idx) volume->config.set_key_value("extruder", new ConfigOptionInt(0)); } -bool ObjectList::has_multi_part_objects() -{ - if (!m_objects_model->IsEmpty()) { - wxDataViewItemArray items; - m_objects_model->GetChildren(wxDataViewItem(0), items); - - for (auto& item : items) - if (m_objects_model->GetItemByType(item, itVolume)) - return true; - } - return false; -} - /* #lm_FIXME_delete_after_testing void ObjectList::update_settings_items() { diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 2d7e9f5f1..5f5d5d625 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -317,7 +317,6 @@ public: void change_part_type(); void last_volume_is_deleted(const int obj_idx); - bool has_multi_part_objects(); void update_settings_items(); void update_and_show_object_settings_item(); void update_settings_item_and_selection(wxDataViewItem item, wxDataViewItemArray& selections); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index fcb047139..308b3f208 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -25,7 +25,7 @@ static double get_volume_min_z(const GLVolume* volume) const Transform3f& world_matrix = volume->world_matrix().cast(); // need to get the ModelVolume pointer - const ModelObject* mo = wxGetApp().model_objects()->at(volume->composite_id.object_id); + const ModelObject* mo = wxGetApp().model().objects[volume->composite_id.object_id]; const ModelVolume* mv = mo->volumes[volume->composite_id.volume_id]; const TriangleMesh& hull = mv->get_convex_hull(); @@ -466,7 +466,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_scale = m_new_size.cwiseProduct(selection.get_unscaled_instance_bounding_box().size().cwiseInverse()) * 100.; } else { m_new_rotation = volume->get_instance_rotation() * (180. / M_PI); - m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct((*wxGetApp().model_objects())[volume->object_idx()]->raw_mesh_bounding_box().size()); + m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size()); m_new_scale = volume->get_instance_scaling_factor() * 100.; } @@ -779,7 +779,7 @@ void ObjectManipulation::change_size_value(int axis, double value) else if (selection.is_single_full_instance()) ref_size = m_world_coordinates ? selection.get_unscaled_instance_bounding_box().size() : - (*wxGetApp().model_objects())[selection.get_volume(*selection.get_volume_idxs().begin())->object_idx()]->raw_mesh_bounding_box().size(); + wxGetApp().model().objects[selection.get_volume(*selection.get_volume_idxs().begin())->object_idx()]->raw_mesh_bounding_box().size(); this->do_scale(axis, 100. * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2))); @@ -902,7 +902,7 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value) return; } // Bake the rotation into the meshes of the object. - (*wxGetApp().model_objects())[volume->composite_id.object_id]->bake_xy_rotation_into_meshes(volume->composite_id.instance_id); + wxGetApp().model().objects[volume->composite_id.object_id]->bake_xy_rotation_into_meshes(volume->composite_id.instance_id); // Update the 3D scene, selections etc. wxGetApp().plater()->update(); // Recalculate cached values at this panel, refresh the screen. diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index cb996a104..5a42cbd31 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -29,7 +29,7 @@ void GLGizmoFlatten::on_set_state() // m_model_object pointer can be invalid (for instance because of undo/redo action), // we should recover it from the object id m_model_object = nullptr; - for (const auto mo : *wxGetApp().model_objects()) { + for (const auto mo : wxGetApp().model().objects) { if (mo->id() == m_model_object_id) { m_model_object = mo; break; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 833ba3ee2..8027906a9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -1049,7 +1049,7 @@ void GLGizmoSlaSupports::on_set_state() // we should recover it from the object id const ModelObject* old_model_object = m_model_object; m_model_object = nullptr; - for (const auto mo : *wxGetApp().model_objects()) { + for (const auto mo : wxGetApp().model().objects) { if (mo->id() == m_current_mesh_object_id) { m_model_object = mo; break; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 7c7488c6a..559145eba 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1646,16 +1646,18 @@ struct Plater::priv if (this->m_prevent_snapshots > 0) return; assert(this->m_prevent_snapshots >= 0); - this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager()); + this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology); this->undo_redo_stack.release_least_recently_used(); + // Save the last active preset name of a particular printer technology. + ((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name(); BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot taken: " << snapshot_name << ", Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack.memsize()) << log_memory_info(); } void take_snapshot(const wxString& snapshot_name) { this->take_snapshot(std::string(snapshot_name.ToUTF8().data())); } int get_active_snapshot_index(); void undo(); void redo(); - void undo_to(size_t time_to_load); - void redo_to(size_t time_to_load); + void undo_redo_to(size_t time_to_load); + void suppress_snapshots() { this->m_prevent_snapshots++; } void allow_snapshots() { this->m_prevent_snapshots--; } @@ -1749,10 +1751,13 @@ private: void update_fff_scene(); void update_sla_scene(); + void undo_redo_to(std::vector::const_iterator it_snapshot); void update_after_undo_redo(bool temp_snapshot_was_taken = false); // path to project file stored with no extension wxString m_project_filename; + std::string m_last_fff_printer_profile_name; + std::string m_last_sla_printer_profile_name; }; const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)", std::regex::icase); @@ -2102,66 +2107,22 @@ std::vector Plater::priv::load_files(const std::vector& input_ } } } - else if ((wxGetApp().get_mode() == comSimple) && (type_3mf || type_any_amf)) - { - bool advanced = false; - for (const ModelObject* model_object : model.objects) + else if ((wxGetApp().get_mode() == comSimple) && (type_3mf || type_any_amf) && model_has_advanced_features(model)) { + wxMessageDialog dlg(q, _(L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?\n")), + _(L("Detected advanced data")), wxICON_WARNING | wxYES | wxNO); + if (dlg.ShowModal() == wxID_YES) { - // is there more than one instance ? - if (model_object->instances.size() > 1) - { - advanced = true; - break; - } - - // is there any advanced config data ? - auto opt_keys = model_object->config.keys(); - if (!opt_keys.empty() && !((opt_keys.size() == 1) && (opt_keys[0] == "extruder"))) - { - advanced = true; - break; - } - - // is there any modifier ? - for (const ModelVolume* model_volume : model_object->volumes) - { - if (!model_volume->is_model_part()) - { - advanced = true; - break; - } - - // is there any advanced config data ? - opt_keys = model_volume->config.keys(); - if (!opt_keys.empty() && !((opt_keys.size() == 1) && (opt_keys[0] == "extruder"))) - { - advanced = true; - break; - } - } - - if (advanced) - break; - } - - if (advanced) - { - wxMessageDialog dlg(q, _(L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?\n")), - _(L("Detected advanced data")), wxICON_WARNING | wxYES | wxNO); - if (dlg.ShowModal() == wxID_YES) - { - Slic3r::GUI::wxGetApp().save_mode(comAdvanced); - view3D->set_as_dirty(); - } - else - return obj_idxs; + Slic3r::GUI::wxGetApp().save_mode(comAdvanced); + view3D->set_as_dirty(); } + else + return obj_idxs; } - for (ModelObject* model_object : model.objects) { - model_object->center_around_origin(false); - model_object->ensure_on_bed(); - } + for (ModelObject* model_object : model.objects) { + model_object->center_around_origin(false); + model_object->ensure_on_bed(); + } // check multi-part object adding for the SLA-printing if (printer_technology == ptSLA) @@ -3629,28 +3590,58 @@ int Plater::priv::get_active_snapshot_index() void Plater::priv::undo() { - bool temp_snapshot_was_taken = this->undo_redo_stack.temp_snapshot_active(); - if (this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager())) - this->update_after_undo_redo(temp_snapshot_was_taken); + const std::vector &snapshots = this->undo_redo_stack.snapshots(); + auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack.active_snapshot_time())); + if (-- it_current != snapshots.begin()) + this->undo_redo_to(it_current); } void Plater::priv::redo() { - if (this->undo_redo_stack.redo(model, this->view3D->get_canvas3d()->get_gizmos_manager())) - this->update_after_undo_redo(); + const std::vector &snapshots = this->undo_redo_stack.snapshots(); + auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack.active_snapshot_time())); + if (++ it_current != snapshots.end()) + this->undo_redo_to(it_current); } -void Plater::priv::undo_to(size_t time_to_load) +void Plater::priv::undo_redo_to(size_t time_to_load) { - bool temp_snapshot_was_taken = this->undo_redo_stack.temp_snapshot_active(); - if (this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), time_to_load)) - this->update_after_undo_redo(temp_snapshot_was_taken); + const std::vector &snapshots = this->undo_redo_stack.snapshots(); + auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(time_to_load)); + assert(it_current != snapshots.end()); + this->undo_redo_to(it_current); } -void Plater::priv::redo_to(size_t time_to_load) -{ - if (this->undo_redo_stack.redo(model, this->view3D->get_canvas3d()->get_gizmos_manager(), time_to_load)) - this->update_after_undo_redo(); +void Plater::priv::undo_redo_to(std::vector::const_iterator it_snapshot) +{ + bool temp_snapshot_was_taken = this->undo_redo_stack.temp_snapshot_active(); + PrinterTechnology new_printer_technology = it_snapshot->printer_technology; + bool printer_technology_changed = this->printer_technology != new_printer_technology; + if (printer_technology_changed) { + // Switching the printer technology when jumping forwards / backwards in time. Switch to the last active printer profile of the other type. + std::string s_pt = (it_snapshot->printer_technology == ptFFF) ? "FFF" : "SLA"; + if (! wxGetApp().check_unsaved_changes(from_u8((boost::format(_utf8( + L("%1% printer was active at the time the target Undo / Redo snapshot was taken. Switching to %1% printer requires reloading of %1% presets."))) % s_pt).str()))) + // Don't switch the profiles. + return; + } + // Save the last active preset name of a particular printer technology. + ((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name(); + // Do the jump in time. + if (it_snapshot->timestamp < this->undo_redo_stack.active_snapshot_time() ? + this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology, it_snapshot->timestamp) : + this->undo_redo_stack.redo(model, this->view3D->get_canvas3d()->get_gizmos_manager(), it_snapshot->timestamp)) { + if (printer_technology_changed) { + // Switch to the other printer technology. Switch to the last printer active for that particular technology. + AppConfig *app_config = wxGetApp().app_config; + app_config->set("presets", "printer", (new_printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name); + wxGetApp().preset_bundle->load_presets(*app_config); + // Load the currently selected preset into the GUI, update the preset selection box. + // This also switches the printer technology based on the printer technology of the active printer profile. + wxGetApp().load_current_presets(); + } + this->update_after_undo_redo(temp_snapshot_was_taken); + } } void Plater::priv::update_after_undo_redo(bool /* temp_snapshot_was_taken */) @@ -3669,6 +3660,13 @@ void Plater::priv::update_after_undo_redo(bool /* temp_snapshot_was_taken */) wxGetApp().obj_list()->update_after_undo_redo(); + if (wxGetApp().get_mode() == comSimple && model_has_advanced_features(this->model)) { + // If the user jumped to a snapshot that require user interface with advanced features, switch to the advanced mode without asking. + // There is a little risk of surprising the user, as he already must have had the advanced or expert mode active for such a snapshot to be taken. + Slic3r::GUI::wxGetApp().save_mode(comAdvanced); + view3D->set_as_dirty(); + } + //FIXME what about the state of the manipulators? //FIXME what about the focus? Cursor in the side panel? @@ -4230,7 +4228,7 @@ void Plater::undo_to(int selection) } const int idx = p->get_active_snapshot_index() - selection - 1; - p->undo_to(p->undo_redo_stack.snapshots()[idx].timestamp); + p->undo_redo_to(p->undo_redo_stack.snapshots()[idx].timestamp); } void Plater::redo_to(int selection) { @@ -4240,7 +4238,7 @@ void Plater::redo_to(int selection) } const int idx = p->get_active_snapshot_index() + selection + 1; - p->redo_to(p->undo_redo_stack.snapshots()[idx].timestamp); + p->undo_redo_to(p->undo_redo_stack.snapshots()[idx].timestamp); } bool Plater::undo_redo_string_getter(const bool is_undo, int idx, const char** out_text) { diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 7ab564beb..b52f9dd46 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2904,7 +2904,7 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr // Because of we can't to print the multi-part objects with SLA technology. bool Tab::may_switch_to_SLA_preset() { - if (wxGetApp().obj_list()->has_multi_part_objects()) + if (model_has_multi_part_objects(wxGetApp().model())) { show_info( parent(), _(L("It's impossible to print multi-part object(s) with SLA technology.")) + "\n\n" + diff --git a/src/slic3r/Utils/UndoRedo.cpp b/src/slic3r/Utils/UndoRedo.cpp index 10873ea89..c4a082fb6 100644 --- a/src/slic3r/Utils/UndoRedo.cpp +++ b/src/slic3r/Utils/UndoRedo.cpp @@ -495,12 +495,12 @@ public: } // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time. - void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos); + void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology); void load_snapshot(size_t timestamp, Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos); bool has_undo_snapshot() const; bool has_redo_snapshot() const; - bool undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, size_t jump_to_time); + bool undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, PrinterTechnology printer_technology, size_t jump_to_time); bool redo(Slic3r::Model &model, Slic3r::GUI::GLGizmosManager &gizmos, size_t jump_to_time); void release_least_recently_used(); @@ -788,7 +788,7 @@ template void StackImpl::load_mutable_object(const Sl } // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time. -void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos) +void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology) { // Release old snapshot data. assert(m_active_snapshot_time <= m_current_time); @@ -808,11 +808,11 @@ void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Mo this->save_mutable_object(m_selection); this->save_mutable_object(gizmos); // Save the snapshot info. - m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id); + m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id, printer_technology); m_active_snapshot_time = m_current_time; // Save snapshot info of the last "current" aka "top most" state, that is only being serialized // if undoing an action. Such a snapshot has an invalid Model ID assigned if it was not taken yet. - m_snapshots.emplace_back(topmost_snapshot_name, m_active_snapshot_time, 0); + m_snapshots.emplace_back(topmost_snapshot_name, m_active_snapshot_time, 0, printer_technology); // Release empty objects from the history. this->collect_garbage(); assert(this->valid()); @@ -858,7 +858,7 @@ bool StackImpl::has_redo_snapshot() const return ++ it != m_snapshots.end(); } -bool StackImpl::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load) +bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, PrinterTechnology printer_technology, size_t time_to_load) { assert(this->valid()); if (time_to_load == SIZE_MAX) { @@ -872,7 +872,7 @@ bool StackImpl::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selecti bool new_snapshot_taken = false; if (m_active_snapshot_time == m_snapshots.back().timestamp && ! m_snapshots.back().is_topmost_captured()) { // The current state is temporary. The current state needs to be captured to be redoable. - this->take_snapshot(topmost_snapshot_name, model, selection, gizmos); + this->take_snapshot(topmost_snapshot_name, model, selection, gizmos, printer_technology); // The line above entered another topmost_snapshot_name. assert(m_snapshots.back().is_topmost()); assert(! m_snapshots.back().is_topmost_captured()); @@ -1020,10 +1020,12 @@ Stack::~Stack() {} void Stack::set_memory_limit(size_t memsize) { pimpl->set_memory_limit(memsize); } size_t Stack::memsize() const { return pimpl->memsize(); } void Stack::release_least_recently_used() { pimpl->release_least_recently_used(); } -void Stack::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos) { pimpl->take_snapshot(snapshot_name, model, selection, gizmos); } +void Stack::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology) + { pimpl->take_snapshot(snapshot_name, model, selection, gizmos, printer_technology); } bool Stack::has_undo_snapshot() const { return pimpl->has_undo_snapshot(); } bool Stack::has_redo_snapshot() const { return pimpl->has_redo_snapshot(); } -bool Stack::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load) { return pimpl->undo(model, selection, gizmos, time_to_load); } +bool Stack::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, PrinterTechnology printer_technology, size_t time_to_load) + { return pimpl->undo(model, selection, gizmos, printer_technology, time_to_load); } bool Stack::redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load) { return pimpl->redo(model, gizmos, time_to_load); } const Selection& Stack::selection_deserialized() const { return pimpl->selection_deserialized(); } diff --git a/src/slic3r/Utils/UndoRedo.hpp b/src/slic3r/Utils/UndoRedo.hpp index 6785cd740..00ab55822 100644 --- a/src/slic3r/Utils/UndoRedo.hpp +++ b/src/slic3r/Utils/UndoRedo.hpp @@ -23,11 +23,13 @@ namespace UndoRedo { struct Snapshot { Snapshot(size_t timestamp) : timestamp(timestamp) {} - Snapshot(const std::string &name, size_t timestamp, size_t model_id) : name(name), timestamp(timestamp), model_id(model_id) {} + Snapshot(const std::string &name, size_t timestamp, size_t model_id, Slic3r::PrinterTechnology printer_technology) : + name(name), timestamp(timestamp), model_id(model_id), printer_technology(printer_technology) {} - std::string name; - size_t timestamp; - size_t model_id; + std::string name; + size_t timestamp; + size_t model_id; + PrinterTechnology printer_technology; bool operator< (const Snapshot &rhs) const { return this->timestamp < rhs.timestamp; } bool operator==(const Snapshot &rhs) const { return this->timestamp == rhs.timestamp; } @@ -66,7 +68,7 @@ public: void release_least_recently_used(); // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time. - void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos); + void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology); // To be queried to enable / disable the Undo / Redo buttons at the UI. bool has_undo_snapshot() const; @@ -74,7 +76,7 @@ public: // Roll back the time. If time_to_load is SIZE_MAX, the previous snapshot is activated. // Undoing an action may need to take a snapshot of the current application state, so that redo to the current state is possible. - bool undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load = SIZE_MAX); + bool undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, PrinterTechnology printer_technology, size_t time_to_load = SIZE_MAX); // Jump forward in time. If time_to_load is SIZE_MAX, the next snapshot is activated. bool redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load = SIZE_MAX);