From a5c64e8477d15cf9a9d923387c86b5a81643d920 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 22 Jul 2019 16:52:47 +0200 Subject: [PATCH] Refactoring of the Undo / Redo stack interface: The Snapshot specific data, which is fully provided from the outside of the Undo / Redo stack is now stored as an StackData structure. The StackData structure may be extended with small size data, like the cursor position in the side bar. --- src/slic3r/GUI/Plater.cpp | 20 +++++++++++--------- src/slic3r/Utils/UndoRedo.cpp | 22 +++++++++++----------- src/slic3r/Utils/UndoRedo.hpp | 24 +++++++++++++++++------- 3 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index a9972d192..97606c0a0 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3725,9 +3725,10 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name) if (this->m_prevent_snapshots > 0) return; assert(this->m_prevent_snapshots >= 0); - unsigned int flags = 0; + UndoRedo::SnapshotData snapshot_data; + snapshot_data.printer_technology = this->printer_technology; if (this->view3D->is_layers_editing_enabled()) - flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE; + snapshot_data.flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE; //FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config. // This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config. if (this->printer_technology == ptFFF) { @@ -3735,7 +3736,7 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name) model.wipe_tower.position = Vec2d(config.opt_float("wipe_tower_x"), config.opt_float("wipe_tower_y")); model.wipe_tower.rotation = config.opt_float("wipe_tower_rotation_angle"); } - this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology, flags); + this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), snapshot_data); 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(); @@ -3769,11 +3770,11 @@ void Plater::priv::undo_redo_to(size_t time_to_load) 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; + PrinterTechnology new_printer_technology = it_snapshot->snapshot_data.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"; + std::string s_pt = (it_snapshot->snapshot_data.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. @@ -3789,17 +3790,18 @@ void Plater::priv::undo_redo_to(std::vector::const_iterator model.wipe_tower.rotation = config.opt_float("wipe_tower_rotation_angle"); } // Flags made of Snapshot::Flags enum values. - unsigned int new_flags = it_snapshot->flags; - unsigned int top_snapshot_flags = 0; + unsigned int new_flags = it_snapshot->snapshot_data.flags; + UndoRedo::SnapshotData top_snapshot_data; + top_snapshot_data.printer_technology = this->printer_technology; if (this->view3D->is_layers_editing_enabled()) - top_snapshot_flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE; + top_snapshot_data.flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE; bool new_variable_layer_editing_active = (new_flags & UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE) != 0; // Disable layer editing before the Undo / Redo jump. if (!new_variable_layer_editing_active && view3D->is_layers_editing_enabled()) view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting")); // 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, top_snapshot_flags, it_snapshot->timestamp) : + this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), top_snapshot_data, 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. diff --git a/src/slic3r/Utils/UndoRedo.cpp b/src/slic3r/Utils/UndoRedo.cpp index a8f9cc134..6eaede6d7 100644 --- a/src/slic3r/Utils/UndoRedo.cpp +++ b/src/slic3r/Utils/UndoRedo.cpp @@ -496,12 +496,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, Slic3r::PrinterTechnology printer_technology, unsigned int flags); + void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, const SnapshotData &snapshot_data); 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, PrinterTechnology printer_technology, unsigned int flags, size_t jump_to_time); + bool undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, const SnapshotData &snapshot_data, size_t jump_to_time); bool redo(Slic3r::Model &model, Slic3r::GUI::GLGizmosManager &gizmos, size_t jump_to_time); void release_least_recently_used(); @@ -786,7 +786,7 @@ template void StackImpl::load_mutable_object(const Slic3r::ObjectID } // 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, Slic3r::PrinterTechnology printer_technology, unsigned int flags) +void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, const SnapshotData &snapshot_data) { // Release old snapshot data. assert(m_active_snapshot_time <= m_current_time); @@ -806,11 +806,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, printer_technology, flags); + m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id, snapshot_data); 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, printer_technology, flags); + m_snapshots.emplace_back(topmost_snapshot_name, m_active_snapshot_time, 0, snapshot_data); // Release empty objects from the history. this->collect_garbage(); assert(this->valid()); @@ -856,7 +856,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, PrinterTechnology printer_technology, unsigned int flags, size_t time_to_load) +bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, const SnapshotData &snapshot_data, size_t time_to_load) { assert(this->valid()); if (time_to_load == SIZE_MAX) { @@ -870,7 +870,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, printer_technology, flags); + this->take_snapshot(topmost_snapshot_name, model, selection, gizmos, snapshot_data); // The line above entered another topmost_snapshot_name. assert(m_snapshots.back().is_topmost()); assert(! m_snapshots.back().is_topmost_captured()); @@ -1019,12 +1019,12 @@ void Stack::set_memory_limit(size_t memsize) { pimpl->set_memory_limit(memsize); size_t Stack::get_memory_limit() const { return pimpl->get_memory_limit(); } 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, Slic3r::PrinterTechnology printer_technology, unsigned int flags) - { pimpl->take_snapshot(snapshot_name, model, selection, gizmos, printer_technology, flags); } +void Stack::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, const SnapshotData &snapshot_data) + { pimpl->take_snapshot(snapshot_name, model, selection, gizmos, snapshot_data); } 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, PrinterTechnology printer_technology, unsigned int flags, size_t time_to_load) - { return pimpl->undo(model, selection, gizmos, printer_technology, flags, time_to_load); } +bool Stack::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, const SnapshotData &snapshot_data, size_t time_to_load) + { return pimpl->undo(model, selection, gizmos, snapshot_data, 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 916e44aa2..209b5cf29 100644 --- a/src/slic3r/Utils/UndoRedo.hpp +++ b/src/slic3r/Utils/UndoRedo.hpp @@ -21,11 +21,23 @@ namespace GUI { namespace UndoRedo { +// Data structure to be stored with each snapshot. +// Storing short data (bit masks, ints) with each snapshot instead of being serialized into the Undo / Redo stack +// is likely cheaper in term of both the runtime and memory allocation. +// Also the SnapshotData is available without having to deserialize the snapshot from the Undo / Redo stack, +// which may be handy sometimes. +struct SnapshotData +{ + PrinterTechnology printer_technology = ptUnknown; + // Bitmap of Flags (see the Flags enum). + unsigned int flags = 0; +}; + struct Snapshot { Snapshot(size_t timestamp) : timestamp(timestamp) {} - Snapshot(const std::string &name, size_t timestamp, size_t model_id, Slic3r::PrinterTechnology printer_technology, unsigned int flags) : - name(name), timestamp(timestamp), model_id(model_id), printer_technology(printer_technology), flags(flags) {} + Snapshot(const std::string &name, size_t timestamp, size_t model_id, const SnapshotData &snapshot_data) : + name(name), timestamp(timestamp), model_id(model_id), snapshot_data(snapshot_data) {} // Bitmask of various binary flags to be stored with the snapshot. enum Flags { @@ -35,9 +47,7 @@ struct Snapshot std::string name; size_t timestamp; size_t model_id; - PrinterTechnology printer_technology; - // Bitmap of Flags (see the Flags enum). - unsigned int flags; + SnapshotData snapshot_data; bool operator< (const Snapshot &rhs) const { return this->timestamp < rhs.timestamp; } bool operator==(const Snapshot &rhs) const { return this->timestamp == rhs.timestamp; } @@ -77,7 +87,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, Slic3r::PrinterTechnology printer_technology, unsigned int flags); + void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, const SnapshotData &snapshot_data); // To be queried to enable / disable the Undo / Redo buttons at the UI. bool has_undo_snapshot() const; @@ -85,7 +95,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, PrinterTechnology printer_technology, unsigned int flags, size_t time_to_load = SIZE_MAX); + bool undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, const SnapshotData &snapshot_data, 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);