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