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

UndoRedo.hpp « Utils « slic3r « src - github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e120c4f79024f02d8ebed651822c13b9d90ea113 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#ifndef slic3r_Utils_UndoRedo_hpp_
#define slic3r_Utils_UndoRedo_hpp_

#include <algorithm>
#include <memory>
#include <string>
#include <vector>
#include <cassert>

#include <libslic3r/ObjectID.hpp>

typedef double                          coordf_t;
typedef std::pair<coordf_t, coordf_t>   t_layer_height_range;

namespace Slic3r {

class Model;
enum PrinterTechnology : unsigned char;

namespace GUI {
	class Selection;
    class GLGizmosManager;
} // 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
{
	// Constructor is defined in .cpp due to the forward declaration of enum PrinterTechnology.
	SnapshotData();

	PrinterTechnology 	printer_technology;
	// Bitmap of Flags (see the Flags enum).
	unsigned int        flags;
    int                 layer_range_idx;

	// Bitmask of various binary flags to be stored with the snapshot.
	enum Flags {
		VARIABLE_LAYER_EDITING_ACTIVE = 1,
		SELECTED_SETTINGS_ON_SIDEBAR  = 2,
		SELECTED_LAYERROOT_ON_SIDEBAR = 4,
		SELECTED_LAYER_ON_SIDEBAR     = 8,
        RECALCULATE_SLA_SUPPORTS      = 16
	};
};

struct Snapshot
{
	Snapshot(size_t timestamp) : timestamp(timestamp) {}
	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) {}
	
	std::string 		name;
	size_t 				timestamp;
	size_t 				model_id;
	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; }

	// The topmost snapshot represents the current state when going forward.
	bool 		is_topmost() const;
	// The topmost snapshot is not being serialized to the Undo / Redo stack until going back in time, 
	// when the top most state is being serialized, so we can redo back to the top most state.
	bool 		is_topmost_captured() const { assert(this->is_topmost()); return model_id > 0; }
};

// Excerpt of Slic3r::GUI::Selection for serialization onto the Undo / Redo stack.
struct Selection : public Slic3r::ObjectBase {
	void clear() { mode = 0; volumes_and_instances.clear(); }
	unsigned char							mode = 0;
	std::vector<std::pair<size_t, size_t>>	volumes_and_instances;
	template<class Archive> void serialize(Archive &ar) { ar(mode, volumes_and_instances); }
};

class StackImpl;

class Stack
{
public:
	// Stack needs to be initialized. An empty stack is not valid, there must be a "New Project" status stored at the beginning.
	// The first "New Project" snapshot shall not be removed.
	Stack();
	~Stack();

	void clear();
	bool empty() const;

	// Set maximum memory threshold. If the threshold is exceeded, least recently used snapshots are released.
	void set_memory_limit(size_t memsize);
	size_t get_memory_limit() const;

	// Estimate size of the RAM consumed by the Undo / Redo stack.
	size_t memsize() const;

	// Release least recently used snapshots up to the memory limit set above.
	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, const SnapshotData &snapshot_data);

	// To be queried to enable / disable the Undo / Redo buttons at the UI.
	bool has_undo_snapshot() const;
	bool has_redo_snapshot() const;
	// To query whether one can undo to a snapshot. Useful for notifications, that want to Undo a specific operation.
	bool has_undo_snapshot(size_t time_to_load) const;

	// 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, 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);

	// Snapshot history (names with timestamps).
	// Each snapshot indicates start of an interval in which this operation is performed.
	// There is one additional snapshot taken at the very end, which indicates the current unnamed state.

	const std::vector<Snapshot>& snapshots() const;
	// 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 is the successive snapshot. The same logic applies to the time_to_load parameter of undo() and redo() operations.
	size_t active_snapshot_time() const;
	// 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.
	bool   temp_snapshot_active() const;

	// After load_snapshot() / undo() / redo() the selection is deserialized into a list of ObjectIDs, which needs to be converted
	// into the list of GLVolume pointers once the 3D scene is updated.
	const Selection& selection_deserialized() const;

private:
	friend class StackImpl;
	std::unique_ptr<StackImpl> 	pimpl;
};

}; // namespace UndoRedo
}; // namespace Slic3r

#endif /* slic3r_Utils_UndoRedo_hpp_ */