|
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 |
|
19 #pragma once |
|
20 #include <type_traits> |
|
21 #include "../main.h" |
|
22 #include "../basics.h" |
|
23 #include "../glShared.h" |
|
24 #include "../colors.h" |
|
25 |
|
26 class Model; |
|
27 class LDDocument; |
|
28 |
|
29 /* |
|
30 * Object type codes. |
|
31 */ |
|
32 enum LDObjectType |
|
33 { |
|
34 SubfileReference, // Object represents a sub-file reference |
|
35 Quadrilateral, // Object represents a quadrilateral |
|
36 Triangle, // Object represents a triangle |
|
37 EdgeLine, // Object represents a line |
|
38 ConditionalEdge, // Object represents a conditional line |
|
39 Bfc, // Object represents a BFC statement |
|
40 Comment, // Object represents a comment |
|
41 Error, // Object is the result of failed parsing |
|
42 Empty, // Object represents an empty line |
|
43 BezierCurve, // Object represents a Bézier curve |
|
44 _End |
|
45 }; |
|
46 |
|
47 MAKE_ITERABLE_ENUM(LDObjectType) |
|
48 |
|
49 /* |
|
50 * Represents one line of code in an LDraw model file. |
|
51 */ |
|
52 class LDObject : public QObject |
|
53 { |
|
54 Q_OBJECT |
|
55 |
|
56 public: |
|
57 virtual QString asText() const = 0; // This object as LDraw code |
|
58 LDColor color() const; |
|
59 virtual LDColor defaultColor() const; // What color does the object default to? |
|
60 Model* model() const; |
|
61 LDPolygon* getPolygon(); |
|
62 virtual void getVertices (QSet<Vertex>& verts) const; |
|
63 virtual bool hasMatrix() const; // Does this object have a matrix and position? (see LDMatrixObject) |
|
64 qint32 id() const; |
|
65 virtual void invert(); // Inverts this object (winding is reversed) |
|
66 virtual bool isColored() const; |
|
67 bool isHidden() const; |
|
68 virtual bool isScemantic() const; // Does this object have meaning in the part model? |
|
69 bool isSelected() const; |
|
70 int lineNumber() const; |
|
71 void move (Vertex vect); |
|
72 LDObject* next() const; |
|
73 virtual int numVertices() const; |
|
74 virtual QString objectListText() const; |
|
75 LDObject* previous() const; |
|
76 bool previousIsInvertnext(class LDBfc*& ptr); |
|
77 QColor randomColor() const; |
|
78 void setColor (LDColor color); |
|
79 void setHidden (bool value); |
|
80 void setVertex (int i, const Vertex& vert); |
|
81 void swap (LDObject* other); |
|
82 virtual int triangleCount() const; |
|
83 virtual LDObjectType type() const = 0; |
|
84 virtual QString typeName() const = 0; |
|
85 const Vertex& vertex (int i) const; |
|
86 |
|
87 static LDObject* fromID(qint32 id); |
|
88 |
|
89 signals: |
|
90 void codeChanged(QString before, QString after); |
|
91 |
|
92 protected: |
|
93 friend class Model; |
|
94 LDObject (Model* model = nullptr); |
|
95 virtual ~LDObject(); |
|
96 void setDocument(Model* model); |
|
97 |
|
98 template<typename T> |
|
99 void changeProperty(T* property, const T& value); |
|
100 |
|
101 private: |
|
102 bool m_isHidden; |
|
103 bool m_isSelected; |
|
104 Model* _model; |
|
105 qint32 m_id; |
|
106 LDColor m_color; |
|
107 QColor m_randomColor; |
|
108 Vertex m_coords[4]; |
|
109 }; |
|
110 |
|
111 /* |
|
112 * Base class for objects with matrices. |
|
113 */ |
|
114 class LDMatrixObject : public LDObject |
|
115 { |
|
116 Vertex m_position; |
|
117 |
|
118 public: |
|
119 const Vertex& position() const; |
|
120 void setCoordinate (const Axis ax, double value); |
|
121 void setPosition (const Vertex& a); |
|
122 void setTransformationMatrix (const Matrix& value); |
|
123 const Matrix& transformationMatrix() const; |
|
124 |
|
125 protected: |
|
126 LDMatrixObject (Model* model = nullptr); |
|
127 LDMatrixObject (const Matrix& transformationMatrix, const Vertex& pos, Model* model = nullptr); |
|
128 |
|
129 private: |
|
130 Matrix m_transformationMatrix; |
|
131 }; |
|
132 |
|
133 /* |
|
134 * Represents a line in the LDraw file that could not be properly parsed. |
|
135 */ |
|
136 class LDError : public LDObject |
|
137 { |
|
138 public: |
|
139 static constexpr LDObjectType SubclassType = LDObjectType::Error; |
|
140 |
|
141 virtual LDObjectType type() const override |
|
142 { |
|
143 return SubclassType; |
|
144 } |
|
145 |
|
146 virtual QString asText() const override; |
|
147 virtual void invert() override; |
|
148 QString reason() const; |
|
149 QString contents() const; |
|
150 QString fileReferenced() const; |
|
151 void setFileReferenced (QString value); |
|
152 QString objectListText() const override; |
|
153 bool isColored() const override { return false; } |
|
154 QString typeName() const override { return "error"; } |
|
155 |
|
156 protected: |
|
157 friend class Model; |
|
158 LDError (Model* model); |
|
159 LDError (QString contents, QString reason, Model* model = nullptr); |
|
160 |
|
161 private: |
|
162 QString m_fileReferenced; // If this error was caused by inability to open a file, what file was that? |
|
163 QString m_contents; // The LDraw code that was being parsed |
|
164 QString m_reason; |
|
165 }; |
|
166 |
|
167 /* |
|
168 * Represents a 0 BFC statement in the LDraw code. |
|
169 */ |
|
170 enum class BfcStatement |
|
171 { |
|
172 CertifyCCW, |
|
173 CCW, |
|
174 CertifyCW, |
|
175 CW, |
|
176 NoCertify, |
|
177 InvertNext, |
|
178 Clip, |
|
179 ClipCCW, |
|
180 ClipCW, |
|
181 NoClip, |
|
182 _End |
|
183 }; |
|
184 |
|
185 MAKE_ITERABLE_ENUM(BfcStatement) |
|
186 |
|
187 class LDBfc : public LDObject |
|
188 { |
|
189 public: |
|
190 static constexpr LDObjectType SubclassType = LDObjectType::Bfc; |
|
191 |
|
192 virtual LDObjectType type() const override |
|
193 { |
|
194 return SubclassType; |
|
195 } |
|
196 |
|
197 virtual QString asText() const override; |
|
198 virtual void invert() override; |
|
199 protected: |
|
200 friend class Model; |
|
201 LDBfc (Model* model); |
|
202 |
|
203 public: |
|
204 bool isScemantic() const override { return statement() == BfcStatement::InvertNext; } |
|
205 QString objectListText() const override; |
|
206 BfcStatement statement() const; |
|
207 void setStatement (BfcStatement value); |
|
208 QString statementToString() const; |
|
209 bool isColored() const override { return false; } |
|
210 QString typeName() const override { return "bfc"; } |
|
211 |
|
212 static QString statementToString (BfcStatement statement); |
|
213 |
|
214 protected: |
|
215 LDBfc (const BfcStatement type, Model* model = nullptr); |
|
216 |
|
217 private: |
|
218 BfcStatement m_statement; |
|
219 }; |
|
220 |
|
221 /* |
|
222 * Represents a single code-1 subfile reference. |
|
223 */ |
|
224 class LDSubfileReference : public LDMatrixObject |
|
225 { |
|
226 public: |
|
227 static constexpr LDObjectType SubclassType = LDObjectType::SubfileReference; |
|
228 |
|
229 virtual LDObjectType type() const override |
|
230 { |
|
231 return SubclassType; |
|
232 } |
|
233 |
|
234 virtual QString asText() const override; |
|
235 virtual void invert() override; |
|
236 LDDocument* fileInfo() const; |
|
237 virtual void getVertices (QSet<Vertex>& verts) const override; |
|
238 void inlineContents(Model& model, bool deep, bool render); |
|
239 QList<LDPolygon> inlinePolygons(); |
|
240 QString objectListText() const override; |
|
241 void setFileInfo (LDDocument* fileInfo); |
|
242 int triangleCount() const override; |
|
243 bool hasMatrix() const override { return true; } |
|
244 QString typeName() const override { return "subfilereference"; } |
|
245 |
|
246 protected: |
|
247 friend class Model; |
|
248 LDSubfileReference (Model* model); |
|
249 LDSubfileReference(LDDocument* reference, const Matrix& transformationMatrix, const Vertex& position, Model* model = nullptr); |
|
250 |
|
251 private: |
|
252 LDDocument* m_fileInfo; |
|
253 }; |
|
254 |
|
255 /* |
|
256 * Represents a single code-3 triangle in the LDraw code file. |
|
257 */ |
|
258 class LDTriangle : public LDObject |
|
259 { |
|
260 public: |
|
261 static constexpr LDObjectType SubclassType = LDObjectType::Triangle; |
|
262 |
|
263 virtual LDObjectType type() const override |
|
264 { |
|
265 return SubclassType; |
|
266 } |
|
267 |
|
268 virtual QString asText() const override; |
|
269 virtual void invert() override; |
|
270 int triangleCount() const override; |
|
271 int numVertices() const override { return 3; } |
|
272 QString typeName() const override { return "triangle"; } |
|
273 |
|
274 protected: |
|
275 friend class Model; |
|
276 LDTriangle (Model* model); |
|
277 LDTriangle (Vertex const& v1, Vertex const& v2, Vertex const& v3, Model* model = nullptr); |
|
278 }; |
|
279 |
|
280 /* |
|
281 * Represents a single code-4 quadrilateral. |
|
282 */ |
|
283 class LDQuadrilateral : public LDObject |
|
284 { |
|
285 public: |
|
286 static constexpr LDObjectType SubclassType = LDObjectType::Quadrilateral; |
|
287 |
|
288 virtual LDObjectType type() const override |
|
289 { |
|
290 return SubclassType; |
|
291 } |
|
292 |
|
293 QString asText() const override; |
|
294 void invert() override; |
|
295 int triangleCount() const override; |
|
296 int numVertices() const override { return 4; } |
|
297 QString typeName() const override { return "quad"; } |
|
298 |
|
299 protected: |
|
300 friend class Model; |
|
301 LDQuadrilateral (Model* model); |
|
302 LDQuadrilateral (const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex& v4, Model* model = nullptr); |
|
303 }; |
|
304 |
|
305 /* |
|
306 * Models a Bézier curve. It is stored as a special comment in the LDraw code file and can be inlined down into line segments. |
|
307 */ |
|
308 class LDBezierCurve : public LDObject |
|
309 { |
|
310 public: |
|
311 static constexpr LDObjectType SubclassType = LDObjectType::BezierCurve; |
|
312 |
|
313 virtual LDObjectType type() const override |
|
314 { |
|
315 return SubclassType; |
|
316 } |
|
317 |
|
318 virtual QString asText() const override; |
|
319 virtual void invert() override; |
|
320 Vertex pointAt (qreal t) const; |
|
321 void rasterize(Model& model, int segments); |
|
322 QVector<LDPolygon> rasterizePolygons (int segments); |
|
323 int numVertices() const override { return 4; } |
|
324 LDColor defaultColor() const override { return EdgeColor; } |
|
325 QString typeName() const override { return "beziercurve"; } |
|
326 |
|
327 protected: |
|
328 friend class Model; |
|
329 LDBezierCurve (Model* model); |
|
330 LDBezierCurve (const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3, Model* model = nullptr); |
|
331 }; |
|
332 |
|
333 enum |
|
334 { |
|
335 LowResolution = 16, |
|
336 HighResolution = 48 |
|
337 }; |
|
338 |
|
339 /* |
|
340 * Changes a property in a manner that emits the appropriate signal to notify that the object changed. |
|
341 */ |
|
342 template<typename T> |
|
343 void LDObject::changeProperty(T* property, const T& value) |
|
344 { |
|
345 if (*property != value) |
|
346 { |
|
347 QString before = asText(); |
|
348 *property = value; |
|
349 emit codeChanged(before, asText()); |
|
350 } |
|
351 } |