|
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 } |