30 CFGENTRY (String, defaultName, ""); |
30 CFGENTRY (String, defaultName, ""); |
31 CFGENTRY (String, defaultUser, ""); |
31 CFGENTRY (String, defaultUser, ""); |
32 CFGENTRY (Int, defaultLicense, 0); |
32 CFGENTRY (Int, defaultLicense, 0); |
33 |
33 |
34 // List of all LDObjects |
34 // List of all LDObjects |
35 static LDObjectList g_LDObjects; |
35 static LDObjectWeakList g_LDObjects; |
36 |
36 |
37 // ============================================================================= |
37 // ============================================================================= |
38 // LDObject constructors |
38 // LDObject constructors |
39 // |
39 // |
40 LDObject::LDObject() : |
40 LDObject::LDObject() : |
41 m_isHidden (false), |
41 m_isHidden (false), |
42 m_isSelected (false), |
42 m_isSelected (false), |
43 m_parent (null), |
|
44 m_document (null), |
43 m_document (null), |
45 qObjListEntry (null) |
44 qObjListEntry (null) |
46 { |
45 { |
47 memset (m_coords, 0, sizeof m_coords); |
46 memset (m_coords, 0, sizeof m_coords); |
48 chooseID(); |
47 chooseID(); |
49 g_LDObjects << this; |
48 g_LDObjects << LDObjectWeakPtr (thisptr()); |
50 setRandomColor (QColor::fromHsv (rand() % 360, rand() % 256, rand() % 96 + 128)); |
49 setRandomColor (QColor::fromHsv (rand() % 360, rand() % 256, rand() % 96 + 128)); |
51 } |
50 } |
52 |
51 |
53 // ============================================================================= |
52 // ============================================================================= |
54 // |
53 // |
55 void LDObject::chooseID() |
54 void LDObject::chooseID() |
56 { |
55 { |
57 int32 id = 1; // 0 shalt be null |
56 int32 id = 1; // 0 shalt be null |
58 |
57 |
59 for (LDObject* obj : g_LDObjects) |
58 for (LDObjectWeakPtr obj : g_LDObjects) |
60 { |
59 { |
61 assert (obj != this); |
60 LDObjectPtr obj2 = obj.toStrongRef(); |
62 |
61 assert (obj2 != this); |
63 if (obj->id() >= id) |
62 |
64 id = obj->id() + 1; |
63 if (obj2->id() >= id) |
|
64 id = obj2->id() + 1; |
65 } |
65 } |
66 |
66 |
67 setID (id); |
67 setID (id); |
68 } |
68 } |
69 |
69 |
187 return format ("0 BFC %1", LDBFC::k_statementStrings[m_statement]); |
187 return format ("0 BFC %1", LDBFC::k_statementStrings[m_statement]); |
188 } |
188 } |
189 |
189 |
190 // ============================================================================= |
190 // ============================================================================= |
191 // |
191 // |
192 QList<LDTriangle*> LDQuad::splitToTriangles() |
192 QList<LDTrianglePtr> LDQuad::splitToTriangles() |
193 { |
193 { |
194 // Create the two triangles based on this quadrilateral: |
194 // Create the two triangles based on this quadrilateral: |
195 // 0---3 0---3 3 |
195 // 0---3 0---3 3 |
196 // | | | / /| |
196 // | | | / /| |
197 // | | ==> | / / | |
197 // | | ==> | / / | |
198 // | | |/ / | |
198 // | | |/ / | |
199 // 1---2 1 1---2 |
199 // 1---2 1 1---2 |
200 LDTriangle* tri1 = new LDTriangle (vertex (0), vertex (1), vertex (3)); |
200 LDTrianglePtr tri1 (spawn<LDTriangle> (vertex (0), vertex (1), vertex (3))); |
201 LDTriangle* tri2 = new LDTriangle (vertex (1), vertex (2), vertex (3)); |
201 LDTrianglePtr tri2 (spawn<LDTriangle> (vertex (1), vertex (2), vertex (3))); |
202 |
202 |
203 // The triangles also inherit the quad's color |
203 // The triangles also inherit the quad's color |
204 tri1->setColor (color()); |
204 tri1->setColor (color()); |
205 tri2->setColor (color()); |
205 tri2->setColor (color()); |
206 |
206 |
207 QList<LDTriangle*> triangles; |
207 return {tri1, tri2}; |
208 triangles << tri1; |
208 } |
209 triangles << tri2; |
209 |
210 return triangles; |
210 // ============================================================================= |
211 } |
211 // |
212 |
212 void LDObject::replace (LDObjectPtr other) |
213 // ============================================================================= |
|
214 // |
|
215 void LDObject::replace (LDObject* other) |
|
216 { |
213 { |
217 long idx = lineNumber(); |
214 long idx = lineNumber(); |
218 assert (idx != -1); |
215 assert (idx != -1); |
219 |
216 |
220 // Replace the instance of the old object with the new object |
217 // Replace the instance of the old object with the new object |
266 if (isSelected()) |
273 if (isSelected()) |
267 deselect(); |
274 deselect(); |
268 |
275 |
269 // If this object was associated to a file, remove it off it now |
276 // If this object was associated to a file, remove it off it now |
270 if (document()) |
277 if (document()) |
271 document()->forgetObject (this); |
278 document()->forgetObject (thisptr()); |
272 |
279 |
273 // Delete the GL lists |
280 // Delete the GL lists |
274 g_win->R()->forgetObject (this); |
281 g_win->R()->forgetObject (thisptr()); |
275 |
282 |
276 // Remove this object from the list of LDObjects |
283 // Remove this object from the list of LDObjects |
277 g_LDObjects.removeOne (this); |
284 g_LDObjects.removeOne (LDObjectWeakPtr (thisptr())); |
278 |
|
279 // The renderer's mouse-over field also needs to be cleared... |
|
280 // Remind me to implement smart pointers someday. |
|
281 if (g_win->R()->objectAtCursor() == this) |
|
282 g_win->R()->setObjectAtCursor (null); |
|
283 |
|
284 delete this; |
285 delete this; |
285 } |
286 } |
286 |
287 |
287 // ============================================================================= |
288 // ============================================================================= |
288 // |
289 // |
289 static void transformObject (LDObject* obj, Matrix transform, Vertex pos, int parentcolor) |
290 static void transformObject (LDObjectPtr obj, Matrix transform, Vertex pos, int parentcolor) |
290 { |
291 { |
291 switch (obj->type()) |
292 switch (obj->type()) |
292 { |
293 { |
293 case LDObject::ELine: |
294 case LDObject::ELine: |
294 case LDObject::ECondLine: |
295 case LDObject::ECondLine: |
329 LDObjectList LDSubfile::inlineContents (bool deep, bool render) |
329 LDObjectList LDSubfile::inlineContents (bool deep, bool render) |
330 { |
330 { |
331 LDObjectList objs = fileInfo()->inlineContents (deep, render); |
331 LDObjectList objs = fileInfo()->inlineContents (deep, render); |
332 |
332 |
333 // Transform the objects |
333 // Transform the objects |
334 for (LDObject* obj : objs) |
334 for (LDObjectPtr obj : objs) |
335 { |
335 { |
336 // Set the parent now so we know what inlined the object. |
336 // Set the parent now so we know what inlined the object. |
337 obj->setParent (this); |
337 obj->setParent (LDObjectWeakPtr (thisptr())); |
338 transformObject (obj, transform(), position(), color()); |
338 transformObject (obj, transform(), position(), color()); |
339 } |
339 } |
340 |
340 |
341 return objs; |
341 return objs; |
342 } |
342 } |
430 |
430 |
431 removeDuplicates (objsToCompile); |
431 removeDuplicates (objsToCompile); |
432 |
432 |
433 // The objects need to be recompiled, otherwise their pick lists are left with |
433 // The objects need to be recompiled, otherwise their pick lists are left with |
434 // the wrong index colors which messes up selection. |
434 // the wrong index colors which messes up selection. |
435 for (LDObject* obj : objsToCompile) |
435 for (LDObjectPtr obj : objsToCompile) |
436 g_win->R()->compileObject (obj); |
436 g_win->R()->compileObject (obj); |
437 } |
437 } |
438 |
438 |
439 // ============================================================================= |
439 // ============================================================================= |
440 // |
440 // |
441 String LDObject::typeName (LDObject::Type type) |
441 String LDObject::typeName (LDObject::Type type) |
442 { |
442 { |
443 LDObject* obj = LDObject::getDefault (type); |
443 LDObjectPtr obj = LDObject::getDefault (type); |
444 String name = obj->typeName(); |
444 String name = obj->typeName(); |
445 obj->destroy(); |
445 obj->destroy(); |
446 return name; |
446 return name; |
447 } |
447 } |
448 |
448 |
481 return text; |
481 return text; |
482 } |
482 } |
483 |
483 |
484 // ============================================================================= |
484 // ============================================================================= |
485 // |
485 // |
486 LDObject* LDObject::topLevelParent() |
486 LDObjectPtr LDObject::topLevelParent() |
487 { |
487 { |
488 if (parent() == null) |
488 if (parent() == null) |
489 return this; |
489 return thisptr(); |
490 |
490 |
491 LDObject* it = this; |
491 LDObjectWeakPtr it (thisptr()); |
492 |
492 |
493 while (it->parent() != null) |
493 while (it.toStrongRef()->parent() != null) |
494 it = it->parent(); |
494 it = it.toStrongRef()->parent(); |
495 |
495 |
496 return it; |
496 return it.toStrongRef(); |
497 } |
497 } |
498 |
498 |
499 // ============================================================================= |
499 // ============================================================================= |
500 // |
500 // |
501 LDObject* LDObject::next() const |
501 LDObjectPtr LDObject::next() const |
502 { |
502 { |
503 long idx = lineNumber(); |
503 long idx = lineNumber(); |
504 assert (idx != -1); |
504 assert (idx != -1); |
505 |
505 |
506 if (idx == (long) document()->getObjectCount() - 1) |
506 if (idx == (long) document()->getObjectCount() - 1) |
507 return null; |
507 return LDObjectPtr(); |
508 |
508 |
509 return document()->getObject (idx + 1); |
509 return document()->getObject (idx + 1); |
510 } |
510 } |
511 |
511 |
512 // ============================================================================= |
512 // ============================================================================= |
513 // |
513 // |
514 LDObject* LDObject::previous() const |
514 LDObjectPtr LDObject::previous() const |
515 { |
515 { |
516 long idx = lineNumber(); |
516 long idx = lineNumber(); |
517 assert (idx != -1); |
517 assert (idx != -1); |
518 |
518 |
519 if (idx == 0) |
519 if (idx == 0) |
520 return null; |
520 return LDObjectPtr(); |
521 |
521 |
522 return document()->getObject (idx - 1); |
522 return document()->getObject (idx - 1); |
523 } |
523 } |
524 |
524 |
525 // ============================================================================= |
525 // ============================================================================= |
526 // |
526 // |
527 void LDObject::move (Vertex vect) |
527 void LDObject::move (Vertex vect) |
528 { |
528 { |
529 if (hasMatrix()) |
529 if (hasMatrix()) |
530 { |
530 { |
531 LDMatrixObject* mo = dynamic_cast<LDMatrixObject*> (this); |
531 LDMatrixObjectPtr mo = thisptr().dynamicCast<LDMatrixObject>(); |
532 mo->setPosition (mo->position() + vect); |
532 mo->setPosition (mo->position() + vect); |
533 } |
533 } |
534 elif (type() == LDObject::EVertex) |
534 elif (type() == LDObject::EVertex) |
535 { |
535 { |
536 // ugh |
536 // ugh |
537 static_cast<LDVertex*> (this)->pos += vect; |
537 thisptr().staticCast<LDVertex>()->pos += vect; |
538 } |
538 } |
539 else |
539 else |
540 { |
540 { |
541 for (int i = 0; i < numVertices(); ++i) |
541 for (int i = 0; i < numVertices(); ++i) |
542 setVertex (i, vertex (i) + vect); |
542 setVertex (i, vertex (i) + vect); |
543 } |
543 } |
544 } |
544 } |
545 |
545 |
546 // ============================================================================= |
546 // ============================================================================= |
547 // |
547 // |
548 #define CHECK_FOR_OBJ(N) \ |
548 LDObjectPtr LDObject::getDefault (const LDObject::Type type) |
549 if (type == LDObject::E##N) \ |
549 { |
550 return new LD##N; |
550 switch (type) |
551 |
551 { |
552 LDObject* LDObject::getDefault (const LDObject::Type type) |
552 case EComment: return spawn<LDComment>(); |
553 { |
553 case EBFC: return spawn<LDBFC>(); |
554 CHECK_FOR_OBJ (Comment) |
554 case ELine: return spawn<LDLine>(); |
555 CHECK_FOR_OBJ (BFC) |
555 case ECondLine: return spawn<LDCondLine>(); |
556 CHECK_FOR_OBJ (Line) |
556 case ESubfile: return spawn<LDSubfile>(); |
557 CHECK_FOR_OBJ (CondLine) |
557 case ETriangle: return spawn<LDTriangle>(); |
558 CHECK_FOR_OBJ (Subfile) |
558 case EQuad: return spawn<LDQuad>(); |
559 CHECK_FOR_OBJ (Triangle) |
559 case EEmpty: return spawn<LDEmpty>(); |
560 CHECK_FOR_OBJ (Quad) |
560 case EError: return spawn<LDError>(); |
561 CHECK_FOR_OBJ (Empty) |
561 case EVertex: return spawn<LDVertex>(); |
562 CHECK_FOR_OBJ (BFC) |
562 case EOverlay: return spawn<LDOverlay>(); |
563 CHECK_FOR_OBJ (Error) |
563 case EUnidentified: assert (false); |
564 CHECK_FOR_OBJ (Vertex) |
564 case ENumTypes: assert (false); |
565 CHECK_FOR_OBJ (Overlay) |
565 } |
566 return null; |
566 return LDObjectPtr(); |
567 } |
567 } |
568 |
568 |
569 // ============================================================================= |
569 // ============================================================================= |
570 // |
570 // |
571 void LDObject::invert() {} |
571 void LDObject::invert() {} |
611 |
611 |
612 int idx = lineNumber(); |
612 int idx = lineNumber(); |
613 |
613 |
614 if (idx > 0) |
614 if (idx > 0) |
615 { |
615 { |
616 LDBFC* bfc = dynamic_cast<LDBFC*> (previous()); |
616 LDBFCPtr bfc = previous().dynamicCast<LDBFC>(); |
617 |
617 |
618 if (bfc && bfc->statement() == LDBFC::InvertNext) |
618 if (not bfc.isNull() && bfc->statement() == LDBFC::InvertNext) |
619 { |
619 { |
620 // This is prefixed with an invertnext, thus remove it. |
620 // This is prefixed with an invertnext, thus remove it. |
621 bfc->destroy(); |
621 bfc->destroy(); |
622 return; |
622 return; |
623 } |
623 } |
624 } |
624 } |
625 |
625 |
626 // Not inverted, thus prefix it with a new invertnext. |
626 // Not inverted, thus prefix it with a new invertnext. |
627 LDBFC* bfc = new LDBFC (LDBFC::InvertNext); |
627 document()->insertObj (idx, spawn<LDBFC> (LDBFC::InvertNext)); |
628 document()->insertObj (idx, bfc); |
628 } |
629 } |
629 |
630 |
630 // ============================================================================= |
631 // ============================================================================= |
631 // |
632 // |
632 void LDLine::invert() |
633 static void invertLine (LDObject* line) |
|
634 { |
633 { |
635 // For lines, we swap the vertices. I don't think that a |
634 // For lines, we swap the vertices. I don't think that a |
636 // cond-line's control points need to be swapped, do they? |
635 // cond-line's control points need to be swapped, do they? |
637 Vertex tmp = line->vertex (0); |
636 Vertex tmp = vertex (0); |
638 line->setVertex (0, line->vertex (1)); |
637 setVertex (0, vertex (1)); |
639 line->setVertex (1, tmp); |
638 setVertex (1, tmp); |
640 } |
|
641 |
|
642 void LDLine::invert() |
|
643 { |
|
644 invertLine (this); |
|
645 } |
639 } |
646 |
640 |
647 void LDCondLine::invert() |
641 void LDCondLine::invert() |
648 { |
642 { |
649 invertLine (this); |
643 static_cast<LDLine*> (this)->invert(); |
650 } |
644 } |
651 |
645 |
652 void LDVertex::invert() {} |
646 void LDVertex::invert() {} |
653 |
647 |
654 // ============================================================================= |
648 // ============================================================================= |
655 // |
649 // |
656 LDLine* LDCondLine::demote() |
650 LDLinePtr LDCondLine::demote() |
657 { |
651 { |
658 LDLine* repl = new LDLine; |
652 LDLinePtr replacement (spawn<LDLine>()); |
659 |
653 |
660 for (int i = 0; i < repl->numVertices(); ++i) |
654 for (int i = 0; i < replacement->numVertices(); ++i) |
661 repl->setVertex (i, vertex (i)); |
655 replacement->setVertex (i, vertex (i)); |
662 |
656 |
663 repl->setColor (color()); |
657 replacement->setColor (color()); |
664 |
658 |
665 replace (repl); |
659 replace (replacement); |
666 return repl; |
660 return replacement; |
667 } |
661 } |
668 |
662 |
669 // ============================================================================= |
663 // ============================================================================= |
670 // |
664 // |
671 LDObject* LDObject::fromID (int id) |
665 LDObjectPtr LDObject::fromID (int id) |
672 { |
666 { |
673 for (LDObject* obj : g_LDObjects) |
667 for (LDObjectWeakPtr obj : g_LDObjects) |
674 if (obj->id() == id) |
668 { |
|
669 LDObjectPtr obj2 = obj.toStrongRef(); |
|
670 |
|
671 if (obj2->id() == id) |
675 return obj; |
672 return obj; |
676 |
673 } |
677 return null; |
674 |
|
675 return LDObjectPtr(); |
678 } |
676 } |
679 |
677 |
680 // ============================================================================= |
678 // ============================================================================= |
681 // |
679 // |
682 String LDOverlay::asText() const |
680 String LDOverlay::asText() const |
735 void LDObject::setVertex (int i, const Vertex& vert) |
734 void LDObject::setVertex (int i, const Vertex& vert) |
736 { |
735 { |
737 if (document() != null) |
736 if (document() != null) |
738 document()->vertexChanged (*m_coords[i], vert); |
737 document()->vertexChanged (*m_coords[i], vert); |
739 |
738 |
740 changeProperty (this, &m_coords[i], LDSharedVertex::getSharedVertex (vert)); |
739 changeProperty (thisptr(), &m_coords[i], LDSharedVertex::getSharedVertex (vert)); |
741 } |
740 } |
742 |
741 |
743 // ============================================================================= |
742 // ============================================================================= |
744 // |
743 // |
745 void LDMatrixObject::setPosition (const Vertex& a) |
744 void LDMatrixObject::setPosition (const Vertex& a) |
807 // ============================================================================= |
806 // ============================================================================= |
808 // |
807 // |
809 void LDObject::select() |
808 void LDObject::select() |
810 { |
809 { |
811 assert (document() != null); |
810 assert (document() != null); |
812 document()->addToSelection (this); |
811 document()->addToSelection (thisptr()); |
813 } |
812 } |
814 |
813 |
815 // ============================================================================= |
814 // ============================================================================= |
816 // |
815 // |
817 void LDObject::deselect() |
816 void LDObject::deselect() |
818 { |
817 { |
819 assert (document() != null); |
818 assert (document() != null); |
820 document()->removeFromSelection (this); |
819 document()->removeFromSelection (thisptr()); |
821 } |
820 } |
822 |
821 |
823 // ============================================================================= |
822 // ============================================================================= |
824 // |
823 // |
825 String getLicenseText (int id) |
824 String getLicenseText (int id) |
840 return ""; |
839 return ""; |
841 } |
840 } |
842 |
841 |
843 // ============================================================================= |
842 // ============================================================================= |
844 // |
843 // |
845 LDObject* LDObject::createCopy() const |
844 LDObjectPtr LDObject::createCopy() const |
846 { |
845 { |
847 /* |
846 LDObjectPtr copy = parseLine (asText()); |
848 LDObject* copy = clone(); |
|
849 copy->setFile (null); |
|
850 copy->chooseID(); |
|
851 copy->setSelected (false); |
|
852 */ |
|
853 |
|
854 /* |
|
855 LDObject* copy = getDefault (getType()); |
|
856 copy->setColor (color()); |
|
857 |
|
858 if (hasMatrix()) |
|
859 { |
|
860 LDMatrixObject* copyMo = static_cast<LDMatrixObject*> (copy); |
|
861 const LDMatrixObject* mo = static_cast<const LDMatrixObject*> (this); |
|
862 copyMo->setPosition (mo->getPosition()); |
|
863 copyMo->setTransform (mo->transform()); |
|
864 } |
|
865 else |
|
866 { |
|
867 for (int i = 0; i < vertices(); ++i) |
|
868 copy->setVertex (getVertex (i)); |
|
869 } |
|
870 |
|
871 switch (getType()) |
|
872 { |
|
873 case Subfile: |
|
874 { |
|
875 LDSubfile* copyRef = static_cast<LDSubfile*> (copy); |
|
876 const LDSubfile* ref = static_cast<const LDSubfile*> (this); |
|
877 |
|
878 copyRef->setFileInfo (ref->fileInfo()); |
|
879 } |
|
880 } |
|
881 */ |
|
882 |
|
883 LDObject* copy = parseLine (asText()); |
|
884 return copy; |
847 return copy; |
885 } |
848 } |
886 |
849 |
887 // ============================================================================= |
850 // ============================================================================= |
888 // |
851 // |
889 void LDSubfile::setFileInfo (const LDDocumentPointer& a) |
852 void LDSubfile::setFileInfo (const LDDocumentPointer& a) |
890 { |
853 { |
891 if (document() != null) |
854 if (document() != null) |
892 document()->removeKnownVerticesOf (this); |
855 document()->removeKnownVerticesOf (thisptr()); |
893 |
856 |
894 m_fileInfo = a; |
857 m_fileInfo = a; |
895 |
858 |
896 // If it's an immediate subfile reference (i.e. this subfile belongs in an |
859 // If it's an immediate subfile reference (i.e. this subfile belongs in an |
897 // explicit file), we need to pre-compile the GL polygons for the document |
860 // explicit file), we need to pre-compile the GL polygons for the document |