p5 2.3.0 → 2.3.1-rc.1

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.
Files changed (103) hide show
  1. package/README.md +3 -11
  2. package/dist/accessibility/color_namer.js +7 -7
  3. package/dist/accessibility/index.js +7 -7
  4. package/dist/app.js +7 -7
  5. package/dist/app.node.js +7 -7
  6. package/dist/color/color_conversion.js +7 -7
  7. package/dist/color/creating_reading.js +1 -1
  8. package/dist/color/index.js +2 -2
  9. package/dist/color/p5.Color.js +1 -1
  10. package/dist/color/setting.js +2 -2
  11. package/dist/{constants-Dv6ZqA6s.js → constants-Bx3_xAam.js} +1 -1
  12. package/dist/core/constants.js +1 -1
  13. package/dist/core/environment.js +1 -1
  14. package/dist/core/filterShaders.js +1 -1
  15. package/dist/core/friendly_errors/fes_core.js +1 -1
  16. package/dist/core/friendly_errors/file_errors.js +1 -1
  17. package/dist/core/friendly_errors/index.js +1 -1
  18. package/dist/core/friendly_errors/param_validator.js +1 -1
  19. package/dist/core/friendly_errors/sketch_verifier.js +1 -1
  20. package/dist/core/helpers.js +1 -1
  21. package/dist/core/init.js +7 -7
  22. package/dist/core/internationalization.js +1 -1
  23. package/dist/core/legacy.js +7 -7
  24. package/dist/core/main.js +7 -7
  25. package/dist/core/p5.Graphics.js +4 -4
  26. package/dist/core/p5.Renderer.js +3 -3
  27. package/dist/core/p5.Renderer2D.js +7 -7
  28. package/dist/core/p5.Renderer3D.js +4 -4
  29. package/dist/core/rendering.js +4 -4
  30. package/dist/{creating_reading-DLkHH80h.js → creating_reading-YUSK33h8.js} +8 -0
  31. package/dist/dom/dom.js +2 -2
  32. package/dist/dom/index.js +2 -2
  33. package/dist/dom/p5.Element.js +2 -2
  34. package/dist/dom/p5.MediaElement.js +2 -2
  35. package/dist/events/pointer.js +15 -0
  36. package/dist/image/const.js +1 -1
  37. package/dist/image/filterRenderer2D.js +6 -6
  38. package/dist/image/image.js +4 -4
  39. package/dist/image/index.js +4 -4
  40. package/dist/image/loading_displaying.js +4 -4
  41. package/dist/image/p5.Image.js +3 -3
  42. package/dist/io/files.js +4 -4
  43. package/dist/io/index.js +4 -4
  44. package/dist/{ir_builders-C8mrXj5z.js → ir_builders-CMXkjMoV.js} +34 -24
  45. package/dist/{main-BR2ALC_6.js → main-BpW7VbDr.js} +39 -208
  46. package/dist/math/Matrices/Matrix.js +1 -1
  47. package/dist/math/Matrices/MatrixNumjs.js +1 -1
  48. package/dist/math/calculation.js +669 -84
  49. package/dist/math/index.js +1 -1
  50. package/dist/math/p5.Matrix.js +1 -1
  51. package/dist/math/p5.Vector.js +9 -1
  52. package/dist/math/patch-vector.js +3 -1
  53. package/dist/math/trigonometry.js +399 -48
  54. package/dist/{p5.Renderer-XOvhEbJn.js → p5.Renderer-op0Y1WO6.js} +2 -2
  55. package/dist/{rendering-C5lX6zKm.js → rendering-SZ71KIDM.js} +24 -9
  56. package/dist/shape/2d_primitives.js +1 -1
  57. package/dist/shape/attributes.js +4 -3
  58. package/dist/shape/custom_shapes.js +205 -3
  59. package/dist/shape/index.js +2 -2
  60. package/dist/strands/ir_builders.js +1 -1
  61. package/dist/strands/p5.strands.js +26 -9
  62. package/dist/strands/strands_FES.js +8 -1
  63. package/dist/strands/strands_api.js +316 -21
  64. package/dist/strands/strands_conditionals.js +1 -1
  65. package/dist/strands/strands_for.js +1 -1
  66. package/dist/strands/strands_node.js +1 -1
  67. package/dist/strands/strands_ternary.js +1 -1
  68. package/dist/{strands_glslBackend-D6G3UyCs.js → strands_glslBackend-DMhOnoGl.js} +2 -2
  69. package/dist/type/index.js +3 -3
  70. package/dist/type/p5.Font.js +13 -4
  71. package/dist/type/textCore.js +3 -3
  72. package/dist/webgl/3d_primitives.js +4 -4
  73. package/dist/webgl/GeometryBuilder.js +1 -1
  74. package/dist/webgl/ShapeBuilder.js +1 -1
  75. package/dist/webgl/enums.js +1 -1
  76. package/dist/webgl/index.js +6 -6
  77. package/dist/webgl/interaction.js +1 -1
  78. package/dist/webgl/light.js +4 -4
  79. package/dist/webgl/loading.js +4 -4
  80. package/dist/webgl/material.js +4 -4
  81. package/dist/webgl/p5.Camera.js +4 -4
  82. package/dist/webgl/p5.Framebuffer.js +4 -4
  83. package/dist/webgl/p5.Geometry.js +1 -1
  84. package/dist/webgl/p5.Quat.js +1 -1
  85. package/dist/webgl/p5.RendererGL.js +6 -6
  86. package/dist/webgl/p5.Shader.js +5 -1
  87. package/dist/webgl/p5.Texture.js +4 -4
  88. package/dist/webgl/strands_glslBackend.js +2 -2
  89. package/dist/webgl/text.js +4 -4
  90. package/dist/webgl/utils.js +4 -4
  91. package/dist/webgpu/index.js +2 -2
  92. package/dist/webgpu/p5.RendererWebGPU.js +2 -2
  93. package/dist/webgpu/strands_wgslBackend.js +2 -2
  94. package/lib/p5.esm.js +1765 -405
  95. package/lib/p5.esm.min.js +1 -1
  96. package/lib/p5.js +1765 -405
  97. package/lib/p5.min.js +1 -1
  98. package/lib/p5.webgpu.esm.js +34 -3
  99. package/lib/p5.webgpu.js +34 -3
  100. package/lib/p5.webgpu.min.js +1 -1
  101. package/package.json +1 -1
  102. package/types/global.d.ts +5539 -2604
  103. package/types/p5.d.ts +2917 -1432
@@ -1,4 +1,4 @@
1
- import { u as unaryOpNode, c as createStrandsNode, S as StrandsNode, p as primitiveConstructorNode, v as variableNode, b as binaryOpNode, a as statementNode, f as functionCallNode, d as structInstanceNode, e as structConstructorNode } from '../ir_builders-C8mrXj5z.js';
1
+ import { u as unaryOpNode, c as createStrandsNode, S as StrandsNode, p as primitiveConstructorNode, v as variableNode, a as structInstanceNode, b as structConstructorNode, d as binaryOpNode, e as statementNode, f as functionCallNode } from '../ir_builders-CMXkjMoV.js';
2
2
  import { OperatorTable, StatementType, NodeType, DataType, BaseType, BlockType, isStructType, structType, HOOK_PARAM_PREFIX } from './ir_types.js';
3
3
  import { strandsBuiltinFunctions } from './strands_builtins.js';
4
4
  import { StrandsConditional } from './strands_conditionals.js';
@@ -6,7 +6,7 @@ import { StrandsFor } from './strands_for.js';
6
6
  import { buildTernary } from './strands_ternary.js';
7
7
  import { createBasicBlock, addEdge, pushBlock, recordInBasicBlock, popBlock } from './ir_cfg.js';
8
8
  import { createNodeData, getOrCreateNode, getNodeDataFromID } from './ir_dag.js';
9
- import { userError } from './strands_FES.js';
9
+ import { userError, dimensionMismatchError } from './strands_FES.js';
10
10
  import './strands_phi_utils.js';
11
11
 
12
12
  const BUILTIN_GLOBAL_SPECS = {
@@ -89,19 +89,116 @@ function installBuiltinGlobalAccessors(strandsContext) {
89
89
 
90
90
  for (const name of Object.keys(BUILTIN_GLOBAL_SPECS)) {
91
91
  const spec = BUILTIN_GLOBAL_SPECS[name];
92
- Object.defineProperty(window, name, {
93
- get: () => {
92
+ const backingKey = `_strands_${name}`;
93
+
94
+ // Define on window for global mode only
95
+ const inst = getRuntimeP5Instance();
96
+ if (inst?._isGlobal) {
97
+ Object.defineProperty(window, name, {
98
+ get: () => {
99
+ if (strandsContext.active) {
100
+ return getBuiltinGlobalNode(strandsContext, name);
101
+ }
102
+ const inst = getRuntimeP5Instance();
103
+ return spec.get(inst);
104
+ },
105
+ configurable: true,
106
+ });
107
+ }
108
+
109
+ // Capture original descriptor (held in closure for the getter to delegate to)
110
+ const originalProtoDesc = Object.getOwnPropertyDescriptor(strandsContext.p5.prototype, name);
111
+
112
+ // Define on p5.prototype for instance mode
113
+ Object.defineProperty(strandsContext.p5.prototype, name, {
114
+ get: function() {
94
115
  if (strandsContext.active) {
95
116
  return getBuiltinGlobalNode(strandsContext, name);
96
117
  }
97
- const inst = getRuntimeP5Instance();
98
- return spec.get(inst);
118
+ // If our setter stored a value on this instance, return it
119
+ if (Object.prototype.hasOwnProperty.call(this, backingKey)) {
120
+ return this[backingKey];
121
+ }
122
+ // Delegate to original getter (e.g. width -> this._renderer?.width)
123
+ if (originalProtoDesc?.get) {
124
+ return originalProtoDesc.get.call(this);
125
+ }
126
+ // Fall back to original value for data properties (like mouseX)
127
+ return originalProtoDesc?.value;
99
128
  },
129
+ set: function(val) {
130
+ this[backingKey] = val;
131
+ },
132
+ configurable: true,
100
133
  });
134
+
135
+ // Define on p5.Graphics.prototype for graphics mode
136
+ const GraphicsProto = strandsContext.p5?.Graphics?.prototype;
137
+ if (GraphicsProto) {
138
+ const originalDesc = Object.getOwnPropertyDescriptor(GraphicsProto, name);
139
+
140
+ Object.defineProperty(GraphicsProto, name, {
141
+ get: function() {
142
+ if (strandsContext.active) {
143
+ return getBuiltinGlobalNode(strandsContext, name);
144
+ }
145
+ // Delegate to original getter if it exists (class-level getters like width, deltaTime)
146
+ if (originalDesc?.get) {
147
+ return originalDesc.get.call(this);
148
+ }
149
+ return this[backingKey];
150
+ },
151
+ set: function(val) {
152
+ if (originalDesc?.set) {
153
+ originalDesc.set.call(this, val);
154
+ } else {
155
+ this[backingKey] = val;
156
+ }
157
+ },
158
+ configurable: true,
159
+ });
160
+ }
101
161
  }
102
162
  strandsContext._builtinGlobalsAccessorsInstalled = true;
103
163
  }
104
164
 
165
+ function installInstanceIndexAccessor(strandsContext) {
166
+ if (strandsContext._instanceIndexAccessorInstalled) return;
167
+
168
+ const getRuntimeP5Instance = () => strandsContext.renderer?._pInst || strandsContext.p5?.instance;
169
+
170
+ const instanceIndexGetter = function() {
171
+ if (strandsContext.active) {
172
+ const node = variableNode(strandsContext, { baseType: BaseType.INT, dimension: 1 }, strandsContext.backend.instanceIdReference());
173
+ return createStrandsNode(node.id, node.dimension, strandsContext);
174
+ }
175
+ return undefined;
176
+ };
177
+
178
+ const inst = getRuntimeP5Instance();
179
+ if (inst?._isGlobal) {
180
+ Object.defineProperty(window, 'instanceIndex', {
181
+ get: instanceIndexGetter,
182
+ configurable: true,
183
+ });
184
+ }
185
+
186
+ Object.defineProperty(strandsContext.p5.prototype, 'instanceIndex', {
187
+ get: instanceIndexGetter,
188
+ configurable: true,
189
+ });
190
+
191
+ const GraphicsProto = strandsContext.p5?.Graphics?.prototype;
192
+ if (GraphicsProto) {
193
+ Object.defineProperty(GraphicsProto, 'instanceIndex', {
194
+ get: instanceIndexGetter,
195
+ configurable: true,
196
+ });
197
+ }
198
+
199
+ strandsContext._instanceIndexAccessorInstalled = true;
200
+ }
201
+
105
202
  //////////////////////////////////////////////
106
203
  // Prototype mirroring helpers
107
204
  //////////////////////////////////////////////
@@ -275,7 +372,7 @@ function initGlobalStrandsAPI(p5, fn, strandsContext) {
275
372
  const originalLerp = fn.lerp;
276
373
  augmentFn(fn, p5, 'lerp', function (...args) {
277
374
  if (strandsContext.active) {
278
- return fn.mix(...args);
375
+ return this.mix(...args);
279
376
  } else {
280
377
  return originalLerp.apply(this, args);
281
378
  }
@@ -298,6 +395,139 @@ function initGlobalStrandsAPI(p5, fn, strandsContext) {
298
395
  return result;
299
396
  });
300
397
 
398
+ const originalColor = fn.color;
399
+ augmentFn(fn, p5, 'color', function (...args) {
400
+ if (!strandsContext.active) {
401
+ return originalColor.apply(this, args);
402
+ }
403
+ // Reuse p5's parser - handles hex strings, rgb(), CSS named colors, numerics
404
+ const c = originalColor.apply(this, args);
405
+ // _getRGBA() returns [r, g, b, a] normalized to 0-1
406
+ const rgba = c._getRGBA();
407
+ const { id, dimension } = primitiveConstructorNode(
408
+ strandsContext,
409
+ { baseType: BaseType.FLOAT, dimension: null },
410
+ rgba
411
+ );
412
+ return createStrandsNode(id, dimension, strandsContext);
413
+ });
414
+ const originalLerpColor = fn.lerpColor;
415
+ augmentFn(fn, p5, 'lerpColor', function (...args) {
416
+ if (!strandsContext.active) {
417
+ return originalLerpColor.apply(this, args);
418
+ }
419
+ // In strands, colors are vec4s - lerpColor maps directly to GLSL mix()
420
+ return this.mix(...args);
421
+ });
422
+ // Component accessors: extract scalar channels from a vec4 color
423
+ const originalRed = fn.red;
424
+ augmentFn(fn, p5, 'red', function (...args) {
425
+ if (!strandsContext.active) {
426
+ return originalRed.apply(this, args);
427
+ }
428
+ return p5.strandsNode(args[0]).x;
429
+ });
430
+
431
+ const originalGreen = fn.green;
432
+ augmentFn(fn, p5, 'green', function (...args) {
433
+ if (!strandsContext.active) {
434
+ return originalGreen.apply(this, args);
435
+ }
436
+ return p5.strandsNode(args[0]).y;
437
+ });
438
+
439
+ const originalBlue = fn.blue;
440
+ augmentFn(fn, p5, 'blue', function (...args) {
441
+ if (!strandsContext.active) {
442
+ return originalBlue.apply(this, args);
443
+ }
444
+ return p5.strandsNode(args[0]).z;
445
+ });
446
+
447
+ const originalAlpha = fn.alpha;
448
+ augmentFn(fn, p5, 'alpha', function (...args) {
449
+ if (!strandsContext.active) {
450
+ return originalAlpha.apply(this, args);
451
+ }
452
+ return p5.strandsNode(args[0]).w;
453
+ });
454
+
455
+ // RGB to HSB conversion based on:
456
+ // https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB
457
+ // Using mix/step to avoid branching, via the compact form from:
458
+ // http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
459
+ const _rgb2hsb = (instance, colorNode) => {
460
+ const r = colorNode.x;
461
+ const g = colorNode.y;
462
+ const b = colorNode.z;
463
+ const K = instance.vec4(0, -1/3, 2/3, -1);
464
+ const p = instance.mix(
465
+ instance.vec4(b, g, K.w, K.z),
466
+ instance.vec4(g, b, K.x, K.y),
467
+ instance.step(b, g)
468
+ );
469
+ const q = instance.mix(
470
+ instance.vec4(p.x, p.y, p.w, r),
471
+ instance.vec4(r, p.y, p.z, p.x),
472
+ instance.step(p.x, r)
473
+ );
474
+ const d = q.x.sub(instance.min(q.w, q.y));
475
+ const e = p5.strandsNode(1e-10);
476
+ const h = instance.abs(q.z.add(q.w.sub(q.y).div(d.mult(6).add(e))));
477
+ const s = d.div(q.x.add(e));
478
+ return instance.vec3(h, s, q.x);
479
+ };
480
+
481
+ const _rgb2hsl = (instance, colorNode) => {
482
+ const r = colorNode.x;
483
+ const g = colorNode.y;
484
+ const b = colorNode.z;
485
+ const maxC = instance.max(r, instance.max(g, b));
486
+ const minC = instance.min(r, instance.min(g, b));
487
+ const l = maxC.add(minC).div(2);
488
+ const d = maxC.sub(minC);
489
+ const e = p5.strandsNode(1e-10);
490
+ const s = instance.mix(
491
+ p5.strandsNode(0),
492
+ d.div(p5.strandsNode(1).sub(instance.abs(l.mult(2).sub(1)))),
493
+ instance.step(e, d)
494
+ );
495
+ const h_rg = instance.mod(g.sub(b).div(d.add(e)), p5.strandsNode(6)).div(6);
496
+ const h_gb = b.sub(r).div(d.add(e)).add(2).div(6);
497
+ const h_br = r.sub(g).div(d.add(e)).add(4).div(6);
498
+ const isR = instance.step(maxC.sub(e), r).mult(instance.step(r.sub(e), maxC));
499
+ const isG = instance.step(maxC.sub(e), g).mult(instance.step(g.sub(e), maxC));
500
+ const h = instance.mix(instance.mix(h_br, h_gb, isG), h_rg, isR);
501
+ return instance.vec3(h, s, l);
502
+ };
503
+ const originalHue = fn.hue;
504
+ augmentFn(fn, p5, 'hue', function (...args) {
505
+ if (!strandsContext.active) return originalHue.apply(this, args);
506
+ const colorNode = p5.strandsNode(args[0]);
507
+ return _rgb2hsl(this, this.vec3(colorNode.x, colorNode.y, colorNode.z)).x;
508
+ });
509
+
510
+ const originalSaturation = fn.saturation;
511
+ augmentFn(fn, p5, 'saturation', function (...args) {
512
+ if (!strandsContext.active) return originalSaturation.apply(this, args);
513
+ const colorNode = p5.strandsNode(args[0]);
514
+ return _rgb2hsl(this, this.vec3(colorNode.x, colorNode.y, colorNode.z)).y;
515
+ });
516
+
517
+ const originalBrightness = fn.brightness;
518
+ augmentFn(fn, p5, 'brightness', function (...args) {
519
+ if (!strandsContext.active) return originalBrightness.apply(this, args);
520
+ const colorNode = p5.strandsNode(args[0]);
521
+ return _rgb2hsb(this, this.vec3(colorNode.x, colorNode.y, colorNode.z)).z;
522
+ });
523
+
524
+ const originalLightness = fn.lightness;
525
+ augmentFn(fn, p5, 'lightness', function (...args) {
526
+ if (!strandsContext.active) return originalLightness.apply(this, args);
527
+ const colorNode = p5.strandsNode(args[0]);
528
+ return _rgb2hsl(this, this.vec3(colorNode.x, colorNode.y, colorNode.z)).z;
529
+ });
530
+
301
531
  augmentFn(fn, p5, 'getTexture', function (...rawArgs) {
302
532
  if (strandsContext.active) {
303
533
  const { id, dimension } = strandsContext.backend.createGetTextureCall(strandsContext, rawArgs);
@@ -323,6 +553,7 @@ function initGlobalStrandsAPI(p5, fn, strandsContext) {
323
553
  const originalNoise = fn.noise;
324
554
  const originalNoiseDetail = fn.noiseDetail;
325
555
  const originalRandom = fn.random;
556
+ const originalRandomGaussian=fn.randomGaussian;
326
557
  const originalRandomSeed = fn.randomSeed;
327
558
  const originalMillis = fn.millis;
328
559
 
@@ -466,6 +697,20 @@ function initGlobalStrandsAPI(p5, fn, strandsContext) {
466
697
  }
467
698
  });
468
699
 
700
+ augmentFn(fn, p5, 'randomGaussian', function(...args){
701
+ if(!strandsContext.active){
702
+ return originalRandomGaussian.apply(this, args);
703
+ }
704
+ const mean = args.length >= 1 ? args[0] : 0;
705
+ const stdDev = args.length >= 2 ? args[1] : 1;
706
+
707
+ const u1 = this.max(this.random(), 1e-6);
708
+ const u2 = this.random();
709
+ const z = this.sqrt(this.log(u1).mult(-2)).mult(this.cos(u2.mult(2*Math.PI)));
710
+
711
+ return z.mult(stdDev).add(mean);
712
+ });
713
+
469
714
  augmentFn(fn, p5, 'millis', function (...args) {
470
715
  if (!strandsContext.active) {
471
716
  return originalMillis.apply(this, args);
@@ -657,6 +902,17 @@ function createHookArguments(strandsContext, parameters){
657
902
  return createStrandsNode(propNode.id, propNode.dimension, strandsContext, onRebind);
658
903
  },
659
904
  set(val) {
905
+ const valDim = val?.isStrandsNode
906
+ ? val.dimension
907
+ : (Array.isArray(val) ? val.length : 1);
908
+ if( valDim !== propertyType.dataType.dimension && valDim !== 1){
909
+ dimensionMismatchError(
910
+ propertyType.dataType.dimension,
911
+ valDim,
912
+ `${param.name}.${propertyType.name}`
913
+ );
914
+ }
915
+
660
916
  const oldDependsOn = dag.dependsOn[structNode.id];
661
917
  const newDependsOn = [...oldDependsOn];
662
918
  let newValueID;
@@ -734,6 +990,7 @@ function enforceReturnTypeMatch(strandsContext, expectedType, returned, hookName
734
990
  }
735
991
  function createShaderHooksFunctions(strandsContext, fn, shader) {
736
992
  installBuiltinGlobalAccessors(strandsContext);
993
+ installInstanceIndexAccessor(strandsContext);
737
994
 
738
995
  // Add shader context to hooks before spreading
739
996
  const vertexHooksWithContext = Object.fromEntries(
@@ -766,6 +1023,54 @@ function createShaderHooksFunctions(strandsContext, fn, shader) {
766
1023
  hook.set = function(result) {
767
1024
  hook._result = result;
768
1025
  };
1026
+ hook._active = false;
1027
+
1028
+ const numStructArgs = hookType.parameters.filter(
1029
+ param => param.type && param.type.properties
1030
+ ).length;
1031
+ let argIdx = -1;
1032
+ if (numStructArgs === 1) {
1033
+ argIdx = hookType.parameters.findIndex(
1034
+ param => param.type && param.type.properties
1035
+ );
1036
+ }
1037
+ if (argIdx >= 0) {
1038
+ const structParam = hookType.parameters[argIdx];
1039
+ if (structParam.type.properties) {
1040
+ const nameMatch = /^get([A-Z0-9]\w*)$/.exec(hookType.name);
1041
+ const displayName = nameMatch
1042
+ ? nameMatch[1][0].toLowerCase() + nameMatch[1].slice(1)
1043
+ : hookType.name;
1044
+ for (const prop of structParam.type.properties) {
1045
+ const key = prop.name;
1046
+ Object.defineProperty(hook, key, {
1047
+ get() {
1048
+ if (!this._active) {
1049
+ userError(
1050
+ 'scope error',
1051
+ `It looks like you're trying to access "${displayName}.${key}" outside of its begin()/end() block.\n\n` +
1052
+ `Properties of ${displayName} are only available between ` +
1053
+ `${displayName}.begin() and ${displayName}.end().\n\n` +
1054
+ `To share data between hooks, use sharedVec3() or sharedFloat() ` +
1055
+ `to pass values between them.`
1056
+ );
1057
+ }
1058
+ return this._args[this._argIdx][key];
1059
+ },
1060
+ set(val) {
1061
+ if (!this._active) {
1062
+ userError(
1063
+ 'scope error',
1064
+ `It looks like you're trying to set "${displayName}.${key}" outside of its begin()/end() block.`
1065
+ );
1066
+ }
1067
+ this._args[this._argIdx][key] = val;
1068
+ },
1069
+ enumerable: true,
1070
+ });
1071
+ }
1072
+ }
1073
+ }
769
1074
 
770
1075
  let entryBlockID;
771
1076
  function setupHook() {
@@ -774,25 +1079,14 @@ function createShaderHooksFunctions(strandsContext, fn, shader) {
774
1079
  addEdge(cfg, cfg.currentBlock, entryBlockID);
775
1080
  pushBlock(cfg, entryBlockID);
776
1081
  const args = createHookArguments(strandsContext, hookType.parameters);
777
- const numStructArgs = hookType.parameters.filter(param => param.type.properties).length;
778
- let argIdx = -1;
779
- if (numStructArgs === 1) {
780
- argIdx = hookType.parameters.findIndex(param => param.type.properties);
781
- }
1082
+ hook._active = true;
1083
+ hook._args = args;
1084
+ hook._argIdx = argIdx;
782
1085
  hook._properties = [];
783
1086
  for (let i = 0; i < args.length; i++) {
784
1087
  if (i === argIdx) {
785
1088
  for (const key of args[argIdx].structProperties || []) {
786
1089
  hook._properties.push(key);
787
- Object.defineProperty(hook, key, {
788
- get() {
789
- return args[argIdx][key];
790
- },
791
- set(val) {
792
- args[argIdx][key] = val;
793
- },
794
- enumerable: true,
795
- });
796
1090
  }
797
1091
  if (hookType.returnType?.typeName === hookType.parameters[argIdx].type.typeName) {
798
1092
  hook.set(args[argIdx]);
@@ -805,6 +1099,7 @@ function createShaderHooksFunctions(strandsContext, fn, shader) {
805
1099
  return args;
806
1100
  }
807
1101
  function finishHook() {
1102
+ hook._active = false;
808
1103
  const userReturned = hook._result;
809
1104
  strandsContext.activeHook = undefined;
810
1105
 
@@ -1,7 +1,7 @@
1
1
  import { createBasicBlock, addEdge, pushBlock, popBlock, pushBlockForModification, recordInBasicBlock } from './ir_cfg.js';
2
2
  import { getOrCreateNode } from './ir_dag.js';
3
3
  import { BlockType, NodeType } from './ir_types.js';
4
- import { c as createStrandsNode } from '../ir_builders-C8mrXj5z.js';
4
+ import { c as createStrandsNode } from '../ir_builders-CMXkjMoV.js';
5
5
  import { createPhiNode } from './strands_phi_utils.js';
6
6
  import './strands_FES.js';
7
7
  import './strands_builtins.js';
@@ -1,7 +1,7 @@
1
1
  import { createBasicBlock, addEdge, pushBlock, popBlock, pushBlockForModification, recordInBasicBlock } from './ir_cfg.js';
2
2
  import { getNodeDataFromID, createNodeData, getOrCreateNode } from './ir_dag.js';
3
3
  import { BlockType, NodeType, StatementType, OpCode, BaseType } from './ir_types.js';
4
- import { c as createStrandsNode, p as primitiveConstructorNode } from '../ir_builders-C8mrXj5z.js';
4
+ import { c as createStrandsNode, p as primitiveConstructorNode } from '../ir_builders-CMXkjMoV.js';
5
5
  import { createPhiNode } from './strands_phi_utils.js';
6
6
  import './strands_FES.js';
7
7
  import './strands_builtins.js';
@@ -1,4 +1,4 @@
1
- export { S as StrandsNode, c as createStrandsNode } from '../ir_builders-C8mrXj5z.js';
1
+ export { S as StrandsNode, c as createStrandsNode } from '../ir_builders-CMXkjMoV.js';
2
2
  import './ir_types.js';
3
3
  import './ir_dag.js';
4
4
  import './ir_cfg.js';
@@ -1,7 +1,7 @@
1
1
  import { extractNodeTypeInfo, propagateTypeToAssignOnUse, createNodeData, getOrCreateNode } from './ir_dag.js';
2
2
  import { recordInBasicBlock } from './ir_cfg.js';
3
3
  import { BaseType, OpCode, NodeType } from './ir_types.js';
4
- import { c as createStrandsNode } from '../ir_builders-C8mrXj5z.js';
4
+ import { c as createStrandsNode } from '../ir_builders-CMXkjMoV.js';
5
5
  import { userError } from './strands_FES.js';
6
6
  import './strands_builtins.js';
7
7
 
@@ -1,7 +1,7 @@
1
1
  import { INSTANCE_ID_VARYING_NAME, NodeTypeToName, NodeType, OpCode, BaseType, OpCodeToSymbol, isStructType, StatementType, HOOK_PARAM_PREFIX, DataType, BlockType } from './strands/ir_types.js';
2
2
  import { getNodeDataFromID, extractNodeTypeInfo } from './strands/ir_dag.js';
3
3
  import { internalError } from './strands/strands_FES.js';
4
- import { f as functionCallNode } from './ir_builders-C8mrXj5z.js';
4
+ import { f as functionCallNode } from './ir_builders-CMXkjMoV.js';
5
5
 
6
6
  var noiseGLSL = "// Based on https://github.com/stegu/webgl-noise/blob/22434e04d7753f7e949e8d724ab3da2864c17a0f/src/noise3D.glsl\n// MIT licensed, adapted for p5.strands\n\nvec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n\nvec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n\nvec4 permute(vec4 x) {\n return mod289(((x*34.0)+10.0)*x);\n}\n\nvec4 taylorInvSqrt(vec4 r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nfloat baseNoise(vec3 v)\n{\n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n // First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n // Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n // Permutations\n i = mod289(i);\n vec4 p = permute( permute( permute(\n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))\n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n // Gradients: 7x7 points over a square, mapped onto an octahedron.\n // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n //Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n // Mix final noise value\n vec4 m = max(0.5 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 105.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),\n dot(p2,x2), dot(p3,x3) ) );\n}\n\nfloat noise(vec3 st, int octaves, float ampFalloff) {\n float result = 0.0;\n float amplitude = 1.0;\n float frequency = 1.0;\n\n for (int i = 0; i < 8; i++) {\n if (i >= octaves) break;\n result += amplitude * baseNoise(st * frequency);\n frequency *= 2.0;\n amplitude *= ampFalloff;\n }\n return (result + 1.0) * 0.5;\n}\n";
7
7
 
@@ -253,7 +253,7 @@ const glslBackend = {
253
253
  }
254
254
  const dag = strandsContext.dag;
255
255
  const rootNode = getNodeDataFromID(dag, rootNodeID);
256
- if (isStructType(returnType)) {
256
+ if (isStructType(returnType) && rootNode.identifier) {
257
257
  const structTypeInfo = returnType;
258
258
  for (let i = 0; i < structTypeInfo.properties.length; i++) {
259
259
  const prop = structTypeInfo.properties[i];
@@ -1,10 +1,10 @@
1
1
  import textCore from './textCore.js';
2
2
  import font from './p5.Font.js';
3
- import '../p5.Renderer-XOvhEbJn.js';
4
- import '../creating_reading-DLkHH80h.js';
3
+ import '../p5.Renderer-op0Y1WO6.js';
4
+ import '../creating_reading-YUSK33h8.js';
5
5
  import 'colorjs.io/fn';
6
6
  import '../color/color_spaces/hsb.js';
7
- import '../constants-Dv6ZqA6s.js';
7
+ import '../constants-Bx3_xAam.js';
8
8
  import '../image/filters.js';
9
9
  import '../math/p5.Vector.js';
10
10
  import '../shape/custom_shapes.js';
@@ -1,12 +1,12 @@
1
1
  import { textCoreConstants } from './textCore.js';
2
- import { t as CENTER, aa as RIGHT, s as RADIUS } from '../constants-Dv6ZqA6s.js';
2
+ import { t as CENTER, aa as RIGHT, s as RADIUS } from '../constants-Bx3_xAam.js';
3
3
  import { UnicodeRange } from '@japont/unicode-range';
4
4
  import { unicodeRanges } from './unicodeRanges.js';
5
5
  import { Vector } from '../math/p5.Vector.js';
6
6
  import Typr from './lib/Typr.js';
7
7
  import { createFromCommands } from '@davepagurek/bezier-path';
8
- import '../p5.Renderer-XOvhEbJn.js';
9
- import '../creating_reading-DLkHH80h.js';
8
+ import '../p5.Renderer-op0Y1WO6.js';
9
+ import '../creating_reading-YUSK33h8.js';
10
10
  import 'colorjs.io/fn';
11
11
  import '../color/color_spaces/hsb.js';
12
12
  import '../image/filters.js';
@@ -266,7 +266,7 @@ class Font {
266
266
  * coordinates of the bounding box's bottom-left corner. See
267
267
  * <a href="#/p5/textAlign">textAlign()</a> for more ways to align text.
268
268
  *
269
- * The fourth parameter, `options`, is also optional. `font.textToPoints()`
269
+ * The fourth parameter, `options`, is also optional. `font.textToContours()`
270
270
  * expects an object with the following properties:
271
271
  *
272
272
  * `sampleFactor` is the ratio of the text's path length to the number of
@@ -349,6 +349,15 @@ class Font {
349
349
  *
350
350
  * The generated model (a Geometry object) can be manipulated further—rotated, scaled,
351
351
  * or styled with shaders—to create engaging, interactive visual art.
352
+ *
353
+ * The `options` parameter is also optional. `font.textToModel()` expects an object
354
+ * with the following properties:
355
+ *
356
+ * `extrude` is the depth to extrude the text. It defaults to 0. A value of 0 produces
357
+ * flat text; higher values create thicker, 3D models.
358
+ *
359
+ * `sampleFactor` is a factor controlling the level of detail for the text contours.
360
+ * It defaults to 1. Higher values result in smoother curves.
352
361
  *
353
362
  * @param {String} str The text string to convert into a 3D model.
354
363
  * @param {Number} x The x-coordinate for the starting position of the text.
@@ -1,8 +1,8 @@
1
- import { R as Renderer } from '../p5.Renderer-XOvhEbJn.js';
2
- import '../creating_reading-DLkHH80h.js';
1
+ import { R as Renderer } from '../p5.Renderer-op0Y1WO6.js';
2
+ import '../creating_reading-YUSK33h8.js';
3
3
  import 'colorjs.io/fn';
4
4
  import '../color/color_spaces/hsb.js';
5
- import '../constants-Dv6ZqA6s.js';
5
+ import '../constants-Bx3_xAam.js';
6
6
  import '../image/filters.js';
7
7
  import '../math/p5.Vector.js';
8
8
  import '../shape/custom_shapes.js';
@@ -1,17 +1,17 @@
1
- import '../constants-Dv6ZqA6s.js';
2
- export { p as default } from '../rendering-C5lX6zKm.js';
1
+ import '../constants-Bx3_xAam.js';
2
+ export { p as default } from '../rendering-SZ71KIDM.js';
3
3
  import '../math/p5.Vector.js';
4
4
  import './p5.Geometry.js';
5
5
  import '../math/p5.Matrix.js';
6
6
  import '../math/Matrices/Matrix.js';
7
- import '../creating_reading-DLkHH80h.js';
7
+ import '../creating_reading-YUSK33h8.js';
8
8
  import 'colorjs.io/fn';
9
9
  import '../color/color_spaces/hsb.js';
10
10
  import '../strands/ir_types.js';
11
11
  import '../dom/p5.Element.js';
12
12
  import '../dom/p5.File.js';
13
13
  import '../io/p5.XML.js';
14
- import '../p5.Renderer-XOvhEbJn.js';
14
+ import '../p5.Renderer-op0Y1WO6.js';
15
15
  import '../image/filters.js';
16
16
  import '../shape/custom_shapes.js';
17
17
  import '../core/States.js';
@@ -1,4 +1,4 @@
1
- import { T as TRIANGLE_STRIP, Y as QUAD_STRIP, X as TRIANGLE_FAN, c as TRIANGLES } from '../constants-Dv6ZqA6s.js';
1
+ import { T as TRIANGLE_STRIP, Y as QUAD_STRIP, X as TRIANGLE_FAN, c as TRIANGLES } from '../constants-Bx3_xAam.js';
2
2
  import '../math/p5.Matrix.js';
3
3
  import { Geometry } from './p5.Geometry.js';
4
4
  import { Matrix } from '../math/Matrices/Matrix.js';
@@ -1,4 +1,4 @@
1
- import { z as PATH, V as QUADS, Y as QUAD_STRIP, T as TRIANGLE_STRIP, c as TRIANGLES, ae as IMAGE, Q as LINES, X as TRIANGLE_FAN } from '../constants-Dv6ZqA6s.js';
1
+ import { z as PATH, V as QUADS, Y as QUAD_STRIP, T as TRIANGLE_STRIP, c as TRIANGLES, ae as IMAGE, Q as LINES, X as TRIANGLE_FAN } from '../constants-Bx3_xAam.js';
2
2
  import { Geometry } from './p5.Geometry.js';
3
3
  import libtess from 'libtess';
4
4
  import { Vector } from '../math/p5.Vector.js';
@@ -1,4 +1,4 @@
1
- import { am as constants } from '../constants-Dv6ZqA6s.js';
1
+ import { am as constants } from '../constants-Bx3_xAam.js';
2
2
 
3
3
  function getStrokeDefs(shaderConstant) {
4
4
  const STROKE_CAP_ENUM = {};
@@ -1,4 +1,4 @@
1
- import { r as renderer3D, p as primitives3D, a as light, m as material, c as camera, b as framebuffer, t as texture } from '../rendering-C5lX6zKm.js';
1
+ import { r as renderer3D, p as primitives3D, a as light, m as material, c as camera, b as framebuffer, t as texture } from '../rendering-SZ71KIDM.js';
2
2
  import interaction from './interaction.js';
3
3
  import loading from './loading.js';
4
4
  import text from './text.js';
@@ -8,15 +8,15 @@ import matrix from '../math/p5.Matrix.js';
8
8
  import geometry from './p5.Geometry.js';
9
9
  import dataArray from './p5.DataArray.js';
10
10
  import rendererGL from './p5.RendererGL.js';
11
- import '../constants-Dv6ZqA6s.js';
12
- import '../creating_reading-DLkHH80h.js';
11
+ import '../constants-Bx3_xAam.js';
12
+ import '../creating_reading-YUSK33h8.js';
13
13
  import 'colorjs.io/fn';
14
14
  import '../color/color_spaces/hsb.js';
15
15
  import '../strands/ir_types.js';
16
16
  import '../dom/p5.Element.js';
17
17
  import '../dom/p5.File.js';
18
18
  import '../io/p5.XML.js';
19
- import '../p5.Renderer-XOvhEbJn.js';
19
+ import '../p5.Renderer-op0Y1WO6.js';
20
20
  import '../image/filters.js';
21
21
  import '../math/p5.Vector.js';
22
22
  import '../shape/custom_shapes.js';
@@ -51,10 +51,10 @@ import '../type/unicodeRanges.js';
51
51
  import '../type/lib/Typr.js';
52
52
  import 'pako';
53
53
  import '@davepagurek/bezier-path';
54
- import '../strands_glslBackend-D6G3UyCs.js';
54
+ import '../strands_glslBackend-DMhOnoGl.js';
55
55
  import '../strands/ir_dag.js';
56
56
  import '../strands/strands_FES.js';
57
- import '../ir_builders-C8mrXj5z.js';
57
+ import '../ir_builders-CMXkjMoV.js';
58
58
  import '../strands/ir_cfg.js';
59
59
  import '../strands/strands_builtins.js';
60
60
  import './shaderHookUtils.js';
@@ -1,4 +1,4 @@
1
- import { a5 as GRID, a6 as AXES } from '../constants-Dv6ZqA6s.js';
1
+ import { a5 as GRID, a6 as AXES } from '../constants-Bx3_xAam.js';
2
2
  import { Vector } from '../math/p5.Vector.js';
3
3
 
4
4
  /**