glre 0.38.0 → 0.40.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 (295) hide show
  1. package/README.md +8 -4
  2. package/dist/addons.cjs +2 -0
  3. package/dist/addons.cjs.map +1 -0
  4. package/dist/addons.d.ts +1287 -0
  5. package/dist/addons.js +2 -0
  6. package/dist/addons.js.map +1 -0
  7. package/dist/index.cjs +31 -43
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.ts +187 -323
  10. package/dist/index.js +31 -43
  11. package/dist/index.js.map +1 -1
  12. package/dist/native.cjs +1 -48
  13. package/dist/native.cjs.map +1 -1
  14. package/dist/native.d.ts +536 -10
  15. package/dist/native.js +1 -48
  16. package/dist/native.js.map +1 -1
  17. package/dist/node.cjs +69 -0
  18. package/dist/node.cjs.map +1 -0
  19. package/dist/node.d.ts +626 -0
  20. package/dist/node.js +69 -0
  21. package/dist/node.js.map +1 -0
  22. package/dist/react.cjs +1 -48
  23. package/dist/react.cjs.map +1 -1
  24. package/dist/react.d.ts +524 -4
  25. package/dist/react.js +1 -48
  26. package/dist/react.js.map +1 -1
  27. package/dist/solid.cjs +1 -48
  28. package/dist/solid.cjs.map +1 -1
  29. package/dist/solid.d.ts +524 -4
  30. package/dist/solid.js +1 -48
  31. package/dist/solid.js.map +1 -1
  32. package/package.json +64 -11
  33. package/src/addons/animation/easing/backIn.ts +10 -0
  34. package/src/addons/animation/easing/backInOut.ts +12 -0
  35. package/src/addons/animation/easing/backOut.ts +10 -0
  36. package/src/addons/animation/easing/bounceIn.ts +10 -0
  37. package/src/addons/animation/easing/bounceInOut.ts +13 -0
  38. package/src/addons/animation/easing/bounceOut.ts +30 -0
  39. package/src/addons/animation/easing/circularIn.ts +9 -0
  40. package/src/addons/animation/easing/circularInOut.ts +11 -0
  41. package/src/addons/animation/easing/circularOut.ts +9 -0
  42. package/src/addons/animation/easing/cubicIn.ts +9 -0
  43. package/src/addons/animation/easing/cubicInOut.ts +11 -0
  44. package/src/addons/animation/easing/cubicOut.ts +10 -0
  45. package/src/addons/animation/easing/elasticIn.ts +10 -0
  46. package/src/addons/animation/easing/elasticInOut.ts +21 -0
  47. package/src/addons/animation/easing/elasticOut.ts +12 -0
  48. package/src/addons/animation/easing/exponentialIn.ts +9 -0
  49. package/src/addons/animation/easing/exponentialInOut.ts +13 -0
  50. package/src/addons/animation/easing/exponentialOut.ts +9 -0
  51. package/src/addons/animation/easing/index.ts +33 -0
  52. package/src/addons/animation/easing/linearIn.ts +9 -0
  53. package/src/addons/animation/easing/linearInOut.ts +9 -0
  54. package/src/addons/animation/easing/linearOut.ts +9 -0
  55. package/src/addons/animation/easing/quadraticIn.ts +9 -0
  56. package/src/addons/animation/easing/quadraticInOut.ts +10 -0
  57. package/src/addons/animation/easing/quadraticOut.ts +9 -0
  58. package/src/addons/animation/easing/quarticIn.ts +9 -0
  59. package/src/addons/animation/easing/quarticInOut.ts +11 -0
  60. package/src/addons/animation/easing/quarticOut.ts +10 -0
  61. package/src/addons/animation/easing/quinticIn.ts +9 -0
  62. package/src/addons/animation/easing/quinticInOut.ts +11 -0
  63. package/src/addons/animation/easing/quinticOut.ts +9 -0
  64. package/src/addons/animation/easing/sineIn.ts +10 -0
  65. package/src/addons/animation/easing/sineInOut.ts +10 -0
  66. package/src/addons/animation/easing/sineOut.ts +10 -0
  67. package/src/addons/color/palette/macbeth.ts +42 -0
  68. package/src/addons/color/space/cmyk2rgb.ts +12 -0
  69. package/src/addons/color/space/gamma2linear.ts +19 -0
  70. package/src/addons/color/space/hsl2rgb.ts +20 -0
  71. package/src/addons/color/space/hsv2rgb.ts +18 -0
  72. package/src/addons/color/space/hue2rgb.ts +12 -0
  73. package/src/addons/color/space/index.ts +29 -0
  74. package/src/addons/color/space/lab2lch.ts +22 -0
  75. package/src/addons/color/space/lab2rgb.ts +19 -0
  76. package/src/addons/color/space/lab2xyz.ts +32 -0
  77. package/src/addons/color/space/lch2lab.ts +21 -0
  78. package/src/addons/color/space/lch2rgb.ts +22 -0
  79. package/src/addons/color/space/linear2gamma.ts +19 -0
  80. package/src/addons/color/space/oklab2rgb.ts +35 -0
  81. package/src/addons/color/space/rgb2cmyk.ts +13 -0
  82. package/src/addons/color/space/rgb2hcv.ts +29 -0
  83. package/src/addons/color/space/rgb2hsl.ts +23 -0
  84. package/src/addons/color/space/rgb2hsv.ts +36 -0
  85. package/src/addons/color/space/rgb2hue.ts +29 -0
  86. package/src/addons/color/space/rgb2lab.ts +19 -0
  87. package/src/addons/color/space/rgb2lch.ts +22 -0
  88. package/src/addons/color/space/rgb2oklab.ts +45 -0
  89. package/src/addons/color/space/rgb2srgb.ts +34 -0
  90. package/src/addons/color/space/rgb2xyz.ts +20 -0
  91. package/src/addons/color/space/rgb2yiq.ts +22 -0
  92. package/src/addons/color/space/rgb2yuv.ts +32 -0
  93. package/src/addons/color/space/srgb2rgb.ts +34 -0
  94. package/src/addons/color/space/xyz2lab.ts +27 -0
  95. package/src/addons/color/space/xyz2rgb.ts +30 -0
  96. package/src/addons/color/space/yiq2rgb.ts +22 -0
  97. package/src/addons/color/space/yuv2rgb.ts +32 -0
  98. package/src/addons/draw/arrows.ts +75 -0
  99. package/src/addons/draw/axis.ts +57 -0
  100. package/src/addons/draw/bridge.ts +81 -0
  101. package/src/addons/draw/char.ts +30 -0
  102. package/src/addons/draw/circle.ts +29 -0
  103. package/src/addons/draw/fill.ts +25 -0
  104. package/src/addons/draw/flip.ts +45 -0
  105. package/src/addons/draw/hex.ts +29 -0
  106. package/src/addons/draw/index.ts +13 -0
  107. package/src/addons/draw/line.ts +16 -0
  108. package/src/addons/draw/point.ts +30 -0
  109. package/src/addons/draw/rect.ts +52 -0
  110. package/src/addons/draw/stroke.ts +31 -0
  111. package/src/addons/draw/tri.ts +29 -0
  112. package/src/addons/generative/cnoise.ts +239 -0
  113. package/src/addons/generative/curl.ts +64 -0
  114. package/src/addons/generative/fbm.ts +69 -0
  115. package/src/addons/generative/gerstnerWave.ts +21 -0
  116. package/src/addons/generative/gnoise.ts +113 -0
  117. package/src/addons/generative/index.ts +15 -0
  118. package/src/addons/generative/noised.ts +139 -0
  119. package/src/addons/generative/pnoise.ts +249 -0
  120. package/src/addons/generative/psrdnoise.ts +277 -0
  121. package/src/addons/generative/random.ts +136 -0
  122. package/src/addons/generative/snoise.ts +199 -0
  123. package/src/addons/generative/srandom.ts +90 -0
  124. package/src/addons/generative/voronoi.ts +134 -0
  125. package/src/addons/generative/voronoise.ts +69 -0
  126. package/src/addons/generative/wavelet.ts +77 -0
  127. package/src/addons/generative/worley.ts +99 -0
  128. package/src/addons/geometry/aabb/aabb.ts +8 -0
  129. package/src/addons/geometry/aabb/centroid.ts +10 -0
  130. package/src/addons/geometry/aabb/contain.ts +19 -0
  131. package/src/addons/geometry/aabb/diagonal.ts +10 -0
  132. package/src/addons/geometry/aabb/expand.ts +16 -0
  133. package/src/addons/geometry/aabb/index.ts +7 -0
  134. package/src/addons/geometry/aabb/intersect.ts +20 -0
  135. package/src/addons/geometry/aabb/square.ts +17 -0
  136. package/src/addons/geometry/index.ts +2 -0
  137. package/src/addons/geometry/triangle/area.ts +10 -0
  138. package/src/addons/geometry/triangle/barycentric.ts +50 -0
  139. package/src/addons/geometry/triangle/centroid.ts +10 -0
  140. package/src/addons/geometry/triangle/closestPoint.ts +85 -0
  141. package/src/addons/geometry/triangle/contain.ts +19 -0
  142. package/src/addons/geometry/triangle/distanceSq.ts +38 -0
  143. package/src/addons/geometry/triangle/index.ts +10 -0
  144. package/src/addons/geometry/triangle/intersect.ts +49 -0
  145. package/src/addons/geometry/triangle/normal.ts +12 -0
  146. package/src/addons/geometry/triangle/signedDistance.ts +31 -0
  147. package/src/addons/geometry/triangle/triangle.ts +9 -0
  148. package/src/addons/index.ts +8 -0
  149. package/src/addons/lighting/ray.ts +8 -0
  150. package/src/addons/math/aafloor.ts +13 -0
  151. package/src/addons/math/aafract.ts +38 -0
  152. package/src/addons/math/aamirror.ts +12 -0
  153. package/src/addons/math/aastep.ts +14 -0
  154. package/src/addons/math/absi.ts +9 -0
  155. package/src/addons/math/adaptiveThreshold.ts +24 -0
  156. package/src/addons/math/bump.ts +20 -0
  157. package/src/addons/math/const.ts +19 -0
  158. package/src/addons/math/cubic.ts +101 -0
  159. package/src/addons/math/cubicMix.ts +49 -0
  160. package/src/addons/math/decimate.ts +12 -0
  161. package/src/addons/math/dist.ts +143 -0
  162. package/src/addons/math/fcos.ts +11 -0
  163. package/src/addons/math/frac.ts +9 -0
  164. package/src/addons/math/gain.ts +14 -0
  165. package/src/addons/math/gaussian.ts +14 -0
  166. package/src/addons/math/grad4.ts +19 -0
  167. package/src/addons/math/hammersley.ts +54 -0
  168. package/src/addons/math/highPass.ts +12 -0
  169. package/src/addons/math/index.ts +63 -0
  170. package/src/addons/math/inside.ts +68 -0
  171. package/src/addons/math/invCubic.ts +9 -0
  172. package/src/addons/math/invQuartic.ts +9 -0
  173. package/src/addons/math/inverse.ts +9 -0
  174. package/src/addons/math/lengthSq.ts +10 -0
  175. package/src/addons/math/map.ts +27 -0
  176. package/src/addons/math/mirror.ts +12 -0
  177. package/src/addons/math/mmax.ts +27 -0
  178. package/src/addons/math/mmin.ts +28 -0
  179. package/src/addons/math/mmix.ts +47 -0
  180. package/src/addons/math/mod2.ts +44 -0
  181. package/src/addons/math/mod289.ts +46 -0
  182. package/src/addons/math/modi.ts +15 -0
  183. package/src/addons/math/nyquist.ts +15 -0
  184. package/src/addons/math/pack.ts +15 -0
  185. package/src/addons/math/parabola.ts +12 -0
  186. package/src/addons/math/permute.ts +42 -0
  187. package/src/addons/math/pow2.ts +10 -0
  188. package/src/addons/math/pow3.ts +9 -0
  189. package/src/addons/math/pow5.ts +10 -0
  190. package/src/addons/math/pow7.ts +12 -0
  191. package/src/addons/math/powFast.ts +18 -0
  192. package/src/addons/math/quartic.ts +15 -0
  193. package/src/addons/math/quat/index.ts +14 -0
  194. package/src/addons/math/quat/quat2mat3.ts +28 -0
  195. package/src/addons/math/quat/quat2mat4.ts +16 -0
  196. package/src/addons/math/quat/quatAdd.ts +18 -0
  197. package/src/addons/math/quat/quatConj.ts +14 -0
  198. package/src/addons/math/quat/quatDiv.ts +18 -0
  199. package/src/addons/math/quat/quatIdentity.ts +9 -0
  200. package/src/addons/math/quat/quatInverse.ts +17 -0
  201. package/src/addons/math/quat/quatLength.ts +15 -0
  202. package/src/addons/math/quat/quatLengthSq.ts +14 -0
  203. package/src/addons/math/quat/quatLerp.ts +40 -0
  204. package/src/addons/math/quat/quatMul.ts +38 -0
  205. package/src/addons/math/quat/quatNeg.ts +14 -0
  206. package/src/addons/math/quat/quatNorm.ts +16 -0
  207. package/src/addons/math/quat/quatSub.ts +18 -0
  208. package/src/addons/math/quintic.ts +16 -0
  209. package/src/addons/math/rotate2d.ts +16 -0
  210. package/src/addons/math/rotate3d.ts +37 -0
  211. package/src/addons/math/rotate3dX.ts +20 -0
  212. package/src/addons/math/rotate3dY.ts +20 -0
  213. package/src/addons/math/rotate3dZ.ts +20 -0
  214. package/src/addons/math/rotate4d.ts +41 -0
  215. package/src/addons/math/rotate4dX.ts +21 -0
  216. package/src/addons/math/rotate4dY.ts +16 -0
  217. package/src/addons/math/rotate4dZ.ts +21 -0
  218. package/src/addons/math/saturateMediump.ts +11 -0
  219. package/src/addons/math/scale2d.ts +44 -0
  220. package/src/addons/math/scale3d.ts +17 -0
  221. package/src/addons/math/scale4d.ts +50 -0
  222. package/src/addons/math/smootherstep.ts +16 -0
  223. package/src/addons/math/taylorInvSqrt.ts +9 -0
  224. package/src/addons/math/toMat3.ts +14 -0
  225. package/src/addons/math/toMat4.ts +14 -0
  226. package/src/addons/math/translate4d.ts +31 -0
  227. package/src/addons/math/unpack.ts +88 -0
  228. package/src/addons/sdf/boxSDF.ts +24 -0
  229. package/src/addons/sdf/circleSDF.ts +20 -0
  230. package/src/addons/sdf/crossSDF.ts +17 -0
  231. package/src/addons/sdf/hexSDF.ts +18 -0
  232. package/src/addons/sdf/index.ts +7 -0
  233. package/src/addons/sdf/lineSDF.ts +33 -0
  234. package/src/addons/sdf/rectSDF.ts +46 -0
  235. package/src/addons/sdf/sphereSDF.ts +20 -0
  236. package/src/addons/sdf/triSDF.ts +14 -0
  237. package/src/addons/space/aspect.ts +14 -0
  238. package/src/addons/space/bracketing.ts +44 -0
  239. package/src/addons/space/brickTile.ts +44 -0
  240. package/src/addons/space/cart2polar.ts +20 -0
  241. package/src/addons/space/center.ts +32 -0
  242. package/src/addons/space/checkerTile.ts +41 -0
  243. package/src/addons/space/depth2viewZ.ts +43 -0
  244. package/src/addons/space/displace.ts +55 -0
  245. package/src/addons/space/equirect2xyz.ts +17 -0
  246. package/src/addons/space/eulerView.ts +19 -0
  247. package/src/addons/space/fisheye2xyz.ts +18 -0
  248. package/src/addons/space/flipY.ts +25 -0
  249. package/src/addons/space/hexTile.ts +18 -0
  250. package/src/addons/space/index.ts +38 -0
  251. package/src/addons/space/kaleidoscope.ts +48 -0
  252. package/src/addons/space/linearizeDepth.ts +17 -0
  253. package/src/addons/space/lookAt.ts +49 -0
  254. package/src/addons/space/lookAtView.ts +40 -0
  255. package/src/addons/space/mirrorTile.ts +73 -0
  256. package/src/addons/space/nearest.ts +13 -0
  257. package/src/addons/space/orthographic.ts +25 -0
  258. package/src/addons/space/parallaxMapping.ts +149 -0
  259. package/src/addons/space/perspective.ts +24 -0
  260. package/src/addons/space/polar2cart.ts +24 -0
  261. package/src/addons/space/ratio.ts +14 -0
  262. package/src/addons/space/rotate.ts +37 -0
  263. package/src/addons/space/rotateX.ts +54 -0
  264. package/src/addons/space/rotateY.ts +54 -0
  265. package/src/addons/space/rotateZ.ts +54 -0
  266. package/src/addons/space/scale.ts +13 -0
  267. package/src/addons/space/sprite.ts +16 -0
  268. package/src/addons/space/sqTile.ts +20 -0
  269. package/src/addons/space/tbn.ts +26 -0
  270. package/src/addons/space/translate.ts +12 -0
  271. package/src/addons/space/triTile.ts +32 -0
  272. package/src/addons/space/uncenter.ts +32 -0
  273. package/src/addons/space/unratio.ts +12 -0
  274. package/src/addons/space/viewZ2depth.ts +25 -0
  275. package/src/addons/space/windmillTile.ts +58 -0
  276. package/src/addons/space/xyz2equirect.ts +10 -0
  277. package/src/index.ts +10 -23
  278. package/src/node/build.ts +127 -0
  279. package/src/node/create.ts +76 -0
  280. package/src/node/index.ts +64 -49
  281. package/src/node/scope.ts +66 -62
  282. package/src/node/types.ts +221 -187
  283. package/src/node/utils/const.ts +74 -13
  284. package/src/node/utils/index.ts +19 -14
  285. package/src/node/utils/infer.ts +32 -34
  286. package/src/node/utils/parse.ts +48 -24
  287. package/src/node/utils/utils.ts +52 -29
  288. package/src/types.ts +11 -6
  289. package/src/utils/helpers.ts +56 -0
  290. package/src/utils/pipeline.ts +24 -8
  291. package/src/utils/program.ts +62 -38
  292. package/src/{webgl.ts → utils/webgl.ts} +46 -30
  293. package/src/{webgpu.ts → utils/webgpu.ts} +22 -17
  294. package/src/node/core.ts +0 -121
  295. package/src/node/node.ts +0 -65
@@ -3,20 +3,20 @@ export const SWIZZLES = ['x', 'y', 'z', 'w', 'r', 'g', 'b', 'a', 's', 't', 'p',
3
3
  // Unified order with TYPE_MAPPING array
4
4
  export const CONVERSIONS = [
5
5
  'toBool',
6
- 'toUint',
6
+ 'toUInt',
7
7
  'toInt',
8
8
  'toFloat',
9
- 'toBvec2',
10
- 'toIvec2',
11
- 'toUvec2',
9
+ 'toBVec2',
10
+ 'toIVec2',
11
+ 'toUVec2',
12
12
  'toVec2',
13
- 'toBvec3',
14
- 'toIvec3',
15
- 'toUvec3',
13
+ 'toBVec3',
14
+ 'toIVec3',
15
+ 'toUVec3',
16
16
  'toVec3',
17
- 'toBvec4',
18
- 'toIvec4',
19
- 'toUvec4',
17
+ 'toBVec4',
18
+ 'toIVec4',
19
+ 'toUVec4',
20
20
  'toVec4',
21
21
  'toColor',
22
22
  'toMat2',
@@ -73,6 +73,16 @@ export const OPERATORS = {
73
73
  bitXor: '^',
74
74
  shiftLeft: '<<',
75
75
  shiftRight: '>>',
76
+ addAssign: '+=',
77
+ subAssign: '-=',
78
+ mulAssign: '*=',
79
+ divAssign: '/=',
80
+ modAssign: '%=',
81
+ bitAndAssign: '&=',
82
+ bitOrAssign: '|=',
83
+ bitXorAssign: '^=',
84
+ shiftLeftAssign: '<<=',
85
+ shiftRightAssign: '>>=',
76
86
  } as const
77
87
 
78
88
  export const OPERATOR_KEYS = Object.keys(OPERATORS) as (keyof typeof OPERATORS)[]
@@ -135,6 +145,28 @@ export const COMPARISON_OPERATORS = [
135
145
 
136
146
  export const LOGICAL_OPERATORS = ['and', 'or'] as const
137
147
 
148
+ // Operator type rules [L, R, Result] format (no duplicates, same-type handled by logic)
149
+ export const OPERATOR_TYPE_RULES = [
150
+ // Scalar broadcast operations (result follows vector type)
151
+ ['float', 'vec2', 'vec2'],
152
+ ['float', 'vec3', 'vec3'],
153
+ ['float', 'vec4', 'vec4'],
154
+ ['int', 'ivec2', 'ivec2'],
155
+ ['int', 'ivec3', 'ivec3'],
156
+ ['int', 'ivec4', 'ivec4'],
157
+ ['uint', 'uvec2', 'uvec2'],
158
+ ['uint', 'uvec3', 'uvec3'],
159
+ ['uint', 'uvec4', 'uvec4'],
160
+ // Matrix-vector operations (mat * vec → vec)
161
+ ['mat2', 'vec2', 'vec2'],
162
+ ['mat3', 'vec3', 'vec3'],
163
+ ['mat4', 'vec4', 'vec4'],
164
+ // Vector-matrix operations (vec * mat → vec)
165
+ ['vec2', 'mat2', 'vec2'],
166
+ ['vec3', 'mat3', 'vec3'],
167
+ ['vec4', 'mat4', 'vec4'],
168
+ ] as const
169
+
138
170
  export const WGSL_TO_GLSL_BUILTIN = {
139
171
  position: 'gl_FragCoord',
140
172
  vertex_index: 'gl_VertexID',
@@ -150,7 +182,7 @@ export const WGSL_TO_GLSL_BUILTIN = {
150
182
  /**
151
183
  * 2.1. unified with:
152
184
  * 1.1. index.ts functions and
153
- * 3.1. types.ts BaseNodeProxy
185
+ * 3.1. types.ts _N
154
186
  */
155
187
  // Function return type mapping for method chaining
156
188
  export const FUNCTION_RETURN_TYPES = {
@@ -176,7 +208,7 @@ export const FUNCTION_RETURN_TYPES = {
176
208
  /**
177
209
  * 2.2. unified with:
178
210
  * 1.2. index.ts functions and
179
- * 3.2. types.ts BaseNodeProxy
211
+ * 3.2. types.ts _N
180
212
  */
181
213
  // All shader functions (type inference now handled by inferFrom)
182
214
  export const FUNCTIONS = [
@@ -200,6 +232,7 @@ export const FUNCTIONS = [
200
232
  'floor',
201
233
  'fract',
202
234
  'fwidth',
235
+ 'inverse',
203
236
  'inverseSqrt',
204
237
  'log',
205
238
  'log2',
@@ -209,7 +242,6 @@ export const FUNCTIONS = [
209
242
  'radians',
210
243
  'reciprocal',
211
244
  'round',
212
- 'saturate',
213
245
  'sign',
214
246
  'sin',
215
247
  'sinh',
@@ -217,6 +249,7 @@ export const FUNCTIONS = [
217
249
  'tan',
218
250
  'tanh',
219
251
  'trunc',
252
+ 'saturate',
220
253
  // 1. Functions where first argument determines return type
221
254
  'atan2',
222
255
  'clamp',
@@ -231,3 +264,31 @@ export const FUNCTIONS = [
231
264
  'step',
232
265
  // @NOTE: mod is operator
233
266
  ] as const
267
+
268
+ // Check if two types are the same (for same-type operations)
269
+ const isSameType = (L: string, R: string): boolean => L === R
270
+
271
+ // Check if combination exists in rules (handles bidirectional matching)
272
+ const isValidCombination = (L: string, R: string): boolean => {
273
+ return OPERATOR_TYPE_RULES.some(
274
+ ([left, right, _]) => (left === L && right === R) || (left === R && right === L)
275
+ )
276
+ }
277
+
278
+ // Type constraint validation for operators ([L, R, Result] format)
279
+ export const validateOperatorTypes = (L: string, R: string, op: string): boolean => {
280
+ if (COMPARISON_OPERATORS.includes(op as any) || LOGICAL_OPERATORS.includes(op as any)) return isSameType(L, R)
281
+ if (isSameType(L, R)) return true
282
+ return isValidCombination(L, R)
283
+ }
284
+
285
+ // Get result type for operator (used by inferOperator)
286
+ export const getOperatorResultType = (L: string, R: string, op: string): string => {
287
+ if (COMPARISON_OPERATORS.includes(op as any) || LOGICAL_OPERATORS.includes(op as any)) return 'bool'
288
+ // Same type operations return the same type
289
+ if (isSameType(L, R)) return L
290
+ const rule = OPERATOR_TYPE_RULES.find(
291
+ ([left, right, _]) => (left === L && right === R) || (left === R && right === L)
292
+ )
293
+ return rule ? rule[2] : L
294
+ }
@@ -7,6 +7,7 @@ import {
7
7
  parseDefine,
8
8
  parseGather,
9
9
  parseIf,
10
+ parseLoop,
10
11
  parseScatter,
11
12
  parseStorageHead,
12
13
  parseStruct,
@@ -16,13 +17,14 @@ import {
16
17
  parseUniformHead,
17
18
  parseVaryingHead,
18
19
  } from './parse'
19
- import { getBluiltin, getOperator, getConversions, safeEventCall, getEventFun, initNodeContext } from './utils'
20
+ import { getBluiltin, getConversions, getOperator, initNodeContext, setupEvent } from './utils'
20
21
  import { is } from '../../utils/helpers'
21
- import type { Constants, NodeContext, X } from '../types'
22
+ import { mod } from '..'
23
+ import type { Constants as C, NodeContext, Y } from '../types'
22
24
 
23
25
  export * from './utils'
24
26
 
25
- export const code = <T extends Constants>(target: X<T>, c?: NodeContext | null): string => {
27
+ export const code = <T extends C>(target: Y<T>, c?: NodeContext | null): string => {
26
28
  if (!c) c = {}
27
29
  initNodeContext(c)
28
30
  if (is.arr(target)) return parseArray(target, c)
@@ -62,13 +64,21 @@ export const code = <T extends Constants>(target: X<T>, c?: NodeContext | null):
62
64
  if (type === 'conversion') return `${getConversions(x, c)}(${parseArray(children.slice(1), c)})`
63
65
  if (type === 'operator') {
64
66
  if (x === 'not' || x === 'bitNot') return `!${code(y, c)}`
67
+ if (x === 'mod') return code(mod(y, z), c)
68
+ if (x.endsWith('Assign')) return `${code(y, c)} ${getOperator(x)} ${code(z, c)};`
65
69
  return `(${code(y, c)} ${getOperator(x)} ${code(z, c)})`
66
70
  }
67
71
  if (type === 'function') {
68
72
  if (x === 'negate') return `(-${code(y, c)})`
73
+ if (x === 'reciprocal') return `(1.0 / ${code(y, c)})`
69
74
  if (x === 'oneMinus') return `(1.0-${code(y, c)})`
75
+ if (x === 'saturate') return `clamp(${code(y, c)}, 0.0, 1.0)`
70
76
  if (x === 'texture') return parseTexture(c, y, z, w)
71
77
  if (x === 'atan2' && c.isWebGL) return `atan(${code(y, c)}, ${code(z, c)})`
78
+ if (!c.isWebGL) {
79
+ if (x === 'dFdx') return `dpdx(${code(y, c)})`
80
+ if (x === 'dFdy') return `dpdy(${code(y, c)})`
81
+ }
72
82
  return `${x}(${parseArray(children.slice(1), c)})`
73
83
  }
74
84
  /**
@@ -77,10 +87,9 @@ export const code = <T extends Constants>(target: X<T>, c?: NodeContext | null):
77
87
  if (type === 'scope') return children.map((child: any) => code(child, c)).join('\n')
78
88
  if (type === 'assign') return `${code(x, c)} = ${code(y, c)};`
79
89
  if (type === 'return') return `return ${code(x, c)};`
80
- if (type === 'loop')
81
- return c.isWebGL
82
- ? `for (int ${id} = 0; ${id} < ${code(x, c)}; ${id} += 1) {\n${code(y, c)}\n}`
83
- : `for (var ${id}: i32 = 0; ${id} < ${code(x, c)}; ${id}++) {\n${code(y, c)}\n}`
90
+ if (type === 'break') return 'break;'
91
+ if (type === 'continue') return 'continue;'
92
+ if (type === 'loop') return parseLoop(c, x, y, id)
84
93
  if (type === 'if') return parseIf(c, x, y, children)
85
94
  if (type === 'switch') return parseSwitch(c, x, children)
86
95
  if (type === 'declare') return parseDeclare(c, x, y)
@@ -112,10 +121,8 @@ export const code = <T extends Constants>(target: X<T>, c?: NodeContext | null):
112
121
  else if (c.label === 'vert') c.code?.vertInputs.set(id, field)
113
122
  return `in.${id}`
114
123
  }
115
- if (type === 'attribute') {
116
- const fun = getEventFun(c, id, true)
117
- safeEventCall(x, fun)
118
- target.listeners.add(fun)
124
+ if (type === 'attribute' || type === 'instance') {
125
+ setupEvent(c, id, type, target, x)
119
126
  c.code?.vertInputs.set(id, parseAttribHead(c, id, infer(target, c)))
120
127
  return c.isWebGL ? `${id}` : `in.${id}`
121
128
  }
@@ -123,9 +130,7 @@ export const code = <T extends Constants>(target: X<T>, c?: NodeContext | null):
123
130
  let head = ''
124
131
  if (type === 'uniform') {
125
132
  const varType = infer(target, c)
126
- const fun = getEventFun(c, id, false, varType === 'texture')
127
- safeEventCall(x, fun)
128
- target.listeners.add(fun)
133
+ setupEvent(c, id, varType, target, x)
129
134
  head = parseUniformHead(c, id, varType)
130
135
  }
131
136
  if (type === 'storage') head = parseStorageHead(c, id, infer(target, c))
@@ -1,63 +1,54 @@
1
- import { isConstants, isNodeProxy, isSwizzle } from './utils'
1
+ import { isConstants, isX, isSwizzle } from './utils'
2
2
  import {
3
3
  BUILTIN_TYPES,
4
- COMPARISON_OPERATORS,
5
4
  COMPONENT_COUNT_TO_TYPE,
6
5
  FUNCTION_RETURN_TYPES,
7
- LOGICAL_OPERATORS,
6
+ getOperatorResultType,
7
+ validateOperatorTypes,
8
8
  } from './const'
9
- import { is } from '../../utils/helpers'
10
- import type { Constants as C, NodeContext, NodeProxy, X } from '../types'
9
+ import { is, getStride } from '../../utils/helpers'
10
+ import type { Constants as C, NodeContext, X, Y } from '../types'
11
11
 
12
12
  const inferBuiltin = <T extends C>(id: string | undefined) => {
13
13
  return BUILTIN_TYPES[id as keyof typeof BUILTIN_TYPES] as T
14
14
  }
15
15
 
16
- // Unified logic with types.ts InferOperator type
17
16
  const inferOperator = <T extends C>(L: T, R: T, op: string): T => {
18
- if (COMPARISON_OPERATORS.includes(op as any) || LOGICAL_OPERATORS.includes(op as any)) return 'bool' as T
19
- if (L === R) return L
20
- // broadcast
21
- if (L === 'float' || L === 'int') return R
22
- if (R === 'float' || R === 'int') return L
23
- // mat * vec → vec
24
- if (L === 'mat4' && R === 'vec4') return R
25
- if (L === 'mat3' && R === 'vec3') return R
26
- if (L === 'mat2' && R === 'vec2') return R
27
- // vec * mat → vec
28
- if (L === 'vec4' && R === 'mat4') return L
29
- if (L === 'vec3' && R === 'mat3') return L
30
- if (L === 'vec2' && R === 'mat2') return L
31
- return L
17
+ if (!validateOperatorTypes(L, R, op))
18
+ console.warn(`GLRE Type Warning: Invalid operator '${op}' between types '${L}' and '${R}'`)
19
+ return getOperatorResultType(L, R, op) as T
32
20
  }
33
21
 
34
- export const inferPrimitiveType = <T extends C>(x: X) => {
22
+ export const inferPrimitiveType = <T extends C>(x: Y<T>) => {
35
23
  if (is.bol(x)) return 'bool' as T
36
24
  if (is.str(x)) return 'texture' as T
37
25
  if (is.num(x)) return 'float' as T // @TODO FIX: Number.isInteger(x) ? 'int' : 'float'
38
26
  if (is.arr(x)) return COMPONENT_COUNT_TO_TYPE[x.length as keyof typeof COMPONENT_COUNT_TO_TYPE] as T
39
- return 'float' as T
27
+ return 'void' as T
40
28
  }
41
29
 
42
30
  const inferFromCount = <T extends C>(count: number) => {
43
- return COMPONENT_COUNT_TO_TYPE[count as keyof typeof COMPONENT_COUNT_TO_TYPE] as T
31
+ const ret = COMPONENT_COUNT_TO_TYPE[count as keyof typeof COMPONENT_COUNT_TO_TYPE] as T
32
+ if (!ret)
33
+ throw `glre node system error: Cannot infer type from array length ${count}. Check your data size. Supported: 1(float), 2(vec2), 3(vec3), 4(vec4), 9(mat3), 16(mat4)`
34
+ return ret
44
35
  }
45
36
 
46
- const inferFromArray = <T extends C>(arr: X<T>[], c: NodeContext) => {
37
+ const inferFromArray = <T extends C>(arr: Y<T>[], c: NodeContext) => {
47
38
  if (arr.length === 0) return 'void' as T
48
39
  const [x] = arr
49
40
  if (is.str(x)) return x as T // for struct
50
41
  const ret = infer(x, c)
51
42
  // for (const x of arr.slice(1))
52
- // if (ret !== infer(x, c)) throw new Error(`glre node system error: defined scope return mismatch`)
43
+ // if (ret !== infer(x, c)) throw `glre node system error: defined scope return mismatch`
53
44
  return ret
54
45
  }
55
46
 
56
- export const inferFunction = <T extends C>(x: X) => {
47
+ export const inferFunction = <T extends C>(x: Y) => {
57
48
  return FUNCTION_RETURN_TYPES[x as keyof typeof FUNCTION_RETURN_TYPES] as T
58
49
  }
59
50
 
60
- export const inferImpl = <T extends C>(target: NodeProxy<T>, c: NodeContext): T => {
51
+ export const inferImpl = <T extends C>(target: X<T>, c: NodeContext): T => {
61
52
  const { type, props } = target
62
53
  const { id, children = [], inferFrom, layout } = props
63
54
  const [x, y, z] = children
@@ -70,25 +61,32 @@ export const inferImpl = <T extends C>(target: NodeProxy<T>, c: NodeContext): T
70
61
  if (!inferFrom || inferFrom.length === 0) return 'void' as T
71
62
  return inferFromArray(inferFrom, c)
72
63
  }
73
- if (type === 'attribute' && is.arr(x) && c.gl?.count) return inferFromCount(x.length / c.gl.count)
64
+ if (type === 'attribute' && is.arr(x)) {
65
+ const stride = getStride(x.length, c.gl?.count, c.gl?.error)
66
+ return inferFromCount(stride)
67
+ }
68
+ if (type === 'instance' && is.arr(x)) {
69
+ const stride = getStride(x.length, c.gl?.instanceCount, c.gl?.error)
70
+ return inferFromCount(stride)
71
+ }
74
72
  if (type === 'member') {
75
73
  if (isSwizzle(y)) return inferFromCount(y.length)
76
- if (isNodeProxy(x)) {
74
+ if (isX(x)) {
77
75
  const structType = infer(x, c)
78
- const fields = c.code?.structFields?.get(structType)
76
+ const fields = c.code?.structStructFields?.get(structType)
79
77
  if (fields && fields[y]) return infer(fields[y], c) as T
80
78
  }
81
79
  return 'float' as T
82
80
  }
83
81
  if (inferFrom) return inferFromArray(inferFrom, c)
84
- return infer(x, c) // for uniform and storage gather and scatter
82
+ return x ? infer(x, c) : ('void' as T) // for uniform and storage gather and scatter
85
83
  }
86
84
 
87
- export const infer = <T extends C>(target: X<T>, c?: NodeContext | null): T => {
85
+ export const infer = <T extends C>(target: Y<T>, c?: NodeContext | null): T => {
88
86
  if (!c) c = {}
89
- if (!isNodeProxy(target)) return inferPrimitiveType(target)
87
+ if (!isX(target)) return inferPrimitiveType(target)
90
88
  if (is.arr(target)) return inferFromCount(target.length)
91
- if (!c.infers) c.infers = new WeakMap<NodeProxy<T>, C>()
89
+ if (!c.infers) c.infers = new WeakMap<X<T>, C>()
92
90
  if (c.infers.has(target)) return c.infers.get(target) as T
93
91
  const ret = inferImpl(target, c)
94
92
  c.infers.set(target, ret)
@@ -2,9 +2,10 @@ import { code } from '.'
2
2
  import { infer } from './infer'
3
3
  import { getConversions, addDependency } from './utils'
4
4
  import { is } from '../../utils/helpers'
5
- import type { Constants, NodeContext, NodeProps, NodeProxy, StructFields, X } from '../types'
5
+ import type { Constants, NodeContext, NodeProps, StructFields, Y } from '../types'
6
+ import { storageSize } from '../../utils/program'
6
7
 
7
- export const parseArray = (children: X[], c: NodeContext) => {
8
+ export const parseArray = (children: Y[], c: NodeContext) => {
8
9
  return children
9
10
  .filter((x) => !is.und(x) && !is.nul(x))
10
11
  .map((x) => code(x, c))
@@ -12,7 +13,7 @@ export const parseArray = (children: X[], c: NodeContext) => {
12
13
  }
13
14
 
14
15
  // only for webgl
15
- export const parseGather = (c: NodeContext, x: X, y: X, target: X) => {
16
+ export const parseGather = (c: NodeContext, x: Y, y: Y, target: Y) => {
16
17
  const parseSwizzle = () => {
17
18
  const valueType = infer(target, c)
18
19
  if (valueType === 'float') return '.x'
@@ -22,14 +23,14 @@ export const parseGather = (c: NodeContext, x: X, y: X, target: X) => {
22
23
  throw new Error(`Unsupported storage scatter type: ${valueType}`)
23
24
  }
24
25
  const indexVar = code(y, c)
25
- const texSize = Math.floor(Math.sqrt(c.gl?.particles || 1024))
26
- const coordX = `int(${indexVar}) % ${texSize}`
27
- const coordY = `int(${indexVar}) / ${texSize}`
26
+ const size = storageSize(c.gl?.particleCount)
27
+ const coordX = `int(${indexVar}) % ${size.x}`
28
+ const coordY = `int(${indexVar}) / ${size.x}`
28
29
  return `texelFetch(${code(x, c)}, ivec2(${coordX}, ${coordY}), 0)${parseSwizzle()}`
29
30
  }
30
31
 
31
32
  // only for webgl
32
- export const parseScatter = (c: NodeContext, storageNode: X, valueNode: X) => {
33
+ export const parseScatter = (c: NodeContext, storageNode: Y, valueNode: Y) => {
33
34
  const storageId = code(storageNode, c)
34
35
  const valueCode = code(valueNode, c)
35
36
  const valueType = infer(valueNode, c)
@@ -40,7 +41,7 @@ export const parseScatter = (c: NodeContext, storageNode: X, valueNode: X) => {
40
41
  throw new Error(`Unsupported storage scatter type: ${valueType}`)
41
42
  }
42
43
 
43
- export const parseTexture = (c: NodeContext, y: X, z: X, w: X) => {
44
+ export const parseTexture = (c: NodeContext, y: Y, z: Y, w: Y) => {
44
45
  if (c.isWebGL) {
45
46
  const args = w ? [y, z, w] : [y, z]
46
47
  return `texture(${parseArray(args, c)})`
@@ -55,7 +56,7 @@ export const parseTexture = (c: NodeContext, y: X, z: X, w: X) => {
55
56
  /**
56
57
  * scopes
57
58
  */
58
- export const parseIf = (c: NodeContext, x: X, y: X, children: X[]) => {
59
+ export const parseIf = (c: NodeContext, x: Y, y: Y, children: Y[]) => {
59
60
  let ret = `if (${code(x, c)}) {\n${code(y, c)}\n}`
60
61
  for (let i = 2; i < children.length; i += 2) {
61
62
  const isElse = i >= children.length - 1
@@ -66,7 +67,7 @@ export const parseIf = (c: NodeContext, x: X, y: X, children: X[]) => {
66
67
  return ret
67
68
  }
68
69
 
69
- export const parseSwitch = (c: NodeContext, x: X, children: X[]) => {
70
+ export const parseSwitch = (c: NodeContext, x: Y, children: Y[]) => {
70
71
  let ret = `switch (${code(x, c)}) {\n`
71
72
  for (let i = 1; i < children.length; i += 2) {
72
73
  const isDefault = i >= children.length - 1
@@ -79,7 +80,7 @@ export const parseSwitch = (c: NodeContext, x: X, children: X[]) => {
79
80
  return ret
80
81
  }
81
82
 
82
- export const parseDeclare = (c: NodeContext, x: X, y: X) => {
83
+ export const parseDeclare = (c: NodeContext, x: Y, y: Y) => {
83
84
  const type = infer(x, c)
84
85
  const varName = (y as any)?.props?.id
85
86
  if (c.isWebGL) return `${type} ${varName} = ${code(x, c)};`
@@ -88,7 +89,7 @@ export const parseDeclare = (c: NodeContext, x: X, y: X) => {
88
89
  }
89
90
 
90
91
  export const parseStructHead = (c: NodeContext, id: string, fields: StructFields = {}) => {
91
- c.code?.structFields?.set(id, fields)
92
+ c.code?.structStructFields?.set(id, fields)
92
93
  const lines: string[] = []
93
94
  for (const key in fields) {
94
95
  const fieldType = fields[key]
@@ -101,7 +102,7 @@ export const parseStructHead = (c: NodeContext, id: string, fields: StructFields
101
102
  }
102
103
 
103
104
  export const parseStruct = (c: NodeContext, id: string, instanceId = '', initialValues?: StructFields) => {
104
- const fields = c.code?.structFields?.get(id) || {}
105
+ const fields = c.code?.structStructFields?.get(id) || {}
105
106
  if (c.isWebGL) {
106
107
  if (initialValues) {
107
108
  const ordered = []
@@ -120,19 +121,16 @@ export const parseStruct = (c: NodeContext, id: string, instanceId = '', initial
120
121
  /**
121
122
  * define
122
123
  */
123
- export const parseDefine = (c: NodeContext, props: NodeProps, target: NodeProxy) => {
124
+ export const parseDefine = (c: NodeContext, props: NodeProps, target: Y) => {
124
125
  const { id, children = [], layout } = props
125
126
  const [x, ...args] = children
126
- const argParams: [name: string, type: string][] = []
127
+ const argParams: [name: string, type: Constants][] = []
127
128
  const params: string[] = []
128
- if (layout?.inputs)
129
- for (const input of layout.inputs) {
130
- argParams.push([input.name, input.type])
131
- }
132
- else
133
- for (let i = 0; i < args.length; i++) {
134
- argParams.push([`p${i}`, infer(args[i], c)])
135
- }
129
+ for (let i = 0; i < args.length; i++) {
130
+ const input = layout?.inputs?.[i]
131
+ if (!input) argParams.push([`p${i}`, infer(args[i], c)])
132
+ else argParams.push([input.name, input.type === 'auto' ? infer(args[i], c) : input.type])
133
+ }
136
134
  const scopeCode = code(x, c) // build struct headers before inferring returnType
137
135
  const returnType = infer(target, c)
138
136
  const ret = []
@@ -158,7 +156,7 @@ export const parseDefine = (c: NodeContext, props: NodeProps, target: NodeProxy)
158
156
  /**
159
157
  * headers
160
158
  */
161
- export const parseVaryingHead = (c: NodeContext, id: string, type: string) => {
159
+ export const parseVaryingHead = (c: NodeContext, id: string, type: Constants) => {
162
160
  return c.isWebGL
163
161
  ? `${type} ${id};`
164
162
  : `@location(${c.code?.vertVaryings?.size || 0}) ${id}: ${getConversions(type, c)}`
@@ -201,6 +199,32 @@ export const parseStorageHead = (c: NodeContext, id: string, type: Constants) =>
201
199
  return `@group(${group}) @binding(${binding}) var<storage, read_write> ${id}: array<${wgslType}>;`
202
200
  }
203
201
 
202
+ export const parseLoop = (c: NodeContext, x: Y, y: Y, id: string) => {
203
+ const conditionType = infer(x, c)
204
+ const bodyCode = code(y, c)
205
+ const conditionCode = code(x, c)
206
+ if (c.isWebGL) {
207
+ if (conditionType === 'int')
208
+ return `for (int ${id} = 0; ${id} < ${conditionCode}; ${id} += 1) {\n${bodyCode}\n}`
209
+ if (conditionType === 'float')
210
+ return `for (float ${id} = 0.0; ${id} < ${conditionCode}; ${id} += 1.0) {\n${bodyCode}\n}`
211
+ if (conditionType === 'vec2')
212
+ return `for (vec2 ${id} = vec2(0.0); ${id}.x < ${conditionCode}.x && ${id}.y < ${conditionCode}.y; ${id} += vec2(1.0)) {\n${bodyCode}\n}`
213
+ if (conditionType === 'vec3')
214
+ return `for (vec3 ${id} = vec3(0.0); ${id}.x < ${conditionCode}.x && ${id}.y < ${conditionCode}.y && ${id}.z < ${conditionCode}.z; ${id} += vec3(1.0)) {\n${bodyCode}\n}`
215
+ return `for (int ${id} = 0; ${id} < ${conditionCode}; ${id} += 1) {\n${bodyCode}\n}`
216
+ }
217
+ if (conditionType === 'int')
218
+ return `for (var ${id}: i32 = 0; ${id} < ${conditionCode}; ${id}++) {\n${bodyCode}\n}`
219
+ if (conditionType === 'float')
220
+ return `for (var ${id}: f32 = 0.0; ${id} < ${conditionCode}; ${id} += 1.0) {\n${bodyCode}\n}`
221
+ if (conditionType === 'vec2')
222
+ return `for (var ${id}: vec2f = vec2f(0.0); ${id}.x < ${conditionCode}.x && ${id}.y < ${conditionCode}.y; ${id} += vec2f(1.0)) {\n${bodyCode}\n}`
223
+ if (conditionType === 'vec3')
224
+ return `for (var ${id}: vec3f = vec3f(0.0); ${id}.x < ${conditionCode}.x && ${id}.y < ${conditionCode}.y && ${id}.z < ${conditionCode}.z; ${id} += vec3f(1.0)) {\n${bodyCode}\n}`
225
+ return `for (var ${id}: i32 = 0; ${id} < ${conditionCode}; ${id}++) {\n${bodyCode}\n}`
226
+ }
227
+
204
228
  export const parseConstantHead = (c: NodeContext, id: string, type: Constants, value: string) => {
205
229
  return c.isWebGL ? `const ${type} ${id} = ${value};` : `const ${id}: ${getConversions(type, c)} = ${value};`
206
230
  }
@@ -8,7 +8,18 @@ import {
8
8
  WGSL_TO_GLSL_BUILTIN,
9
9
  } from './const'
10
10
  import { is } from '../../utils/helpers'
11
- import type { Constants, Conversions, Functions, NodeContext, NodeProxy, Operators, Swizzles, X } from '../types'
11
+ import type {
12
+ Constants as C,
13
+ Conversions,
14
+ Functions,
15
+ NodeContext,
16
+ NodeTypes,
17
+ Operators,
18
+ Swizzles,
19
+ X,
20
+ Y,
21
+ } from '../types'
22
+ import { storageSize } from '../../utils/program'
12
23
 
13
24
  export const isSwizzle = (key: unknown): key is Swizzles => {
14
25
  return is.str(key) && /^[xyzwrgbastpq]{1,4}$/.test(key)
@@ -26,13 +37,13 @@ export const isConversion = (key: unknown): key is Conversions => {
26
37
  return CONVERSIONS.includes(key as Conversions)
27
38
  }
28
39
 
29
- export const isNodeProxy = <T extends Constants>(x: unknown): x is NodeProxy<T> => {
40
+ export const isX = (x: unknown): x is X => {
30
41
  if (!x) return false
31
42
  if (typeof x !== 'object') return false // @ts-ignore
32
43
  return x.isProxy
33
44
  }
34
45
 
35
- export const isConstants = (type?: unknown): type is Constants => {
46
+ export const isConstants = (type?: unknown): type is C => {
36
47
  if (!is.str(type)) return false
37
48
  return CONSTANTS.includes(type as any)
38
49
  }
@@ -50,49 +61,29 @@ export const getId = () => `x${count++}`
50
61
 
51
62
  export const getBluiltin = (c: NodeContext, id: string) => {
52
63
  if (id === 'global_invocation_id') {
53
- const size = Math.floor(Math.sqrt(c.gl?.particles || 1024))
54
- return `uvec3(uint(gl_FragCoord.y) * uint(${size}) + uint(gl_FragCoord.x), 0u, 0u)`
64
+ const size = storageSize(c.gl?.particleCount)
65
+ return `uvec3(uint(gl_FragCoord.y) * uint(${size.x}) + uint(gl_FragCoord.x), 0u, 0u)`
55
66
  }
56
67
  const ret = WGSL_TO_GLSL_BUILTIN[id as keyof typeof WGSL_TO_GLSL_BUILTIN]
57
68
  if (!ret) throw new Error(`Error: unknown builtin variable ${id}`)
58
69
  return ret
59
70
  }
60
71
 
61
- export const getConversions = <T extends Constants>(x: X<T>, c?: NodeContext) => {
72
+ export const getConversions = <T extends C>(x: T, c?: NodeContext) => {
62
73
  if (!is.str(x)) return ''
63
74
  if (c?.isWebGL) return x
64
75
  return TYPE_MAPPING[x as keyof typeof TYPE_MAPPING] || x // for struct type
65
76
  }
66
77
 
67
- export const getOperator = (op: X) => {
78
+ export const getOperator = (op: Y) => {
68
79
  return OPERATORS[op as keyof typeof OPERATORS] || op
69
80
  }
70
81
 
71
- export const getConstant = (conversionKey: string): Constants => {
82
+ export const getConstant = (conversionKey: string): C => {
72
83
  const index = CONVERSIONS.indexOf(conversionKey as Conversions)
73
84
  return index !== -1 ? CONSTANTS[index] : 'float'
74
85
  }
75
86
 
76
- export const getEventFun = (c: NodeContext, id: string, isAttribute = false, isTexture = false) => {
77
- if (c.isWebGL) {
78
- if (isAttribute) return (value: any) => c.gl?.attribute?.(id, value)
79
- if (isTexture) return (value: any) => c.gl?.texture?.(id, value)
80
- return (value: any) => c.gl?.uniform?.(id, value)
81
- }
82
- if (isAttribute) return (value: any) => c.gl?._attribute?.(id, value)
83
- if (isTexture) return (value: any) => c.gl?._texture?.(id, value)
84
- return (value: any) => c.gl?._uniform?.(id, value)
85
- }
86
-
87
- export const safeEventCall = <T extends Constants>(x: X<T>, fun: (value: unknown) => void) => {
88
- if (is.und(x)) return
89
- if (!isNodeProxy(x)) return fun(x) // for uniform(0) or uniform([0, 1])
90
- if (x.type !== 'conversion') return
91
- const args = x.props.children?.slice(1)
92
- if (is.und(args?.[0])) return // ignore if uniform(vec2())
93
- fun(args.map((x) => x ?? args[0])) // for uniform(vec2(1)) or uniform(vec2(1, 1))
94
- }
95
-
96
87
  export const initNodeContext = (c: NodeContext) => {
97
88
  if (c.code) return c
98
89
  c.code = {
@@ -103,7 +94,7 @@ export const initNodeContext = (c: NodeContext) => {
103
94
  vertVaryings: new Map(),
104
95
  computeInputs: new Map(),
105
96
  dependencies: new Map(),
106
- structFields: new Map(),
97
+ structStructFields: new Map(),
107
98
  }
108
99
  if (c.isWebGL) return c
109
100
  c.code.fragInputs.set('position', '@builtin(position) position: vec4f')
@@ -119,3 +110,35 @@ export const addDependency = (c: NodeContext, id = '', type: string) => {
119
110
  if (!c.code?.dependencies?.has(id)) c.code!.dependencies.set(id, new Set())
120
111
  if (!isConstants(type)) c.code!.dependencies.get(id)!.add(type)
121
112
  }
113
+
114
+ /**
115
+ * uniform ant attribute event listeners
116
+ */
117
+ const getEventFun = (c: NodeContext, id: string, type: string) => {
118
+ if (c.isWebGL) {
119
+ if (type === 'attribute') return (value: any) => c.gl?.attribute?.(id, value)
120
+ if (type === 'instance') return (value: any) => c.gl?.instance?.(id, value)
121
+ if (type === 'texture') return (value: any) => c.gl?.texture?.(id, value)
122
+ return (value: any) => c.gl?.uniform?.(id, value)
123
+ }
124
+ if (type === 'attribute') return (value: any) => c.gl?._attribute?.(id, value)
125
+ if (type === 'instance') return (value: any) => c.gl?._instance?.(id, value)
126
+ if (type === 'texture') return (value: any) => c.gl?._texture?.(id, value)
127
+ return (value: any) => c.gl?._uniform?.(id, value)
128
+ }
129
+
130
+ const safeEventCall = <T extends C>(x: X<T>, fun: (value: unknown) => void) => {
131
+ if (is.und(x)) return
132
+ if (!isX(x)) return fun(x) // for uniform(0) or uniform([0, 1])
133
+ if (x.type !== 'conversion') return
134
+ const args = x.props.children?.slice(1)
135
+ if (is.und(args?.[0])) return // ignore if uniform(vec2())
136
+ fun(args.map((x) => x ?? args[0])) // for uniform(vec2(1)) or uniform(vec2(1, 1))
137
+ }
138
+
139
+ export const setupEvent = (c: NodeContext, id: string, type: string, target: X, child: X) => {
140
+ const fun = getEventFun(c, id, type)
141
+ safeEventCall(child, fun)
142
+ target.listeners.add(fun)
143
+ return fun
144
+ }