30 CFGENTRY (String, DefaultName, "") |
30 CFGENTRY (String, DefaultName, "") |
31 CFGENTRY (String, DefaultUser, "") |
31 CFGENTRY (String, DefaultUser, "") |
32 CFGENTRY (Bool, UseCALicense, true) |
32 CFGENTRY (Bool, UseCALicense, true) |
33 |
33 |
34 // List of all LDObjects |
34 // List of all LDObjects |
35 QMap<long, LDObjectWeakPtr> g_allObjects; |
35 QMap<int32, LDObjectWeakPtr> g_allObjects; |
36 static int32 g_idcursor = 1; // 0 shalt be null |
36 static int32 g_idcursor = 1; // 0 shalt be null |
37 static constexpr int32 g_maxID = (1 << 24); |
37 |
|
38 enum { MAX_LDOBJECT_IDS = (1 << 24) }; |
38 |
39 |
39 #define LDOBJ_DEFAULT_CTOR(T,BASE) \ |
40 #define LDOBJ_DEFAULT_CTOR(T,BASE) \ |
40 T :: T (LDObjectPtr* selfptr) : \ |
41 T :: T (LDDocument* document) : \ |
41 BASE (selfptr) {} |
42 BASE (document) {} |
42 |
43 |
43 // ============================================================================= |
44 // ============================================================================= |
44 // LDObject constructors |
45 // LDObject constructors |
45 // |
46 // |
46 LDObject::LDObject (LDObjectPtr* selfptr) : |
47 LDObject::LDObject (LDDocument* document) : |
47 m_isHidden (false), |
48 m_isHidden (false), |
48 m_isSelected (false), |
49 m_isSelected (false), |
49 m_isDestructed (false), |
50 m_isDestructed (false), |
50 qObjListEntry (null) |
51 qObjListEntry (null) |
51 { |
52 { |
52 *selfptr = LDObjectPtr (this, [](LDObject* obj){ obj->finalDelete(); }); |
53 if (document) |
|
54 document->addObject (this); |
|
55 |
53 memset (m_coords, 0, sizeof m_coords); |
56 memset (m_coords, 0, sizeof m_coords); |
54 m_self = selfptr->toWeakRef(); |
|
55 chooseID(); |
57 chooseID(); |
56 g_allObjects[id()] = self(); |
58 |
|
59 if (id() != 0) |
|
60 g_allObjects[id()] = this; |
|
61 |
57 setRandomColor (QColor::fromHsv (rand() % 360, rand() % 256, rand() % 96 + 128)); |
62 setRandomColor (QColor::fromHsv (rand() % 360, rand() % 256, rand() % 96 + 128)); |
58 } |
63 } |
59 |
64 |
60 LDSubfile::LDSubfile (LDObjectPtr* selfptr) : |
65 LDSubfile::LDSubfile (LDDocument* document) : |
61 LDMatrixObject (selfptr) {} |
66 LDMatrixObject (document) {} |
62 |
67 |
63 LDOBJ_DEFAULT_CTOR (LDEmpty, LDObject) |
68 LDOBJ_DEFAULT_CTOR (LDEmpty, LDObject) |
64 LDOBJ_DEFAULT_CTOR (LDError, LDObject) |
69 LDOBJ_DEFAULT_CTOR (LDError, LDObject) |
65 LDOBJ_DEFAULT_CTOR (LDLine, LDObject) |
70 LDOBJ_DEFAULT_CTOR (LDLine, LDObject) |
66 LDOBJ_DEFAULT_CTOR (LDTriangle, LDObject) |
71 LDOBJ_DEFAULT_CTOR (LDTriangle, LDObject) |
73 |
78 |
74 // ============================================================================= |
79 // ============================================================================= |
75 // |
80 // |
76 void LDObject::chooseID() |
81 void LDObject::chooseID() |
77 { |
82 { |
78 // If this is the first pass we can just use a global ID counter for each |
83 // Let's hope that nobody goes to create 17 million objects anytime soon... |
79 // unique object. Let's hope that nobody goes to create 17 million objects |
84 if (g_idcursor < MAX_LDOBJECT_IDS) |
80 // anytime soon. |
|
81 if (g_idcursor < g_maxID) |
|
82 { |
|
83 setID (g_idcursor++); |
85 setID (g_idcursor++); |
84 return; |
86 else |
85 } |
87 setID (0); |
86 |
|
87 // In case someone does, we cannot really continue execution. We must abort, |
|
88 // give the user a chance to save their documents though. |
|
89 Critical ("Created too many objects. Execution cannot continue. You have a " |
|
90 "chance to save any changes to documents, then restart."); |
|
91 (void) IsSafeToCloseAll(); |
|
92 Exit(); |
|
93 } |
88 } |
94 |
89 |
95 // ============================================================================= |
90 // ============================================================================= |
96 // |
91 // |
97 void LDObject::setVertexCoord (int i, Axis ax, double value) |
92 void LDObject::setVertexCoord (int i, Axis ax, double value) |
218 // 0---3 0---3 3 |
213 // 0---3 0---3 3 |
219 // | | | / /| |
214 // | | | / /| |
220 // | | ==> | / / | |
215 // | | ==> | / / | |
221 // | | |/ / | |
216 // | | |/ / | |
222 // 1---2 1 1---2 |
217 // 1---2 1 1---2 |
223 LDTrianglePtr tri1 (LDSpawn<LDTriangle> (vertex (0), vertex (1), vertex (3))); |
218 LDTrianglePtr tri1 (new LDTriangle (vertex (0), vertex (1), vertex (3))); |
224 LDTrianglePtr tri2 (LDSpawn<LDTriangle> (vertex (1), vertex (2), vertex (3))); |
219 LDTrianglePtr tri2 (new LDTriangle (vertex (1), vertex (2), vertex (3))); |
225 |
220 |
226 // The triangles also inherit the quad's color |
221 // The triangles also inherit the quad's color |
227 tri1->setColor (color()); |
222 tri1->setColor (color()); |
228 tri2->setColor (color()); |
223 tri2->setColor (color()); |
229 |
224 |
232 |
227 |
233 // ============================================================================= |
228 // ============================================================================= |
234 // |
229 // |
235 void LDObject::replace (LDObjectPtr other) |
230 void LDObject::replace (LDObjectPtr other) |
236 { |
231 { |
237 long idx = lineNumber(); |
232 int idx = lineNumber(); |
238 assert (idx != -1); |
233 |
239 |
234 if (idx != -1) |
240 // Replace the instance of the old object with the new object |
235 { |
241 document().toStrongRef()->setObject (idx, other); |
236 // Replace the instance of the old object with the new object |
242 |
237 document()->setObject (idx, other); |
243 // Remove the old object |
238 |
244 destroy(); |
239 // Remove the old object |
|
240 destroy(); |
|
241 } |
245 } |
242 } |
246 |
243 |
247 // ============================================================================= |
244 // ============================================================================= |
248 // |
245 // |
249 void LDObject::swap (LDObjectPtr other) |
246 void LDObject::swap (LDObjectPtr other) |
250 { |
247 { |
251 assert (document() == other->document()); |
248 assert (document() == other->document()); |
252 document().toStrongRef()->swapObjects (self(), other); |
249 document()->swapObjects (self(), other); |
253 } |
250 } |
254 |
251 |
255 // ============================================================================= |
252 // ============================================================================= |
256 // |
253 // |
257 LDLine::LDLine (LDObjectPtr* selfptr, Vertex v1, Vertex v2) : |
254 LDLine::LDLine (Vertex v1, Vertex v2, LDDocument* document) : |
258 LDObject (selfptr) |
255 LDObject (document) |
259 { |
256 { |
260 setVertex (0, v1); |
257 setVertex (0, v1); |
261 setVertex (1, v2); |
258 setVertex (1, v2); |
262 } |
259 } |
263 |
260 |
264 // ============================================================================= |
261 // ============================================================================= |
265 // |
262 // |
266 LDTriangle::LDTriangle (LDObjectPtr* selfptr, const Vertex& v1, const Vertex& v2, const Vertex& v3) : |
263 LDTriangle::LDTriangle (const Vertex& v1, const Vertex& v2, const Vertex& v3, LDDocument* document) : |
267 LDObject (selfptr) |
264 LDObject (document) |
268 { |
265 { |
269 setVertex (0, v1); |
266 setVertex (0, v1); |
270 setVertex (1, v2); |
267 setVertex (1, v2); |
271 setVertex (2, v3); |
268 setVertex (2, v3); |
272 } |
269 } |
273 |
270 |
274 // ============================================================================= |
271 // ============================================================================= |
275 // |
272 // |
276 LDQuad::LDQuad (LDObjectPtr* selfptr, const Vertex& v1, const Vertex& v2, |
273 LDQuad::LDQuad (const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex& v4, LDDocument* document) : |
277 const Vertex& v3, const Vertex& v4) : |
274 LDObject (document) |
278 LDObject (selfptr) |
|
279 { |
275 { |
280 setVertex (0, v1); |
276 setVertex (0, v1); |
281 setVertex (1, v2); |
277 setVertex (1, v2); |
282 setVertex (2, v3); |
278 setVertex (2, v3); |
283 setVertex (3, v4); |
279 setVertex (3, v4); |
284 } |
280 } |
285 |
281 |
286 // ============================================================================= |
282 // ============================================================================= |
287 // |
283 // |
288 LDCondLine::LDCondLine (LDObjectPtr* selfptr, const Vertex& v0, const Vertex& v1, |
284 LDCondLine::LDCondLine (const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3, LDDocument* document) : |
289 const Vertex& v2, const Vertex& v3) : |
285 LDLine (document) |
290 LDLine (selfptr) |
|
291 { |
286 { |
292 setVertex (0, v0); |
287 setVertex (0, v0); |
293 setVertex (1, v1); |
288 setVertex (1, v1); |
294 setVertex (2, v2); |
289 setVertex (2, v2); |
295 setVertex (3, v3); |
290 setVertex (3, v3); |
546 |
541 |
547 // ============================================================================= |
542 // ============================================================================= |
548 // |
543 // |
549 LDObjectPtr LDObject::topLevelParent() |
544 LDObjectPtr LDObject::topLevelParent() |
550 { |
545 { |
551 if (parent() == null) |
546 LDObject* it; |
552 return self(); |
547 |
553 |
548 for (it = self(); it->parent(); it = it->parent()) |
554 LDObjectWeakPtr it (self()); |
549 ; |
555 |
550 |
556 while (it.toStrongRef()->parent() != null) |
551 return it; |
557 it = it.toStrongRef()->parent(); |
|
558 |
|
559 return it.toStrongRef(); |
|
560 } |
552 } |
561 |
553 |
562 // ============================================================================= |
554 // ============================================================================= |
563 // |
555 // |
564 LDObjectPtr LDObject::next() const |
556 LDObjectPtr LDObject::next() const |
565 { |
557 { |
566 long idx = lineNumber(); |
558 int idx = lineNumber(); |
567 assert (idx != -1); |
559 assert (idx != -1); |
568 |
560 |
569 if (idx == (long) document().toStrongRef()->getObjectCount() - 1) |
561 if (idx == document()->getObjectCount() - 1) |
570 return LDObjectPtr(); |
562 return nullptr; |
571 |
563 |
572 return document().toStrongRef()->getObject (idx + 1); |
564 return document()->getObject (idx + 1); |
573 } |
565 } |
574 |
566 |
575 // ============================================================================= |
567 // ============================================================================= |
576 // |
568 // |
577 LDObjectPtr LDObject::previous() const |
569 LDObjectPtr LDObject::previous() const |
578 { |
570 { |
579 long idx = lineNumber(); |
571 int idx = lineNumber(); |
580 assert (idx != -1); |
572 assert (idx != -1); |
581 |
573 |
582 if (idx == 0) |
574 if (idx == 0) |
583 return LDObjectPtr(); |
575 return nullptr; |
584 |
576 |
585 return document().toStrongRef()->getObject (idx - 1); |
577 return document()->getObject (idx - 1); |
586 } |
578 } |
587 |
579 |
588 // ============================================================================= |
580 // ============================================================================= |
589 // |
581 // |
590 bool LDObject::previousIsInvertnext (LDBFCPtr& ptr) |
582 bool LDObject::previousIsInvertnext (LDBFC*& ptr) |
591 { |
583 { |
592 LDObjectPtr prev (previous()); |
584 LDObject* prev = previous(); |
593 |
585 |
594 if (prev != null and prev->type() == OBJ_BFC and |
586 if (prev and prev->type() == OBJ_BFC and static_cast<LDBFC*> (prev)->statement() == BFCStatement::InvertNext) |
595 prev.staticCast<LDBFC>()->statement() == BFCStatement::InvertNext) |
587 { |
596 { |
588 ptr = static_cast<LDBFC*> (prev); |
597 ptr = prev.staticCast<LDBFC>(); |
|
598 return true; |
589 return true; |
599 } |
590 } |
600 |
591 |
601 return false; |
592 return false; |
602 } |
593 } |
605 // |
596 // |
606 void LDObject::move (Vertex vect) |
597 void LDObject::move (Vertex vect) |
607 { |
598 { |
608 if (hasMatrix()) |
599 if (hasMatrix()) |
609 { |
600 { |
610 LDMatrixObjectPtr mo = self().toStrongRef().dynamicCast<LDMatrixObject>(); |
601 LDMatrixObject* mo = static_cast<LDMatrixObject*> (this); |
611 mo->setPosition (mo->position() + vect); |
602 mo->setPosition (mo->position() + vect); |
612 } |
603 } |
613 elif (type() == OBJ_Vertex) |
604 else if (type() == OBJ_Vertex) |
614 { |
605 { |
615 // ugh |
606 // ugh |
616 self().toStrongRef().staticCast<LDVertex>()->pos += vect; |
607 static_cast<LDVertex*> (self)->pos += vect; |
617 } |
608 } |
618 else |
609 else |
619 { |
610 { |
620 for (int i = 0; i < numVertices(); ++i) |
611 for (int i = 0; i < numVertices(); ++i) |
621 setVertex (i, vertex (i) + vect); |
612 setVertex (i, vertex (i) + vect); |
639 case OBJ_Error: return LDSpawn<LDError>(); |
630 case OBJ_Error: return LDSpawn<LDError>(); |
640 case OBJ_Vertex: return LDSpawn<LDVertex>(); |
631 case OBJ_Vertex: return LDSpawn<LDVertex>(); |
641 case OBJ_Overlay: return LDSpawn<LDOverlay>(); |
632 case OBJ_Overlay: return LDSpawn<LDOverlay>(); |
642 case OBJ_NumTypes: assert (false); |
633 case OBJ_NumTypes: assert (false); |
643 } |
634 } |
644 return LDObjectPtr(); |
635 return nullptr; |
645 } |
636 } |
646 |
637 |
647 // ============================================================================= |
638 // ============================================================================= |
648 // |
639 // |
649 void LDObject::invert() {} |
640 void LDObject::invert() {} |
667 |
658 |
668 // ============================================================================= |
659 // ============================================================================= |
669 // |
660 // |
670 void LDQuad::invert() |
661 void LDQuad::invert() |
671 { |
662 { |
672 // Quad: 0 -> 1 -> 2 -> 3 |
663 // Quad: 0 -> 1 -> 2 -> 3 |
673 // rev: 0 -> 3 -> 2 -> 1 |
664 // reversed: 0 -> 3 -> 2 -> 1 |
674 // Thus, we swap 1 and 3. |
665 // Thus, we swap 1 and 3. |
675 Vertex tmp = vertex (1); |
666 Vertex tmp = vertex (1); |
676 setVertex (1, vertex (3)); |
667 setVertex (1, vertex (3)); |
677 setVertex (3, tmp); |
668 setVertex (3, tmp); |
678 } |
669 } |
679 |
670 |
680 // ============================================================================= |
671 // ============================================================================= |
681 // |
672 // |
682 void LDSubfile::invert() |
673 void LDSubfile::invert() |
683 { |
674 { |
684 if (document() == null) |
675 if (document() == nullptr) |
685 return; |
676 return; |
686 |
677 |
687 // Check whether subfile is flat |
678 // Check whether subfile is flat |
688 int axisSet = (1 << X) | (1 << Y) | (1 << Z); |
679 int axisSet = (1 << X) | (1 << Y) | (1 << Z); |
689 LDObjectList objs = fileInfo()->inlineContents (true, false); |
680 LDObjectList objs = fileInfo()->inlineContents (true, false); |
758 |
749 |
759 // ============================================================================= |
750 // ============================================================================= |
760 // |
751 // |
761 void LDCondLine::invert() |
752 void LDCondLine::invert() |
762 { |
753 { |
763 // I don't think that a conditional line's control points need to be |
754 // I don't think that a conditional line's control points need to be swapped, do they? |
764 // swapped, do they? |
|
765 Vertex tmp = vertex (0); |
755 Vertex tmp = vertex (0); |
766 setVertex (0, vertex (1)); |
756 setVertex (0, vertex (1)); |
767 setVertex (1, tmp); |
757 setVertex (1, tmp); |
768 } |
758 } |
769 |
759 |
770 void LDVertex::invert() {} |
760 void LDVertex::invert() {} |
771 |
761 |
772 // ============================================================================= |
762 // ============================================================================= |
773 // |
763 // |
774 LDLinePtr LDCondLine::toEdgeLine() |
764 LDLine* LDCondLine::toEdgeLine() |
775 { |
765 { |
776 LDLinePtr replacement (LDSpawn<LDLine>()); |
766 LDLine* replacement = new LDLine; |
777 |
767 |
778 for (int i = 0; i < replacement->numVertices(); ++i) |
768 for (int i = 0; i < replacement->numVertices(); ++i) |
779 replacement->setVertex (i, vertex (i)); |
769 replacement->setVertex (i, vertex (i)); |
780 |
770 |
781 replacement->setColor (color()); |
771 replacement->setColor (color()); |
782 |
|
783 replace (replacement); |
772 replace (replacement); |
784 return replacement; |
773 return replacement; |
785 } |
774 } |
786 |
775 |
787 // ============================================================================= |
776 // ============================================================================= |
813 // makes history stuff work out of the box. |
802 // makes history stuff work out of the box. |
814 // |
803 // |
815 template<typename T> |
804 template<typename T> |
816 static void changeProperty (LDObjectPtr obj, T* ptr, const T& val) |
805 static void changeProperty (LDObjectPtr obj, T* ptr, const T& val) |
817 { |
806 { |
818 long idx; |
807 int idx; |
819 |
808 |
820 if (*ptr == val) |
809 if (*ptr == val) |
821 return; |
810 return; |
822 |
811 |
823 if (obj->document() != null and (idx = obj->lineNumber()) != -1) |
812 if (obj->document() and (idx = obj->lineNumber()) != -1) |
824 { |
813 { |
825 QString before = obj->asText(); |
814 QString before = obj->asText(); |
826 *ptr = val; |
815 *ptr = val; |
827 QString after = obj->asText(); |
816 QString after = obj->asText(); |
828 |
817 |
829 if (before != after) |
818 if (before != after) |
830 { |
819 { |
831 obj->document().toStrongRef()->addToHistory (new EditHistory (idx, before, after)); |
820 obj->document()->addToHistory (new EditHistory (idx, before, after)); |
832 g_win->R()->compileObject (obj); |
821 g_win->R()->compileObject (obj); |
833 CurrentDocument()->redoVertices(); |
822 CurrentDocument()->redoVertices(); |
834 } |
823 } |
835 } |
824 } |
836 else |
825 else |
|
826 { |
837 *ptr = val; |
827 *ptr = val; |
|
828 } |
838 } |
829 } |
839 |
830 |
840 // ============================================================================= |
831 // ============================================================================= |
841 // |
832 // |
842 void LDObject::setColor (LDColor const& val) |
833 void LDObject::setColor (LDColor const& val) |
874 |
865 |
875 // ============================================================================= |
866 // ============================================================================= |
876 // |
867 // |
877 void LDObject::select() |
868 void LDObject::select() |
878 { |
869 { |
879 assert (document() != null); |
870 if (document() != null) |
880 document().toStrongRef()->addToSelection (self()); |
871 document()->addToSelection (self()); |
881 |
|
882 // If this object is inverted with INVERTNEXT, pick the INVERTNEXT as well. |
|
883 /* |
|
884 LDBFCPtr invertnext; |
|
885 |
|
886 if (previousIsInvertnext (invertnext)) |
|
887 invertnext->select(); |
|
888 */ |
|
889 } |
872 } |
890 |
873 |
891 // ============================================================================= |
874 // ============================================================================= |
892 // |
875 // |
893 void LDObject::deselect() |
876 void LDObject::deselect() |
894 { |
877 { |
895 assert (document() != null); |
878 if (document() != null) |
896 document().toStrongRef()->removeFromSelection (self()); |
879 { |
897 |
880 document()->removeFromSelection (self()); |
898 // If this object is inverted with INVERTNEXT, deselect the INVERTNEXT as well. |
881 |
899 LDBFCPtr invertnext; |
882 // If this object is inverted with INVERTNEXT, deselect the INVERTNEXT as well. |
900 |
883 LDBFCPtr invertnext; |
901 if (previousIsInvertnext (invertnext)) |
884 |
902 invertnext->deselect(); |
885 if (previousIsInvertnext (invertnext)) |
|
886 invertnext->deselect(); |
|
887 } |
903 } |
888 } |
904 |
889 |
905 // ============================================================================= |
890 // ============================================================================= |
906 // |
891 // |
907 QString PreferredLicenseText() |
892 QString PreferredLicenseText() |