src/file.cpp

changeset 460
b230ae09c8e5
parent 459
51cca3ce540d
child 461
fbcc91ae1dd2
equal deleted inserted replaced
459:51cca3ce540d 460:b230ae09c8e5
277 277
278 LDObject* obj = parseLine (line); 278 LDObject* obj = parseLine (line);
279 279
280 // Check for parse errors and warn about tthem 280 // Check for parse errors and warn about tthem
281 if (obj->getType() == LDObject::Error) { 281 if (obj->getType() == LDObject::Error) {
282 log ("Couldn't parse line #%1: %2", m_progress + 1, static_cast<LDErrorObject*> (obj)->reason); 282 log ("Couldn't parse line #%1: %2", m_progress + 1, static_cast<LDError*> (obj)->reason);
283 283
284 if (m_warningsPointer) 284 if (m_warningsPointer)
285 (*m_warningsPointer)++; 285 (*m_warningsPointer)++;
286 } 286 }
287 287
548 return false; 548 return false;
549 549
550 // If the second object in the list holds the file name, update that now. 550 // If the second object in the list holds the file name, update that now.
551 // Only do this if the file is explicitly open. If it's saved into a directory 551 // Only do this if the file is explicitly open. If it's saved into a directory
552 // called "s" or "48", prepend that into the name. 552 // called "s" or "48", prepend that into the name.
553 LDCommentObject* fpathComment = null; 553 LDComment* fpathComment = null;
554 LDObject* first = object (1); 554 LDObject* first = object (1);
555 555
556 if (!implicit() && first != null && first->getType() == LDObject::Comment) { 556 if (!implicit() && first != null && first->getType() == LDObject::Comment) {
557 fpathComment = static_cast<LDCommentObject*> (first); 557 fpathComment = static_cast<LDComment*> (first);
558 558
559 if (fpathComment->text.left (6) == "Name: ") { 559 if (fpathComment->text.left (6) == "Name: ") {
560 str newname; 560 str newname;
561 str dir = basename (dirname (savepath)); 561 str dir = basename (dirname (savepath));
562 562
588 588
589 // ============================================================================= 589 // =============================================================================
590 // ----------------------------------------------------------------------------- 590 // -----------------------------------------------------------------------------
591 #define CHECK_TOKEN_COUNT(N) \ 591 #define CHECK_TOKEN_COUNT(N) \
592 if (tokens.size() != N) \ 592 if (tokens.size() != N) \
593 return new LDErrorObject (line, "Bad amount of tokens"); 593 return new LDError (line, "Bad amount of tokens");
594 594
595 #define CHECK_TOKEN_NUMBERS(MIN, MAX) \ 595 #define CHECK_TOKEN_NUMBERS(MIN, MAX) \
596 for (ushort i = MIN; i <= MAX; ++i) \ 596 for (ushort i = MIN; i <= MAX; ++i) \
597 if (!isNumber (tokens[i])) \ 597 if (!isNumber (tokens[i])) \
598 return new LDErrorObject (line, fmt ("Token #%1 was `%2`, expected a number", (i + 1), tokens[i])); 598 return new LDError (line, fmt ("Token #%1 was `%2`, expected a number", (i + 1), tokens[i]));
599 599
600 // ============================================================================= 600 // =============================================================================
601 // ----------------------------------------------------------------------------- 601 // -----------------------------------------------------------------------------
602 static vertex parseVertex (QStringList& s, const ushort n) { 602 static vertex parseVertex (QStringList& s, const ushort n) {
603 vertex v; 603 vertex v;
616 LDObject* parseLine (str line) { 616 LDObject* parseLine (str line) {
617 QStringList tokens = line.split (" ", str::SkipEmptyParts); 617 QStringList tokens = line.split (" ", str::SkipEmptyParts);
618 618
619 if (tokens.size() <= 0) { 619 if (tokens.size() <= 0) {
620 // Line was empty, or only consisted of whitespace 620 // Line was empty, or only consisted of whitespace
621 return new LDEmptyObject; 621 return new LDEmpty;
622 } 622 }
623 623
624 if (tokens[0].length() != 1 || tokens[0][0].isDigit() == false) 624 if (tokens[0].length() != 1 || tokens[0][0].isDigit() == false)
625 return new LDErrorObject (line, "Illogical line code"); 625 return new LDError (line, "Illogical line code");
626 626
627 int num = tokens[0][0].digitValue(); 627 int num = tokens[0][0].digitValue();
628 628
629 switch (num) { 629 switch (num) {
630 case 0: { 630 case 0: {
635 while (comm[0] == ' ') 635 while (comm[0] == ' ')
636 comm.remove (0, 1); 636 comm.remove (0, 1);
637 637
638 // Handle BFC statements 638 // Handle BFC statements
639 if (tokens.size() > 2 && tokens[1] == "BFC") { 639 if (tokens.size() > 2 && tokens[1] == "BFC") {
640 for (short i = 0; i < LDBFCObject::NumStatements; ++i) 640 for (short i = 0; i < LDBFC::NumStatements; ++i)
641 if (comm == fmt ("BFC %1", LDBFCObject::statements [i])) 641 if (comm == fmt ("BFC %1", LDBFC::statements [i]))
642 return new LDBFCObject ((LDBFCObject::Type) i); 642 return new LDBFC ((LDBFC::Type) i);
643 643
644 // MLCAD is notorious for stuffing these statements in parts it 644 // MLCAD is notorious for stuffing these statements in parts it
645 // creates. The above block only handles valid statements, so we 645 // creates. The above block only handles valid statements, so we
646 // need to handle MLCAD-style invertnext, clip and noclip separately. 646 // need to handle MLCAD-style invertnext, clip and noclip separately.
647 struct { 647 struct {
648 const char* a; 648 const char* a;
649 LDBFCObject::Type b; 649 LDBFC::Type b;
650 } BFCData[] = { 650 } BFCData[] = {
651 { "INVERTNEXT", LDBFCObject::InvertNext }, 651 { "INVERTNEXT", LDBFC::InvertNext },
652 { "NOCLIP", LDBFCObject::NoClip }, 652 { "NOCLIP", LDBFC::NoClip },
653 { "CLIP", LDBFCObject::Clip } 653 { "CLIP", LDBFC::Clip }
654 }; 654 };
655 655
656 for (const auto& i : BFCData) 656 for (const auto& i : BFCData)
657 if (comm == fmt ("BFC CERTIFY %1", i.a)) 657 if (comm == fmt ("BFC CERTIFY %1", i.a))
658 return new LDBFCObject (i.b); 658 return new LDBFC (i.b);
659 } 659 }
660 660
661 if (tokens.size() > 2 && tokens[1] == "!LDFORGE") { 661 if (tokens.size() > 2 && tokens[1] == "!LDFORGE") {
662 // Handle LDForge-specific types, they're embedded into comments too 662 // Handle LDForge-specific types, they're embedded into comments too
663 if (tokens[2] == "VERTEX") { 663 if (tokens[2] == "VERTEX") {
664 // Vertex (0 !LDFORGE VERTEX) 664 // Vertex (0 !LDFORGE VERTEX)
665 CHECK_TOKEN_COUNT (7) 665 CHECK_TOKEN_COUNT (7)
666 CHECK_TOKEN_NUMBERS (3, 6) 666 CHECK_TOKEN_NUMBERS (3, 6)
667 667
668 LDVertexObject* obj = new LDVertexObject; 668 LDVertex* obj = new LDVertex;
669 obj->setColor (tokens[3].toLong()); 669 obj->setColor (tokens[3].toLong());
670 670
671 for (const Axis ax : g_Axes) 671 for (const Axis ax : g_Axes)
672 obj->pos[ax] = tokens[4 + ax].toDouble(); // 4 - 6 672 obj->pos[ax] = tokens[4 + ax].toDouble(); // 4 - 6
673 673
674 return obj; 674 return obj;
675 } elif (tokens[2] == "OVERLAY") { 675 } elif (tokens[2] == "OVERLAY") {
676 CHECK_TOKEN_COUNT (9); 676 CHECK_TOKEN_COUNT (9);
677 CHECK_TOKEN_NUMBERS (5, 8) 677 CHECK_TOKEN_NUMBERS (5, 8)
678 678
679 LDOverlayObject* obj = new LDOverlayObject; 679 LDOverlay* obj = new LDOverlay;
680 obj->setFilename (tokens[3]); 680 obj->setFilename (tokens[3]);
681 obj->setCamera (tokens[4].toLong()); 681 obj->setCamera (tokens[4].toLong());
682 obj->setX (tokens[5].toLong()); 682 obj->setX (tokens[5].toLong());
683 obj->setY (tokens[6].toLong()); 683 obj->setY (tokens[6].toLong());
684 obj->setWidth (tokens[7].toLong()); 684 obj->setWidth (tokens[7].toLong());
686 return obj; 686 return obj;
687 } 687 }
688 } 688 }
689 689
690 // Just a regular comment: 690 // Just a regular comment:
691 LDCommentObject* obj = new LDCommentObject; 691 LDComment* obj = new LDComment;
692 obj->text = comm; 692 obj->text = comm;
693 return obj; 693 return obj;
694 } 694 }
695 695
696 case 1: { 696 case 1: {
705 LDFile* load = getFile (tokens[14]); 705 LDFile* load = getFile (tokens[14]);
706 g_loadingMainFile = tmp; 706 g_loadingMainFile = tmp;
707 707
708 // If we cannot open the file, mark it an error 708 // If we cannot open the file, mark it an error
709 if (!load) { 709 if (!load) {
710 LDErrorObject* obj = new LDErrorObject (line, fmt ("Could not open %1", tokens[14])); 710 LDError* obj = new LDError (line, fmt ("Could not open %1", tokens[14]));
711 obj->setFileRef (tokens[14]); 711 obj->setFileRef (tokens[14]);
712 return obj; 712 return obj;
713 } 713 }
714 714
715 LDSubfileObject* obj = new LDSubfileObject; 715 LDSubfile* obj = new LDSubfile;
716 obj->setColor (tokens[1].toLong()); 716 obj->setColor (tokens[1].toLong());
717 obj->setPosition (parseVertex (tokens, 2)); // 2 - 4 717 obj->setPosition (parseVertex (tokens, 2)); // 2 - 4
718 718
719 matrix transform; 719 matrix transform;
720 720
729 case 2: { 729 case 2: {
730 CHECK_TOKEN_COUNT (8) 730 CHECK_TOKEN_COUNT (8)
731 CHECK_TOKEN_NUMBERS (1, 7) 731 CHECK_TOKEN_NUMBERS (1, 7)
732 732
733 // Line 733 // Line
734 LDLineObject* obj = new LDLineObject; 734 LDLine* obj = new LDLine;
735 obj->setColor (tokens[1].toLong()); 735 obj->setColor (tokens[1].toLong());
736 736
737 for (short i = 0; i < 2; ++i) 737 for (short i = 0; i < 2; ++i)
738 obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 7 738 obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 7
739 739
743 case 3: { 743 case 3: {
744 CHECK_TOKEN_COUNT (11) 744 CHECK_TOKEN_COUNT (11)
745 CHECK_TOKEN_NUMBERS (1, 10) 745 CHECK_TOKEN_NUMBERS (1, 10)
746 746
747 // Triangle 747 // Triangle
748 LDTriangleObject* obj = new LDTriangleObject; 748 LDTriangle* obj = new LDTriangle;
749 obj->setColor (tokens[1].toLong()); 749 obj->setColor (tokens[1].toLong());
750 750
751 for (short i = 0; i < 3; ++i) 751 for (short i = 0; i < 3; ++i)
752 obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 10 752 obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 10
753 753
761 761
762 // Quadrilateral / Conditional line 762 // Quadrilateral / Conditional line
763 LDObject* obj; 763 LDObject* obj;
764 764
765 if (num == 4) 765 if (num == 4)
766 obj = new LDQuadObject; 766 obj = new LDQuad;
767 else 767 else
768 obj = new LDCondLineObject; 768 obj = new LDCndLine;
769 769
770 obj->setColor (tokens[1].toLong()); 770 obj->setColor (tokens[1].toLong());
771 771
772 for (short i = 0; i < 4; ++i) 772 for (short i = 0; i < 4; ++i)
773 obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 13 773 obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 13
774 774
775 return obj; 775 return obj;
776 } 776 }
777 777
778 default: // Strange line we couldn't parse 778 default: // Strange line we couldn't parse
779 return new LDErrorObject (line, "Unknown line code number"); 779 return new LDError (line, "Unknown line code number");
780 } 780 }
781 } 781 }
782 782
783 // ============================================================================= 783 // =============================================================================
784 // ----------------------------------------------------------------------------- 784 // -----------------------------------------------------------------------------
803 g_loadedFiles << LDFile::current(); 803 g_loadedFiles << LDFile::current();
804 804
805 // Go through all objects in the current file and reload the subfiles 805 // Go through all objects in the current file and reload the subfiles
806 for (LDObject* obj : LDFile::current()->objs()) { 806 for (LDObject* obj : LDFile::current()->objs()) {
807 if (obj->getType() == LDObject::Subfile) { 807 if (obj->getType() == LDObject::Subfile) {
808 LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj); 808 LDSubfile* ref = static_cast<LDSubfile*> (obj);
809 LDFile* fileInfo = getFile (ref->fileInfo()->name()); 809 LDFile* fileInfo = getFile (ref->fileInfo()->name());
810 810
811 if (fileInfo) 811 if (fileInfo)
812 ref->setFileInfo (fileInfo); 812 ref->setFileInfo (fileInfo);
813 else 813 else
814 ref->replace (new LDErrorObject (ref->raw(), "Could not open referred file")); 814 ref->replace (new LDError (ref->raw(), "Could not open referred file"));
815 } 815 }
816 816
817 // Reparse gibberish files. It could be that they are invalid because 817 // Reparse gibberish files. It could be that they are invalid because
818 // of loading errors. Circumstances may be different now. 818 // of loading errors. Circumstances may be different now.
819 if (obj->getType() == LDObject::Error) 819 if (obj->getType() == LDObject::Error)
820 obj->replace (parseLine (static_cast<LDErrorObject*> (obj)->contents)); 820 obj->replace (parseLine (static_cast<LDError*> (obj)->contents));
821 } 821 }
822 822
823 // Close all files left unused 823 // Close all files left unused
824 LDFile::closeUnused(); 824 LDFile::closeUnused();
825 } 825 }
885 885
886 for (LDObject* obj : *node) { 886 for (LDObject* obj : *node) {
887 if (obj->getType() != LDObject::Subfile) 887 if (obj->getType() != LDObject::Subfile)
888 continue; 888 continue;
889 889
890 LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj); 890 LDSubfile* ref = static_cast<LDSubfile*> (obj);
891 filesUsed << ref->fileInfo(); 891 filesUsed << ref->fileInfo();
892 filesUsed << getFilesUsed (ref->fileInfo()); 892 filesUsed << getFilesUsed (ref->fileInfo());
893 } 893 }
894 894
895 return filesUsed; 895 return filesUsed;
973 return tr ("<anonymous>"); 973 return tr ("<anonymous>");
974 } 974 }
975 975
976 // ============================================================================= 976 // =============================================================================
977 // ----------------------------------------------------------------------------- 977 // -----------------------------------------------------------------------------
978 List<LDObject*> LDFile::inlineContents (LDSubfileObject::InlineFlags flags) { 978 List<LDObject*> LDFile::inlineContents (LDSubfile::InlineFlags flags) {
979 // Possibly substitute with logoed studs: 979 // Possibly substitute with logoed studs:
980 // stud.dat -> stud-logo.dat 980 // stud.dat -> stud-logo.dat
981 // stud2.dat -> stud-logo2.dat 981 // stud2.dat -> stud-logo2.dat
982 if (gl_logostuds && (flags & LDSubfileObject::RendererInline)) { 982 if (gl_logostuds && (flags & LDSubfile::RendererInline)) {
983 if (name() == "stud.dat" && g_logoedStud) 983 if (name() == "stud.dat" && g_logoedStud)
984 return g_logoedStud->inlineContents (flags); 984 return g_logoedStud->inlineContents (flags);
985 elif (name() == "stud2.dat" && g_logoedStud2) 985 elif (name() == "stud2.dat" && g_logoedStud2)
986 return g_logoedStud2->inlineContents (flags); 986 return g_logoedStud2->inlineContents (flags);
987 } 987 }
988 988
989 List<LDObject*> objs, objcache; 989 List<LDObject*> objs, objcache;
990 990
991 bool deep = flags & LDSubfileObject::DeepInline, 991 bool deep = flags & LDSubfile::DeepInline,
992 doCache = flags & LDSubfileObject::CacheInline; 992 doCache = flags & LDSubfile::CacheInline;
993 993
994 // If we have this cached, just clone that 994 // If we have this cached, just clone that
995 if (deep && cache().size()) { 995 if (deep && cache().size()) {
996 for (LDObject* obj : cache()) 996 for (LDObject* obj : cache())
997 objs << obj->clone(); 997 objs << obj->clone();
1006 1006
1007 // Got another sub-file reference, inline it if we're deep-inlining. If not, 1007 // Got another sub-file reference, inline it if we're deep-inlining. If not,
1008 // just add it into the objects normally. Also, we only cache immediate 1008 // just add it into the objects normally. Also, we only cache immediate
1009 // subfiles and this is not one. Yay, recursion! 1009 // subfiles and this is not one. Yay, recursion!
1010 if (deep && obj->getType() == LDObject::Subfile) { 1010 if (deep && obj->getType() == LDObject::Subfile) {
1011 LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj); 1011 LDSubfile* ref = static_cast<LDSubfile*> (obj);
1012 1012
1013 // We only want to cache immediate subfiles, so shed the caching 1013 // We only want to cache immediate subfiles, so shed the caching
1014 // flag when recursing deeper in hierarchy. 1014 // flag when recursing deeper in hierarchy.
1015 List<LDObject*> otherobjs = ref->inlineContents (flags & ~(LDSubfileObject::CacheInline)); 1015 List<LDObject*> otherobjs = ref->inlineContents (flags & ~(LDSubfile::CacheInline));
1016 1016
1017 for (LDObject* otherobj : otherobjs) { 1017 for (LDObject* otherobj : otherobjs) {
1018 // Cache this object, if desired 1018 // Cache this object, if desired
1019 if (doCache) 1019 if (doCache)
1020 objcache << otherobj->clone(); 1020 objcache << otherobj->clone();

mercurial