414 QChar c; |
414 QChar c; |
415 |
415 |
416 while (line.endsWith ("\n") or line.endsWith ("\r")) |
416 while (line.endsWith ("\n") or line.endsWith ("\r")) |
417 line.chop (1); |
417 line.chop (1); |
418 |
418 |
419 LDObjectPtr obj = ParseLine (line); |
419 LDObject* obj = ParseLine (line); |
420 |
420 |
421 // Check for parse errors and warn about tthem |
421 // Check for parse errors and warn about tthem |
422 if (obj->type() == OBJ_Error) |
422 if (obj->type() == OBJ_Error) |
423 { |
423 { |
424 print ("Couldn't parse line #%1: %2", |
424 print ("Couldn't parse line #%1: %2", |
425 progress() + 1, obj.staticCast<LDError>()->reason()); |
425 progress() + 1, static_cast<LDError*> (obj)->reason()); |
426 |
426 |
427 if (warnings() != null) |
427 if (warnings() != null) |
428 (*warnings())++; |
428 (*warnings())++; |
429 } |
429 } |
430 |
430 |
744 |
744 |
745 // If there were problems loading subfile references, try see if we can find these |
745 // If there were problems loading subfile references, try see if we can find these |
746 // files on the parts tracker. |
746 // files on the parts tracker. |
747 QStringList unknowns; |
747 QStringList unknowns; |
748 |
748 |
749 for (LDObjectPtr obj : file->objects()) |
749 for (LDObject* obj : file->objects()) |
750 { |
750 { |
751 if (obj->type() != OBJ_Error or obj.staticCast<LDError>()->fileReferenced().isEmpty()) |
751 if (obj->type() != OBJ_Error or static_cast<LDError*> (obj)->fileReferenced().isEmpty(j) |
752 continue; |
752 continue; |
753 |
753 |
754 unknowns << obj.staticCast<LDError>()->fileReferenced(); |
754 unknowns << static_cast<LDError*> (obj)->fileReferenced(); |
755 } |
755 } |
756 |
756 |
757 if (cfg::TryDownloadMissingFiles and not unknowns.isEmpty()) |
757 if (cfg::TryDownloadMissingFiles and not unknowns.isEmpty()) |
758 { |
758 { |
759 PartDownloader dl; |
759 PartDownloader dl; |
782 |
782 |
783 if (not path.length()) |
783 if (not path.length()) |
784 path = fullPath(); |
784 path = fullPath(); |
785 |
785 |
786 // If the second object in the list holds the file name, update that now. |
786 // If the second object in the list holds the file name, update that now. |
787 LDObjectPtr nameObject = getObject (1); |
787 LDObject* nameObject = getObject (1); |
788 |
788 |
789 if (nameObject != null and nameObject->type() == OBJ_Comment) |
789 if (nameObject != null and nameObject->type() == OBJ_Comment) |
790 { |
790 { |
791 LDCommentPtr nameComment = nameObject.staticCast<LDComment>(); |
791 LDCommentPtr nameComment = static_cast<LDComment*> (nameObject); |
792 |
792 |
793 if (nameComment->text().left (6) == "Name: ") |
793 if (nameComment->text().left (6) == "Name: ") |
794 { |
794 { |
795 QString newname = shortenName (path); |
795 QString newname = shortenName (path); |
796 nameComment->setText (format ("Name: %1", newname)); |
796 nameComment->setText (format ("Name: %1", newname)); |
801 QByteArray data; |
801 QByteArray data; |
802 |
802 |
803 if (sizeptr != null) |
803 if (sizeptr != null) |
804 *sizeptr = 0; |
804 *sizeptr = 0; |
805 |
805 |
806 // File is open, now save the model to it. Note that LDraw requires files to |
806 // File is open, now save the model to it. Note that LDraw requires files to have DOS line endings. |
807 // have DOS line endings, so we terminate the lines with \r\n. |
807 for (LDObject* obj : objects()) |
808 for (LDObjectPtr obj : objects()) |
|
809 { |
808 { |
810 QByteArray subdata ((obj->asText() + "\r\n").toUtf8()); |
809 QByteArray subdata ((obj->asText() + "\r\n").toUtf8()); |
811 data.append (subdata); |
810 data.append (subdata); |
812 |
811 |
813 if (sizeptr != null) |
812 if (sizeptr != null) |
906 // ============================================================================= |
905 // ============================================================================= |
907 // This is the LDraw code parser function. It takes in a string containing LDraw |
906 // This is the LDraw code parser function. It takes in a string containing LDraw |
908 // code and returns the object parsed from it. parseLine never returns null, |
907 // code and returns the object parsed from it. parseLine never returns null, |
909 // the object will be LDError if it could not be parsed properly. |
908 // the object will be LDError if it could not be parsed properly. |
910 // ============================================================================= |
909 // ============================================================================= |
911 LDObjectPtr ParseLine (QString line) |
910 LDObject* ParseLine (QString line) |
912 { |
911 { |
913 try |
912 try |
914 { |
913 { |
915 QStringList tokens = line.split (" ", QString::SkipEmptyParts); |
914 QStringList tokens = line.split (" ", QString::SkipEmptyParts); |
916 |
915 |
1064 { |
1063 { |
1065 CheckTokenCount (tokens, 14); |
1064 CheckTokenCount (tokens, 14); |
1066 CheckTokenNumbers (tokens, 1, 13); |
1065 CheckTokenNumbers (tokens, 1, 13); |
1067 |
1066 |
1068 // Quadrilateral / Conditional line |
1067 // Quadrilateral / Conditional line |
1069 LDObjectPtr obj; |
1068 LDObject* obj; |
1070 |
1069 |
1071 if (num == 4) |
1070 if (num == 4) |
1072 obj = LDSpawn<LDQuad>(); |
1071 obj = LDSpawn<LDQuad>(); |
1073 else |
1072 else |
1074 obj = LDSpawn<LDCondLine>(); |
1073 obj = LDSpawn<LDCondLine>(); |
1111 void LDDocument::reloadAllSubfiles() |
1110 void LDDocument::reloadAllSubfiles() |
1112 { |
1111 { |
1113 print ("Reloading subfiles of %1", getDisplayName()); |
1112 print ("Reloading subfiles of %1", getDisplayName()); |
1114 |
1113 |
1115 // Go through all objects in the current file and reload the subfiles |
1114 // Go through all objects in the current file and reload the subfiles |
1116 for (LDObjectPtr obj : objects()) |
1115 for (LDObject* obj : objects()) |
1117 { |
1116 { |
1118 if (obj->type() == OBJ_Subfile) |
1117 if (obj->type() == OBJ_Subfile) |
1119 { |
1118 { |
1120 LDSubfilePtr ref = obj.staticCast<LDSubfile>(); |
1119 LDSubfilePtr ref = static_cast<LDSubfile*> (obj); |
1121 LDDocumentPtr fileInfo = GetDocument (ref->fileInfo()->name()); |
1120 LDDocumentPtr fileInfo = GetDocument (ref->fileInfo()->name()); |
1122 |
1121 |
1123 if (fileInfo != null) |
1122 if (fileInfo != null) |
1124 { |
1123 { |
1125 ref->setFileInfo (fileInfo); |
1124 ref->setFileInfo (fileInfo); |
1132 } |
1131 } |
1133 |
1132 |
1134 // Reparse gibberish files. It could be that they are invalid because |
1133 // Reparse gibberish files. It could be that they are invalid because |
1135 // of loading errors. Circumstances may be different now. |
1134 // of loading errors. Circumstances may be different now. |
1136 if (obj->type() == OBJ_Error) |
1135 if (obj->type() == OBJ_Error) |
1137 obj->replace (ParseLine (obj.staticCast<LDError>()->contents())); |
1136 obj->replace (ParseLine (static_cast<LDError*> (obj)->contents())); |
1138 } |
1137 } |
1139 |
1138 |
1140 m_needsReCache = true; |
1139 m_needsReCache = true; |
1141 |
1140 |
1142 if (this == CurrentDocument()) |
1141 if (this == CurrentDocument()) |
1143 g_win->buildObjList(); |
1142 g_win->buildObjList(); |
1144 } |
1143 } |
1145 |
1144 |
1146 // ============================================================================= |
1145 // ============================================================================= |
1147 // |
1146 // |
1148 int LDDocument::addObject (LDObjectPtr obj) |
1147 int LDDocument::addObject (LDObject* obj) |
1149 { |
1148 { |
1150 history()->add (new AddHistory (objects().size(), obj)); |
1149 history()->add (new AddHistory (objects().size(), obj)); |
1151 m_objects << obj; |
1150 m_objects << obj; |
1152 addKnownVertices (obj); |
1151 addKnownVertices (obj); |
1153 obj->setDocument (this); |
1152 obj->setDocument (this); |
1157 |
1156 |
1158 // ============================================================================= |
1157 // ============================================================================= |
1159 // |
1158 // |
1160 void LDDocument::addObjects (const LDObjectList& objs) |
1159 void LDDocument::addObjects (const LDObjectList& objs) |
1161 { |
1160 { |
1162 for (LDObjectPtr obj : objs) |
1161 for (LDObject* obj : objs) |
1163 { |
1162 { |
1164 if (obj != null) |
1163 if (obj != null) |
1165 addObject (obj); |
1164 addObject (obj); |
1166 } |
1165 } |
1167 } |
1166 } |
1168 |
1167 |
1169 // ============================================================================= |
1168 // ============================================================================= |
1170 // |
1169 // |
1171 void LDDocument::insertObj (int pos, LDObjectPtr obj) |
1170 void LDDocument::insertObj (int pos, LDObject* obj) |
1172 { |
1171 { |
1173 history()->add (new AddHistory (pos, obj)); |
1172 history()->add (new AddHistory (pos, obj)); |
1174 m_objects.insert (pos, obj); |
1173 m_objects.insert (pos, obj); |
1175 obj->setDocument (this); |
1174 obj->setDocument (this); |
1176 g_win->R()->compileObject (obj); |
1175 g_win->R()->compileObject (obj); |
1182 #endif |
1181 #endif |
1183 } |
1182 } |
1184 |
1183 |
1185 // ============================================================================= |
1184 // ============================================================================= |
1186 // |
1185 // |
1187 void LDDocument::addKnownVertices (LDObjectPtr obj) |
1186 void LDDocument::addKnownVertices (LDObject* obj) |
1188 { |
1187 { |
1189 auto it = m_objectVertices.find (obj); |
1188 auto it = m_objectVertices.find (obj); |
1190 |
1189 |
1191 if (it == m_objectVertices.end()) |
1190 if (it == m_objectVertices.end()) |
1192 it = m_objectVertices.insert (obj, QVector<Vertex>()); |
1191 it = m_objectVertices.insert (obj, QVector<Vertex>()); |
1228 return true; |
1227 return true; |
1229 } |
1228 } |
1230 |
1229 |
1231 // ============================================================================= |
1230 // ============================================================================= |
1232 // |
1231 // |
1233 void LDDocument::setObject (int idx, LDObjectPtr obj) |
1232 void LDDocument::setObject (int idx, LDObject* obj) |
1234 { |
1233 { |
1235 assert (idx >= 0 and idx < m_objects.size()); |
1234 assert (idx >= 0 and idx < m_objects.size()); |
1236 |
1235 |
1237 // Mark this change to history |
1236 // Mark this change to history |
1238 if (not m_history->isIgnoring()) |
1237 if (not m_history->isIgnoring()) |
1295 { |
1294 { |
1296 if (m_needsReCache) |
1295 if (m_needsReCache) |
1297 { |
1296 { |
1298 m_vertices.clear(); |
1297 m_vertices.clear(); |
1299 |
1298 |
1300 for (LDObjectPtr obj : inlineContents (true, true)) |
1299 for (LDObject* obj : inlineContents (true, true)) |
1301 { |
1300 { |
1302 if (obj->type() == OBJ_Subfile) |
1301 if (obj->type() == OBJ_Subfile) |
1303 { |
1302 { |
1304 print ("Warning: unable to inline %1 into %2", |
1303 print ("Warning: unable to inline %1 into %2", |
1305 obj.staticCast<LDSubfile>()->fileInfo()->getDisplayName(), |
1304 static_cast<LDSubfile*> (obj)->fileInfo()->getDisplayName(), |
1306 getDisplayName()); |
1305 getDisplayName()); |
1307 continue; |
1306 continue; |
1308 } |
1307 } |
1309 |
1308 |
1310 LDPolygon* data = obj->getPolygon(); |
1309 LDPolygon* data = obj->getPolygon(); |
1321 |
1320 |
1322 if (m_verticesOutdated) |
1321 if (m_verticesOutdated) |
1323 { |
1322 { |
1324 m_objectVertices.clear(); |
1323 m_objectVertices.clear(); |
1325 |
1324 |
1326 for (LDObjectPtr obj : inlineContents (true, false)) |
1325 for (LDObject* obj : inlineContents (true, false)) |
1327 addKnownVertices (obj); |
1326 addKnownVertices (obj); |
1328 |
1327 |
1329 mergeVertices(); |
1328 mergeVertices(); |
1330 m_verticesOutdated = false; |
1329 m_verticesOutdated = false; |
1331 } |
1330 } |
1373 return g_logoedStud2->inlineContents (deep, renderinline); |
1372 return g_logoedStud2->inlineContents (deep, renderinline); |
1374 } |
1373 } |
1375 |
1374 |
1376 LDObjectList objs, objcache; |
1375 LDObjectList objs, objcache; |
1377 |
1376 |
1378 for (LDObjectPtr obj : objects()) |
1377 for (LDObject* obj : objects()) |
1379 { |
1378 { |
1380 // Skip those without scemantic meaning |
1379 // Skip those without scemantic meaning |
1381 if (not obj->isScemantic()) |
1380 if (not obj->isScemantic()) |
1382 continue; |
1381 continue; |
1383 |
1382 |
1384 // Got another sub-file reference, inline it if we're deep-inlining. If not, |
1383 // Got another sub-file reference, inline it if we're deep-inlining. If not, |
1385 // just add it into the objects normally. Yay, recursion! |
1384 // just add it into the objects normally. Yay, recursion! |
1386 if (deep == true and obj->type() == OBJ_Subfile) |
1385 if (deep == true and obj->type() == OBJ_Subfile) |
1387 { |
1386 { |
1388 for (LDObjectPtr otherobj : obj.staticCast<LDSubfile>()->inlineContents (deep, renderinline)) |
1387 for (LDObject* otherobj : static_cast<LDSubfile*> (obj)->inlineContents (deep, renderinline)) |
1389 objs << otherobj; |
1388 objs << otherobj; |
1390 } |
1389 } |
1391 else |
1390 else |
1392 objs << obj->createCopy(); |
1391 objs << obj->createCopy(); |
1393 } |
1392 } |
1466 g_loadingLogoedStuds = false; |
1465 g_loadingLogoedStuds = false; |
1467 } |
1466 } |
1468 |
1467 |
1469 // ============================================================================= |
1468 // ============================================================================= |
1470 // |
1469 // |
1471 void LDDocument::addToSelection (LDObjectPtr obj) // [protected] |
1470 void LDDocument::addToSelection (LDObject* obj) // [protected] |
1472 { |
1471 { |
1473 if (obj->isSelected()) |
1472 if (obj->isSelected()) |
1474 return; |
1473 return; |
1475 |
1474 |
1476 assert (obj->document() == this); |
1475 assert (obj->document() == this); |
1479 obj->setSelected (true); |
1478 obj->setSelected (true); |
1480 } |
1479 } |
1481 |
1480 |
1482 // ============================================================================= |
1481 // ============================================================================= |
1483 // |
1482 // |
1484 void LDDocument::removeFromSelection (LDObjectPtr obj) // [protected] |
1483 void LDDocument::removeFromSelection (LDObject* obj) // [protected] |
1485 { |
1484 { |
1486 if (not obj->isSelected()) |
1485 if (not obj->isSelected()) |
1487 return; |
1486 return; |
1488 |
1487 |
1489 assert (obj->document() == this); |
1488 assert (obj->document() == this); |
1494 |
1493 |
1495 // ============================================================================= |
1494 // ============================================================================= |
1496 // |
1495 // |
1497 void LDDocument::clearSelection() |
1496 void LDDocument::clearSelection() |
1498 { |
1497 { |
1499 for (LDObjectPtr obj : m_sel) |
1498 for (LDObject* obj : m_sel) |
1500 removeFromSelection (obj); |
1499 removeFromSelection (obj); |
1501 |
1500 |
1502 assert (m_sel.isEmpty()); |
1501 assert (m_sel.isEmpty()); |
1503 } |
1502 } |
1504 |
1503 |
1509 return m_sel; |
1508 return m_sel; |
1510 } |
1509 } |
1511 |
1510 |
1512 // ============================================================================= |
1511 // ============================================================================= |
1513 // |
1512 // |
1514 void LDDocument::swapObjects (LDObjectPtr one, LDObjectPtr other) |
1513 void LDDocument::swapObjects (LDObject* one, LDObject* other) |
1515 { |
1514 { |
1516 int a = m_objects.indexOf (one); |
1515 int a = m_objects.indexOf (one); |
1517 int b = m_objects.indexOf (other); |
1516 int b = m_objects.indexOf (other); |
1518 assert (a != b and a != -1 and b != -1); |
1517 assert (a != b and a != -1 and b != -1); |
1519 m_objects[b] = one; |
1518 m_objects[b] = one; |