| 1 /* |
|
| 2 * LDForge: LDraw parts authoring CAD |
|
| 3 * Copyright (C) 2013, 2014 Santeri 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 #include "main.h" |
|
| 20 #include "ldtypes.h" |
|
| 21 #include "document.h" |
|
| 22 #include "misc.h" |
|
| 23 #include "gui.h" |
|
| 24 #include "history.h" |
|
| 25 #include "gldraw.h" |
|
| 26 #include "colors.h" |
|
| 27 |
|
| 28 cfg (String, ld_defaultname, ""); |
|
| 29 cfg (String, ld_defaultuser, ""); |
|
| 30 cfg (Int, ld_defaultlicense, 0); |
|
| 31 |
|
| 32 // List of all LDObjects |
|
| 33 static LDObjectList g_LDObjects; |
|
| 34 |
|
| 35 // ============================================================================= |
|
| 36 // LDObject constructors |
|
| 37 // ----------------------------------------------------------------------------- |
|
| 38 LDObject::LDObject() : |
|
| 39 m_Hidden (false), |
|
| 40 m_Selected (false), |
|
| 41 m_Parent (null), |
|
| 42 m_File (null), |
|
| 43 m_GLInit (false), |
|
| 44 qObjListEntry (null) |
|
| 45 { |
|
| 46 memset (m_coords, 0, sizeof m_coords); |
|
| 47 chooseID(); |
|
| 48 g_LDObjects << this; |
|
| 49 } |
|
| 50 |
|
| 51 // ============================================================================= |
|
| 52 // ----------------------------------------------------------------------------- |
|
| 53 void LDObject::chooseID() |
|
| 54 { |
|
| 55 int32 id = 1; // 0 shalt be null |
|
| 56 |
|
| 57 for (LDObject* obj : g_LDObjects) |
|
| 58 { |
|
| 59 assert (obj != this); |
|
| 60 |
|
| 61 if (obj->getID() >= id) |
|
| 62 id = obj->getID() + 1; |
|
| 63 } |
|
| 64 |
|
| 65 setID (id); |
|
| 66 } |
|
| 67 |
|
| 68 // ============================================================================= |
|
| 69 // ----------------------------------------------------------------------------- |
|
| 70 void LDObject::setVertexCoord (int i, Axis ax, double value) |
|
| 71 { |
|
| 72 Vertex v = getVertex (i); |
|
| 73 v[ax] = value; |
|
| 74 setVertex (i, v); |
|
| 75 } |
|
| 76 |
|
| 77 LDError::LDError() {} |
|
| 78 |
|
| 79 // ============================================================================= |
|
| 80 // ----------------------------------------------------------------------------- |
|
| 81 QString LDComment::raw() const |
|
| 82 { |
|
| 83 return fmt ("0 %1", text); |
|
| 84 } |
|
| 85 |
|
| 86 // ============================================================================= |
|
| 87 // ----------------------------------------------------------------------------- |
|
| 88 QString LDSubfile::raw() const |
|
| 89 { |
|
| 90 QString val = fmt ("1 %1 %2 ", getColor(), getPosition()); |
|
| 91 val += getTransform().toString(); |
|
| 92 val += ' '; |
|
| 93 val += getFileInfo()->getName(); |
|
| 94 return val; |
|
| 95 } |
|
| 96 |
|
| 97 // ============================================================================= |
|
| 98 // ----------------------------------------------------------------------------- |
|
| 99 QString LDLine::raw() const |
|
| 100 { |
|
| 101 QString val = fmt ("2 %1", getColor()); |
|
| 102 |
|
| 103 for (int i = 0; i < 2; ++i) |
|
| 104 val += fmt (" %1", getVertex (i)); |
|
| 105 |
|
| 106 return val; |
|
| 107 } |
|
| 108 |
|
| 109 // ============================================================================= |
|
| 110 // ----------------------------------------------------------------------------- |
|
| 111 QString LDTriangle::raw() const |
|
| 112 { |
|
| 113 QString val = fmt ("3 %1", getColor()); |
|
| 114 |
|
| 115 for (int i = 0; i < 3; ++i) |
|
| 116 val += fmt (" %1", getVertex (i)); |
|
| 117 |
|
| 118 return val; |
|
| 119 } |
|
| 120 |
|
| 121 // ============================================================================= |
|
| 122 // ----------------------------------------------------------------------------- |
|
| 123 QString LDQuad::raw() const |
|
| 124 { |
|
| 125 QString val = fmt ("4 %1", getColor()); |
|
| 126 |
|
| 127 for (int i = 0; i < 4; ++i) |
|
| 128 val += fmt (" %1", getVertex (i)); |
|
| 129 |
|
| 130 return val; |
|
| 131 } |
|
| 132 |
|
| 133 // ============================================================================= |
|
| 134 // ----------------------------------------------------------------------------- |
|
| 135 QString LDCondLine::raw() const |
|
| 136 { |
|
| 137 QString val = fmt ("5 %1", getColor()); |
|
| 138 |
|
| 139 // Add the coordinates |
|
| 140 for (int i = 0; i < 4; ++i) |
|
| 141 val += fmt (" %1", getVertex (i)); |
|
| 142 |
|
| 143 return val; |
|
| 144 } |
|
| 145 |
|
| 146 // ============================================================================= |
|
| 147 // ----------------------------------------------------------------------------- |
|
| 148 QString LDError::raw() const |
|
| 149 { |
|
| 150 return contents; |
|
| 151 } |
|
| 152 |
|
| 153 // ============================================================================= |
|
| 154 // ----------------------------------------------------------------------------- |
|
| 155 QString LDVertex::raw() const |
|
| 156 { |
|
| 157 return fmt ("0 !LDFORGE VERTEX %1 %2", getColor(), pos); |
|
| 158 } |
|
| 159 |
|
| 160 // ============================================================================= |
|
| 161 // ----------------------------------------------------------------------------- |
|
| 162 QString LDEmpty::raw() const |
|
| 163 { |
|
| 164 return ""; |
|
| 165 } |
|
| 166 |
|
| 167 // ============================================================================= |
|
| 168 // ----------------------------------------------------------------------------- |
|
| 169 const char* LDBFC::statements[] = |
|
| 170 { |
|
| 171 "CERTIFY CCW", |
|
| 172 "CCW", |
|
| 173 "CERTIFY CW", |
|
| 174 "CW", |
|
| 175 "NOCERTIFY", |
|
| 176 "INVERTNEXT", |
|
| 177 "CLIP", |
|
| 178 "CLIP CCW", |
|
| 179 "CLIP CW", |
|
| 180 "NOCLIP", |
|
| 181 }; |
|
| 182 |
|
| 183 QString LDBFC::raw() const |
|
| 184 { |
|
| 185 return fmt ("0 BFC %1", LDBFC::statements[type]); |
|
| 186 } |
|
| 187 |
|
| 188 // ============================================================================= |
|
| 189 // ----------------------------------------------------------------------------- |
|
| 190 QList<LDTriangle*> LDQuad::splitToTriangles() |
|
| 191 { |
|
| 192 // Create the two triangles based on this quadrilateral: |
|
| 193 // 0---3 0---3 3 |
|
| 194 // | | | / /| |
|
| 195 // | | ==> | / / | |
|
| 196 // | | |/ / | |
|
| 197 // 1---2 1 1---2 |
|
| 198 LDTriangle* tri1 = new LDTriangle (getVertex (0), getVertex (1), getVertex (3)); |
|
| 199 LDTriangle* tri2 = new LDTriangle (getVertex (1), getVertex (2), getVertex (3)); |
|
| 200 |
|
| 201 // The triangles also inherit the quad's color |
|
| 202 tri1->setColor (getColor()); |
|
| 203 tri2->setColor (getColor()); |
|
| 204 |
|
| 205 QList<LDTriangle*> triangles; |
|
| 206 triangles << tri1; |
|
| 207 triangles << tri2; |
|
| 208 return triangles; |
|
| 209 } |
|
| 210 |
|
| 211 // ============================================================================= |
|
| 212 // ----------------------------------------------------------------------------- |
|
| 213 void LDObject::replace (LDObject* other) |
|
| 214 { |
|
| 215 long idx = getIndex(); |
|
| 216 assert (idx != -1); |
|
| 217 |
|
| 218 // Replace the instance of the old object with the new object |
|
| 219 getFile()->setObject (idx, other); |
|
| 220 |
|
| 221 // Remove the old object |
|
| 222 deleteSelf(); |
|
| 223 } |
|
| 224 |
|
| 225 // ============================================================================= |
|
| 226 // ----------------------------------------------------------------------------- |
|
| 227 void LDObject::swap (LDObject* other) |
|
| 228 { |
|
| 229 assert (getFile() == other->getFile()); |
|
| 230 getFile()->swapObjects (this, other); |
|
| 231 } |
|
| 232 |
|
| 233 // ============================================================================= |
|
| 234 // ----------------------------------------------------------------------------- |
|
| 235 LDLine::LDLine (Vertex v1, Vertex v2) |
|
| 236 { |
|
| 237 setVertex (0, v1); |
|
| 238 setVertex (1, v2); |
|
| 239 } |
|
| 240 |
|
| 241 // ============================================================================= |
|
| 242 // ----------------------------------------------------------------------------- |
|
| 243 LDQuad::LDQuad (const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3) |
|
| 244 { |
|
| 245 setVertex (0, v0); |
|
| 246 setVertex (1, v1); |
|
| 247 setVertex (2, v2); |
|
| 248 setVertex (3, v3); |
|
| 249 } |
|
| 250 |
|
| 251 // ============================================================================= |
|
| 252 // ----------------------------------------------------------------------------- |
|
| 253 LDObject::~LDObject() {} |
|
| 254 |
|
| 255 // ============================================================================= |
|
| 256 // ----------------------------------------------------------------------------- |
|
| 257 LDSubfile::~LDSubfile() {} |
|
| 258 |
|
| 259 // ============================================================================= |
|
| 260 // ----------------------------------------------------------------------------- |
|
| 261 void LDObject::deleteSelf() |
|
| 262 { |
|
| 263 // If this object was selected, unselect it now |
|
| 264 if (isSelected()) |
|
| 265 unselect(); |
|
| 266 |
|
| 267 // If this object was associated to a file, remove it off it now |
|
| 268 if (getFile()) |
|
| 269 getFile()->forgetObject (this); |
|
| 270 |
|
| 271 // Delete the GL lists |
|
| 272 GL::deleteLists (this); |
|
| 273 |
|
| 274 // Remove this object from the list of LDObjects |
|
| 275 g_LDObjects.removeOne (this); |
|
| 276 |
|
| 277 delete this; |
|
| 278 } |
|
| 279 |
|
| 280 // ============================================================================= |
|
| 281 // ----------------------------------------------------------------------------- |
|
| 282 static void transformObject (LDObject* obj, Matrix transform, Vertex pos, int parentcolor) |
|
| 283 { |
|
| 284 switch (obj->getType()) |
|
| 285 { |
|
| 286 case LDObject::ELine: |
|
| 287 case LDObject::ECondLine: |
|
| 288 case LDObject::ETriangle: |
|
| 289 case LDObject::EQuad: |
|
| 290 |
|
| 291 for (int i = 0; i < obj->vertices(); ++i) |
|
| 292 { |
|
| 293 Vertex v = obj->getVertex (i); |
|
| 294 v.transform (transform, pos); |
|
| 295 obj->setVertex (i, v); |
|
| 296 } |
|
| 297 |
|
| 298 break; |
|
| 299 |
|
| 300 case LDObject::ESubfile: |
|
| 301 { |
|
| 302 LDSubfile* ref = static_cast<LDSubfile*> (obj); |
|
| 303 Matrix newMatrix = transform * ref->getTransform(); |
|
| 304 Vertex newpos = ref->getPosition(); |
|
| 305 |
|
| 306 newpos.transform (transform, pos); |
|
| 307 ref->setPosition (newpos); |
|
| 308 ref->setTransform (newMatrix); |
|
| 309 } |
|
| 310 break; |
|
| 311 |
|
| 312 default: |
|
| 313 break; |
|
| 314 } |
|
| 315 |
|
| 316 if (obj->getColor() == maincolor) |
|
| 317 obj->setColor (parentcolor); |
|
| 318 } |
|
| 319 |
|
| 320 // ============================================================================= |
|
| 321 // ----------------------------------------------------------------------------- |
|
| 322 LDObjectList LDSubfile::inlineContents (InlineFlags flags) |
|
| 323 { |
|
| 324 LDObjectList objs = getFileInfo()->inlineContents (flags); |
|
| 325 |
|
| 326 // Transform the objects |
|
| 327 for (LDObject* obj : objs) |
|
| 328 { |
|
| 329 // Set the parent now so we know what inlined the object. |
|
| 330 obj->setParent (this); |
|
| 331 transformObject (obj, getTransform(), getPosition(), getColor()); |
|
| 332 } |
|
| 333 |
|
| 334 return objs; |
|
| 335 } |
|
| 336 |
|
| 337 // ============================================================================= |
|
| 338 // ----------------------------------------------------------------------------- |
|
| 339 long LDObject::getIndex() const |
|
| 340 { |
|
| 341 assert (getFile() != null); |
|
| 342 |
|
| 343 for (int i = 0; i < getFile()->getObjectCount(); ++i) |
|
| 344 if (getFile()->getObject (i) == this) |
|
| 345 return i; |
|
| 346 |
|
| 347 return -1; |
|
| 348 } |
|
| 349 |
|
| 350 // ============================================================================= |
|
| 351 // ----------------------------------------------------------------------------- |
|
| 352 void LDObject::moveObjects (LDObjectList objs, const bool up) |
|
| 353 { |
|
| 354 if (objs.isEmpty()) |
|
| 355 return; |
|
| 356 |
|
| 357 // If we move down, we need to iterate the array in reverse order. |
|
| 358 const long start = up ? 0 : (objs.size() - 1); |
|
| 359 const long end = up ? objs.size() : -1; |
|
| 360 const long incr = up ? 1 : -1; |
|
| 361 LDObjectList objsToCompile; |
|
| 362 LDDocument* file = objs[0]->getFile(); |
|
| 363 |
|
| 364 for (long i = start; i != end; i += incr) |
|
| 365 { |
|
| 366 LDObject* obj = objs[i]; |
|
| 367 |
|
| 368 const long idx = obj->getIndex(), |
|
| 369 target = idx + (up ? -1 : 1); |
|
| 370 |
|
| 371 if ( (up && idx == 0) || (!up && idx == (long) (file->getObjects().size() - 1))) |
|
| 372 { |
|
| 373 // One of the objects hit the extrema. If this happens, this should be the first |
|
| 374 // object to be iterated on. Thus, nothing has changed yet and it's safe to just |
|
| 375 // abort the entire operation. |
|
| 376 assert (i == start); |
|
| 377 return; |
|
| 378 } |
|
| 379 |
|
| 380 objsToCompile << obj; |
|
| 381 objsToCompile << file->getObject (target); |
|
| 382 |
|
| 383 obj->swap (file->getObject (target)); |
|
| 384 } |
|
| 385 |
|
| 386 removeDuplicates (objsToCompile); |
|
| 387 |
|
| 388 // The objects need to be recompiled, otherwise their pick lists are left with |
|
| 389 // the wrong index colors which messes up selection. |
|
| 390 for (LDObject* obj : objsToCompile) |
|
| 391 g_win->R()->compileObject (obj); |
|
| 392 } |
|
| 393 |
|
| 394 // ============================================================================= |
|
| 395 // ----------------------------------------------------------------------------- |
|
| 396 QString LDObject::typeName (LDObject::Type type) |
|
| 397 { |
|
| 398 LDObject* obj = LDObject::getDefault (type); |
|
| 399 QString name = obj->getTypeName(); |
|
| 400 obj->deleteSelf(); |
|
| 401 return name; |
|
| 402 } |
|
| 403 |
|
| 404 // ============================================================================= |
|
| 405 // ----------------------------------------------------------------------------- |
|
| 406 QString LDObject::describeObjects (const LDObjectList& objs) |
|
| 407 { |
|
| 408 bool firstDetails = true; |
|
| 409 QString text = ""; |
|
| 410 |
|
| 411 if (objs.isEmpty()) |
|
| 412 return "nothing"; // :) |
|
| 413 |
|
| 414 for (long i = 0; i < ENumTypes; ++i) |
|
| 415 { |
|
| 416 Type objType = (Type) i; |
|
| 417 int count = 0; |
|
| 418 |
|
| 419 for (LDObject * obj : objs) |
|
| 420 if (obj->getType() == objType) |
|
| 421 count++; |
|
| 422 |
|
| 423 if (count == 0) |
|
| 424 continue; |
|
| 425 |
|
| 426 if (!firstDetails) |
|
| 427 text += ", "; |
|
| 428 |
|
| 429 QString noun = fmt ("%1%2", typeName (objType), plural (count)); |
|
| 430 |
|
| 431 // Plural of "vertex" is "vertices", correct that |
|
| 432 if (objType == EVertex && count != 1) |
|
| 433 noun = "vertices"; |
|
| 434 |
|
| 435 text += fmt ("%1 %2", count, noun); |
|
| 436 firstDetails = false; |
|
| 437 } |
|
| 438 |
|
| 439 return text; |
|
| 440 } |
|
| 441 |
|
| 442 // ============================================================================= |
|
| 443 // ----------------------------------------------------------------------------- |
|
| 444 LDObject* LDObject::topLevelParent() |
|
| 445 { |
|
| 446 if (!getParent()) |
|
| 447 return this; |
|
| 448 |
|
| 449 LDObject* it = this; |
|
| 450 |
|
| 451 while (it->getParent()) |
|
| 452 it = it->getParent(); |
|
| 453 |
|
| 454 return it; |
|
| 455 } |
|
| 456 |
|
| 457 // ============================================================================= |
|
| 458 // ----------------------------------------------------------------------------- |
|
| 459 LDObject* LDObject::next() const |
|
| 460 { |
|
| 461 long idx = getIndex(); |
|
| 462 assert (idx != -1); |
|
| 463 |
|
| 464 if (idx == (long) getFile()->getObjectCount() - 1) |
|
| 465 return null; |
|
| 466 |
|
| 467 return getFile()->getObject (idx + 1); |
|
| 468 } |
|
| 469 |
|
| 470 // ============================================================================= |
|
| 471 // ----------------------------------------------------------------------------- |
|
| 472 LDObject* LDObject::prev() const |
|
| 473 { |
|
| 474 long idx = getIndex(); |
|
| 475 assert (idx != -1); |
|
| 476 |
|
| 477 if (idx == 0) |
|
| 478 return null; |
|
| 479 |
|
| 480 return getFile()->getObject (idx - 1); |
|
| 481 } |
|
| 482 |
|
| 483 // ============================================================================= |
|
| 484 // ----------------------------------------------------------------------------- |
|
| 485 void LDObject::move (Vertex vect) |
|
| 486 { |
|
| 487 if (hasMatrix()) |
|
| 488 { |
|
| 489 LDMatrixObject* mo = dynamic_cast<LDMatrixObject*> (this); |
|
| 490 mo->setPosition (mo->getPosition() + vect); |
|
| 491 } |
|
| 492 elif (getType() == LDObject::EVertex) |
|
| 493 { |
|
| 494 // ugh |
|
| 495 static_cast<LDVertex*> (this)->pos += vect; |
|
| 496 } |
|
| 497 else |
|
| 498 { |
|
| 499 for (int i = 0; i < vertices(); ++i) |
|
| 500 setVertex (i, getVertex (i) + vect); |
|
| 501 } |
|
| 502 } |
|
| 503 |
|
| 504 // ============================================================================= |
|
| 505 // ----------------------------------------------------------------------------- |
|
| 506 #define CHECK_FOR_OBJ(N) \ |
|
| 507 if (type == LDObject::E##N) \ |
|
| 508 return new LD##N; |
|
| 509 |
|
| 510 LDObject* LDObject::getDefault (const LDObject::Type type) |
|
| 511 { |
|
| 512 CHECK_FOR_OBJ (Comment) |
|
| 513 CHECK_FOR_OBJ (BFC) |
|
| 514 CHECK_FOR_OBJ (Line) |
|
| 515 CHECK_FOR_OBJ (CondLine) |
|
| 516 CHECK_FOR_OBJ (Subfile) |
|
| 517 CHECK_FOR_OBJ (Triangle) |
|
| 518 CHECK_FOR_OBJ (Quad) |
|
| 519 CHECK_FOR_OBJ (Empty) |
|
| 520 CHECK_FOR_OBJ (BFC) |
|
| 521 CHECK_FOR_OBJ (Error) |
|
| 522 CHECK_FOR_OBJ (Vertex) |
|
| 523 CHECK_FOR_OBJ (Overlay) |
|
| 524 return null; |
|
| 525 } |
|
| 526 |
|
| 527 // ============================================================================= |
|
| 528 // ----------------------------------------------------------------------------- |
|
| 529 void LDObject::invert() {} |
|
| 530 void LDBFC::invert() {} |
|
| 531 void LDEmpty::invert() {} |
|
| 532 void LDComment::invert() {} |
|
| 533 void LDError::invert() {} |
|
| 534 |
|
| 535 // ============================================================================= |
|
| 536 // ----------------------------------------------------------------------------- |
|
| 537 void LDTriangle::invert() |
|
| 538 { |
|
| 539 // Triangle goes 0 -> 1 -> 2, reversed: 0 -> 2 -> 1. |
|
| 540 // Thus, we swap 1 and 2. |
|
| 541 Vertex tmp = getVertex (1); |
|
| 542 setVertex (1, getVertex (2)); |
|
| 543 setVertex (2, tmp); |
|
| 544 |
|
| 545 return; |
|
| 546 } |
|
| 547 |
|
| 548 // ============================================================================= |
|
| 549 // ----------------------------------------------------------------------------- |
|
| 550 void LDQuad::invert() |
|
| 551 { |
|
| 552 // Quad: 0 -> 1 -> 2 -> 3 |
|
| 553 // rev: 0 -> 3 -> 2 -> 1 |
|
| 554 // Thus, we swap 1 and 3. |
|
| 555 Vertex tmp = getVertex (1); |
|
| 556 setVertex (1, getVertex (3)); |
|
| 557 setVertex (3, tmp); |
|
| 558 } |
|
| 559 |
|
| 560 // ============================================================================= |
|
| 561 // ----------------------------------------------------------------------------- |
|
| 562 void LDSubfile::invert() |
|
| 563 { |
|
| 564 // Subfiles are inverted when they're prefixed with |
|
| 565 // a BFC INVERTNEXT statement. Thus we need to toggle this status. |
|
| 566 // For flat primitives it's sufficient that the determinant is |
|
| 567 // flipped but I don't have a method for checking flatness yet. |
|
| 568 // Food for thought... |
|
| 569 |
|
| 570 int idx = getIndex(); |
|
| 571 |
|
| 572 if (idx > 0) |
|
| 573 { |
|
| 574 LDBFC* bfc = dynamic_cast<LDBFC*> (prev()); |
|
| 575 |
|
| 576 if (bfc && bfc->type == LDBFC::InvertNext) |
|
| 577 { |
|
| 578 // This is prefixed with an invertnext, thus remove it. |
|
| 579 bfc->deleteSelf(); |
|
| 580 return; |
|
| 581 } |
|
| 582 } |
|
| 583 |
|
| 584 // Not inverted, thus prefix it with a new invertnext. |
|
| 585 LDBFC* bfc = new LDBFC (LDBFC::InvertNext); |
|
| 586 getFile()->insertObj (idx, bfc); |
|
| 587 } |
|
| 588 |
|
| 589 // ============================================================================= |
|
| 590 // ----------------------------------------------------------------------------- |
|
| 591 static void invertLine (LDObject* line) |
|
| 592 { |
|
| 593 // For lines, we swap the vertices. I don't think that a |
|
| 594 // cond-line's control points need to be swapped, do they? |
|
| 595 Vertex tmp = line->getVertex (0); |
|
| 596 line->setVertex (0, line->getVertex (1)); |
|
| 597 line->setVertex (1, tmp); |
|
| 598 } |
|
| 599 |
|
| 600 void LDLine::invert() |
|
| 601 { |
|
| 602 invertLine (this); |
|
| 603 } |
|
| 604 |
|
| 605 void LDCondLine::invert() |
|
| 606 { |
|
| 607 invertLine (this); |
|
| 608 } |
|
| 609 |
|
| 610 void LDVertex::invert() {} |
|
| 611 |
|
| 612 // ============================================================================= |
|
| 613 // ----------------------------------------------------------------------------- |
|
| 614 LDLine* LDCondLine::demote() |
|
| 615 { |
|
| 616 LDLine* repl = new LDLine; |
|
| 617 |
|
| 618 for (int i = 0; i < repl->vertices(); ++i) |
|
| 619 repl->setVertex (i, getVertex (i)); |
|
| 620 |
|
| 621 repl->setColor (getColor()); |
|
| 622 |
|
| 623 replace (repl); |
|
| 624 return repl; |
|
| 625 } |
|
| 626 |
|
| 627 // ============================================================================= |
|
| 628 // ----------------------------------------------------------------------------- |
|
| 629 LDObject* LDObject::fromID (int id) |
|
| 630 { |
|
| 631 for (LDObject* obj : g_LDObjects) |
|
| 632 if (obj->getID() == id) |
|
| 633 return obj; |
|
| 634 |
|
| 635 return null; |
|
| 636 } |
|
| 637 |
|
| 638 // ============================================================================= |
|
| 639 // ----------------------------------------------------------------------------- |
|
| 640 QString LDOverlay::raw() const |
|
| 641 { |
|
| 642 return fmt ("0 !LDFORGE OVERLAY %1 %2 %3 %4 %5 %6", |
|
| 643 getFileName(), getCamera(), getX(), getY(), getWidth(), getHeight()); |
|
| 644 } |
|
| 645 |
|
| 646 void LDOverlay::invert() {} |
|
| 647 |
|
| 648 // ============================================================================= |
|
| 649 // Hook the set accessors of certain properties to this changeProperty function. |
|
| 650 // It takes care of history management so we can capture low-level changes, this |
|
| 651 // makes history stuff work out of the box. |
|
| 652 // ----------------------------------------------------------------------------- |
|
| 653 template<class T> static void changeProperty (LDObject* obj, T* ptr, const T& val) |
|
| 654 { |
|
| 655 long idx; |
|
| 656 |
|
| 657 if (*ptr == val) |
|
| 658 return; |
|
| 659 |
|
| 660 if (obj->getFile() && (idx = obj->getIndex()) != -1) |
|
| 661 { |
|
| 662 QString before = obj->raw(); |
|
| 663 *ptr = val; |
|
| 664 QString after = obj->raw(); |
|
| 665 |
|
| 666 if (before != after) |
|
| 667 obj->getFile()->addToHistory (new EditHistory (idx, before, after)); |
|
| 668 } |
|
| 669 else |
|
| 670 *ptr = val; |
|
| 671 } |
|
| 672 |
|
| 673 // ============================================================================= |
|
| 674 // ----------------------------------------------------------------------------- |
|
| 675 void LDObject::setColor (const int& val) |
|
| 676 { |
|
| 677 changeProperty (this, &m_Color, val); |
|
| 678 } |
|
| 679 |
|
| 680 // ============================================================================= |
|
| 681 // ----------------------------------------------------------------------------- |
|
| 682 const Vertex& LDObject::getVertex (int i) const |
|
| 683 { |
|
| 684 return m_coords[i]->data(); |
|
| 685 } |
|
| 686 |
|
| 687 // ============================================================================= |
|
| 688 // ----------------------------------------------------------------------------- |
|
| 689 void LDObject::setVertex (int i, const Vertex& vert) |
|
| 690 { |
|
| 691 changeProperty (this, &m_coords[i], LDSharedVertex::getSharedVertex (vert)); |
|
| 692 } |
|
| 693 |
|
| 694 // ============================================================================= |
|
| 695 // ----------------------------------------------------------------------------- |
|
| 696 void LDMatrixObject::setPosition (const Vertex& a) |
|
| 697 { |
|
| 698 changeProperty (getLinkPointer(), &m_Position, LDSharedVertex::getSharedVertex (a)); |
|
| 699 } |
|
| 700 |
|
| 701 // ============================================================================= |
|
| 702 // ----------------------------------------------------------------------------- |
|
| 703 void LDMatrixObject::setTransform (const Matrix& val) |
|
| 704 { |
|
| 705 changeProperty (getLinkPointer(), &m_Transform, val); |
|
| 706 } |
|
| 707 |
|
| 708 // ============================================================================= |
|
| 709 // ----------------------------------------------------------------------------- |
|
| 710 static QMap<Vertex, LDSharedVertex*> g_sharedVerts; |
|
| 711 |
|
| 712 LDSharedVertex* LDSharedVertex::getSharedVertex (const Vertex& a) |
|
| 713 { |
|
| 714 auto it = g_sharedVerts.find (a); |
|
| 715 |
|
| 716 if (it == g_sharedVerts.end()) |
|
| 717 { |
|
| 718 LDSharedVertex* v = new LDSharedVertex (a); |
|
| 719 g_sharedVerts[a] = v; |
|
| 720 return v; |
|
| 721 } |
|
| 722 |
|
| 723 return *it; |
|
| 724 } |
|
| 725 |
|
| 726 // ============================================================================= |
|
| 727 // ----------------------------------------------------------------------------- |
|
| 728 void LDSharedVertex::addRef (LDObject* a) |
|
| 729 { |
|
| 730 m_refs << a; |
|
| 731 } |
|
| 732 |
|
| 733 // ============================================================================= |
|
| 734 // ----------------------------------------------------------------------------- |
|
| 735 void LDSharedVertex::delRef (LDObject* a) |
|
| 736 { |
|
| 737 m_refs.removeOne (a); |
|
| 738 |
|
| 739 if (m_refs.empty()) |
|
| 740 { |
|
| 741 g_sharedVerts.remove (m_data); |
|
| 742 delete this; |
|
| 743 } |
|
| 744 } |
|
| 745 |
|
| 746 // ============================================================================= |
|
| 747 // ----------------------------------------------------------------------------- |
|
| 748 void LDObject::select() |
|
| 749 { |
|
| 750 if (!getFile()) |
|
| 751 { |
|
| 752 log ("Warning: Object #%1 cannot be selected as it is not assigned a file!\n", getID()); |
|
| 753 return; |
|
| 754 } |
|
| 755 |
|
| 756 getFile()->addToSelection (this); |
|
| 757 } |
|
| 758 |
|
| 759 // ============================================================================= |
|
| 760 // ----------------------------------------------------------------------------- |
|
| 761 void LDObject::unselect() |
|
| 762 { |
|
| 763 if (!getFile()) |
|
| 764 { |
|
| 765 log ("Warning: Object #%1 cannot be unselected as it is not assigned a file!\n", getID()); |
|
| 766 return; |
|
| 767 } |
|
| 768 |
|
| 769 getFile()->removeFromSelection (this); |
|
| 770 } |
|
| 771 |
|
| 772 // ============================================================================= |
|
| 773 // ----------------------------------------------------------------------------- |
|
| 774 QString getLicenseText (int id) |
|
| 775 { |
|
| 776 switch (id) |
|
| 777 { |
|
| 778 case 0: |
|
| 779 return CALicense; |
|
| 780 |
|
| 781 case 1: |
|
| 782 return NonCALicense; |
|
| 783 |
|
| 784 case 2: |
|
| 785 return ""; |
|
| 786 } |
|
| 787 |
|
| 788 assert (false); |
|
| 789 return ""; |
|
| 790 } |
|
| 791 |
|
| 792 // ============================================================================= |
|
| 793 // ----------------------------------------------------------------------------- |
|
| 794 LDObject* LDObject::createCopy() const |
|
| 795 { |
|
| 796 /* |
|
| 797 LDObject* copy = clone(); |
|
| 798 copy->setFile (null); |
|
| 799 copy->setGLInit (false); |
|
| 800 copy->chooseID(); |
|
| 801 copy->setSelected (false); |
|
| 802 */ |
|
| 803 |
|
| 804 /* |
|
| 805 LDObject* copy = getDefault (getType()); |
|
| 806 copy->setColor (getColor()); |
|
| 807 |
|
| 808 if (hasMatrix()) |
|
| 809 { |
|
| 810 LDMatrixObject* copyMo = static_cast<LDMatrixObject*> (copy); |
|
| 811 const LDMatrixObject* mo = static_cast<const LDMatrixObject*> (this); |
|
| 812 copyMo->setPosition (mo->getPosition()); |
|
| 813 copyMo->setTransform (mo->getTransform()); |
|
| 814 } |
|
| 815 else |
|
| 816 { |
|
| 817 for (int i = 0; i < vertices(); ++i) |
|
| 818 copy->setVertex (getVertex (i)); |
|
| 819 } |
|
| 820 |
|
| 821 switch (getType()) |
|
| 822 { |
|
| 823 case Subfile: |
|
| 824 { |
|
| 825 LDSubfile* copyRef = static_cast<LDSubfile*> (copy); |
|
| 826 const LDSubfile* ref = static_cast<const LDSubfile*> (this); |
|
| 827 |
|
| 828 copyRef->setFileInfo (ref->getFileInfo()); |
|
| 829 } |
|
| 830 } |
|
| 831 */ |
|
| 832 |
|
| 833 LDObject* copy = parseLine (raw()); |
|
| 834 return copy; |
|
| 835 } |
|