Merge branch 'vb_undoredo_timestamp'
This commit is contained in:
commit
0d6eb842b0
4 changed files with 56 additions and 11 deletions
|
@ -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.
|
// Check that there are extrusions on the very first layer.
|
||||||
if (layers_to_print.size() == 1u) {
|
if (layers_to_print.size() == 1u) {
|
||||||
if (!has_extrusions)
|
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.
|
// In case there are extrusions on this layer, check there is a layer to lay it on.
|
||||||
|
|
|
@ -448,7 +448,11 @@ public:
|
||||||
Vec3d mesh_offset{ Vec3d::Zero() };
|
Vec3d mesh_offset{ Vec3d::Zero() };
|
||||||
Geometry::Transformation transform;
|
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;
|
Source source;
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,11 @@ class ObjectBase
|
||||||
{
|
{
|
||||||
public:
|
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:
|
protected:
|
||||||
// Constructors to be only called by derived classes.
|
// Constructors to be only called by derived classes.
|
||||||
|
@ -59,7 +64,7 @@ protected:
|
||||||
// by an existing ID copied from elsewhere.
|
// by an existing ID copied from elsewhere.
|
||||||
ObjectBase(int) : m_id(ObjectID(0)) {}
|
ObjectBase(int) : m_id(ObjectID(0)) {}
|
||||||
// The class tree will have virtual tables and type information.
|
// The class tree will have virtual tables and type information.
|
||||||
virtual ~ObjectBase() {}
|
virtual ~ObjectBase() = default;
|
||||||
|
|
||||||
// Use with caution!
|
// Use with caution!
|
||||||
void set_new_unique_id() { m_id = generate_new_id(); }
|
void set_new_unique_id() { m_id = generate_new_id(); }
|
||||||
|
|
|
@ -307,7 +307,11 @@ private:
|
||||||
size_t size;
|
size_t size;
|
||||||
char data[1];
|
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; }
|
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, ×tamp, 8) == 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
Interval m_interval;
|
Interval m_interval;
|
||||||
|
@ -350,6 +354,7 @@ public:
|
||||||
size_t size() const { return m_data->size; }
|
size_t size() const { return m_data->size; }
|
||||||
size_t refcnt() const { return m_data->refcnt; }
|
size_t refcnt() const { return m_data->refcnt; }
|
||||||
bool matches(const std::string& data) { return m_data->matches(data); }
|
bool matches(const std::string& data) { return m_data->matches(data); }
|
||||||
|
bool matches_timestamp(uint64_t timestamp) { return m_data->matches_timestamp(timestamp); }
|
||||||
size_t memsize() const {
|
size_t memsize() const {
|
||||||
return m_data->refcnt == 1 ?
|
return m_data->refcnt == 1 ?
|
||||||
// Count just the size of the snapshot data.
|
// Count just the size of the snapshot data.
|
||||||
|
@ -398,6 +403,27 @@ public:
|
||||||
return memsize;
|
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) {
|
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);
|
assert(m_history.empty() || m_history.back().end() <= active_snapshot_time);
|
||||||
if (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())
|
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>())));
|
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());
|
auto *object_history = static_cast<MutableObjectHistory<T>*>(it_object_history->second.get());
|
||||||
// Then serialize the object into a string.
|
bool needs_to_save = true;
|
||||||
|
{
|
||||||
|
// 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;
|
std::ostringstream oss;
|
||||||
{
|
{
|
||||||
Slic3r::UndoRedo::OutputArchive archive(*this, oss);
|
Slic3r::UndoRedo::OutputArchive archive(*this, oss);
|
||||||
archive(object);
|
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();
|
return object.id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue