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