src/model.h

changeset 1091
4a754362f660
parent 1087
80e25f6b0bb0
child 1113
5f3139c802bf
equal deleted inserted replaced
1090:ed73c4f48ca4 1091:4a754362f660
1 /*
2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2013 - 2017 Teemu Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
1 #pragma once 19 #pragma once
2 #include "main.h" 20 #include "main.h"
3 #include "ldObject.h" 21 #include "ldObject.h"
4 22
23 /*
24 * This class represents a LDraw model, consisting of a vector of objects. It manages LDObject ownership.
25 */
5 class Model 26 class Model
6 { 27 {
7 public: 28 public:
8 Model(DocumentManager* manager); 29 Model(DocumentManager* manager);
9 Model(const Model& other) = delete; 30 Model(const Model& other) = delete;
10 ~Model(); 31 ~Model();
11 32
12 virtual void addObject(LDObject* object); 33 void addObject(LDObject* object);
13 virtual void insertObject(int position, LDObject* object); 34 virtual void insertObject(int position, LDObject* object);
14 virtual bool swapObjects(LDObject* one, LDObject* other); 35 virtual bool swapObjects(LDObject* one, LDObject* other);
15 virtual bool setObjectAt(int idx, LDObject* obj); 36 virtual bool setObjectAt(int idx, LDObject* obj);
37 template<typename T, typename... Args> T* emplace(Args&& ...args);
38 template<typename T, typename... Args> T* emplaceAt(int position, Args&& ...args);
39 template<typename T, typename... Args> T* emplaceReplacement(LDObject* object, Args&& ...args);
40 template<typename T, typename... Args> T* emplaceReplacementAt(int position, Args&& ...args);
16 void removeAt(int position); 41 void removeAt(int position);
17 void remove(LDObject* object); 42 void remove(LDObject* object);
18 void replace(LDObject *object, Model& model); 43 void replace(LDObject *object, Model& model);
19 void clear(); 44 void clear();
20 void merge(Model& other, int position = -1); 45 void merge(Model& other, int position = -1);
29 DocumentManager* documentManager() const; 54 DocumentManager* documentManager() const;
30 LDObject* insertFromString(int position, QString line); 55 LDObject* insertFromString(int position, QString line);
31 LDObject* addFromString(QString line); 56 LDObject* addFromString(QString line);
32 LDObject* replaceWithFromString(LDObject* object, QString line); 57 LDObject* replaceWithFromString(LDObject* object, QString line);
33 58
34 template<typename T, typename... Args>
35 T* emplace(Args&& ...args)
36 {
37 T* object = constructObject<T>(args...);
38 addObject(object);
39 return object;
40 }
41
42 template<typename T, typename... Args>
43 T* emplaceAt(int position, Args&& ...args)
44 {
45 T* object = constructObject<T>(args...);
46 insertObject(position, object);
47 return object;
48 }
49
50 template<typename T, typename... Args>
51 T* emplaceReplacement(LDObject* object, Args&& ...args)
52 {
53 if (object->model() == this)
54 {
55 int position = object->lineNumber();
56 T* replacement = constructObject<T>(args...);
57 setObjectAt(position, replacement);
58 return replacement;
59 }
60 else
61 return nullptr;
62 }
63
64 template<typename T, typename... Args>
65 T* emplaceReplacementAt(int position, Args&& ...args)
66 {
67 T* replacement = constructObject<T>(args...);
68 setObjectAt(position, replacement);
69 return replacement;
70 }
71
72 protected: 59 protected:
73 template<typename T, typename... Args> 60 template<typename T, typename... Args> T* constructObject(Args&& ...args);
74 T* constructObject(Args&& ...args)
75 {
76 static_assert (std::is_base_of<LDObject, T>::value, "Can only use this function with LDObject-derivatives");
77 T* object = new T {args..., this};
78
79 // Set default color. Relying on virtual functions, this cannot be done in the c-tor.
80 // TODO: store -1 as the default color
81 if (object->isColored())
82 object->setColor(object->defaultColor());
83
84 return object;
85 }
86
87 void withdraw(LDObject* object); 61 void withdraw(LDObject* object);
88 virtual LDObject* withdrawAt(int position); 62 virtual LDObject* withdrawAt(int position);
89 63
90 QVector<LDObject*> _objects; 64 QVector<LDObject*> _objects;
91 DocumentManager* _manager; 65 DocumentManager* _manager;
92 mutable int _triangleCount = 0; 66 mutable int _triangleCount = 0;
93 mutable bool _needsTriangleRecount; 67 mutable bool _needsTriangleRecount;
94 }; 68 };
95 69
96 int countof(Model& model); 70 int countof(Model& model);
71
72 /*
73 * Given an LDObject type as the template parameter, and any number of variadic parameters, constructs an LDObject derivative
74 * and inserts it into this model. The variadic parameters and this model pointer are passed to the constructor. The constructed object
75 * is added to the end of the model.
76 *
77 * For instance, the LDLine contains a constructor as such:
78 *
79 * LDLine(Vertex v1, Vertex v2, Model* model);
80 *
81 * This constructor can be invoked as such:
82 *
83 * model->emplace<LDLine>(v1, v2);
84 */
85 template<typename T, typename... Args>
86 T* Model::emplace(Args&& ...args)
87 {
88 T* object = constructObject<T>(args...);
89 addObject(object);
90 return object;
91 }
92
93 /*
94 * Like emplace<>() but also takes a position as the first argument and emplaces the object at the given position instead of the
95 * end of the model.
96 */
97 template<typename T, typename... Args>
98 T* Model::emplaceAt(int position, Args&& ...args)
99 {
100 T* object = constructObject<T>(args...);
101 insertObject(position, object);
102 return object;
103 }
104
105 /*
106 * Like emplace<>() but instead of inserting the constructed object, the new object replaces the object given in the first parameter.
107 * If the old object cannot be replaced, the new object will not be constructed at all.
108 */
109 template<typename T, typename... Args>
110 T* Model::emplaceReplacement(LDObject* object, Args&& ...args)
111 {
112 if (object->model() == this)
113 {
114 int position = object->lineNumber();
115 T* replacement = constructObject<T>(args...);
116 setObjectAt(position, replacement);
117 return replacement;
118 }
119 else
120 return nullptr;
121 }
122
123 /*
124 * Like emplaceAt<>() but instead of inserting the constructed object, it replaces the document at the given spot instead.
125 * The replaced object is deleted in the process.
126 */
127 template<typename T, typename... Args>
128 T* Model::emplaceReplacementAt(int position, Args&& ...args)
129 {
130 T* replacement = constructObject<T>(args...);
131 setObjectAt(position, replacement);
132 return replacement;
133 }
134
135 /*
136 * Constructs an LDObject such that it gets this model as its model pointer.
137 */
138 template<typename T, typename... Args>
139 T* Model::constructObject(Args&& ...args)
140 {
141 static_assert (std::is_base_of<LDObject, T>::value, "Can only use this function with LDObject-derivatives");
142 T* object = new T {args..., this};
143
144 // Set default color. Relying on virtual functions, this cannot be done in the c-tor.
145 // TODO: store -1 as the default color
146 if (object->isColored())
147 object->setColor(object->defaultColor());
148
149 return object;
150 }

mercurial