@nexart/ui-renderer 0.3.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -60,6 +60,50 @@ export function compilePrimitive(config, foreground = 'rgb(45, 45, 45)') {
60
60
  return generateCirclesPrimitive(count, sw, speed, color, alpha);
61
61
  case 'stripes':
62
62
  return generateStripesPrimitive(count, sw, speed, color, alpha);
63
+ case 'spirals':
64
+ return generateSpiralsPrimitive(count, sw, speed, color, alpha);
65
+ case 'rays':
66
+ return generateRaysPrimitive(count, sw, speed, color, alpha);
67
+ case 'stars':
68
+ return generateStarsPrimitive(count, sw, speed, color, alpha);
69
+ case 'polygons':
70
+ return generatePolygonsPrimitive(count, sw, speed, color, alpha);
71
+ case 'hexgrid':
72
+ return generateHexgridPrimitive(count, sw, color, alpha);
73
+ case 'arcs':
74
+ return generateArcsPrimitive(count, sw, speed, color, alpha);
75
+ case 'crosshatch':
76
+ return generateCrosshatchPrimitive(count, sw, color, alpha);
77
+ case 'chevrons':
78
+ return generateChevronsPrimitive(count, sw, speed, color, alpha);
79
+ case 'zigzag':
80
+ return generateZigzagPrimitive(count, sw, speed, color, alpha);
81
+ case 'rings':
82
+ return generateRingsPrimitive(count, sw, speed, color, alpha);
83
+ case 'diamonds':
84
+ return generateDiamondsPrimitive(count, sw, speed, color, alpha);
85
+ case 'bubbles':
86
+ return generateBubblesPrimitive(count, sw, speed, color, alpha);
87
+ case 'mesh':
88
+ return generateMeshPrimitive(count, sw, color, alpha);
89
+ case 'curves':
90
+ return generateCurvesPrimitive(count, sw, speed, color, alpha);
91
+ case 'noise':
92
+ return generateNoisePrimitive(count, sw, speed, color, alpha);
93
+ case 'particles':
94
+ return generateParticlesPrimitive(count, sw, speed, color, alpha);
95
+ case 'petals':
96
+ return generatePetalsPrimitive(count, sw, speed, color, alpha);
97
+ case 'branches':
98
+ return generateBranchesPrimitive(count, sw, color, alpha);
99
+ case 'weave':
100
+ return generateWeavePrimitive(count, sw, speed, color, alpha);
101
+ case 'moire':
102
+ return generateMoirePrimitive(count, sw, speed, color, alpha);
103
+ case 'radialLines':
104
+ return generateRadialLinesPrimitive(count, sw, speed, color, alpha);
105
+ case 'concentricSquares':
106
+ return generateConcentricSquaresPrimitive(count, sw, speed, color, alpha);
63
107
  default:
64
108
  return generateWavesPrimitive(count, sw, speed, color, alpha);
65
109
  }
@@ -280,3 +324,610 @@ for (let i = 0; i < ${count}; i++) {
280
324
  pop();
281
325
  `;
282
326
  }
327
+ function generateSpiralsPrimitive(count, sw, speed, color, alpha) {
328
+ return `
329
+ push();
330
+ noFill();
331
+ strokeWeight(${sw});
332
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
333
+
334
+ const cx = width / 2;
335
+ const cy = height / 2;
336
+ const maxRadius = min(width, height) * 0.45;
337
+
338
+ for (let s = 0; s < ${count}; s++) {
339
+ const offset = (s / ${count}) * TWO_PI;
340
+ beginShape();
341
+ for (let i = 0; i < 200; i++) {
342
+ const angle = i * 0.1 + offset + t * TWO_PI * ${speed};
343
+ const radius = (i / 200) * maxRadius;
344
+ const x = cx + cos(angle) * radius;
345
+ const y = cy + sin(angle) * radius;
346
+ vertex(x, y);
347
+ }
348
+ endShape();
349
+ }
350
+ pop();
351
+ `;
352
+ }
353
+ function generateRaysPrimitive(count, sw, speed, color, alpha) {
354
+ return `
355
+ push();
356
+ noFill();
357
+ strokeWeight(${sw});
358
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
359
+
360
+ const cx = width / 2;
361
+ const cy = height / 2;
362
+ const maxLen = min(width, height) * 0.5;
363
+
364
+ for (let i = 0; i < ${count}; i++) {
365
+ const angle = (i / ${count}) * TWO_PI + t * ${speed};
366
+ const len = maxLen * (0.5 + noise(i * 0.5, t) * 0.5);
367
+ const x2 = cx + cos(angle) * len;
368
+ const y2 = cy + sin(angle) * len;
369
+ line(cx, cy, x2, y2);
370
+ }
371
+ pop();
372
+ `;
373
+ }
374
+ function generateStarsPrimitive(count, sw, speed, color, alpha) {
375
+ return `
376
+ push();
377
+ noFill();
378
+ strokeWeight(${sw});
379
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
380
+
381
+ const margin = width * 0.15;
382
+
383
+ for (let i = 0; i < ${count}; i++) {
384
+ const x = margin + random() * (width - margin * 2);
385
+ const y = margin + random() * (height - margin * 2);
386
+ const size = 10 + random() * 20;
387
+ const points = 5 + floor(random() * 3);
388
+ const rotation = random() * TWO_PI + t * ${speed};
389
+
390
+ push();
391
+ translate(x, y);
392
+ rotate(rotation);
393
+ beginShape();
394
+ for (let j = 0; j < points * 2; j++) {
395
+ const angle = (j / (points * 2)) * TWO_PI;
396
+ const r = j % 2 === 0 ? size : size * 0.4;
397
+ vertex(cos(angle) * r, sin(angle) * r);
398
+ }
399
+ endShape(CLOSE);
400
+ pop();
401
+ }
402
+ pop();
403
+ `;
404
+ }
405
+ function generatePolygonsPrimitive(count, sw, speed, color, alpha) {
406
+ return `
407
+ push();
408
+ noFill();
409
+ strokeWeight(${sw});
410
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
411
+
412
+ const margin = width * 0.12;
413
+
414
+ for (let i = 0; i < ${count}; i++) {
415
+ const x = margin + random() * (width - margin * 2);
416
+ const y = margin + random() * (height - margin * 2);
417
+ const size = 15 + random() * 30;
418
+ const sides = 3 + floor(random() * 5);
419
+ const rotation = random() * PI + t * ${speed} * (random() > 0.5 ? 1 : -1);
420
+
421
+ push();
422
+ translate(x, y);
423
+ rotate(rotation);
424
+ beginShape();
425
+ for (let j = 0; j < sides; j++) {
426
+ const angle = (j / sides) * TWO_PI;
427
+ vertex(cos(angle) * size, sin(angle) * size);
428
+ }
429
+ endShape(CLOSE);
430
+ pop();
431
+ }
432
+ pop();
433
+ `;
434
+ }
435
+ function generateHexgridPrimitive(count, sw, color, alpha) {
436
+ const cols = Math.ceil(Math.sqrt(count * 1.5));
437
+ return `
438
+ push();
439
+ noFill();
440
+ strokeWeight(${sw});
441
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
442
+
443
+ const margin = width * 0.1;
444
+ const hexSize = (width - margin * 2) / ${cols} * 0.5;
445
+ const cols = ${cols};
446
+ const rows = ceil(${count} / cols);
447
+
448
+ for (let i = 0; i < cols; i++) {
449
+ for (let j = 0; j < rows; j++) {
450
+ const offsetX = j % 2 === 0 ? 0 : hexSize * 0.866;
451
+ const x = margin + i * hexSize * 1.732 + offsetX + hexSize;
452
+ const y = margin + j * hexSize * 1.5 + hexSize;
453
+
454
+ if (x > width - margin || y > height - margin) continue;
455
+
456
+ beginShape();
457
+ for (let k = 0; k < 6; k++) {
458
+ const angle = k * PI / 3 + PI / 6;
459
+ vertex(x + cos(angle) * hexSize, y + sin(angle) * hexSize);
460
+ }
461
+ endShape(CLOSE);
462
+ }
463
+ }
464
+ pop();
465
+ `;
466
+ }
467
+ function generateArcsPrimitive(count, sw, speed, color, alpha) {
468
+ return `
469
+ push();
470
+ noFill();
471
+ strokeWeight(${sw});
472
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
473
+
474
+ const cx = width / 2;
475
+ const cy = height / 2;
476
+ const maxRadius = min(width, height) * 0.4;
477
+
478
+ for (let i = 0; i < ${count}; i++) {
479
+ const radius = maxRadius * (0.3 + (i / ${count}) * 0.7);
480
+ const startAngle = random() * TWO_PI + t * ${speed};
481
+ const arcLength = PI * 0.3 + random() * PI;
482
+
483
+ arc(cx, cy, radius * 2, radius * 2, startAngle, startAngle + arcLength);
484
+ }
485
+ pop();
486
+ `;
487
+ }
488
+ function generateCrosshatchPrimitive(count, sw, color, alpha) {
489
+ return `
490
+ push();
491
+ noFill();
492
+ strokeWeight(${sw * 0.5});
493
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
494
+
495
+ const margin = width * 0.1;
496
+ const spacing = (width - margin * 2) / ${count};
497
+
498
+ for (let i = 0; i <= ${count}; i++) {
499
+ const x = margin + i * spacing;
500
+ line(x, margin, x, height - margin);
501
+ }
502
+
503
+ for (let i = 0; i <= ${count}; i++) {
504
+ const y = margin + i * spacing * (height / width);
505
+ line(margin, y, width - margin, y);
506
+ }
507
+
508
+ for (let i = 0; i <= ${count * 1.5}; i++) {
509
+ const offset = i * spacing * 0.7;
510
+ line(margin + offset, margin, margin, margin + offset);
511
+ line(width - margin - offset, height - margin, width - margin, height - margin - offset);
512
+ }
513
+ pop();
514
+ `;
515
+ }
516
+ function generateChevronsPrimitive(count, sw, speed, color, alpha) {
517
+ return `
518
+ push();
519
+ noFill();
520
+ strokeWeight(${sw});
521
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
522
+
523
+ const margin = width * 0.1;
524
+ const spacing = (height - margin * 2) / ${count};
525
+ const amplitude = width * 0.15;
526
+
527
+ for (let i = 0; i < ${count}; i++) {
528
+ const y = margin + i * spacing;
529
+ const phase = sin(t * TWO_PI * ${speed} + i * 0.3) * 20;
530
+
531
+ beginShape();
532
+ vertex(margin, y + phase);
533
+ vertex(width / 2, y - amplitude * 0.5 + phase);
534
+ vertex(width - margin, y + phase);
535
+ endShape();
536
+ }
537
+ pop();
538
+ `;
539
+ }
540
+ function generateZigzagPrimitive(count, sw, speed, color, alpha) {
541
+ return `
542
+ push();
543
+ noFill();
544
+ strokeWeight(${sw});
545
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
546
+
547
+ const margin = width * 0.08;
548
+ const lineSpacing = (height - margin * 2) / ${count};
549
+ const zigWidth = 30;
550
+
551
+ for (let i = 0; i < ${count}; i++) {
552
+ const baseY = margin + i * lineSpacing;
553
+ const phase = t * ${speed} * zigWidth;
554
+
555
+ beginShape();
556
+ for (let x = margin; x <= width - margin; x += zigWidth) {
557
+ const segIndex = floor((x - margin + phase) / zigWidth);
558
+ const yOffset = segIndex % 2 === 0 ? -10 : 10;
559
+ vertex(x, baseY + yOffset);
560
+ }
561
+ endShape();
562
+ }
563
+ pop();
564
+ `;
565
+ }
566
+ function generateRingsPrimitive(count, sw, speed, color, alpha) {
567
+ return `
568
+ push();
569
+ noFill();
570
+ strokeWeight(${sw});
571
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
572
+
573
+ const cx = width / 2;
574
+ const cy = height / 2;
575
+ const maxRadius = min(width, height) * 0.45;
576
+ const gap = maxRadius / ${count};
577
+
578
+ for (let i = 0; i < ${count}; i++) {
579
+ const baseRadius = gap * (i + 1);
580
+ const pulse = sin(t * TWO_PI * ${speed} + i * 0.5) * 5;
581
+
582
+ if (i % 2 === 0) {
583
+ ellipse(cx, cy, (baseRadius + pulse) * 2);
584
+ }
585
+ }
586
+ pop();
587
+ `;
588
+ }
589
+ function generateDiamondsPrimitive(count, sw, speed, color, alpha) {
590
+ const gridSize = Math.ceil(Math.sqrt(count));
591
+ return `
592
+ push();
593
+ noFill();
594
+ strokeWeight(${sw});
595
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
596
+
597
+ const margin = width * 0.1;
598
+ const cols = ${gridSize};
599
+ const rows = ${gridSize};
600
+ const cellW = (width - margin * 2) / cols;
601
+ const cellH = (height - margin * 2) / rows;
602
+
603
+ for (let i = 0; i < cols; i++) {
604
+ for (let j = 0; j < rows; j++) {
605
+ const x = margin + i * cellW + cellW / 2;
606
+ const y = margin + j * cellH + cellH / 2;
607
+ const size = min(cellW, cellH) * 0.35;
608
+ const rotation = noise(i * 0.3, j * 0.3, t * ${speed}) * 0.3;
609
+
610
+ push();
611
+ translate(x, y);
612
+ rotate(PI / 4 + rotation);
613
+ rect(0, 0, size, size);
614
+ pop();
615
+ }
616
+ }
617
+ pop();
618
+ `;
619
+ }
620
+ function generateBubblesPrimitive(count, sw, speed, color, alpha) {
621
+ return `
622
+ push();
623
+ noFill();
624
+ strokeWeight(${sw});
625
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
626
+
627
+ const margin = width * 0.1;
628
+
629
+ for (let i = 0; i < ${count * 3}; i++) {
630
+ const baseX = random() * width;
631
+ const baseY = random() * height;
632
+ const size = 10 + random() * 40;
633
+
634
+ const floatY = baseY - t * height * ${speed} * 0.5;
635
+ const y = ((floatY % height) + height) % height;
636
+ const wobble = sin(t * TWO_PI * 2 + i) * 5;
637
+
638
+ ellipse(baseX + wobble, y, size);
639
+ }
640
+ pop();
641
+ `;
642
+ }
643
+ function generateMeshPrimitive(count, sw, color, alpha) {
644
+ const gridSize = Math.ceil(Math.sqrt(count));
645
+ return `
646
+ push();
647
+ noFill();
648
+ strokeWeight(${sw * 0.5});
649
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
650
+
651
+ const margin = width * 0.1;
652
+ const cols = ${gridSize};
653
+ const rows = ${gridSize};
654
+ const cellW = (width - margin * 2) / cols;
655
+ const cellH = (height - margin * 2) / rows;
656
+
657
+ const points = [];
658
+ for (let i = 0; i <= cols; i++) {
659
+ points[i] = [];
660
+ for (let j = 0; j <= rows; j++) {
661
+ const x = margin + i * cellW + (noise(i * 0.3, j * 0.3, t) - 0.5) * cellW * 0.5;
662
+ const y = margin + j * cellH + (noise(i * 0.3 + 100, j * 0.3, t) - 0.5) * cellH * 0.5;
663
+ points[i][j] = { x, y };
664
+ }
665
+ }
666
+
667
+ for (let i = 0; i < cols; i++) {
668
+ for (let j = 0; j < rows; j++) {
669
+ const p1 = points[i][j];
670
+ const p2 = points[i + 1][j];
671
+ const p3 = points[i + 1][j + 1];
672
+ const p4 = points[i][j + 1];
673
+
674
+ line(p1.x, p1.y, p2.x, p2.y);
675
+ line(p2.x, p2.y, p3.x, p3.y);
676
+ line(p1.x, p1.y, p3.x, p3.y);
677
+ }
678
+ }
679
+ pop();
680
+ `;
681
+ }
682
+ function generateCurvesPrimitive(count, sw, speed, color, alpha) {
683
+ return `
684
+ push();
685
+ noFill();
686
+ strokeWeight(${sw});
687
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
688
+
689
+ const margin = width * 0.15;
690
+
691
+ for (let i = 0; i < ${count}; i++) {
692
+ const x1 = margin + random() * (width - margin * 2);
693
+ const y1 = margin + random() * (height - margin * 2);
694
+ const x2 = margin + random() * (width - margin * 2);
695
+ const y2 = margin + random() * (height - margin * 2);
696
+
697
+ const cx1 = x1 + (random() - 0.5) * 100 + sin(t * TWO_PI * ${speed}) * 20;
698
+ const cy1 = y1 + (random() - 0.5) * 100;
699
+ const cx2 = x2 + (random() - 0.5) * 100;
700
+ const cy2 = y2 + (random() - 0.5) * 100 + cos(t * TWO_PI * ${speed}) * 20;
701
+
702
+ bezier(x1, y1, cx1, cy1, cx2, cy2, x2, y2);
703
+ }
704
+ pop();
705
+ `;
706
+ }
707
+ function generateNoisePrimitive(count, sw, speed, color, alpha) {
708
+ return `
709
+ push();
710
+ noFill();
711
+ strokeWeight(${sw * 0.7});
712
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
713
+
714
+ const margin = width * 0.08;
715
+ const resolution = ${Math.max(8, Math.ceil(count / 3))};
716
+ const cellW = (width - margin * 2) / resolution;
717
+ const cellH = (height - margin * 2) / resolution;
718
+
719
+ for (let i = 0; i < resolution; i++) {
720
+ for (let j = 0; j < resolution; j++) {
721
+ const x = margin + i * cellW + cellW / 2;
722
+ const y = margin + j * cellH + cellH / 2;
723
+ const n = noise(i * 0.2, j * 0.2, t * ${speed});
724
+ const len = n * min(cellW, cellH) * 0.8;
725
+ const angle = n * TWO_PI * 2;
726
+
727
+ line(
728
+ x - cos(angle) * len / 2,
729
+ y - sin(angle) * len / 2,
730
+ x + cos(angle) * len / 2,
731
+ y + sin(angle) * len / 2
732
+ );
733
+ }
734
+ }
735
+ pop();
736
+ `;
737
+ }
738
+ function generateParticlesPrimitive(count, sw, speed, color, alpha) {
739
+ return `
740
+ push();
741
+ strokeWeight(${sw});
742
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
743
+ fill(red('${color}'), green('${color}'), blue('${color}'), ${alpha * 0.5});
744
+
745
+ const cx = width / 2;
746
+ const cy = height / 2;
747
+
748
+ for (let i = 0; i < ${count * 5}; i++) {
749
+ const angle = random() * TWO_PI;
750
+ const dist = random() * min(width, height) * 0.4;
751
+ const x = cx + cos(angle + t * ${speed}) * dist;
752
+ const y = cy + sin(angle + t * ${speed}) * dist;
753
+ const size = 2 + random() * 4;
754
+
755
+ const tailAngle = angle + t * ${speed} - PI;
756
+ const tailLen = 5 + random() * 10;
757
+
758
+ ellipse(x, y, size);
759
+ line(x, y, x + cos(tailAngle) * tailLen, y + sin(tailAngle) * tailLen);
760
+ }
761
+ pop();
762
+ `;
763
+ }
764
+ function generatePetalsPrimitive(count, sw, speed, color, alpha) {
765
+ return `
766
+ push();
767
+ noFill();
768
+ strokeWeight(${sw});
769
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
770
+
771
+ const cx = width / 2;
772
+ const cy = height / 2;
773
+ const petalCount = ${count};
774
+ const maxRadius = min(width, height) * 0.35;
775
+
776
+ for (let i = 0; i < petalCount; i++) {
777
+ const angle = (i / petalCount) * TWO_PI + t * ${speed};
778
+
779
+ beginShape();
780
+ for (let j = 0; j <= 20; j++) {
781
+ const t2 = j / 20;
782
+ const petalAngle = angle + sin(t2 * PI) * 0.5;
783
+ const r = sin(t2 * PI) * maxRadius;
784
+ const x = cx + cos(petalAngle) * r;
785
+ const y = cy + sin(petalAngle) * r;
786
+ vertex(x, y);
787
+ }
788
+ endShape();
789
+ }
790
+ pop();
791
+ `;
792
+ }
793
+ function generateBranchesPrimitive(count, sw, color, alpha) {
794
+ return `
795
+ push();
796
+ noFill();
797
+ strokeWeight(${sw});
798
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
799
+
800
+ function drawBranch(x, y, len, angle, depth) {
801
+ if (depth <= 0 || len < 5) return;
802
+
803
+ const x2 = x + cos(angle) * len;
804
+ const y2 = y + sin(angle) * len;
805
+ line(x, y, x2, y2);
806
+
807
+ const spread = PI * 0.25;
808
+ drawBranch(x2, y2, len * 0.7, angle - spread + noise(depth, t) * 0.3, depth - 1);
809
+ drawBranch(x2, y2, len * 0.7, angle + spread + noise(depth + 50, t) * 0.3, depth - 1);
810
+ }
811
+
812
+ const startX = width / 2;
813
+ const startY = height * 0.85;
814
+ const branchLen = height * 0.15;
815
+ const maxDepth = min(${Math.ceil(Math.log2(count) + 2)}, 7);
816
+
817
+ drawBranch(startX, startY, branchLen, -HALF_PI, maxDepth);
818
+ pop();
819
+ `;
820
+ }
821
+ function generateWeavePrimitive(count, sw, speed, color, alpha) {
822
+ return `
823
+ push();
824
+ noFill();
825
+ strokeWeight(${sw});
826
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
827
+
828
+ const margin = width * 0.1;
829
+ const spacing = (width - margin * 2) / ${count};
830
+
831
+ for (let i = 0; i < ${count}; i++) {
832
+ const x = margin + i * spacing;
833
+ const phase = i * 0.4 + t * TWO_PI * ${speed};
834
+
835
+ beginShape();
836
+ for (let y = margin; y <= height - margin; y += 4) {
837
+ const wave = sin((y / height) * PI * 4 + phase) * spacing * 0.4;
838
+ vertex(x + wave, y);
839
+ }
840
+ endShape();
841
+ }
842
+
843
+ for (let j = 0; j < ${count}; j++) {
844
+ const y = margin + j * spacing * (height / width);
845
+ const phase = j * 0.4 + t * TWO_PI * ${speed} + PI;
846
+
847
+ beginShape();
848
+ for (let x = margin; x <= width - margin; x += 4) {
849
+ const wave = sin((x / width) * PI * 4 + phase) * spacing * 0.4;
850
+ vertex(x, y + wave);
851
+ }
852
+ endShape();
853
+ }
854
+ pop();
855
+ `;
856
+ }
857
+ function generateMoirePrimitive(count, sw, speed, color, alpha) {
858
+ return `
859
+ push();
860
+ noFill();
861
+ strokeWeight(${sw * 0.5});
862
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha * 0.6});
863
+
864
+ const cx = width / 2;
865
+ const cy = height / 2;
866
+ const maxRadius = min(width, height) * 0.5;
867
+ const rings = ${count * 2};
868
+
869
+ for (let i = 0; i < rings; i++) {
870
+ const radius = (i / rings) * maxRadius;
871
+ ellipse(cx, cy, radius * 2);
872
+ }
873
+
874
+ const offset = sin(t * TWO_PI * ${speed}) * 30;
875
+ for (let i = 0; i < rings; i++) {
876
+ const radius = (i / rings) * maxRadius;
877
+ ellipse(cx + offset, cy, radius * 2);
878
+ }
879
+ pop();
880
+ `;
881
+ }
882
+ function generateRadialLinesPrimitive(count, sw, speed, color, alpha) {
883
+ return `
884
+ push();
885
+ noFill();
886
+ strokeWeight(${sw});
887
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
888
+
889
+ const cx = width / 2;
890
+ const cy = height / 2;
891
+ const innerRadius = min(width, height) * 0.1;
892
+ const outerRadius = min(width, height) * 0.45;
893
+
894
+ for (let i = 0; i < ${count * 3}; i++) {
895
+ const angle = (i / ${count * 3}) * TWO_PI + t * ${speed};
896
+ const r1 = innerRadius + noise(i * 0.2, t) * 20;
897
+ const r2 = outerRadius - noise(i * 0.2 + 50, t) * 40;
898
+
899
+ const x1 = cx + cos(angle) * r1;
900
+ const y1 = cy + sin(angle) * r1;
901
+ const x2 = cx + cos(angle) * r2;
902
+ const y2 = cy + sin(angle) * r2;
903
+
904
+ line(x1, y1, x2, y2);
905
+ }
906
+ pop();
907
+ `;
908
+ }
909
+ function generateConcentricSquaresPrimitive(count, sw, speed, color, alpha) {
910
+ return `
911
+ push();
912
+ rectMode(CENTER);
913
+ noFill();
914
+ strokeWeight(${sw});
915
+ stroke(red('${color}'), green('${color}'), blue('${color}'), ${alpha});
916
+
917
+ const cx = width / 2;
918
+ const cy = height / 2;
919
+ const maxSize = min(width, height) * 0.8;
920
+
921
+ for (let i = 0; i < ${count}; i++) {
922
+ const size = maxSize * ((i + 1) / ${count});
923
+ const rotation = (i * 0.05) + t * ${speed} * (i % 2 === 0 ? 1 : -1);
924
+
925
+ push();
926
+ translate(cx, cy);
927
+ rotate(rotation);
928
+ rect(0, 0, size, size);
929
+ pop();
930
+ }
931
+ pop();
932
+ `;
933
+ }
@@ -1,17 +1,30 @@
1
1
  /**
2
- * @nexart/ui-renderer v0.3.0 - Code Mode Renderer
2
+ * @nexart/ui-renderer v0.6.0 - Code Mode Renderer
3
3
  *
4
- * Renders Code Mode systems using the canonical NexArt p5-like runtime.
5
- * This uses the exact same execution logic as nexart.xyz for determinism.
4
+ * ╔══════════════════════════════════════════════════════════════════════════╗
5
+ * ║ PREVIEW RENDERER MIRRORS @nexart/codemode-sdk BEHAVIOR ║
6
+ * ║ ║
7
+ * ║ This file is a MIRROR, not an authority. ║
8
+ * ║ ║
9
+ * ║ Authority: @nexart/codemode-sdk (Protocol v1.0.0) ║
10
+ * ╚══════════════════════════════════════════════════════════════════════════╝
11
+ *
12
+ * ARCHITECTURAL NOTE:
13
+ * -------------------
14
+ * Live preview animation requires local p5 runtime execution because:
15
+ * - @nexart/codemode-sdk.executeCodeMode() returns blobs (PNG/MP4), not frames
16
+ * - Real-time animation in the browser requires frame-by-frame canvas updates
17
+ * - The SDK's loop mode produces video files, not real-time rendering
18
+ *
19
+ * To ensure faithful mirroring, this renderer:
20
+ * 1. Uses identical forbidden pattern validation as the SDK
21
+ * 2. Uses identical VAR handling (read-only, 0-10 input → 10 runtime, 0-100 strict, errors not clamps)
22
+ * 3. Uses identical seeded RNG (Mulberry32) and Perlin noise
23
+ * 4. Uses identical time variable semantics (frameCount, t, time, tGlobal)
24
+ *
25
+ * For archival/canonical output, use @nexart/codemode-sdk directly.
6
26
  */
7
27
  import type { NexArtCodeSystem, PreviewOptions } from '../types';
8
- interface P5Runtime {
9
- [key: string]: any;
10
- width: number;
11
- height: number;
12
- frameCount: number;
13
- }
14
- export declare function createP5Runtime(canvas: HTMLCanvasElement, width: number, height: number, seed: number): P5Runtime;
15
28
  export interface CodeRenderer {
16
29
  render: () => void;
17
30
  start: () => void;
@@ -20,6 +33,14 @@ export interface CodeRenderer {
20
33
  isCanonical: false;
21
34
  isArchival: false;
22
35
  }
36
+ interface P5Runtime {
37
+ [key: string]: any;
38
+ width: number;
39
+ height: number;
40
+ frameCount: number;
41
+ VAR: readonly number[];
42
+ }
43
+ export declare function createP5Runtime(canvas: HTMLCanvasElement, width: number, height: number, seed: number, vars?: number[]): P5Runtime;
23
44
  export declare function renderCodeModeSystem(system: NexArtCodeSystem, canvas: HTMLCanvasElement, options?: PreviewOptions): CodeRenderer;
24
45
  export {};
25
46
  //# sourceMappingURL=code-renderer.d.ts.map