p5 2.2.3 → 2.3.0-rc.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.
Files changed (137) hide show
  1. package/dist/accessibility/color_namer.js +9 -11
  2. package/dist/accessibility/describe.js +0 -1
  3. package/dist/accessibility/gridOutput.js +0 -1
  4. package/dist/accessibility/index.js +9 -10
  5. package/dist/accessibility/outputs.js +0 -1
  6. package/dist/accessibility/textOutput.js +0 -1
  7. package/dist/app.js +11 -10
  8. package/dist/app.node.js +122 -0
  9. package/dist/color/color_conversion.js +9 -11
  10. package/dist/color/creating_reading.js +1 -1
  11. package/dist/color/index.js +2 -2
  12. package/dist/color/p5.Color.js +1 -1
  13. package/dist/color/setting.js +25 -12
  14. package/dist/{constants-BdTiYOQI.js → constants-CYF6mp5_.js} +2 -2
  15. package/dist/core/States.js +1 -1
  16. package/dist/core/constants.js +1 -1
  17. package/dist/core/environment.js +28 -29
  18. package/dist/core/filterShaders.js +1 -1
  19. package/dist/core/friendly_errors/fes_core.js +9 -8
  20. package/dist/core/friendly_errors/file_errors.js +1 -2
  21. package/dist/core/friendly_errors/index.js +1 -1
  22. package/dist/core/friendly_errors/param_validator.js +737 -640
  23. package/dist/core/friendly_errors/sketch_verifier.js +1 -1
  24. package/dist/core/friendly_errors/stacktrace.js +0 -1
  25. package/dist/core/helpers.js +3 -4
  26. package/dist/core/init.js +24 -21
  27. package/dist/core/internationalization.js +1 -1
  28. package/dist/core/legacy.js +9 -11
  29. package/dist/core/main.js +9 -10
  30. package/dist/core/p5.Graphics.js +5 -5
  31. package/dist/core/p5.Renderer.js +3 -3
  32. package/dist/core/p5.Renderer2D.js +9 -10
  33. package/dist/core/p5.Renderer3D.js +5 -5
  34. package/dist/core/rendering.js +5 -5
  35. package/dist/core/structure.js +0 -1
  36. package/dist/core/transform.js +7 -16
  37. package/dist/{creating_reading-C7hu6sg1.js → creating_reading-DLkHH80h.js} +11 -8
  38. package/dist/data/local_storage.js +0 -1
  39. package/dist/dom/dom.js +2 -3
  40. package/dist/dom/index.js +2 -2
  41. package/dist/dom/p5.Element.js +2 -2
  42. package/dist/dom/p5.MediaElement.js +2 -2
  43. package/dist/events/acceleration.js +5 -3
  44. package/dist/events/keyboard.js +0 -1
  45. package/dist/events/pointer.js +0 -2
  46. package/dist/image/const.js +1 -1
  47. package/dist/image/filterRenderer2D.js +19 -12
  48. package/dist/image/image.js +5 -5
  49. package/dist/image/index.js +5 -5
  50. package/dist/image/loading_displaying.js +5 -5
  51. package/dist/image/p5.Image.js +3 -3
  52. package/dist/image/pixels.js +0 -1
  53. package/dist/io/files.js +5 -5
  54. package/dist/io/index.js +5 -5
  55. package/dist/io/p5.Table.js +0 -1
  56. package/dist/io/p5.TableRow.js +0 -1
  57. package/dist/io/p5.XML.js +0 -1
  58. package/dist/{ir_builders-Cd6rU9Vm.js → ir_builders-C2ebb6Lu.js} +234 -1
  59. package/dist/{main-H_nu4eDs.js → main-D2MtO721.js} +107 -136
  60. package/dist/math/Matrices/Matrix.js +1 -1
  61. package/dist/math/Matrices/MatrixNumjs.js +1 -1
  62. package/dist/math/calculation.js +0 -1
  63. package/dist/math/index.js +3 -1
  64. package/dist/math/math.js +3 -17
  65. package/dist/math/noise.js +0 -1
  66. package/dist/math/p5.Matrix.js +1 -2
  67. package/dist/math/p5.Vector.js +233 -279
  68. package/dist/math/patch-vector.js +75 -0
  69. package/dist/math/random.js +0 -1
  70. package/dist/math/trigonometry.js +3 -4
  71. package/dist/{p5.Renderer-BmD2P6Wv.js → p5.Renderer-C0Kzy71d.js} +31 -24
  72. package/dist/{rendering-CC8JNTwG.js → rendering-CvNr0bB8.js} +732 -44
  73. package/dist/shape/2d_primitives.js +1 -4
  74. package/dist/shape/attributes.js +43 -8
  75. package/dist/shape/curves.js +0 -1
  76. package/dist/shape/custom_shapes.js +260 -5
  77. package/dist/shape/index.js +2 -2
  78. package/dist/shape/vertex.js +0 -2
  79. package/dist/strands/ir_builders.js +1 -1
  80. package/dist/strands/ir_types.js +5 -1
  81. package/dist/strands/p5.strands.js +286 -31
  82. package/dist/strands/strands_api.js +179 -8
  83. package/dist/strands/strands_codegen.js +26 -8
  84. package/dist/strands/strands_conditionals.js +1 -1
  85. package/dist/strands/strands_for.js +1 -1
  86. package/dist/strands/strands_node.js +1 -1
  87. package/dist/strands/strands_ternary.js +56 -0
  88. package/dist/strands/strands_transpiler.js +416 -251
  89. package/dist/strands_glslBackend-i-ReKgZo.js +423 -0
  90. package/dist/type/index.js +3 -3
  91. package/dist/type/lib/Typr.js +1 -1
  92. package/dist/type/p5.Font.js +3 -3
  93. package/dist/type/textCore.js +31 -24
  94. package/dist/utilities/conversion.js +0 -1
  95. package/dist/utilities/time_date.js +0 -1
  96. package/dist/utilities/utility_functions.js +0 -1
  97. package/dist/webgl/3d_primitives.js +5 -5
  98. package/dist/webgl/GeometryBuilder.js +1 -1
  99. package/dist/webgl/ShapeBuilder.js +26 -1
  100. package/dist/webgl/enums.js +1 -1
  101. package/dist/webgl/index.js +8 -9
  102. package/dist/webgl/interaction.js +8 -4
  103. package/dist/webgl/light.js +5 -5
  104. package/dist/webgl/loading.js +60 -21
  105. package/dist/webgl/material.js +5 -5
  106. package/dist/webgl/p5.Camera.js +5 -5
  107. package/dist/webgl/p5.Framebuffer.js +5 -5
  108. package/dist/webgl/p5.Geometry.js +3 -5
  109. package/dist/webgl/p5.Quat.js +1 -1
  110. package/dist/webgl/p5.RendererGL.js +17 -21
  111. package/dist/webgl/p5.Shader.js +129 -36
  112. package/dist/webgl/p5.Texture.js +5 -5
  113. package/dist/webgl/strands_glslBackend.js +5 -386
  114. package/dist/webgl/text.js +5 -5
  115. package/dist/webgl/utils.js +5 -5
  116. package/dist/webgl2Compatibility-DA7DLMuq.js +7 -0
  117. package/dist/webgpu/index.js +7 -3
  118. package/dist/webgpu/p5.RendererWebGPU.js +1036 -180
  119. package/dist/webgpu/shaders/color.js +1 -1
  120. package/dist/webgpu/shaders/compute.js +32 -0
  121. package/dist/webgpu/shaders/functions/randomComputeWGSL.js +31 -0
  122. package/dist/webgpu/shaders/functions/randomVertWGSL.js +30 -0
  123. package/dist/webgpu/shaders/functions/randomWGSL.js +30 -0
  124. package/dist/webgpu/shaders/line.js +1 -1
  125. package/dist/webgpu/shaders/material.js +3 -3
  126. package/dist/webgpu/strands_wgslBackend.js +137 -15
  127. package/lib/p5.esm.js +4088 -1950
  128. package/lib/p5.esm.min.js +1 -1
  129. package/lib/p5.js +4088 -1950
  130. package/lib/p5.min.js +1 -1
  131. package/lib/p5.webgpu.esm.js +1638 -306
  132. package/lib/p5.webgpu.js +1637 -305
  133. package/lib/p5.webgpu.min.js +1 -1
  134. package/package.json +6 -1
  135. package/types/global.d.ts +4137 -2396
  136. package/types/p5.d.ts +2702 -1658
  137. package/dist/noise3DGLSL-Bwrdi4gi.js +0 -9
@@ -0,0 +1,423 @@
1
+ import { INSTANCE_ID_VARYING_NAME, NodeTypeToName, NodeType, OpCode, BaseType, OpCodeToSymbol, isStructType, StatementType, DataType, BlockType } from './strands/ir_types.js';
2
+ import { getNodeDataFromID, extractNodeTypeInfo } from './strands/ir_dag.js';
3
+ import { internalError } from './strands/strands_FES.js';
4
+ import { f as functionCallNode } from './ir_builders-C2ebb6Lu.js';
5
+
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
+
8
+ var randomGLSL = "// _p5_hash: \"Hash without Sine\" by Dave Hoskins (https://www.shadertoy.com/view/4djSRW)\n// Mixing constants: R₂ sequence by Martin Roberts (https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/)\n// α₁ = 1/φ₂ = 0.7548776662 (plastic constant reciprocal)\n// α₂ = 1/φ₂² = 0.5698402910\n// 1/φ = 0.6180339887 (golden ratio conjugate)\n\nint _p5_randomCallIndex = 0;\n\nfloat _p5_hash(vec3 p) {\n p = fract(p * vec3(0.1031, 0.1030, 0.0973));\n p += dot(p, p.yxz + 33.33);\n return fract((p.x + p.y) * p.z);\n}\n\nfloat random(float seed) {\n vec2 pixelCoord = gl_FragCoord.xy;\n float callIndex = float(_p5_randomCallIndex);\n _p5_randomCallIndex += 1;\n // fract(seed * α₁) normalizes large seeds (e.g. performance.now()) into [0,1)\n // and spreads them optimally via the R₂ sequence's plastic constant\n float s = fract(seed * 0.7548776662);\n return _p5_hash(vec3(\n pixelCoord.x + s,\n pixelCoord.y + callIndex * 0.5698402910,\n s + callIndex * 0.6180339887\n ));\n}\n";
9
+
10
+ var randomVertGLSL = "// _p5_hash: \"Hash without Sine\" by Dave Hoskins (https://www.shadertoy.com/view/4djSRW)\n// Mixing constants: R₂ sequence by Martin Roberts (https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/)\n// α₁ = 1/φ₂ = 0.7548776662 (plastic constant reciprocal)\n// α₂ = 1/φ₂² = 0.5698402910\n// 1/φ = 0.6180339887 (golden ratio conjugate)\n\nint _p5_randomCallIndex = 0;\n\nfloat _p5_hash(vec3 p) {\n p = fract(p * vec3(0.1031, 0.1030, 0.0973));\n p += dot(p, p.yxz + 33.33);\n return fract((p.x + p.y) * p.z);\n}\n\nfloat random(float seed) {\n float vid = float(gl_VertexID);\n float callIndex = float(_p5_randomCallIndex);\n _p5_randomCallIndex += 1;\n float s = fract(seed * 0.7548776662);\n return _p5_hash(vec3(\n vid + s,\n vid * 0.5698402910 + callIndex * 0.6180339887,\n s + callIndex * 0.7548776662\n ));\n}\n";
11
+
12
+ function shouldCreateTemp(dag, nodeID) {
13
+ const nodeType = dag.nodeTypes[nodeID];
14
+ if (nodeType !== NodeType.OPERATION) return false;
15
+ if (dag.baseTypes[nodeID] === BaseType.SAMPLER2D) return false;
16
+ const uses = dag.usedBy[nodeID] || [];
17
+ return uses.length > 1;
18
+ }
19
+ const TypeNames = {
20
+ 'float1': 'float',
21
+ 'float2': 'vec2',
22
+ 'float3': 'vec3',
23
+ 'float4': 'vec4',
24
+ 'int1': 'int',
25
+ 'int2': 'ivec2',
26
+ 'int3': 'ivec3',
27
+ 'int4': 'ivec4',
28
+ 'bool1': 'bool',
29
+ 'bool2': 'bvec2',
30
+ 'bool3': 'bvec3',
31
+ 'bool4': 'bvec4',
32
+ 'mat2': 'mat2x2',
33
+ 'mat3': 'mat3x3',
34
+ 'mat4': 'mat4x4',
35
+ };
36
+ const cfgHandlers = {
37
+ [BlockType.DEFAULT]: (blockID, strandsContext, generationContext) => {
38
+ const { dag, cfg } = strandsContext;
39
+ const instructions = cfg.blockInstructions[blockID] || [];
40
+ for (const nodeID of instructions) {
41
+ const nodeType = dag.nodeTypes[nodeID];
42
+ if (shouldCreateTemp(dag, nodeID)) {
43
+ const declaration = glslBackend.generateDeclaration(generationContext, dag, nodeID);
44
+ generationContext.write(declaration);
45
+ }
46
+ if (nodeType === NodeType.STATEMENT) {
47
+ glslBackend.generateStatement(generationContext, dag, nodeID);
48
+ }
49
+ if (nodeType === NodeType.ASSIGNMENT) {
50
+ glslBackend.generateAssignment(generationContext, dag, nodeID);
51
+ generationContext.visitedNodes.add(nodeID);
52
+ }
53
+ }
54
+ },
55
+ [BlockType.BRANCH](blockID, strandsContext, generationContext) {
56
+ const { dag, cfg } = strandsContext;
57
+ // Find all phi nodes in this branch block and declare them
58
+ const blockInstructions = cfg.blockInstructions[blockID] || [];
59
+ for (const nodeID of blockInstructions) {
60
+ const node = getNodeDataFromID(dag, nodeID);
61
+ if (node.nodeType === NodeType.PHI) {
62
+ // Check if the phi node's first dependency already has a temp name
63
+ const dependsOn = node.dependsOn || [];
64
+ if (dependsOn.length > 0) {
65
+ const firstDependency = dependsOn[0];
66
+ const existingTempName = generationContext.tempNames[firstDependency];
67
+ if (existingTempName) {
68
+ // Reuse the existing temp name instead of creating a new one
69
+ generationContext.tempNames[nodeID] = existingTempName;
70
+ continue; // Skip declaration, just alias to existing variable
71
+ }
72
+ }
73
+
74
+ // Otherwise, create a new temp variable for the phi node
75
+ const tmp = `T${generationContext.nextTempID++}`;
76
+ generationContext.tempNames[nodeID] = tmp;
77
+ const T = extractNodeTypeInfo(dag, nodeID);
78
+ const typeName = glslBackend.getTypeName(T.baseType, T.dimension);
79
+ generationContext.write(`${typeName} ${tmp};`);
80
+ }
81
+ }
82
+ this[BlockType.DEFAULT](blockID, strandsContext, generationContext);
83
+ },
84
+ [BlockType.IF_COND](blockID, strandsContext, generationContext) {
85
+ const { dag, cfg } = strandsContext;
86
+ const conditionID = cfg.blockConditions[blockID];
87
+ const condExpr = glslBackend.generateExpression(generationContext, dag, conditionID);
88
+ generationContext.write(`if (${condExpr})`);
89
+ this[BlockType.DEFAULT](blockID, strandsContext, generationContext);
90
+ },
91
+ [BlockType.ELSE_COND](blockID, strandsContext, generationContext) {
92
+ generationContext.write(`else`);
93
+ this[BlockType.DEFAULT](blockID, strandsContext, generationContext);
94
+ },
95
+ [BlockType.IF_BODY](blockID, strandsContext, generationContext) {
96
+ this[BlockType.DEFAULT](blockID, strandsContext, generationContext);
97
+ this.assignPhiNodeValues(blockID, strandsContext, generationContext);
98
+ },
99
+ [BlockType.SCOPE_START](blockID, strandsContext, generationContext) {
100
+ generationContext.write(`{`);
101
+ generationContext.indent++;
102
+ },
103
+ [BlockType.SCOPE_END](blockID, strandsContext, generationContext) {
104
+ generationContext.indent--;
105
+ generationContext.write(`}`);
106
+ },
107
+ [BlockType.MERGE](blockID, strandsContext, generationContext) {
108
+ this[BlockType.DEFAULT](blockID, strandsContext, generationContext);
109
+ },
110
+ [BlockType.FUNCTION](blockID, strandsContext, generationContext) {
111
+ this[BlockType.DEFAULT](blockID, strandsContext, generationContext);
112
+ },
113
+ [BlockType.FOR](blockID, strandsContext, generationContext) {
114
+ const { dag, cfg } = strandsContext;
115
+ const instructions = cfg.blockInstructions[blockID] || [];
116
+
117
+ generationContext.write(`for (`);
118
+
119
+ // Set flag to suppress semicolon on the last statement
120
+ const originalSuppressSemicolon = generationContext.suppressSemicolon;
121
+
122
+ for (let i = 0; i < instructions.length; i++) {
123
+ const nodeID = instructions[i];
124
+ const node = getNodeDataFromID(dag, nodeID);
125
+ const isLast = i === instructions.length - 1;
126
+
127
+ // Suppress semicolon on the last statement
128
+ generationContext.suppressSemicolon = isLast;
129
+
130
+ if (shouldCreateTemp(dag, nodeID)) {
131
+ const declaration = glslBackend.generateDeclaration(generationContext, dag, nodeID);
132
+ generationContext.write(declaration);
133
+ }
134
+ if (node.nodeType === NodeType.STATEMENT) {
135
+ glslBackend.generateStatement(generationContext, dag, nodeID);
136
+ }
137
+ if (node.nodeType === NodeType.ASSIGNMENT) {
138
+ glslBackend.generateAssignment(generationContext, dag, nodeID);
139
+ generationContext.visitedNodes.add(nodeID);
140
+ }
141
+ }
142
+
143
+ // Restore original flag
144
+ generationContext.suppressSemicolon = originalSuppressSemicolon;
145
+
146
+ generationContext.write(`)`);
147
+ },
148
+ assignPhiNodeValues(blockID, strandsContext, generationContext) {
149
+ const { dag, cfg } = strandsContext;
150
+ // Find all phi nodes that this block feeds into
151
+ const successors = cfg.outgoingEdges[blockID] || [];
152
+ for (const successorBlockID of successors) {
153
+ const instructions = cfg.blockInstructions[successorBlockID] || [];
154
+ for (const nodeID of instructions) {
155
+ const node = getNodeDataFromID(dag, nodeID);
156
+ if (node.nodeType === NodeType.PHI) {
157
+ // Find which input of this phi node corresponds to our block
158
+ const branchIndex = node.phiBlocks?.indexOf(blockID);
159
+ if (branchIndex !== -1 && branchIndex < node.dependsOn.length) {
160
+ const sourceNodeID = node.dependsOn[branchIndex];
161
+ const tempName = generationContext.tempNames[nodeID];
162
+ if (tempName && sourceNodeID !== null) {
163
+ const sourceExpr = glslBackend.generateExpression(generationContext, dag, sourceNodeID);
164
+ generationContext.write(`${tempName} = ${sourceExpr};`);
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+ },
171
+ };
172
+ const glslBackend = {
173
+ hookEntry(hookType) {
174
+ const firstLine = `(${hookType.parameters.flatMap((param) => {
175
+ return `${param.qualifiers?.length ? param.qualifiers.join(' ') : ''}${param.type.typeName} ${param.name}`;
176
+ }).join(', ')}) {`;
177
+ return firstLine;
178
+ },
179
+ getNoiseShaderSnippet() {
180
+ return noiseGLSL;
181
+ },
182
+ getRandomFragmentShaderSnippet() {
183
+ return randomGLSL;
184
+ },
185
+ getRandomVertexShaderSnippet() {
186
+ return randomVertGLSL;
187
+ },
188
+ getTypeName(baseType, dimension) {
189
+ const primitiveTypeName = TypeNames[baseType + dimension];
190
+ if (!primitiveTypeName) {
191
+ return baseType;
192
+ }
193
+ return primitiveTypeName;
194
+ },
195
+ generateHookUniformKey(name, typeInfo) {
196
+ return `${this.getTypeName(typeInfo.baseType, typeInfo.dimension)} ${name}`;
197
+ },
198
+ generateVaryingVariable(varName, typeInfo) {
199
+ return `${typeInfo.fnName} ${varName}`;
200
+ },
201
+ generateLocalDeclaration(varName, typeInfo) {
202
+ const typeName = typeInfo.fnName;
203
+ return `${typeName} ${varName};`;
204
+ },
205
+ generateStatement(generationContext, dag, nodeID) {
206
+ const node = getNodeDataFromID(dag, nodeID);
207
+ // Generate the expression followed by semicolon (unless suppressed)
208
+ const semicolon = generationContext.suppressSemicolon ? '' : ';';
209
+ if (node.statementType === StatementType.DISCARD) {
210
+ generationContext.write(`discard${semicolon}`);
211
+ } else if (node.statementType === StatementType.BREAK) {
212
+ generationContext.write(`break${semicolon}`);
213
+ } else if (node.statementType === StatementType.EXPRESSION) {
214
+ const exprNodeID = node.dependsOn[0];
215
+ const expr = this.generateExpression(generationContext, dag, exprNodeID);
216
+ generationContext.write(`${expr}${semicolon}`);
217
+ } else if (node.statementType === StatementType.EMPTY) {
218
+ generationContext.write(semicolon);
219
+ } else if (node.statementType === StatementType.EARLY_RETURN) {
220
+ const exprNodeID = node.dependsOn[0];
221
+ const expr = this.generateExpression(generationContext, dag, exprNodeID);
222
+ generationContext.write(`return ${expr}${semicolon}`);
223
+ }
224
+ },
225
+ generateAssignment(generationContext, dag, nodeID) {
226
+ const node = getNodeDataFromID(dag, nodeID);
227
+ // dependsOn[0] = targetNodeID, dependsOn[1] = sourceNodeID
228
+ const targetNodeID = node.dependsOn[0];
229
+ const sourceNodeID = node.dependsOn[1];
230
+
231
+ // Generate the target expression (could be variable or swizzle)
232
+ const targetExpr = this.generateExpression(generationContext, dag, targetNodeID);
233
+ const sourceExpr = this.generateExpression(generationContext, dag, sourceNodeID);
234
+ const semicolon = generationContext.suppressSemicolon ? '' : ';';
235
+
236
+ // Generate assignment if we have both target and source
237
+ if (targetExpr && sourceExpr && targetExpr !== sourceExpr) {
238
+ generationContext.write(`${targetExpr} = ${sourceExpr}${semicolon}`);
239
+ }
240
+ },
241
+ generateDeclaration(generationContext, dag, nodeID) {
242
+ const expr = this.generateExpression(generationContext, dag, nodeID);
243
+ const tmp = `T${generationContext.nextTempID++}`;
244
+ generationContext.tempNames[nodeID] = tmp;
245
+ const T = extractNodeTypeInfo(dag, nodeID);
246
+ const typeName = this.getTypeName(T.baseType, T.dimension);
247
+ return `${typeName} ${tmp} = ${expr};`;
248
+ },
249
+ generateReturnStatement(strandsContext, generationContext, rootNodeID, returnType) {
250
+ if (!returnType) {
251
+ generationContext.write('return;');
252
+ return;
253
+ }
254
+ const dag = strandsContext.dag;
255
+ const rootNode = getNodeDataFromID(dag, rootNodeID);
256
+ if (isStructType(returnType)) {
257
+ const structTypeInfo = returnType;
258
+ for (let i = 0; i < structTypeInfo.properties.length; i++) {
259
+ const prop = structTypeInfo.properties[i];
260
+ const val = this.generateExpression(generationContext, dag, rootNode.dependsOn[i]);
261
+ if (prop.name !== val) {
262
+ generationContext.write(
263
+ `${rootNode.identifier}.${prop.name} = ${val};`
264
+ );
265
+ }
266
+ }
267
+ }
268
+ generationContext.write(`return ${this.generateExpression(generationContext, dag, rootNodeID)};`);
269
+ },
270
+ generateExpression(generationContext, dag, nodeID) {
271
+ const node = getNodeDataFromID(dag, nodeID);
272
+ if (generationContext.tempNames?.[nodeID]) {
273
+ return generationContext.tempNames[nodeID];
274
+ }
275
+ switch (node.nodeType) {
276
+ case NodeType.LITERAL:
277
+ if (node.baseType === BaseType.FLOAT) {
278
+ return node.value.toFixed(4);
279
+ }
280
+ else {
281
+ return node.value;
282
+ }
283
+ case NodeType.VARIABLE:
284
+ // Track shared variable usage context
285
+ if (generationContext.shaderContext && generationContext.strandsContext?.sharedVariables?.has(node.identifier)) {
286
+ const sharedVar = generationContext.strandsContext.sharedVariables.get(node.identifier);
287
+ if (generationContext.shaderContext === 'vertex') {
288
+ sharedVar.usedInVertex = true;
289
+ } else if (generationContext.shaderContext === 'fragment') {
290
+ sharedVar.usedInFragment = true;
291
+ }
292
+ }
293
+
294
+ // Detect instanceID usage in fragment context and rewrite to varying name
295
+ if (node.identifier === this.instanceIdReference() && generationContext.shaderContext === 'fragment') {
296
+ generationContext.strandsContext._instanceIDUsedInFragment = true;
297
+ return INSTANCE_ID_VARYING_NAME;
298
+ }
299
+
300
+ return node.identifier;
301
+ case NodeType.OPERATION:
302
+ const useParantheses = node.usedBy.length > 0;
303
+ if (node.opCode === OpCode.Nary.CONSTRUCTOR) {
304
+ // TODO: differentiate casts and constructors for more efficient codegen.
305
+ // if (node.dependsOn.length === 1 && node.dimension === 1) {
306
+ // return this.generateExpression(generationContext, dag, node.dependsOn[0]);
307
+ // }
308
+ if (node.baseType === BaseType.SAMPLER2D) {
309
+ return this.generateExpression(generationContext, dag, node.dependsOn[0]);
310
+ }
311
+ const T = this.getTypeName(node.baseType, node.dimension);
312
+ const deps = node.dependsOn.map((dep) => this.generateExpression(generationContext, dag, dep));
313
+ return `${T}(${deps.join(', ')})`;
314
+ }
315
+ if (node.opCode === OpCode.Nary.FUNCTION_CALL) {
316
+ const functionArgs = node.dependsOn.map(arg =>this.generateExpression(generationContext, dag, arg));
317
+ return `${node.identifier}(${functionArgs.join(', ')})`;
318
+ }
319
+ if (node.opCode === OpCode.Nary.TERNARY) {
320
+ const [condID, trueID, falseID] = node.dependsOn;
321
+ const cond = this.generateExpression(generationContext, dag, condID);
322
+ const trueExpr = this.generateExpression(generationContext, dag, trueID);
323
+ const falseExpr = this.generateExpression(generationContext, dag, falseID);
324
+ return `(${cond} ? ${trueExpr} : ${falseExpr})`;
325
+ }
326
+ if (node.opCode === OpCode.Binary.MEMBER_ACCESS) {
327
+ const [lID, rID] = node.dependsOn;
328
+ const lName = this.generateExpression(generationContext, dag, lID);
329
+ const rName = this.generateExpression(generationContext, dag, rID);
330
+ return `${lName}.${rName}`;
331
+ }
332
+ if (node.opCode === OpCode.Unary.SWIZZLE) {
333
+ const parentID = node.dependsOn[0];
334
+ const parentExpr = this.generateExpression(generationContext, dag, parentID);
335
+ return `${parentExpr}.${node.swizzle}`;
336
+ }
337
+ if (node.dependsOn.length === 2) {
338
+ const [lID, rID] = node.dependsOn;
339
+ const left = this.generateExpression(generationContext, dag, lID);
340
+ const right = this.generateExpression(generationContext, dag, rID);
341
+
342
+ // Special case for modulo: use mod() function for floats in GLSL
343
+ if (node.opCode === OpCode.Binary.MODULO) {
344
+ const leftNode = getNodeDataFromID(dag, lID);
345
+ const rightNode = getNodeDataFromID(dag, rID);
346
+ // If either operand is float, use mod() function
347
+ if (leftNode.baseType === BaseType.FLOAT || rightNode.baseType === BaseType.FLOAT) {
348
+ return `mod(${left}, ${right})`;
349
+ }
350
+ // For integers, use % operator
351
+ return `(${left} % ${right})`;
352
+ }
353
+
354
+ const opSym = OpCodeToSymbol[node.opCode];
355
+ if (useParantheses) {
356
+ return `(${left} ${opSym} ${right})`;
357
+ } else {
358
+ return `${left} ${opSym} ${right}`;
359
+ }
360
+ }
361
+ if (node.opCode === OpCode.Unary.LOGICAL_NOT
362
+ || node.opCode === OpCode.Unary.NEGATE
363
+ || node.opCode === OpCode.Unary.PLUS
364
+ ) {
365
+ const [i] = node.dependsOn;
366
+ const val = this.generateExpression(generationContext, dag, i);
367
+ const sym = OpCodeToSymbol[node.opCode];
368
+ return `${sym}${val}`;
369
+ }
370
+ case NodeType.PHI:
371
+ // Phi nodes represent conditional merging of values
372
+ // If this phi node has an identifier (like varying variables), use that
373
+ if (node.identifier) {
374
+ return node.identifier;
375
+ }
376
+ // Otherwise, they should have been declared as temporary variables
377
+ // and assigned in the appropriate branches
378
+ if (generationContext.tempNames?.[nodeID]) {
379
+ return generationContext.tempNames[nodeID];
380
+ } else {
381
+ // If no temp was created, this phi node only has one input
382
+ // so we can just use that directly
383
+ const validInputs = node.dependsOn.filter(id => id !== null);
384
+ if (validInputs.length > 0) {
385
+ return this.generateExpression(generationContext, dag, validInputs[0]);
386
+ } else {
387
+ throw new Error(`No valid inputs for node`)
388
+ }
389
+ }
390
+ case NodeType.ASSIGNMENT:
391
+ internalError(`ASSIGNMENT nodes should not be used as expressions`);
392
+ default:
393
+ internalError(`${NodeTypeToName[node.nodeType]} code generation not implemented yet`);
394
+ }
395
+ },
396
+ generateBlock(blockID, strandsContext, generationContext) {
397
+ const type = strandsContext.cfg.blockTypes[blockID];
398
+ const handler = cfgHandlers[type] || cfgHandlers[BlockType.DEFAULT];
399
+ handler.call(cfgHandlers, blockID, strandsContext, generationContext);
400
+ },
401
+
402
+ createGetTextureCall(strandsContext, args) {
403
+ // In GLSL, getTexture is straightforward - just pass through the args
404
+ // First argument should be a texture (sampler2D), second should be coordinates
405
+ const { id, dimension } = functionCallNode(strandsContext, 'getTexture', args, {
406
+ overloads: [{
407
+ params: [DataType.sampler2D, DataType.float2],
408
+ returnType: DataType.float4
409
+ }]
410
+ });
411
+ return { id, dimension };
412
+ },
413
+
414
+ instanceIdReference() {
415
+ return 'gl_InstanceID';
416
+ },
417
+
418
+ generateInstanceIDVarying() {
419
+ return { name: INSTANCE_ID_VARYING_NAME, declaration: `int ${INSTANCE_ID_VARYING_NAME}`, source: 'gl_InstanceID', interpolation: 'flat' };
420
+ },
421
+ };
422
+
423
+ export { randomVertGLSL as a, glslBackend as g, randomGLSL as r };
@@ -1,10 +1,10 @@
1
1
  import textCore from './textCore.js';
2
2
  import font from './p5.Font.js';
3
- import '../p5.Renderer-BmD2P6Wv.js';
4
- import '../creating_reading-C7hu6sg1.js';
3
+ import '../p5.Renderer-C0Kzy71d.js';
4
+ import '../creating_reading-DLkHH80h.js';
5
5
  import 'colorjs.io/fn';
6
6
  import '../color/color_spaces/hsb.js';
7
- import '../constants-BdTiYOQI.js';
7
+ import '../constants-CYF6mp5_.js';
8
8
  import '../image/filters.js';
9
9
  import '../math/p5.Vector.js';
10
10
  import '../shape/custom_shapes.js';
@@ -324,7 +324,7 @@ Typr["B"] = {
324
324
  }
325
325
  return s;
326
326
  },
327
- _tdec: window["TextDecoder"] ? new window["TextDecoder"]() : null,
327
+ _tdec: globalThis["TextDecoder"] ? new globalThis["TextDecoder"]() : null,
328
328
  readUTF8: function (buff, p, l) {
329
329
  var tdec = Typr["B"]._tdec;
330
330
  if (tdec && p == 0 && l == buff.length) return tdec["decode"](buff);
@@ -1,12 +1,12 @@
1
1
  import { textCoreConstants } from './textCore.js';
2
- import { v as CENTER, a9 as RIGHT, u as RADIUS } from '../constants-BdTiYOQI.js';
2
+ import { t as CENTER, aa as RIGHT, s as RADIUS } from '../constants-CYF6mp5_.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-BmD2P6Wv.js';
9
- import '../creating_reading-C7hu6sg1.js';
8
+ import '../p5.Renderer-C0Kzy71d.js';
9
+ import '../creating_reading-DLkHH80h.js';
10
10
  import 'colorjs.io/fn';
11
11
  import '../color/color_spaces/hsb.js';
12
12
  import '../image/filters.js';
@@ -1,8 +1,8 @@
1
- import { R as Renderer } from '../p5.Renderer-BmD2P6Wv.js';
2
- import '../creating_reading-C7hu6sg1.js';
1
+ import { R as Renderer } from '../p5.Renderer-C0Kzy71d.js';
2
+ import '../creating_reading-DLkHH80h.js';
3
3
  import 'colorjs.io/fn';
4
4
  import '../color/color_spaces/hsb.js';
5
- import '../constants-BdTiYOQI.js';
5
+ import '../constants-CYF6mp5_.js';
6
6
  import '../image/filters.js';
7
7
  import '../math/p5.Vector.js';
8
8
  import '../shape/custom_shapes.js';
@@ -11,7 +11,6 @@ import '../io/utilities.js';
11
11
 
12
12
  /**
13
13
  * @module Typography
14
- * @requires core
15
14
  */
16
15
 
17
16
 
@@ -1469,22 +1468,37 @@ function textCore(p5, fn) {
1469
1468
 
1470
1469
  Renderer.prototype.textAlign = function (h, v) {
1471
1470
 
1472
- // the setter
1473
- if (typeof h !== 'undefined') {
1471
+ if (arguments.length === 0) { // the getter
1472
+ return {
1473
+ horizontal: this.states.textAlign,
1474
+ vertical: this.states.textBaseline
1475
+ };
1476
+ }
1477
+
1478
+ // allow an object with horizontal and vertical properties
1479
+ if (typeof h === 'object' && h !== null) {
1480
+ if (h.hasOwnProperty('vertical')) {
1481
+ v = h.vertical;
1482
+ }
1483
+ if (h.hasOwnProperty('horizontal')) {
1484
+ h = h.horizontal;
1485
+ }
1486
+ }
1487
+
1488
+ // horizontal value as separate argument
1489
+ if (typeof h === 'string' || h instanceof String) {
1474
1490
  this.states.setValue('textAlign', h);
1475
- if (typeof v !== 'undefined') {
1476
- if (v === fn.CENTER) {
1477
- v = textCoreConstants._CTX_MIDDLE;
1478
- }
1479
- this.states.setValue('textBaseline', v);
1491
+ }
1492
+
1493
+ // vertical value as separate argument
1494
+ if (typeof v === 'string' || v instanceof String) {
1495
+ if (v === fn.CENTER) {
1496
+ v = textCoreConstants._CTX_MIDDLE;
1480
1497
  }
1481
- return this._applyTextProperties();
1498
+ this.states.setValue('textBaseline', v);
1482
1499
  }
1483
- // the getter
1484
- return {
1485
- horizontal: this.states.textAlign,
1486
- vertical: this.states.textBaseline
1487
- };
1500
+
1501
+ return this._applyTextProperties();
1488
1502
  };
1489
1503
 
1490
1504
  Renderer.prototype._currentTextFont = function () {
@@ -1583,13 +1597,6 @@ function textCore(p5, fn) {
1583
1597
  if (typeof weight === 'number') {
1584
1598
  this.states.setValue('fontWeight', weight);
1585
1599
  this._applyTextProperties();
1586
-
1587
- // Safari works without weight set in the canvas style attribute, and actually
1588
- // has buggy behavior if it is present, using the wrong weight when drawing
1589
- // multiple times with different weights
1590
- if (!p5.prototype._isSafari()) {
1591
- this._setCanvasStyleProperty('font-variation-settings', `"wght" ${weight}`);
1592
- }
1593
1600
  return;
1594
1601
  }
1595
1602
  // the getter
@@ -2,7 +2,6 @@
2
2
  * @module Data
3
3
  * @submodule Conversion
4
4
  * @for p5
5
- * @requires core
6
5
  */
7
6
 
8
7
  function conversion(p5, fn){
@@ -2,7 +2,6 @@
2
2
  * @module IO
3
3
  * @submodule Time & Date
4
4
  * @for p5
5
- * @requires core
6
5
  */
7
6
 
8
7
  function timeDate(p5, fn){
@@ -2,7 +2,6 @@
2
2
  * @module Data
3
3
  * @submodule Utility Functions
4
4
  * @for p5
5
- * @requires core
6
5
  */
7
6
 
8
7
  function utilityFunctions(p5, fn){
@@ -1,16 +1,17 @@
1
- import '../constants-BdTiYOQI.js';
2
- export { p as default } from '../rendering-CC8JNTwG.js';
1
+ import '../constants-CYF6mp5_.js';
2
+ export { p as default } from '../rendering-CvNr0bB8.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-C7hu6sg1.js';
7
+ import '../creating_reading-DLkHH80h.js';
8
8
  import 'colorjs.io/fn';
9
9
  import '../color/color_spaces/hsb.js';
10
+ import '../strands/ir_types.js';
10
11
  import '../dom/p5.Element.js';
11
12
  import '../dom/p5.File.js';
12
13
  import '../io/p5.XML.js';
13
- import '../p5.Renderer-BmD2P6Wv.js';
14
+ import '../p5.Renderer-C0Kzy71d.js';
14
15
  import '../image/filters.js';
15
16
  import '../shape/custom_shapes.js';
16
17
  import '../core/States.js';
@@ -24,7 +25,6 @@ import '../shape/vertex.js';
24
25
  import '../color/setting.js';
25
26
  import 'omggif';
26
27
  import '../io/csv.js';
27
- import 'gifenc';
28
28
  import '../image/pixels.js';
29
29
  import '../core/transform.js';
30
30
  import './GeometryBuilder.js';
@@ -1,4 +1,4 @@
1
- import { T as TRIANGLE_STRIP, $ as QUAD_STRIP, _ as TRIANGLE_FAN, c as TRIANGLES } from '../constants-BdTiYOQI.js';
1
+ import { T as TRIANGLE_STRIP, Y as QUAD_STRIP, X as TRIANGLE_FAN, c as TRIANGLES } from '../constants-CYF6mp5_.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 { K as PATH, Z as QUADS, $ as QUAD_STRIP, T as TRIANGLE_STRIP, c as TRIANGLES, ad as IMAGE, Y as LINES, _ as TRIANGLE_FAN } from '../constants-BdTiYOQI.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-CYF6mp5_.js';
2
2
  import { Geometry } from './p5.Geometry.js';
3
3
  import libtess from 'libtess';
4
4
  import { Vector } from '../math/p5.Vector.js';
@@ -47,6 +47,10 @@ class ShapeBuilder {
47
47
  this.bufferStrides = { ...INITIAL_BUFFER_STRIDES };
48
48
  }
49
49
 
50
+ friendlyErrorsDisabled() {
51
+ return false;
52
+ }
53
+
50
54
  constructFromContours(shape, contours) {
51
55
  if (this._useUserVertexProperties){
52
56
  this._resetUserVertexProperties();
@@ -150,6 +154,27 @@ class ShapeBuilder {
150
154
  }
151
155
 
152
156
  if (this.shapeMode === PATH) {
157
+ const vertexCount = this.geometry.vertices.length;
158
+ const MAX_SAFE_TESSELLATION_VERTICES = 50000;
159
+
160
+ if (
161
+ vertexCount > MAX_SAFE_TESSELLATION_VERTICES &&
162
+ !this.friendlyErrorsDisabled() &&
163
+ !this.renderer._largeTessellationAcknowledged
164
+ ) {
165
+ const proceed = window.confirm(
166
+ '🌸 p5.js says:\n\n' +
167
+ `This shape has ${vertexCount} vertices. Tessellating shapes with this ` +
168
+ 'many vertices can be very slow and may cause your browser to become ' +
169
+ 'unresponsive.\n\n' +
170
+ 'Do you want to continue tessellating this shape?'
171
+ );
172
+ if (!proceed) {
173
+ return;
174
+ }
175
+ this.renderer._largeTessellationAcknowledged = true;
176
+ }
177
+
153
178
  this.isProcessingVertices = true;
154
179
  this._tesselateShape();
155
180
  this.isProcessingVertices = false;
@@ -1,4 +1,4 @@
1
- import { a3 as constants } from '../constants-BdTiYOQI.js';
1
+ import { am as constants } from '../constants-CYF6mp5_.js';
2
2
 
3
3
  function getStrokeDefs(shaderConstant) {
4
4
  const STROKE_CAP_ENUM = {};