Merge remote-tracking branch 'remotes/origin/vb_project_state'

This commit is contained in:
Vojtech Bubnik 2021-09-27 14:36:22 +02:00
commit 8f4f02f84c
9 changed files with 74 additions and 27 deletions

View File

@ -23,6 +23,7 @@
#include "slic3r/GUI/3DBed.hpp" #include "slic3r/GUI/3DBed.hpp"
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/MainFrame.hpp" #include "slic3r/GUI/MainFrame.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "GUI_ObjectList.hpp" #include "GUI_ObjectList.hpp"
@ -6427,7 +6428,7 @@ void GLCanvas3D::_update_selection_from_hover()
// the selection is going to be modified (Add) // the selection is going to be modified (Add)
if (!contains_all) { if (!contains_all) {
wxGetApp().plater()->take_snapshot(_(L("Selection-Add from rectangle"))); wxGetApp().plater()->take_snapshot(_(L("Selection-Add from rectangle")), UndoRedo::SnapshotType::Selection);
selection_changed = true; selection_changed = true;
} }
} }
@ -6442,7 +6443,7 @@ void GLCanvas3D::_update_selection_from_hover()
// the selection is going to be modified (Remove) // the selection is going to be modified (Remove)
if (contains_any) { if (contains_any) {
wxGetApp().plater()->take_snapshot(_(L("Selection-Remove from rectangle"))); wxGetApp().plater()->take_snapshot(_(L("Selection-Remove from rectangle")), UndoRedo::SnapshotType::Selection);
selection_changed = true; selection_changed = true;
} }
} }

View File

@ -10,6 +10,7 @@
#include "BitmapComboBox.hpp" #include "BitmapComboBox.hpp"
#include "GalleryDialog.hpp" #include "GalleryDialog.hpp"
#include "MainFrame.hpp" #include "MainFrame.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include "OptionsGroup.hpp" #include "OptionsGroup.hpp"
#include "Tab.hpp" #include "Tab.hpp"
@ -3469,7 +3470,7 @@ void ObjectList::update_selections_on_canvas()
volume_idxs = selection.get_missing_volume_idxs_from(volume_idxs); volume_idxs = selection.get_missing_volume_idxs_from(volume_idxs);
if (volume_idxs.size() > 0) if (volume_idxs.size() > 0)
{ {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Selection-Remove from list"))); Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Selection-Remove from list")), UndoRedo::SnapshotType::Selection);
selection.remove_volumes(mode, volume_idxs); selection.remove_volumes(mode, volume_idxs);
} }
} }
@ -3481,7 +3482,7 @@ void ObjectList::update_selections_on_canvas()
// OR there is no single selection // OR there is no single selection
if (selection.get_mode() == mode || !single_selection) if (selection.get_mode() == mode || !single_selection)
volume_idxs = selection.get_unselected_volume_idxs_from(volume_idxs); volume_idxs = selection.get_unselected_volume_idxs_from(volume_idxs);
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Selection-Add from list"))); Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Selection-Add from list")), UndoRedo::SnapshotType::Selection);
selection.add_volumes(mode, volume_idxs, single_selection); selection.add_volumes(mode, volume_idxs, single_selection);
} }

View File

@ -8,6 +8,7 @@
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "libslic3r/PresetBundle.hpp" #include "libslic3r/PresetBundle.hpp"
#include "libslic3r/TriangleMesh.hpp" #include "libslic3r/TriangleMesh.hpp"
@ -42,14 +43,14 @@ void GLGizmoPainterBase::activate_internal_undo_redo_stack(bool activate)
if (activate && !m_internal_stack_active) { if (activate && !m_internal_stack_active) {
if (std::string str = this->get_gizmo_entering_text(); last_snapshot_name != str) if (std::string str = this->get_gizmo_entering_text(); last_snapshot_name != str)
Plater::TakeSnapshot(plater, str); Plater::TakeSnapshot(plater, str, UndoRedo::SnapshotType::EnteringGizmo);
plater->enter_gizmos_stack(); plater->enter_gizmos_stack();
m_internal_stack_active = true; m_internal_stack_active = true;
} }
if (!activate && m_internal_stack_active) { if (!activate && m_internal_stack_active) {
plater->leave_gizmos_stack(); plater->leave_gizmos_stack();
if (std::string str = this->get_gizmo_leaving_text(); last_snapshot_name != str) if (std::string str = this->get_gizmo_leaving_text(); last_snapshot_name != str)
Plater::TakeSnapshot(plater, str); Plater::TakeSnapshot(plater, str, UndoRedo::SnapshotType::LeavingGizmoWithAction);
m_internal_stack_active = false; m_internal_stack_active = false;
} }
} }

View File

@ -4,6 +4,7 @@
#include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" #include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
#include "slic3r/GUI/MainFrame.hpp" #include "slic3r/GUI/MainFrame.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include <GL/glew.h> #include <GL/glew.h>

View File

@ -1530,25 +1530,25 @@ struct Plater::priv
void arrange() void arrange()
{ {
m->take_snapshot(_(L("Arrange"))); m->take_snapshot(_L("Arrange"));
start(m_arrange_id); start(m_arrange_id);
} }
void fill_bed() void fill_bed()
{ {
m->take_snapshot(_(L("Fill bed"))); m->take_snapshot(_L("Fill bed"));
start(m_fill_bed_id); start(m_fill_bed_id);
} }
void optimize_rotation() void optimize_rotation()
{ {
m->take_snapshot(_(L("Optimize Rotation"))); m->take_snapshot(_L("Optimize Rotation"));
start(m_rotoptimize_id); start(m_rotoptimize_id);
} }
void import_sla_arch() void import_sla_arch()
{ {
m->take_snapshot(_(L("Import SLA archive"))); m->take_snapshot(_L("Import SLA archive"));
start(m_sla_import_id); start(m_sla_import_id);
} }
@ -1677,8 +1677,9 @@ struct Plater::priv
void enter_gizmos_stack(); void enter_gizmos_stack();
void leave_gizmos_stack(); void leave_gizmos_stack();
void take_snapshot(const std::string& snapshot_name); void take_snapshot(const std::string& snapshot_name, UndoRedo::SnapshotType snapshot_type = UndoRedo::SnapshotType::Action);
void take_snapshot(const wxString& snapshot_name) { this->take_snapshot(std::string(snapshot_name.ToUTF8().data())); } void take_snapshot(const wxString& snapshot_name, UndoRedo::SnapshotType snapshot_type = UndoRedo::SnapshotType::Action)
{ this->take_snapshot(std::string(snapshot_name.ToUTF8().data()), snapshot_type); }
int get_active_snapshot_index(); int get_active_snapshot_index();
void undo(); void undo();
@ -2062,7 +2063,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
} }
// Initialize the Undo / Redo stack with a first snapshot. // Initialize the Undo / Redo stack with a first snapshot.
this->take_snapshot(_L("New Project")); this->take_snapshot(_L("New Project"), UndoRedo::SnapshotType::ProjectSeparator);
this->q->Bind(EVT_LOAD_MODEL_OTHER_INSTANCE, [this](LoadFromOtherInstanceEvent& evt) { this->q->Bind(EVT_LOAD_MODEL_OTHER_INSTANCE, [this](LoadFromOtherInstanceEvent& evt) {
BOOST_LOG_TRIVIAL(trace) << "Received load from other instance event."; BOOST_LOG_TRIVIAL(trace) << "Received load from other instance event.";
@ -2818,7 +2819,7 @@ void Plater::priv::delete_all_objects_from_model()
void Plater::priv::reset() void Plater::priv::reset()
{ {
Plater::TakeSnapshot snapshot(q, _L("Reset Project")); Plater::TakeSnapshot snapshot(q, _L("Reset Project"), UndoRedo::SnapshotType::ProjectSeparator);
clear_warnings(); clear_warnings();
@ -4660,12 +4661,13 @@ int Plater::priv::get_active_snapshot_index()
return it - ss_stack.begin(); return it - ss_stack.begin();
} }
void Plater::priv::take_snapshot(const std::string& snapshot_name) void Plater::priv::take_snapshot(const std::string& snapshot_name, const UndoRedo::SnapshotType snapshot_type)
{ {
if (m_prevent_snapshots > 0) if (m_prevent_snapshots > 0)
return; return;
assert(m_prevent_snapshots >= 0); assert(m_prevent_snapshots >= 0);
UndoRedo::SnapshotData snapshot_data; UndoRedo::SnapshotData snapshot_data;
snapshot_data.snapshot_type = snapshot_type;
snapshot_data.printer_technology = this->printer_technology; snapshot_data.printer_technology = this->printer_technology;
if (this->view3D->is_layers_editing_enabled()) if (this->view3D->is_layers_editing_enabled())
snapshot_data.flags |= UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE; snapshot_data.flags |= UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE;
@ -4951,7 +4953,7 @@ void Plater::new_project()
} }
p->select_view_3D("3D"); p->select_view_3D("3D");
take_snapshot(_L("New Project")); take_snapshot(_L("New Project"), UndoRedo::SnapshotType::ProjectSeparator);
Plater::SuppressSnapshots suppress(this); Plater::SuppressSnapshots suppress(this);
reset(); reset();
reset_project_dirty_initial_presets(); reset_project_dirty_initial_presets();
@ -4976,7 +4978,7 @@ void Plater::load_project(const wxString& filename)
return; return;
// Take the Undo / Redo snapshot. // Take the Undo / Redo snapshot.
Plater::TakeSnapshot snapshot(this, _L("Load Project") + ": " + wxString::FromUTF8(into_path(filename).stem().string().c_str())); Plater::TakeSnapshot snapshot(this, _L("Load Project") + ": " + wxString::FromUTF8(into_path(filename).stem().string().c_str()), UndoRedo::SnapshotType::ProjectSeparator);
p->reset(); p->reset();
@ -5992,6 +5994,8 @@ void Plater::eject_drive()
void Plater::take_snapshot(const std::string &snapshot_name) { p->take_snapshot(snapshot_name); } void Plater::take_snapshot(const std::string &snapshot_name) { p->take_snapshot(snapshot_name); }
void Plater::take_snapshot(const wxString &snapshot_name) { p->take_snapshot(snapshot_name); } void Plater::take_snapshot(const wxString &snapshot_name) { p->take_snapshot(snapshot_name); }
void Plater::take_snapshot(const std::string &snapshot_name, UndoRedo::SnapshotType snapshot_type) { p->take_snapshot(snapshot_name, snapshot_type); }
void Plater::take_snapshot(const wxString &snapshot_name, UndoRedo::SnapshotType snapshot_type) { p->take_snapshot(snapshot_name, snapshot_type); }
void Plater::suppress_snapshots() { p->suppress_snapshots(); } void Plater::suppress_snapshots() { p->suppress_snapshots(); }
void Plater::allow_snapshots() { p->allow_snapshots(); } void Plater::allow_snapshots() { p->allow_snapshots(); }
void Plater::undo() { p->undo(); } void Plater::undo() { p->undo(); }

View File

@ -37,6 +37,7 @@ using ModelInstancePtrs = std::vector<ModelInstance*>;
namespace UndoRedo { namespace UndoRedo {
class Stack; class Stack;
enum class SnapshotType : unsigned char;
struct Snapshot; struct Snapshot;
} }
@ -240,6 +241,9 @@ public:
void take_snapshot(const std::string &snapshot_name); void take_snapshot(const std::string &snapshot_name);
void take_snapshot(const wxString &snapshot_name); void take_snapshot(const wxString &snapshot_name);
void take_snapshot(const std::string &snapshot_name, UndoRedo::SnapshotType snapshot_type);
void take_snapshot(const wxString &snapshot_name, UndoRedo::SnapshotType snapshot_type);
void undo(); void undo();
void redo(); void redo();
void undo_to(int selection); void undo_to(int selection);
@ -391,6 +395,12 @@ public:
m_plater->take_snapshot(snapshot_name); m_plater->take_snapshot(snapshot_name);
m_plater->suppress_snapshots(); m_plater->suppress_snapshots();
} }
TakeSnapshot(Plater *plater, const wxString &snapshot_name, UndoRedo::SnapshotType snapshot_type) : m_plater(plater)
{
m_plater->take_snapshot(snapshot_name, snapshot_type);
m_plater->suppress_snapshots();
}
~TakeSnapshot() ~TakeSnapshot()
{ {
m_plater->allow_snapshots(); m_plater->allow_snapshots();

View File

@ -10,6 +10,7 @@
#include "Gizmos/GLGizmoBase.hpp" #include "Gizmos/GLGizmoBase.hpp"
#include "Camera.hpp" #include "Camera.hpp"
#include "Plater.hpp" #include "Plater.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include "libslic3r/LocalesUtils.hpp" #include "libslic3r/LocalesUtils.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
@ -162,7 +163,7 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection, bool chec
needs_reset |= is_any_modifier() && !volume->is_modifier; needs_reset |= is_any_modifier() && !volume->is_modifier;
if (!already_contained || needs_reset) { if (!already_contained || needs_reset) {
wxGetApp().plater()->take_snapshot(_L("Selection-Add")); wxGetApp().plater()->take_snapshot(_L("Selection-Add"), UndoRedo::SnapshotType::Selection);
if (needs_reset) if (needs_reset)
clear(); clear();
@ -203,7 +204,7 @@ void Selection::remove(unsigned int volume_idx)
if (!contains_volume(volume_idx)) if (!contains_volume(volume_idx))
return; return;
wxGetApp().plater()->take_snapshot(_L("Selection-Remove")); wxGetApp().plater()->take_snapshot(_L("Selection-Remove"), UndoRedo::SnapshotType::Selection);
GLVolume* volume = (*m_volumes)[volume_idx]; GLVolume* volume = (*m_volumes)[volume_idx];
@ -235,7 +236,7 @@ void Selection::add_object(unsigned int object_idx, bool as_single_selection)
(as_single_selection && matches(volume_idxs))) (as_single_selection && matches(volume_idxs)))
return; return;
wxGetApp().plater()->take_snapshot(_L("Selection-Add Object")); wxGetApp().plater()->take_snapshot(_L("Selection-Add Object"), UndoRedo::SnapshotType::Selection);
// resets the current list if needed // resets the current list if needed
if (as_single_selection) if (as_single_selection)
@ -254,7 +255,7 @@ void Selection::remove_object(unsigned int object_idx)
if (!m_valid) if (!m_valid)
return; return;
wxGetApp().plater()->take_snapshot(_L("Selection-Remove Object")); wxGetApp().plater()->take_snapshot(_L("Selection-Remove Object"), UndoRedo::SnapshotType::Selection);
do_remove_object(object_idx); do_remove_object(object_idx);
@ -272,7 +273,7 @@ void Selection::add_instance(unsigned int object_idx, unsigned int instance_idx,
(as_single_selection && matches(volume_idxs))) (as_single_selection && matches(volume_idxs)))
return; return;
wxGetApp().plater()->take_snapshot(_L("Selection-Add Instance")); wxGetApp().plater()->take_snapshot(_L("Selection-Add Instance"), UndoRedo::SnapshotType::Selection);
// resets the current list if needed // resets the current list if needed
if (as_single_selection) if (as_single_selection)
@ -291,7 +292,7 @@ void Selection::remove_instance(unsigned int object_idx, unsigned int instance_i
if (!m_valid) if (!m_valid)
return; return;
wxGetApp().plater()->take_snapshot(_L("Selection-Remove Instance")); wxGetApp().plater()->take_snapshot(_L("Selection-Remove Instance"), UndoRedo::SnapshotType::Selection);
do_remove_instance(object_idx, instance_idx); do_remove_instance(object_idx, instance_idx);
@ -388,7 +389,7 @@ void Selection::add_all()
if ((unsigned int)m_list.size() == count) if ((unsigned int)m_list.size() == count)
return; return;
wxGetApp().plater()->take_snapshot(_(L("Selection-Add All"))); wxGetApp().plater()->take_snapshot(_(L("Selection-Add All")), UndoRedo::SnapshotType::Selection);
m_mode = Instance; m_mode = Instance;
clear(); clear();
@ -413,7 +414,7 @@ void Selection::remove_all()
// Not taking the snapshot with non-empty Redo stack will likely be more confusing than losing the Redo stack. // Not taking the snapshot with non-empty Redo stack will likely be more confusing than losing the Redo stack.
// Let's wait for user feedback. // Let's wait for user feedback.
// if (!wxGetApp().plater()->can_redo()) // if (!wxGetApp().plater()->can_redo())
wxGetApp().plater()->take_snapshot(_L("Selection-Remove All")); wxGetApp().plater()->take_snapshot(_L("Selection-Remove All"), UndoRedo::SnapshotType::Selection);
m_mode = Instance; m_mode = Instance;
clear(); clear();

View File

@ -556,6 +556,12 @@ public:
// Snapshot history (names with timestamps). // Snapshot history (names with timestamps).
const std::vector<Snapshot>& snapshots() const { return m_snapshots; } const std::vector<Snapshot>& snapshots() const { return m_snapshots; }
const Snapshot& snapshot(size_t time) const {
const auto it = std::lower_bound(m_snapshots.cbegin(), m_snapshots.cend(), UndoRedo::Snapshot(time));
assert(it != m_snapshots.end() && it->timestamp == time);
return *it;
}
// Timestamp of the active snapshot. // Timestamp of the active snapshot.
size_t active_snapshot_time() const { return m_active_snapshot_time; } size_t active_snapshot_time() const { return m_active_snapshot_time; }
bool temp_snapshot_active() const { return m_snapshots.back().timestamp == m_active_snapshot_time && ! m_snapshots.back().is_topmost_captured(); } bool temp_snapshot_active() const { return m_snapshots.back().timestamp == m_active_snapshot_time && ! m_snapshots.back().is_topmost_captured(); }
@ -1097,6 +1103,7 @@ bool Stack::redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, siz
const Selection& Stack::selection_deserialized() const { return pimpl->selection_deserialized(); } const Selection& Stack::selection_deserialized() const { return pimpl->selection_deserialized(); }
const std::vector<Snapshot>& Stack::snapshots() const { return pimpl->snapshots(); } const std::vector<Snapshot>& Stack::snapshots() const { return pimpl->snapshots(); }
const Snapshot& Stack::snapshot(size_t time) const { return pimpl->snapshot(time); }
size_t Stack::active_snapshot_time() const { return pimpl->active_snapshot_time(); } size_t Stack::active_snapshot_time() const { return pimpl->active_snapshot_time(); }
bool Stack::temp_snapshot_active() const { return pimpl->temp_snapshot_active(); } bool Stack::temp_snapshot_active() const { return pimpl->temp_snapshot_active(); }

View File

@ -24,6 +24,23 @@ namespace GUI {
namespace UndoRedo { namespace UndoRedo {
enum class SnapshotType : unsigned char {
// Some action modifying project state.
Action,
// Selection change at the Plater.
Selection,
// New project, Reset project, Load project ...
ProjectSeparator,
// Entering a Gizmo, which opens a secondary Undo / Redo stack.
EnteringGizmo,
// Leaving a Gizmo, which closes a secondary Undo / Redo stack.
// No action modifying a project state was done between EnteringGizmo / LeavingGizmo.
LeavingGizmoNoAction,
// Leaving a Gizmo, which closes a secondary Undo / Redo stack.
// Some action modifying a project state was done between EnteringGizmo / LeavingGizmo.
LeavingGizmoWithAction,
};
// Data structure to be stored with each snapshot. // 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 // 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. // is likely cheaper in term of both the runtime and memory allocation.
@ -34,6 +51,7 @@ struct SnapshotData
// Constructor is defined in .cpp due to the forward declaration of enum PrinterTechnology. // Constructor is defined in .cpp due to the forward declaration of enum PrinterTechnology.
SnapshotData(); SnapshotData();
SnapshotType snapshot_type;
PrinterTechnology printer_technology; PrinterTechnology printer_technology;
// Bitmap of Flags (see the Flags enum). // Bitmap of Flags (see the Flags enum).
unsigned int flags; unsigned int flags;
@ -122,10 +140,13 @@ public:
// There is one additional snapshot taken at the very end, which indicates the current unnamed state. // There is one additional snapshot taken at the very end, which indicates the current unnamed state.
const std::vector<Snapshot>& snapshots() const; const std::vector<Snapshot>& snapshots() const;
const Snapshot& snapshot(size_t time) const;
// Timestamp of the active snapshot. One of the snapshots of this->snapshots() shall have Snapshot::timestamp equal to this->active_snapshot_time(). // Timestamp of the active snapshot. One of the snapshots of this->snapshots() shall have Snapshot::timestamp equal to this->active_snapshot_time().
// The snapshot time indicates start of an operation, which is finished at the time of the following snapshot, therefore // The active snapshot may be a special placeholder "@@@ Topmost @@@" indicating an uncaptured current state,
// the active snapshot is the successive snapshot. The same logic applies to the time_to_load parameter of undo() and redo() operations. // or the active snapshot may be an active state to which the application state was undoed or redoed.
size_t active_snapshot_time() const; size_t active_snapshot_time() const;
const Snapshot& active_snapshot() const { return this->snapshot(this->active_snapshot_time()); }
// Temporary snapshot is active if the topmost snapshot is active and it has not been captured yet. // Temporary snapshot is active if the topmost snapshot is active and it has not been captured yet.
// In that case the Undo action will capture the last snapshot. // In that case the Undo action will capture the last snapshot.
bool temp_snapshot_active() const; bool temp_snapshot_active() const;