1 /* This file is part of Dilay 2 * Copyright © 2015-2018 Alexander Bau 3 * Use and redistribute under the terms of the GNU General Public License 4 */ 5 #include <list> 6 #include <vector> 7 #include "config.hpp" 8 #include "dynamic/mesh.hpp" 9 #include "history.hpp" 10 #include "maybe.hpp" 11 #include "mesh.hpp" 12 #include "scene.hpp" 13 #include "sketch/mesh.hpp" 14 #include "sketch/path.hpp" 15 #include "state.hpp" 16 17 namespace 18 { 19 struct SnapshotConfig 20 { 21 bool snapshotDynamicMeshes; 22 bool snapshotSketchMeshes; 23 SnapshotConfig__anon82ebc8310111::SnapshotConfig24 SnapshotConfig (bool d, bool s) 25 : snapshotDynamicMeshes (d) 26 , snapshotSketchMeshes (s) 27 { 28 assert (this->snapshotDynamicMeshes || this->snapshotSketchMeshes); 29 } 30 }; 31 32 struct SceneSnapshot 33 { 34 const SnapshotConfig config; 35 std::list<DynamicMesh> dynamicMeshes; 36 std::list<SketchMesh> sketchMeshes; 37 SceneSnapshot__anon82ebc8310111::SceneSnapshot38 SceneSnapshot (const SnapshotConfig& c) 39 : config (c) 40 { 41 } 42 }; 43 44 typedef std::list<SceneSnapshot> Timeline; 45 sceneSnapshot(const Scene & scene,const SnapshotConfig & config)46 SceneSnapshot sceneSnapshot (const Scene& scene, const SnapshotConfig& config) 47 { 48 SceneSnapshot snapshot (config); 49 50 if (config.snapshotDynamicMeshes) 51 { 52 scene.forEachConstMesh ( 53 [&snapshot](const DynamicMesh& mesh) { snapshot.dynamicMeshes.emplace_back (mesh); }); 54 } 55 if (config.snapshotSketchMeshes) 56 { 57 scene.forEachConstMesh ( 58 [&snapshot](const SketchMesh& mesh) { snapshot.sketchMeshes.emplace_back (mesh); }); 59 } 60 return snapshot; 61 } 62 resetToSnapshot(const SceneSnapshot & snapshot,State & state)63 void resetToSnapshot (const SceneSnapshot& snapshot, State& state) 64 { 65 Scene& scene = state.scene (); 66 67 if (snapshot.config.snapshotDynamicMeshes) 68 { 69 scene.deleteDynamicMeshes (); 70 71 for (const DynamicMesh& mesh : snapshot.dynamicMeshes) 72 { 73 scene.newDynamicMesh (state.config (), mesh); 74 } 75 } 76 if (snapshot.config.snapshotSketchMeshes) 77 { 78 scene.deleteSketchMeshes (); 79 80 for (const SketchMesh& mesh : snapshot.sketchMeshes) 81 { 82 scene.newSketchMesh (state.config (), mesh); 83 } 84 } 85 } 86 } 87 88 struct History::Impl 89 { 90 unsigned int undoDepth; 91 Timeline past; 92 Timeline future; 93 ImplHistory::Impl94 Impl (const Config& config) { this->runFromConfig (config); } 95 snapshotAllHistory::Impl96 void snapshotAll (const Scene& scene) { this->snapshot (scene, SnapshotConfig (true, true)); } 97 snapshotDynamicMeshesHistory::Impl98 void snapshotDynamicMeshes (const Scene& scene) 99 { 100 this->snapshot (scene, SnapshotConfig (true, false)); 101 } 102 snapshotSketchMeshesHistory::Impl103 void snapshotSketchMeshes (const Scene& scene) 104 { 105 this->snapshot (scene, SnapshotConfig (false, true)); 106 } 107 snapshotHistory::Impl108 void snapshot (const Scene& scene, const SnapshotConfig& config) 109 { 110 assert (undoDepth > 0); 111 112 this->future.clear (); 113 114 while (this->past.size () >= this->undoDepth) 115 { 116 this->past.pop_back (); 117 } 118 this->past.push_front (sceneSnapshot (scene, config)); 119 } 120 dropPastSnapshotHistory::Impl121 void dropPastSnapshot () 122 { 123 if (this->past.empty () == false) 124 { 125 this->past.pop_front (); 126 } 127 } 128 dropFutureSnapshotHistory::Impl129 void dropFutureSnapshot () 130 { 131 if (this->future.empty () == false) 132 { 133 this->future.pop_front (); 134 } 135 } 136 undoHistory::Impl137 void undo (State& state) 138 { 139 if (this->past.empty () == false) 140 { 141 const SnapshotConfig& config = this->past.front ().config; 142 143 this->future.push_front (sceneSnapshot (state.scene (), config)); 144 resetToSnapshot (this->past.front (), state); 145 this->past.pop_front (); 146 } 147 } 148 redoHistory::Impl149 void redo (State& state) 150 { 151 if (this->future.empty () == false) 152 { 153 const SnapshotConfig& config = this->future.front ().config; 154 155 this->past.push_front (sceneSnapshot (state.scene (), config)); 156 resetToSnapshot (this->future.front (), state); 157 this->future.pop_front (); 158 } 159 } 160 hasRecentDynamicMeshHistory::Impl161 bool hasRecentDynamicMesh () const 162 { 163 return this->past.empty () == false && this->past.front ().config.snapshotDynamicMeshes; 164 } 165 forEachRecentDynamicMeshHistory::Impl166 void forEachRecentDynamicMesh (const std::function<void(const DynamicMesh&)>& f) const 167 { 168 assert (this->hasRecentDynamicMesh ()); 169 170 for (const DynamicMesh& m : this->past.front ().dynamicMeshes) 171 { 172 f (m); 173 } 174 } 175 resetHistory::Impl176 void reset () 177 { 178 this->past.clear (); 179 this->future.clear (); 180 } 181 runFromConfigHistory::Impl182 void runFromConfig (const Config& config) 183 { 184 this->undoDepth = config.get<int> ("editor/undo-depth"); 185 } 186 }; 187 188 DELEGATE1_BIG3 (History, const Config&) 189 DELEGATE1 (void, History, snapshotAll, const Scene&) 190 DELEGATE1 (void, History, snapshotDynamicMeshes, const Scene&) 191 DELEGATE1 (void, History, snapshotSketchMeshes, const Scene&) 192 DELEGATE (void, History, dropPastSnapshot) 193 DELEGATE (void, History, dropFutureSnapshot) 194 DELEGATE1 (void, History, undo, State&) 195 DELEGATE1 (void, History, redo, State&) 196 DELEGATE_CONST (bool, History, hasRecentDynamicMesh) 197 DELEGATE1_CONST (void, History, forEachRecentDynamicMesh, 198 const std::function<void(const DynamicMesh&)>&) 199 DELEGATE (void, History, reset) 200 DELEGATE1 (void, History, runFromConfig, const Config&) 201