Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::UndoRedo::StackImpl Class Reference
+ Collaboration diagram for Slic3r::UndoRedo::StackImpl:

Public Member Functions

 StackImpl ()
 
void clear ()
 
bool empty () const
 
void set_memory_limit (size_t memsize)
 
size_t get_memory_limit () const
 
size_t memsize () const
 
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 reduce_noisy_snapshots (const std::string &new_name)
 
void load_snapshot (size_t timestamp, Slic3r::Model &model, Slic3r::GUI::GLGizmosManager &gizmos)
 
bool has_undo_snapshot () const
 
bool has_undo_snapshot (size_t time_to_load) const
 
bool has_redo_snapshot () const
 
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 ()
 
const std::vector< Snapshot > & snapshots () const
 
const Snapshotsnapshot (size_t time) const
 
size_t active_snapshot_time () const
 
bool temp_snapshot_active () const
 
void mark_current_as_saved ()
 
bool project_modified () const
 
const Selectionselection_deserialized () const
 
template<typename T >
ObjectID save_mutable_object (const T &object)
 
template<typename T >
ObjectID save_immutable_object (std::shared_ptr< const T > &object, bool optional)
 
template<typename T >
T * load_mutable_object (const Slic3r::ObjectID id)
 
template<typename T >
std::shared_ptr< const T > load_immutable_object (const Slic3r::ObjectID id, bool optional)
 
template<typename T >
void load_mutable_object (const Slic3r::ObjectID id, T &target)
 
bool valid () const
 

Private Member Functions

template<typename T >
ObjectID immutable_object_id (const std::shared_ptr< const T > &ptr)
 
ObjectID immutable_object_id_impl (const void *ptr)
 
void collect_garbage ()
 
std::vector< Snapshot >::iterator release_snapshots (std::vector< Snapshot >::iterator begin, std::vector< Snapshot >::iterator end)
 

Private Attributes

size_t m_memory_limit
 
std::map< ObjectID, std::unique_ptr< ObjectHistoryBase > > m_objects
 
std::map< const void *, ObjectIDm_shared_ptr_to_object_id
 
std::vector< Snapshotm_snapshots
 
size_t m_active_snapshot_time
 
size_t m_saved_snapshot_time { size_t(-1) }
 
size_t m_current_time
 
Selection m_selection
 

Detailed Description

Constructor & Destructor Documentation

◆ StackImpl()

Slic3r::UndoRedo::StackImpl::StackImpl ( )
inline
#define UNDO_REDO_DEBUG_LOW_MEM_FACTOR
Definition UndoRedo.cpp:35
size_t m_memory_limit
Definition UndoRedo.cpp:675
size_t m_active_snapshot_time
Definition UndoRedo.cpp:684
size_t m_current_time
Definition UndoRedo.cpp:689
size_t total_physical_memory()
Definition utils.cpp:1143

Member Function Documentation

◆ active_snapshot_time()

size_t Slic3r::UndoRedo::StackImpl::active_snapshot_time ( ) const
inline
600{ return m_active_snapshot_time; }

References m_active_snapshot_time.

◆ clear()

void Slic3r::UndoRedo::StackImpl::clear ( )
inline
553 {
554 m_objects.clear();
556 m_snapshots.clear();
558 m_current_time = 0;
559 m_saved_snapshot_time = size_t(-1);
561 }
std::vector< Snapshot > m_snapshots
Definition UndoRedo.cpp:682
std::map< const void *, ObjectID > m_shared_ptr_to_object_id
Definition UndoRedo.cpp:680
Selection m_selection
Definition UndoRedo.cpp:691
std::map< ObjectID, std::unique_ptr< ObjectHistoryBase > > m_objects
Definition UndoRedo.cpp:679
size_t m_saved_snapshot_time
Definition UndoRedo.cpp:687
void clear()
Definition UndoRedo.hpp:92

References Slic3r::UndoRedo::Selection::clear(), m_active_snapshot_time, m_current_time, m_objects, m_saved_snapshot_time, m_selection, m_shared_ptr_to_object_id, and m_snapshots.

+ Here is the call graph for this function:

◆ collect_garbage()

void Slic3r::UndoRedo::StackImpl::collect_garbage ( )
private
1107{
1108 // Purge objects with empty histories.
1109 for (auto it = m_objects.begin(); it != m_objects.end();) {
1110 if (it->second->empty()) {
1111 if (it->second->immutable_object_ptr() != nullptr)
1112 // Release the immutable object from the ptr to ObjectID map.
1113 m_shared_ptr_to_object_id.erase(it->second->immutable_object_ptr());
1114 it = m_objects.erase(it);
1115 } else
1116 ++ it;
1117 }
1118}

References m_objects, and m_shared_ptr_to_object_id.

Referenced by take_snapshot().

+ Here is the caller graph for this function:

◆ empty()

bool Slic3r::UndoRedo::StackImpl::empty ( ) const
inline
563 {
564 assert(m_objects.empty() == m_snapshots.empty());
565 assert(! m_objects.empty() || (m_current_time == 0 && m_active_snapshot_time == 0));
566 return m_snapshots.empty();
567 }

References m_active_snapshot_time, m_current_time, m_objects, and m_snapshots.

◆ get_memory_limit()

size_t Slic3r::UndoRedo::StackImpl::get_memory_limit ( ) const
inline
570{ return m_memory_limit; }

References m_memory_limit.

◆ has_redo_snapshot()

bool Slic3r::UndoRedo::StackImpl::has_redo_snapshot ( ) const
1000{
1001 assert(this->valid());
1002 auto it = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time));
1003 return ++ it != m_snapshots.end();
1004}
bool valid() const
Definition UndoRedo.cpp:642

References m_active_snapshot_time, m_snapshots, and valid().

+ Here is the call graph for this function:

◆ has_undo_snapshot() [1/2]

bool Slic3r::UndoRedo::StackImpl::has_undo_snapshot ( ) const
988{
989 assert(this->valid());
990 auto it = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time));
991 return -- it != m_snapshots.begin();
992}

References m_active_snapshot_time, m_snapshots, and valid().

+ Here is the call graph for this function:

◆ has_undo_snapshot() [2/2]

bool Slic3r::UndoRedo::StackImpl::has_undo_snapshot ( size_t  time_to_load) const
995{
996 return time_to_load < m_active_snapshot_time && std::binary_search(m_snapshots.begin(), m_snapshots.end(), Snapshot(time_to_load));
997}

References m_active_snapshot_time, and m_snapshots.

◆ immutable_object_id()

template<typename T >
ObjectID Slic3r::UndoRedo::StackImpl::immutable_object_id ( const std::shared_ptr< const T > &  ptr)
inlineprivate
655 {
656 return this->immutable_object_id_impl((const void*)ptr.get());
657 }
ObjectID immutable_object_id_impl(const void *ptr)
Definition UndoRedo.cpp:658

References immutable_object_id_impl().

Referenced by save_immutable_object().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ immutable_object_id_impl()

ObjectID Slic3r::UndoRedo::StackImpl::immutable_object_id_impl ( const void ptr)
inlineprivate
658 {
659 auto it = m_shared_ptr_to_object_id.find(ptr);
660 if (it == m_shared_ptr_to_object_id.end()) {
661 // Allocate a new temporary ObjectID for this shared pointer.
662 ObjectBase object_with_id;
663 it = m_shared_ptr_to_object_id.insert(it, std::make_pair(ptr, object_with_id.id()));
664 }
665 return it->second;
666 }

References Slic3r::ObjectBase::id(), and m_shared_ptr_to_object_id.

Referenced by immutable_object_id().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ load_immutable_object()

template<typename T >
std::shared_ptr< const T > Slic3r::UndoRedo::StackImpl::load_immutable_object ( const Slic3r::ObjectID  id,
bool  optional 
)
873{
874 // First find a history stack for the ObjectID of this object instance.
875 auto it_object_history = m_objects.find(id);
876 assert(optional || it_object_history != m_objects.end());
877 if (it_object_history == m_objects.end())
878 return std::shared_ptr<const T>();
879 auto *object_history = static_cast<ImmutableObjectHistory<T>*>(it_object_history->second.get());
880 assert(object_history->has_snapshot(m_active_snapshot_time));
881 object_history->restore_optional();
882 return object_history->shared_ptr(*this);
883}

References m_active_snapshot_time, and m_objects.

Referenced by cereal::load(), and cereal::load_optional().

+ Here is the caller graph for this function:

◆ load_mutable_object() [1/2]

template<typename T >
T * Slic3r::UndoRedo::StackImpl::load_mutable_object ( const Slic3r::ObjectID  id)
866{
867 T *target = new T();
868 this->load_mutable_object<T>(id, *target);
869 return target;
870}

Referenced by cereal::load(), cereal::load(), and cereal::load_by_value().

+ Here is the caller graph for this function:

◆ load_mutable_object() [2/2]

template<typename T >
void Slic3r::UndoRedo::StackImpl::load_mutable_object ( const Slic3r::ObjectID  id,
T &  target 
)
886{
887 // First find a history stack for the ObjectID of this object instance.
888 auto it_object_history = m_objects.find(id);
889 assert(it_object_history != m_objects.end());
890 auto *object_history = static_cast<const MutableObjectHistory<T>*>(it_object_history->second.get());
891 // Then get the data associated with the object history and m_active_snapshot_time.
892 std::istringstream iss(object_history->load(m_active_snapshot_time));
893 Slic3r::UndoRedo::InputArchive archive(*this, iss);
894 target.m_id = id;
895 archive(target);
896}
cereal::UserDataAdapter< StackImpl, cereal::BinaryInputArchive > InputArchive
Definition UndoRedo.cpp:694

References m_active_snapshot_time, and m_objects.

◆ load_snapshot()

void Slic3r::UndoRedo::StackImpl::load_snapshot ( size_t  timestamp,
Slic3r::Model model,
Slic3r::GUI::GLGizmosManager gizmos 
)
966{
967 // Find the snapshot by time. It must exist.
968 const auto it_snapshot = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(timestamp));
969 if (it_snapshot == m_snapshots.end() || it_snapshot->timestamp != timestamp)
970 throw Slic3r::RuntimeError((boost::format("Snapshot with timestamp %1% does not exist") % timestamp).str());
971
972 m_active_snapshot_time = timestamp;
973 model.clear_objects();
974 model.clear_materials();
975 this->load_mutable_object<Slic3r::Model>(ObjectID(it_snapshot->model_id), model);
978 this->load_mutable_object<Selection>(m_selection.id(), m_selection);
979 //gizmos.reset_all_states(); FIXME: is this really necessary? It is quite unpleasant for the gizmo undo/redo substack
980 this->load_mutable_object<Slic3r::GUI::GLGizmosManager>(gizmos.id(), gizmos);
981 // Sort the volumes so that we may use binary search.
983 m_active_snapshot_time = timestamp;
984 assert(this->valid());
985}
void clear_materials()
Definition Model.cpp:288
void update_links_bottom_up_recursive()
Definition Model.cpp:90
void clear_objects()
Definition Model.cpp:272
ObjectID id() const
Definition ObjectID.hpp:55
std::vector< std::pair< size_t, size_t > > volumes_and_instances
Definition UndoRedo.hpp:94

References Slic3r::Model::clear_materials(), Slic3r::Model::clear_objects(), Slic3r::ObjectBase::id(), m_active_snapshot_time, m_selection, m_snapshots, Slic3r::Model::update_links_bottom_up_recursive(), valid(), and Slic3r::UndoRedo::Selection::volumes_and_instances.

Referenced by redo(), and undo().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mark_current_as_saved()

void Slic3r::UndoRedo::StackImpl::mark_current_as_saved ( )
inline

◆ memsize()

size_t Slic3r::UndoRedo::StackImpl::memsize ( ) const
inline
572 {
573 size_t memsize = 0;
574 for (const auto &object : m_objects)
575 memsize += object.second->memsize();
576 return memsize;
577 }
size_t memsize() const
Definition UndoRedo.cpp:572

References m_objects, and memsize().

Referenced by memsize(), release_least_recently_used(), and set_memory_limit().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ project_modified()

bool Slic3r::UndoRedo::StackImpl::project_modified ( ) const
1205{
1206 assert(! m_snapshots.empty());
1207
1208 if (m_saved_snapshot_time == size_t(-1))
1209 // Don't know anything about the project state.
1210 return true;
1212 // Just saved at this step.
1213 return false;
1214
1215 assert(m_saved_snapshot_time >= m_snapshots.front().timestamp && m_saved_snapshot_time <= m_snapshots.back().timestamp);
1216
1217 auto it_saved = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_saved_snapshot_time));
1218 assert(it_saved != m_snapshots.end() && it_saved->timestamp == m_saved_snapshot_time);
1219
1220#ifndef NDEBUG
1221 // Verify that there is a snapshot with "current time".
1222 auto it_current = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time));
1223 assert(it_current != m_snapshots.end() && it_current->timestamp == m_active_snapshot_time);
1224#endif // NDEBUG
1225
1227 // Search upwards. Ignore state of the "active" snapshot.
1228 for (auto it = it_saved; it->timestamp < m_active_snapshot_time; ++ it)
1230 return true;
1231 } else {
1232 // Search downwards. Ignore state of the "saved" snapshot.
1234 for (auto it = it_saved - 1; it->timestamp >= m_active_snapshot_time; -- it)
1236 return true;
1237 }
1238
1239 return false;
1240}
static bool snapshot_modifies_project(SnapshotType type)
Definition UndoRedo.cpp:1067

References m_active_snapshot_time, m_saved_snapshot_time, m_snapshots, and Slic3r::UndoRedo::snapshot_modifies_project().

+ Here is the call graph for this function:

◆ redo()

bool Slic3r::UndoRedo::StackImpl::redo ( Slic3r::Model model,
Slic3r::GUI::GLGizmosManager gizmos,
size_t  jump_to_time 
)
1048{
1049 assert(this->valid());
1050 if (time_to_load == SIZE_MAX) {
1051 auto it_current = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time));
1052 if (++ it_current == m_snapshots.end())
1053 return false;
1054 time_to_load = it_current->timestamp;
1055 }
1056 assert(time_to_load > m_active_snapshot_time);
1057 assert(std::binary_search(m_snapshots.begin(), m_snapshots.end(), Snapshot(time_to_load)));
1058 this->load_snapshot(time_to_load, model, gizmos);
1059#ifdef SLIC3R_UNDOREDO_DEBUG
1060 std::cout << "After redo" << std::endl;
1061 this->print();
1062#endif /* SLIC3R_UNDOREDO_DEBUG */
1063 return true;
1064}
void load_snapshot(size_t timestamp, Slic3r::Model &model, Slic3r::GUI::GLGizmosManager &gizmos)
Definition UndoRedo.cpp:965
#define SIZE_MAX
Definition lexer.c:87

References load_snapshot(), m_active_snapshot_time, m_snapshots, SIZE_MAX, and valid().

+ Here is the call graph for this function:

◆ reduce_noisy_snapshots()

void Slic3r::UndoRedo::StackImpl::reduce_noisy_snapshots ( const std::string &  new_name)
940{
941 // Preceding snapshot must be a "leave gizmo" snapshot.
942 assert(! m_snapshots.empty() && m_snapshots.back().is_topmost() && m_snapshots.back().timestamp == m_active_snapshot_time);
943 auto it_last = m_snapshots.end();
944 -- it_last; -- it_last;
945 assert(it_last != m_snapshots.begin() && (it_last->snapshot_data.snapshot_type == SnapshotType::LeavingGizmoNoAction || it_last->snapshot_data.snapshot_type == SnapshotType::LeavingGizmoWithAction));
946 if (it_last->snapshot_data.snapshot_type == SnapshotType::LeavingGizmoWithAction) {
947 for (-- it_last; it_last->snapshot_data.snapshot_type != SnapshotType::EnteringGizmo; -- it_last) {
948 if (it_last->snapshot_data.snapshot_type == SnapshotType::GizmoAction) {
949 it_last->name = new_name;
950 auto it = it_last;
951 for (-- it; it->snapshot_data.snapshot_type == SnapshotType::GizmoAction; -- it) ;
952 if (++ it < it_last) {
953 // Drop (it, it_last>
954 for (auto &kvp : m_objects)
955 // Drop products of <it + 1, it_last + 1>
956 kvp.second->release_between_timestamps(it->timestamp, (it_last + 1)->timestamp);
957 it_last = this->release_snapshots(it + 1, it_last + 1);
958 }
959 }
960 assert(it_last != m_snapshots.begin());
961 }
962 }
963}
std::vector< Snapshot >::iterator release_snapshots(std::vector< Snapshot >::iterator begin, std::vector< Snapshot >::iterator end)
Definition UndoRedo.cpp:1079

References Slic3r::UndoRedo::EnteringGizmo, Slic3r::UndoRedo::GizmoAction, Slic3r::UndoRedo::LeavingGizmoNoAction, Slic3r::UndoRedo::LeavingGizmoWithAction, m_active_snapshot_time, m_objects, m_snapshots, and release_snapshots().

+ Here is the call graph for this function:

◆ release_least_recently_used()

void Slic3r::UndoRedo::StackImpl::release_least_recently_used ( )
1121{
1122 assert(this->valid());
1123 size_t current_memsize = this->memsize();
1124#ifdef SLIC3R_UNDOREDO_DEBUG
1125 bool released = false;
1126#endif
1127 // First try to release the optional immutable data (for example the convex hulls),
1128 // or the shared vertices of triangle meshes.
1129 for (auto it = m_objects.begin(); current_memsize > m_memory_limit && it != m_objects.end();) {
1130 const void *ptr = it->second->immutable_object_ptr();
1131 size_t mem_released = it->second->release_optional();
1132 if (it->second->empty()) {
1133 if (ptr != nullptr)
1134 // Release the immutable object from the ptr to ObjectID map.
1135 m_shared_ptr_to_object_id.erase(ptr);
1136 mem_released += it->second->memsize();
1137 it = m_objects.erase(it);
1138 } else
1139 ++ it;
1140 assert(current_memsize >= mem_released);
1141 if (current_memsize >= mem_released)
1142 current_memsize -= mem_released;
1143 else
1144 current_memsize = 0;
1145 }
1146 while (current_memsize > m_memory_limit && m_snapshots.size() >= 3) {
1147 // From which side to remove a snapshot?
1148 assert(m_snapshots.front().timestamp < m_active_snapshot_time);
1149 size_t mem_released = 0;
1150 if (m_snapshots[1].timestamp == m_active_snapshot_time) {
1151 // Remove the last snapshot.
1152#if 0
1153 for (auto it = m_objects.begin(); it != m_objects.end();) {
1154 mem_released += it->second->release_after_timestamp(m_snapshots.back().timestamp);
1155 if (it->second->empty()) {
1156 if (it->second->immutable_object_ptr() != nullptr)
1157 // Release the immutable object from the ptr to ObjectID map.
1158 m_shared_ptr_to_object_id.erase(it->second->immutable_object_ptr());
1159 mem_released += it->second->memsize();
1160 it = m_objects.erase(it);
1161 } else
1162 ++ it;
1163 }
1164 m_snapshots.pop_back();
1165 m_snapshots.back().name = topmost_snapshot_name;
1166#else
1167 // Rather don't release the last snapshot as it will be very confusing to the user
1168 // as of why he cannot jump to the top most state. The Undo / Redo stack maximum size
1169 // should be set low enough to accomodate for the top most snapshot.
1170 break;
1171#endif
1172 } else {
1173 // Remove the first snapshot.
1174 for (auto it = m_objects.begin(); it != m_objects.end();) {
1175 mem_released += it->second->release_before_timestamp(m_snapshots[1].timestamp);
1176 if (it->second->empty()) {
1177 if (it->second->immutable_object_ptr() != nullptr)
1178 // Release the immutable object from the ptr to ObjectID map.
1179 m_shared_ptr_to_object_id.erase(it->second->immutable_object_ptr());
1180 mem_released += it->second->memsize();
1181 it = m_objects.erase(it);
1182 } else
1183 ++ it;
1184 }
1185 //FIXME update the "saved" snapshot time.
1186 m_snapshots.erase(m_snapshots.begin());
1187 }
1188 assert(current_memsize >= mem_released);
1189 if (current_memsize >= mem_released)
1190 current_memsize -= mem_released;
1191 else
1192 current_memsize = 0;
1193#ifdef SLIC3R_UNDOREDO_DEBUG
1194 released = true;
1195#endif
1196 }
1197 assert(this->valid());
1198#ifdef SLIC3R_UNDOREDO_DEBUG
1199 std::cout << "After release_least_recently_used" << std::endl;
1200 this->print();
1201#endif /* SLIC3R_UNDOREDO_DEBUG */
1202}
static std::string topmost_snapshot_name
Definition UndoRedo.cpp:50

References m_active_snapshot_time, m_memory_limit, m_objects, m_shared_ptr_to_object_id, m_snapshots, memsize(), Slic3r::UndoRedo::topmost_snapshot_name, and valid().

+ Here is the call graph for this function:

◆ release_snapshots()

std::vector< Snapshot >::iterator Slic3r::UndoRedo::StackImpl::release_snapshots ( std::vector< Snapshot >::iterator  begin,
std::vector< Snapshot >::iterator  end 
)
private
1080{
1081 assert(! m_snapshots.empty());
1082 assert(begin <= end);
1083 if (m_saved_snapshot_time != size_t(-1) && m_saved_snapshot_time >= begin->timestamp && (end == m_snapshots.end() || m_saved_snapshot_time < end->timestamp)) {
1084 assert(m_saved_snapshot_time <= m_snapshots.back().timestamp);
1085 auto it_saved = std::lower_bound(begin, end, Snapshot(m_saved_snapshot_time));
1086 assert(it_saved != m_snapshots.end() && it_saved->timestamp == m_saved_snapshot_time);
1087 auto it = it_saved;
1088 for (; it != begin && ! snapshot_modifies_project(*it); -- it) ;
1089 if (it == begin && ! snapshot_modifies_project(*it)) {
1090 // Found a snapshot before begin, which captures the same project state.
1091 m_saved_snapshot_time = (-- it)->timestamp;
1092 } else {
1093 auto it = it_saved;
1094 for (; it != end && ! snapshot_modifies_project(*it); ++ it) ;
1095 if (it == end && end != m_snapshots.end())
1096 // Found a snapshot after end, which captures the same project state.
1097 m_saved_snapshot_time = (-- it)->timestamp;
1098 else
1099 // State of the project is being lost. Indicate a "likely modified" project state until the project is saved again.
1100 m_saved_snapshot_time = size_t(-1);
1101 }
1102 }
1103 return m_snapshots.erase(begin, end);
1104}
S::iterator begin(S &sh, const PathTag &)
Definition geometry_traits.hpp:614
S::iterator end(S &sh, const PathTag &)
Definition geometry_traits.hpp:620

References m_saved_snapshot_time, m_snapshots, and Slic3r::UndoRedo::snapshot_modifies_project().

Referenced by reduce_noisy_snapshots(), and take_snapshot().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ save_immutable_object()

template<typename T >
ObjectID Slic3r::UndoRedo::StackImpl::save_immutable_object ( std::shared_ptr< const T > &  object,
bool  optional 
)
851{
852 // First allocate a temporary ObjectID for this pointer.
853 ObjectID object_id = this->immutable_object_id(object);
854 // and find or allocate a history stack for the ObjectID associated to this shared_ptr.
855 auto it_object_history = m_objects.find(object_id);
856 if (it_object_history == m_objects.end())
857 it_object_history = m_objects.emplace_hint(it_object_history, object_id, std::unique_ptr<ImmutableObjectHistory<T>>(new ImmutableObjectHistory<T>(object, optional)));
858 else
859 assert(it_object_history->second.get()->is_optional() == optional);
860 // Then save the interval.
861 static_cast<ImmutableObjectHistory<T>*>(it_object_history->second.get())->save(m_active_snapshot_time, m_current_time);
862 return object_id;
863}
void save(Archive &archive, wxString const &d)
Definition GLGizmoEmboss.cpp:1557
ObjectID immutable_object_id(const std::shared_ptr< const T > &ptr)
Definition UndoRedo.cpp:655

References immutable_object_id(), m_active_snapshot_time, m_current_time, m_objects, and save().

+ Here is the call graph for this function:

◆ save_mutable_object()

template<typename T >
ObjectID Slic3r::UndoRedo::StackImpl::save_mutable_object ( const T &  object)
824{
825 // First find or allocate a history stack for the ObjectID of this object instance.
826 auto it_object_history = m_objects.find(object.id());
827 if (it_object_history == m_objects.end())
828 it_object_history = m_objects.insert(it_object_history, std::make_pair(object.id(), std::unique_ptr<MutableObjectHistory<T>>(new MutableObjectHistory<T>())));
829 auto *object_history = static_cast<MutableObjectHistory<T>*>(it_object_history->second.get());
830 bool needs_to_save = true;
831 {
832 // If the timestamp returned is non zero, then it is considered reliable.
833 // The caller is supposed to serialize the timestamp first.
834 uint64_t timestamp = object.timestamp();
835 if (timestamp > 0)
836 needs_to_save = ! object_history->try_save_timestamp(m_active_snapshot_time, m_current_time, timestamp);
837 }
838 if (needs_to_save) {
839 // Serialize the object into a string.
840 std::ostringstream oss;
841 {
842 Slic3r::UndoRedo::OutputArchive archive(*this, oss);
843 archive(object);
844 }
845 object_history->save(m_active_snapshot_time, m_current_time, oss.str());
846 }
847 return object.id();
848}
cereal::UserDataAdapter< StackImpl, cereal::BinaryOutputArchive > OutputArchive
Definition UndoRedo.cpp:695
unsigned __int64 uint64_t
Definition unistd.h:80

References m_active_snapshot_time, m_current_time, m_objects, and Slic3r::UndoRedo::MutableObjectHistory< T >::try_save_timestamp().

+ Here is the call graph for this function:

◆ selection_deserialized()

const Selection & Slic3r::UndoRedo::StackImpl::selection_deserialized ( ) const
inline
607{ return m_selection; }

References m_selection.

◆ set_memory_limit()

void Slic3r::UndoRedo::StackImpl::set_memory_limit ( size_t  memsize)
inline

References m_memory_limit, and memsize().

+ Here is the call graph for this function:

◆ snapshot()

const Snapshot & Slic3r::UndoRedo::StackImpl::snapshot ( size_t  time) const
inline
593 {
594 const auto it = std::lower_bound(m_snapshots.cbegin(), m_snapshots.cend(), UndoRedo::Snapshot(time));
595 assert(it != m_snapshots.end() && it->timestamp == time);
596 return *it;
597 }

References m_snapshots.

◆ snapshots()

const std::vector< Snapshot > & Slic3r::UndoRedo::StackImpl::snapshots ( ) const
inline
592{ return m_snapshots; }

References m_snapshots.

◆ take_snapshot()

void Slic3r::UndoRedo::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 
)
900{
901 // Release old snapshot data.
903 for (auto &kvp : m_objects)
904 kvp.second->release_after_timestamp(m_active_snapshot_time);
905 bool topmost_saved = false;
906 if (! m_snapshots.empty()) {
907 // If the project was saved for the topmost snapshot, restore the "saved" state after the "topmost" snapshot is taken.
908 topmost_saved = m_active_snapshot_time == m_saved_snapshot_time && m_active_snapshot_time == m_snapshots.back().timestamp;
909 auto it = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time));
910 this->release_snapshots(it, m_snapshots.end());
911 }
912 // Take new snapshots.
913 this->save_mutable_object<Slic3r::Model>(model);
915 m_selection.volumes_and_instances.reserve(selection.get_volume_idxs().size());
916 m_selection.mode = selection.get_mode();
917 for (unsigned int volume_idx : selection.get_volume_idxs())
918 m_selection.volumes_and_instances.emplace_back(selection.get_volume(volume_idx)->geometry_id);
919 this->save_mutable_object<Selection>(m_selection);
920 this->save_mutable_object<Slic3r::GUI::GLGizmosManager>(gizmos);
921 // Save the snapshot info.
922 m_snapshots.emplace_back(snapshot_name, m_current_time, model.id().id, snapshot_data);
923 if (topmost_saved)
924 // Restore the "saved" timestamp.
927 // Save snapshot info of the last "current" aka "top most" state, that is only being serialized
928 // if undoing an action. Such a snapshot has an invalid Model ID assigned if it was not taken yet.
929 m_snapshots.emplace_back(topmost_snapshot_name, m_active_snapshot_time, 0, snapshot_data);
930 // Release empty objects from the history.
931 this->collect_garbage();
932 assert(this->valid());
933#ifdef SLIC3R_UNDOREDO_DEBUG
934 std::cout << "After snapshot" << std::endl;
935 this->print();
936#endif /* SLIC3R_UNDOREDO_DEBUG */
937}
EMode get_mode() const
Definition Selection.hpp:209
const IndicesList & get_volume_idxs() const
Definition Selection.hpp:290
size_t id
Definition ObjectID.hpp:37
void collect_garbage()
Definition UndoRedo.cpp:1106
unsigned char mode
Definition UndoRedo.hpp:93
static float get_volume(stl_file *stl)
Definition util.cpp:276

References collect_garbage(), Slic3r::GLVolume::geometry_id, Slic3r::GUI::Selection::get_mode(), Slic3r::GUI::Selection::get_volume(), Slic3r::GUI::Selection::get_volume_idxs(), Slic3r::ObjectID::id, Slic3r::ObjectBase::id(), m_active_snapshot_time, m_current_time, m_objects, m_saved_snapshot_time, m_selection, m_snapshots, Slic3r::UndoRedo::Selection::mode, release_snapshots(), Slic3r::UndoRedo::topmost_snapshot_name, valid(), and Slic3r::UndoRedo::Selection::volumes_and_instances.

Referenced by undo().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ temp_snapshot_active()

bool Slic3r::UndoRedo::StackImpl::temp_snapshot_active ( ) const
inline
601{ return m_snapshots.back().timestamp == m_active_snapshot_time && ! m_snapshots.back().is_topmost_captured(); }

References m_active_snapshot_time, and m_snapshots.

◆ undo()

bool Slic3r::UndoRedo::StackImpl::undo ( Slic3r::Model model,
const Slic3r::GUI::Selection selection,
Slic3r::GUI::GLGizmosManager gizmos,
const SnapshotData snapshot_data,
size_t  jump_to_time 
)
1007{
1008 assert(this->valid());
1009 if (time_to_load == SIZE_MAX) {
1010 auto it_current = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time));
1011 if (-- it_current == m_snapshots.begin())
1012 return false;
1013 time_to_load = it_current->timestamp;
1014 }
1015 assert(time_to_load < m_active_snapshot_time);
1016 assert(std::binary_search(m_snapshots.begin(), m_snapshots.end(), Snapshot(time_to_load)));
1017 bool new_snapshot_taken = false;
1018 if (m_active_snapshot_time == m_snapshots.back().timestamp && ! m_snapshots.back().is_topmost_captured()) {
1019 // The current state is temporary. The current state needs to be captured to be redoable.
1020 //FIXME add new a "topmost" SnapshotType?
1021 this->take_snapshot(topmost_snapshot_name, model, selection, gizmos, snapshot_data);
1022 // The line above entered another topmost_snapshot_name.
1023 assert(m_snapshots.back().is_topmost());
1024 assert(! m_snapshots.back().is_topmost_captured());
1025 // Pop it back, it is not needed as there is now a captured topmost state.
1026 m_snapshots.pop_back();
1027 // current_time was extended, but it should not cause any harm. Resetting it back may complicate the logic unnecessarily.
1028 //-- m_current_time;
1029 assert(m_snapshots.back().is_topmost());
1030 assert(m_snapshots.back().is_topmost_captured());
1031 new_snapshot_taken = true;
1032 }
1033 this->load_snapshot(time_to_load, model, gizmos);
1034 if (new_snapshot_taken) {
1035 // Release old snapshots if the memory allocated due to capturing the top most state is excessive.
1036 // Don't release the snapshots here, release them first after the scene and background processing gets updated, as this will release some references
1037 // to the shared TriangleMeshes.
1038 //this->release_least_recently_used();
1039 }
1040#ifdef SLIC3R_UNDOREDO_DEBUG
1041 std::cout << "After undo" << std::endl;
1042 this->print();
1043#endif /* SLIC3R_UNDOREDO_DEBUG */
1044 return true;
1045}
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)
Definition UndoRedo.cpp:899

References load_snapshot(), m_active_snapshot_time, m_snapshots, SIZE_MAX, take_snapshot(), and valid().

+ Here is the call graph for this function:

◆ valid()

bool Slic3r::UndoRedo::StackImpl::valid ( ) const
inline
642 {
643 assert(! m_snapshots.empty());
644 assert(m_snapshots.back().is_topmost());
645 auto it = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time));
646 assert(it != m_snapshots.begin() && it != m_snapshots.end() && it->timestamp == m_active_snapshot_time);
647 assert(m_active_snapshot_time <= m_snapshots.back().timestamp);
648 for (auto it = m_objects.begin(); it != m_objects.end(); ++ it)
649 assert(it->second->valid());
650 return true;
651 }

References m_active_snapshot_time, m_objects, and m_snapshots.

Referenced by has_redo_snapshot(), has_undo_snapshot(), load_snapshot(), redo(), release_least_recently_used(), take_snapshot(), and undo().

+ Here is the caller graph for this function:

Member Data Documentation

◆ m_active_snapshot_time

◆ m_current_time

size_t Slic3r::UndoRedo::StackImpl::m_current_time
private

◆ m_memory_limit

size_t Slic3r::UndoRedo::StackImpl::m_memory_limit
private

◆ m_objects

◆ m_saved_snapshot_time

size_t Slic3r::UndoRedo::StackImpl::m_saved_snapshot_time { size_t(-1) }
private

◆ m_selection

Selection Slic3r::UndoRedo::StackImpl::m_selection
private

◆ m_shared_ptr_to_object_id

std::map<const void*, ObjectID> Slic3r::UndoRedo::StackImpl::m_shared_ptr_to_object_id
private

◆ m_snapshots


The documentation for this class was generated from the following file: