Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVojtech Bubnik <bubnikv@gmail.com>2020-09-23 14:00:01 +0300
committerVojtech Bubnik <bubnikv@gmail.com>2020-09-23 14:00:01 +0300
commit0d6eb842b0b71dda30080e2286e3e7bb65f766d8 (patch)
tree9e2bf32023c7ac44d3de21c737c333e0eaf41b91 /src
parent4bf49d960c554106e494200dafe0ea5ca3529443 (diff)
parentdde64d361b58247516acc8f69f33dea33466edec (diff)
Merge branch 'vb_undoredo_timestamp'
Diffstat (limited to 'src')
-rw-r--r--src/libslic3r/GCode.cpp2
-rw-r--r--src/libslic3r/Model.hpp8
-rw-r--r--src/libslic3r/ObjectID.hpp9
-rw-r--r--src/slic3r/Utils/UndoRedo.cpp48
4 files changed, 56 insertions, 11 deletions
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index 32e762985..febdff7e0 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -601,7 +601,7 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
// Check that there are extrusions on the very first layer.
if (layers_to_print.size() == 1u) {
if (!has_extrusions)
- throw Slic3r::RuntimeError(_(L("There is an object with no extrusions on the first layer.")));
+ throw Slic3r::SlicingError(_(L("There is an object with no extrusions on the first layer.")));
}
// In case there are extrusions on this layer, check there is a layer to lay it on.
diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp
index b9045e28b..c6b7c6030 100644
--- a/src/libslic3r/Model.hpp
+++ b/src/libslic3r/Model.hpp
@@ -448,7 +448,11 @@ public:
Vec3d mesh_offset{ Vec3d::Zero() };
Geometry::Transformation transform;
- template<class Archive> void serialize(Archive& ar) { ar(input_file, object_idx, volume_idx, mesh_offset, transform); }
+ template<class Archive> void serialize(Archive& ar) {
+ //FIXME Vojtech: Serialize / deserialize only if the Source is set.
+ // likely testing input_file or object_idx would be sufficient.
+ ar(input_file, object_idx, volume_idx, mesh_offset, transform);
+ }
};
Source source;
@@ -467,7 +471,7 @@ public:
FacetsAnnotation m_supported_facets;
// List of seam enforcers/blockers.
- FacetsAnnotation m_seam_facets;
+ FacetsAnnotation m_seam_facets;
// A parent object owning this modifier volume.
ModelObject* get_object() const { return this->object; }
diff --git a/src/libslic3r/ObjectID.hpp b/src/libslic3r/ObjectID.hpp
index 920f512de..fd5cc80ae 100644
--- a/src/libslic3r/ObjectID.hpp
+++ b/src/libslic3r/ObjectID.hpp
@@ -49,7 +49,12 @@ private:
class ObjectBase
{
public:
- ObjectID id() const { return m_id; }
+ ObjectID id() const { return m_id; }
+ // Return an optional timestamp of this object.
+ // If the timestamp returned is non-zero, then the serialization framework will
+ // only save this object on the Undo/Redo stack if the timestamp is different
+ // from the timestmap of the object at the top of the Undo / Redo stack.
+ virtual uint64_t timestamp() const { return 0; }
protected:
// Constructors to be only called by derived classes.
@@ -59,7 +64,7 @@ protected:
// by an existing ID copied from elsewhere.
ObjectBase(int) : m_id(ObjectID(0)) {}
// The class tree will have virtual tables and type information.
- virtual ~ObjectBase() {}
+ virtual ~ObjectBase() = default;
// Use with caution!
void set_new_unique_id() { m_id = generate_new_id(); }
diff --git a/src/slic3r/Utils/UndoRedo.cpp b/src/slic3r/Utils/UndoRedo.cpp
index 10b8062f7..79cf3e82e 100644
--- a/src/slic3r/Utils/UndoRedo.cpp
+++ b/src/slic3r/Utils/UndoRedo.cpp
@@ -307,7 +307,11 @@ private:
size_t size;
char data[1];
+ // The serialized data matches the data stored here.
bool matches(const std::string& rhs) { return this->size == rhs.size() && memcmp(this->data, rhs.data(), this->size) == 0; }
+
+ // The timestamp matches the timestamp serialized in the data stored here.
+ bool matches_timestamp(uint64_t timestamp) { assert(timestamp > 0); assert(this->size > 8); return memcmp(this->data, &timestamp, 8) == 0; }
};
Interval m_interval;
@@ -350,7 +354,8 @@ public:
size_t size() const { return m_data->size; }
size_t refcnt() const { return m_data->refcnt; }
bool matches(const std::string& data) { return m_data->matches(data); }
- size_t memsize() const {
+ bool matches_timestamp(uint64_t timestamp) { return m_data->matches_timestamp(timestamp); }
+ size_t memsize() const {
return m_data->refcnt == 1 ?
// Count just the size of the snapshot data.
m_data->size :
@@ -398,6 +403,27 @@ public:
return memsize;
}
+ // If an object provides a reliable timestamp and the object serializes the timestamp first,
+ // then we may just check the validity of the timestamp against the last snapshot without
+ // having to serialize the whole object. This reduces the amount of serialization and memcmp
+ // when taking a snapshot.
+ bool try_save_timestamp(size_t active_snapshot_time, size_t current_time, uint64_t timestamp) {
+ assert(m_history.empty() || m_history.back().end() <= active_snapshot_time);
+ if (! m_history.empty() && m_history.back().matches_timestamp(timestamp)) {
+ if (m_history.back().end() < active_snapshot_time)
+ // Share the previous data by reference counting.
+ m_history.emplace_back(Interval(current_time, current_time + 1), m_history.back());
+ else {
+ assert(m_history.back().end() == active_snapshot_time);
+ // Just extend the last interval using the old data.
+ m_history.back().extend_end(current_time + 1);
+ }
+ return true;
+ }
+ // The timestamp is not valid, the caller has to call this->save() with the serialized data.
+ return false;
+ }
+
void save(size_t active_snapshot_time, size_t current_time, const std::string &data) {
assert(m_history.empty() || m_history.back().end() <= active_snapshot_time);
if (m_history.empty() || m_history.back().end() < active_snapshot_time) {
@@ -749,13 +775,23 @@ template<typename T> ObjectID StackImpl::save_mutable_object(const T &object)
if (it_object_history == m_objects.end())
it_object_history = m_objects.insert(it_object_history, std::make_pair(object.id(), std::unique_ptr<MutableObjectHistory<T>>(new MutableObjectHistory<T>())));
auto *object_history = static_cast<MutableObjectHistory<T>*>(it_object_history->second.get());
- // Then serialize the object into a string.
- std::ostringstream oss;
+ bool needs_to_save = true;
{
- Slic3r::UndoRedo::OutputArchive archive(*this, oss);
- archive(object);
+ // If the timestamp returned is non zero, then it is considered reliable.
+ // The caller is supposed to serialize the timestamp first.
+ uint64_t timestamp = object.timestamp();
+ if (timestamp > 0)
+ needs_to_save = ! object_history->try_save_timestamp(m_active_snapshot_time, m_current_time, timestamp);
+ }
+ if (needs_to_save) {
+ // Serialize the object into a string.
+ std::ostringstream oss;
+ {
+ Slic3r::UndoRedo::OutputArchive archive(*this, oss);
+ archive(object);
+ }
+ object_history->save(m_active_snapshot_time, m_current_time, oss.str());
}
- object_history->save(m_active_snapshot_time, m_current_time, oss.str());
return object.id();
}