src/primitives.cc

changeset 861
83426c5fa732
parent 852
cbd89b33f70d
child 866
4951b737f8cb
equal deleted inserted replaced
860:a496e72af069 861:83426c5fa732
43 "ndis", 43 "ndis",
44 "ring", 44 "ring",
45 "con" 45 "con"
46 }; 46 };
47 47
48 PrimitiveScanner* getActivePrimitiveScanner() 48 PrimitiveScanner* ActivePrimitiveScanner()
49 { 49 {
50 return g_activeScanner; 50 return g_activeScanner;
51 } 51 }
52 52
53 // ============================================================================= 53 // =============================================================================
54 // 54 //
55 void loadPrimitives() 55 void LoadPrimitives()
56 { 56 {
57 // Try to load prims.cfg 57 // Try to load prims.cfg
58 QFile conf (Config::FilePath ("prims.cfg")); 58 QFile conf (Config::FilePath ("prims.cfg"));
59 59
60 if (not conf.open (QIODevice::ReadOnly)) 60 if (not conf.open (QIODevice::ReadOnly))
90 } 90 }
91 } 91 }
92 92
93 // ============================================================================= 93 // =============================================================================
94 // 94 //
95 static void recursiveGetFilenames (QDir dir, QList<QString>& fnames) 95 static void GetRecursiveFilenames (QDir dir, QList<QString>& fnames)
96 { 96 {
97 QFileInfoList flist = dir.entryInfoList (QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); 97 QFileInfoList flist = dir.entryInfoList (QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
98 98
99 for (const QFileInfo& info : flist) 99 for (const QFileInfo& info : flist)
100 { 100 {
101 if (info.isDir()) 101 if (info.isDir())
102 recursiveGetFilenames (QDir (info.absoluteFilePath()), fnames); 102 GetRecursiveFilenames (QDir (info.absoluteFilePath()), fnames);
103 else 103 else
104 fnames << info.absoluteFilePath(); 104 fnames << info.absoluteFilePath();
105 } 105 }
106 } 106 }
107 107
113 { 113 {
114 g_activeScanner = this; 114 g_activeScanner = this;
115 QDir dir (LDPaths::prims()); 115 QDir dir (LDPaths::prims());
116 assert (dir.exists()); 116 assert (dir.exists());
117 m_baselen = dir.absolutePath().length(); 117 m_baselen = dir.absolutePath().length();
118 recursiveGetFilenames (dir, m_files); 118 GetRecursiveFilenames (dir, m_files);
119 emit starting (m_files.size()); 119 emit starting (m_files.size());
120 print ("Scanning primitives..."); 120 print ("Scanning primitives...");
121 } 121 }
122 122
123 // ============================================================================= 123 // =============================================================================
129 129
130 // ============================================================================= 130 // =============================================================================
131 // 131 //
132 void PrimitiveScanner::work() 132 void PrimitiveScanner::work()
133 { 133 {
134 int j = min (m_i + 100, m_files.size()); 134 int j = Min (m_i + 100, m_files.size());
135 135
136 for (; m_i < j; ++m_i) 136 for (; m_i < j; ++m_i)
137 { 137 {
138 QString fname = m_files[m_i]; 138 QString fname = m_files[m_i];
139 QFile f (fname); 139 QFile f (fname);
166 // Done with primitives, now save to a config file 166 // Done with primitives, now save to a config file
167 QString path = Config::FilePath ("prims.cfg"); 167 QString path = Config::FilePath ("prims.cfg");
168 QFile conf (path); 168 QFile conf (path);
169 169
170 if (not conf.open (QIODevice::WriteOnly | QIODevice::Text)) 170 if (not conf.open (QIODevice::WriteOnly | QIODevice::Text))
171 critical (format ("Couldn't write primitive list %1: %2", 171 CriticalError (format ("Couldn't write primitive list %1: %2",
172 path, conf.errorString())); 172 path, conf.errorString()));
173 else 173 else
174 { 174 {
175 for (Primitive& info : m_prims) 175 for (Primitive& info : m_prims)
176 fprint (conf, "%1 %2\r\n", info.name, info.title); 176 fprint (conf, "%1 %2\r\n", info.name, info.title);
290 290
291 QFile f (path); 291 QFile f (path);
292 292
293 if (not f.open (QIODevice::ReadOnly)) 293 if (not f.open (QIODevice::ReadOnly))
294 { 294 {
295 critical (format (QObject::tr ("Failed to open primitive categories: %1"), f.errorString())); 295 CriticalError (format (QObject::tr ("Failed to open primitive categories: %1"), f.errorString()));
296 return; 296 return;
297 } 297 }
298 298
299 PrimitiveCategory* cat = null; 299 PrimitiveCategory* cat = null;
300 300
364 return true; 364 return true;
365 } 365 }
366 366
367 // ============================================================================= 367 // =============================================================================
368 // 368 //
369 bool isPrimitiveLoaderBusy() 369 bool IsPrimitiveLoaderBusy()
370 { 370 {
371 return g_activeScanner != null; 371 return g_activeScanner != null;
372 } 372 }
373 373
374 // ============================================================================= 374 // =============================================================================
375 // 375 //
376 static double radialPoint (int i, int divs, double (*func) (double)) 376 static double GetRadialPoint (int i, int divs, double (*func) (double))
377 { 377 {
378 return (*func) ((i * 2 * pi) / divs); 378 return (*func) ((i * 2 * Pi) / divs);
379 } 379 }
380 380
381 // ============================================================================= 381 // =============================================================================
382 // 382 //
383 void makeCircle (int segs, int divs, double radius, QList<QLineF>& lines) 383 void MakeCircle (int segs, int divs, double radius, QList<QLineF>& lines)
384 { 384 {
385 for (int i = 0; i < segs; ++i) 385 for (int i = 0; i < segs; ++i)
386 { 386 {
387 double x0 = radius * radialPoint (i, divs, cos), 387 double x0 = radius * GetRadialPoint (i, divs, cos),
388 x1 = radius * radialPoint (i + 1, divs, cos), 388 x1 = radius * GetRadialPoint (i + 1, divs, cos),
389 z0 = radius * radialPoint (i, divs, sin), 389 z0 = radius * GetRadialPoint (i, divs, sin),
390 z1 = radius * radialPoint (i + 1, divs, sin); 390 z1 = radius * GetRadialPoint (i + 1, divs, sin);
391 391
392 lines << QLineF (QPointF (x0, z0), QPointF (x1, z1)); 392 lines << QLineF (QPointF (x0, z0), QPointF (x1, z1));
393 } 393 }
394 } 394 }
395 395
396 // ============================================================================= 396 // =============================================================================
397 // 397 //
398 LDObjectList makePrimitive (PrimitiveType type, int segs, int divs, int num) 398 LDObjectList MakePrimitive (PrimitiveType type, int segs, int divs, int num)
399 { 399 {
400 LDObjectList objs; 400 LDObjectList objs;
401 QList<int> condLineSegs; 401 QList<int> condLineSegs;
402 QList<QLineF> circle; 402 QList<QLineF> circle;
403 403
404 makeCircle (segs, divs, 1, circle); 404 MakeCircle (segs, divs, 1, circle);
405 405
406 for (int i = 0; i < segs; ++i) 406 for (int i = 0; i < segs; ++i)
407 { 407 {
408 double x0 = circle[i].x1(), 408 double x0 = circle[i].x1(),
409 x1 = circle[i].x2(), 409 x1 = circle[i].x2(),
415 case Circle: 415 case Circle:
416 { 416 {
417 Vertex v0 (x0, 0.0f, z0), 417 Vertex v0 (x0, 0.0f, z0),
418 v1 (x1, 0.0f, z1); 418 v1 (x1, 0.0f, z1);
419 419
420 LDLinePtr line (spawn<LDLine>()); 420 LDLinePtr line (LDSpawn<LDLine>());
421 line->setVertex (0, v0); 421 line->setVertex (0, v0);
422 line->setVertex (1, v1); 422 line->setVertex (1, v1);
423 line->setColor (edgecolor()); 423 line->setColor (EdgeColor());
424 objs << line; 424 objs << line;
425 } break; 425 } break;
426 426
427 case Cylinder: 427 case Cylinder:
428 case Ring: 428 case Ring:
465 Vertex v0 (x0, y0, z0), 465 Vertex v0 (x0, y0, z0),
466 v1 (x1, y1, z1), 466 v1 (x1, y1, z1),
467 v2 (x2, y2, z2), 467 v2 (x2, y2, z2),
468 v3 (x3, y3, z3); 468 v3 (x3, y3, z3);
469 469
470 LDQuadPtr quad (spawn<LDQuad> (v0, v1, v2, v3)); 470 LDQuadPtr quad (LDSpawn<LDQuad> (v0, v1, v2, v3));
471 quad->setColor (maincolor()); 471 quad->setColor (MainColor());
472 472
473 if (type == Cylinder) 473 if (type == Cylinder)
474 quad->invert(); 474 quad->invert();
475 475
476 objs << quad; 476 objs << quad;
496 v1 (x1, 0.0f, z1), 496 v1 (x1, 0.0f, z1),
497 v2 (x2, 0.0f, z2); 497 v2 (x2, 0.0f, z2);
498 498
499 // Disc negatives need to go the other way around, otherwise 499 // Disc negatives need to go the other way around, otherwise
500 // they'll end up upside-down. 500 // they'll end up upside-down.
501 LDTrianglePtr seg (spawn<LDTriangle>()); 501 LDTrianglePtr seg (LDSpawn<LDTriangle>());
502 seg->setColor (maincolor()); 502 seg->setColor (MainColor());
503 seg->setVertex (type == Disc ? 0 : 2, v0); 503 seg->setVertex (type == Disc ? 0 : 2, v0);
504 seg->setVertex (1, v1); 504 seg->setVertex (1, v1);
505 seg->setVertex (type == Disc ? 2 : 0, v2); 505 seg->setVertex (type == Disc ? 2 : 0, v2);
506 objs << seg; 506 objs << seg;
507 } break; 507 } break;
513 if (segs < divs and condLineSegs.size() != 0) 513 if (segs < divs and condLineSegs.size() != 0)
514 condLineSegs << segs; 514 condLineSegs << segs;
515 515
516 for (int i : condLineSegs) 516 for (int i : condLineSegs)
517 { 517 {
518 Vertex v0 (radialPoint (i, divs, cos), 0.0f, radialPoint (i, divs, sin)), 518 Vertex v0 (GetRadialPoint (i, divs, cos), 0.0f, GetRadialPoint (i, divs, sin)),
519 v1, 519 v1,
520 v2 (radialPoint (i + 1, divs, cos), 0.0f, radialPoint (i + 1, divs, sin)), 520 v2 (GetRadialPoint (i + 1, divs, cos), 0.0f, GetRadialPoint (i + 1, divs, sin)),
521 v3 (radialPoint (i - 1, divs, cos), 0.0f, radialPoint (i - 1, divs, sin)); 521 v3 (GetRadialPoint (i - 1, divs, cos), 0.0f, GetRadialPoint (i - 1, divs, sin));
522 522
523 if (type == Cylinder) 523 if (type == Cylinder)
524 { 524 {
525 v1 = Vertex (v0[X], 1.0f, v0[Z]); 525 v1 = Vertex (v0[X], 1.0f, v0[Z]);
526 } 526 }
530 v0.setX (v0.x() * num); 530 v0.setX (v0.x() * num);
531 v0.setY (1.0); 531 v0.setY (1.0);
532 v0.setZ (v0.z() * num); 532 v0.setZ (v0.z() * num);
533 } 533 }
534 534
535 LDCondLinePtr line = (spawn<LDCondLine>()); 535 LDCondLinePtr line = (LDSpawn<LDCondLine>());
536 line->setColor (edgecolor()); 536 line->setColor (EdgeColor());
537 line->setVertex (0, v0); 537 line->setVertex (0, v0);
538 line->setVertex (1, v1); 538 line->setVertex (1, v1);
539 line->setVertex (2, v2); 539 line->setVertex (2, v2);
540 line->setVertex (3, v3); 540 line->setVertex (3, v3);
541 objs << line; 541 objs << line;
544 return objs; 544 return objs;
545 } 545 }
546 546
547 // ============================================================================= 547 // =============================================================================
548 // 548 //
549 static QString primitiveTypeName (PrimitiveType type) 549 static QString PrimitiveTypeName (PrimitiveType type)
550 { 550 {
551 // Not translated as primitives are in English. 551 // Not translated as primitives are in English.
552 return type == Circle ? "Circle" : 552 return type == Circle ? "Circle" :
553 type == Cylinder ? "Cylinder" : 553 type == Cylinder ? "Cylinder" :
554 type == Disc ? "Disc" : 554 type == Disc ? "Disc" :
556 type == Ring ? "Ring" : "Cone"; 556 type == Ring ? "Ring" : "Cone";
557 } 557 }
558 558
559 // ============================================================================= 559 // =============================================================================
560 // 560 //
561 QString radialFileName (PrimitiveType type, int segs, int divs, int num) 561 QString MakeRadialFileName (PrimitiveType type, int segs, int divs, int num)
562 { 562 {
563 int numer = segs, 563 int numer = segs,
564 denom = divs; 564 denom = divs;
565 565
566 // Simplify the fractional part, but the denominator must be at least 4. 566 // Simplify the fractional part, but the denominator must be at least 4.
567 simplify (numer, denom); 567 Simplify (numer, denom);
568 568
569 if (denom < 4) 569 if (denom < 4)
570 { 570 {
571 const int factor = 4 / denom; 571 const int factor = 4 / denom;
572 numer *= factor; 572 numer *= factor;
580 QString numstr = (type == Ring or type == Cone) ? format ("%1", num) : ""; 580 QString numstr = (type == Ring or type == Cone) ? format ("%1", num) : "";
581 581
582 // Truncate the root if necessary (7-16rin4.dat for instance). 582 // Truncate the root if necessary (7-16rin4.dat for instance).
583 // However, always keep the root at least 2 characters. 583 // However, always keep the root at least 2 characters.
584 int extra = (frac.length() + numstr.length() + root.length()) - 8; 584 int extra = (frac.length() + numstr.length() + root.length()) - 8;
585 root.chop (clamp (extra, 0, 2)); 585 root.chop (Clamp (extra, 0, 2));
586 586
587 // Stick them all together and return the result. 587 // Stick them all together and return the result.
588 return prefix + frac + root + numstr + ".dat"; 588 return prefix + frac + root + numstr + ".dat";
589 } 589 }
590 590
591 // ============================================================================= 591 // =============================================================================
592 // 592 //
593 LDDocumentPtr generatePrimitive (PrimitiveType type, int segs, int divs, int num) 593 LDDocumentPtr GeneratePrimitive (PrimitiveType type, int segs, int divs, int num)
594 { 594 {
595 // Make the description 595 // Make the description
596 QString frac = QString::number ((float) segs / divs); 596 QString frac = QString::number ((float) segs / divs);
597 QString name = radialFileName (type, segs, divs, num); 597 QString name = MakeRadialFileName (type, segs, divs, num);
598 QString descr; 598 QString descr;
599 599
600 // Ensure that there's decimals, even if they're 0. 600 // Ensure that there's decimals, even if they're 0.
601 if (frac.indexOf (".") == -1) 601 if (frac.indexOf (".") == -1)
602 frac += ".0"; 602 frac += ".0";
605 { 605 {
606 QString spacing = 606 QString spacing =
607 (num < 10) ? " " : 607 (num < 10) ? " " :
608 (num < 100) ? " " : ""; 608 (num < 100) ? " " : "";
609 609
610 descr = format ("%1 %2%3 x %4", primitiveTypeName (type), spacing, num, frac); 610 descr = format ("%1 %2%3 x %4", PrimitiveTypeName (type), spacing, num, frac);
611 } 611 }
612 else 612 else
613 descr = format ("%1 %2", primitiveTypeName (type), frac); 613 descr = format ("%1 %2", PrimitiveTypeName (type), frac);
614 614
615 // Prepend "Hi-Res" if 48/ primitive. 615 // Prepend "Hi-Res" if 48/ primitive.
616 if (divs == HighResolution) 616 if (divs == HighResolution)
617 descr.insert (0, "Hi-Res "); 617 descr.insert (0, "Hi-Res ");
618 618
628 author = format ("%1 [%2]", cfg::DefaultName, cfg::DefaultUser); 628 author = format ("%1 [%2]", cfg::DefaultName, cfg::DefaultUser);
629 } 629 }
630 630
631 LDObjectList objs; 631 LDObjectList objs;
632 632
633 objs << spawn<LDComment> (descr) 633 objs << LDSpawn<LDComment> (descr)
634 << spawn<LDComment> (format ("Name: %1", name)) 634 << LDSpawn<LDComment> (format ("Name: %1", name))
635 << spawn<LDComment> (format ("Author: %1", author)) 635 << LDSpawn<LDComment> (format ("Author: %1", author))
636 << spawn<LDComment> (format ("!LDRAW_ORG Unofficial_%1Primitive", divs == HighResolution ? 636 << LDSpawn<LDComment> (format ("!LDRAW_ORG Unofficial_%1Primitive",
637 "48_" : "")) 637 divs == HighResolution ? "48_" : ""))
638 << spawn<LDComment> (license) 638 << LDSpawn<LDComment> (license)
639 << spawn<LDEmpty>() 639 << LDSpawn<LDEmpty>()
640 << spawn<LDBFC> (BFCStatement::CertifyCCW) 640 << LDSpawn<LDBFC> (BFCStatement::CertifyCCW)
641 << spawn<LDEmpty>(); 641 << LDSpawn<LDEmpty>();
642 642
643 f->addObjects (objs); 643 f->addObjects (objs);
644 f->addObjects (makePrimitive (type, segs, divs, num)); 644 f->addObjects (MakePrimitive (type, segs, divs, num));
645 return f; 645 return f;
646 } 646 }
647 647
648 // ============================================================================= 648 // =============================================================================
649 // 649 //
650 LDDocumentPtr getPrimitive (PrimitiveType type, int segs, int divs, int num) 650 LDDocumentPtr GetPrimitive (PrimitiveType type, int segs, int divs, int num)
651 { 651 {
652 QString name = radialFileName (type, segs, divs, num); 652 QString name = MakeRadialFileName (type, segs, divs, num);
653 LDDocumentPtr f = getDocument (name); 653 LDDocumentPtr f = GetDocument (name);
654 654
655 if (f != null) 655 if (f != null)
656 return f; 656 return f;
657 657
658 return generatePrimitive (type, segs, divs, num); 658 return GeneratePrimitive (type, segs, divs, num);
659 } 659 }
660 660
661 // ============================================================================= 661 // =============================================================================
662 // 662 //
663 PrimitivePrompt::PrimitivePrompt (QWidget* parent, Qt::WindowFlags f) : 663 PrimitivePrompt::PrimitivePrompt (QWidget* parent, Qt::WindowFlags f) :
704 dlg->ui->rb_cylinder->isChecked() ? Cylinder : 704 dlg->ui->rb_cylinder->isChecked() ? Cylinder :
705 dlg->ui->rb_disc->isChecked() ? Disc : 705 dlg->ui->rb_disc->isChecked() ? Disc :
706 dlg->ui->rb_ndisc->isChecked() ? DiscNeg : 706 dlg->ui->rb_ndisc->isChecked() ? DiscNeg :
707 dlg->ui->rb_ring->isChecked() ? Ring : Cone; 707 dlg->ui->rb_ring->isChecked() ? Ring : Cone;
708 708
709 LDDocumentPtr f = generatePrimitive (type, segs, divs, num); 709 LDDocumentPtr f = GeneratePrimitive (type, segs, divs, num);
710 f->setImplicit (false); 710 f->setImplicit (false);
711 g_win->save (f, false); 711 g_win->save (f, false);
712 } 712 }

mercurial