glre 0.26.0 → 0.28.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 (53) hide show
  1. package/README.md +10 -9
  2. package/dist/index.cjs +66 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +547 -0
  5. package/dist/index.js +39 -21
  6. package/dist/index.js.map +1 -1
  7. package/dist/native.cjs +66 -0
  8. package/dist/native.cjs.map +1 -0
  9. package/dist/native.d.cts +53 -0
  10. package/dist/native.js +39 -21
  11. package/dist/native.js.map +1 -1
  12. package/dist/react.cjs +66 -0
  13. package/dist/react.cjs.map +1 -0
  14. package/dist/react.d.cts +8 -0
  15. package/dist/react.js +40 -22
  16. package/dist/react.js.map +1 -1
  17. package/dist/solid.cjs +66 -0
  18. package/dist/solid.cjs.map +1 -0
  19. package/dist/solid.d.cts +8 -0
  20. package/dist/solid.js +40 -22
  21. package/dist/solid.js.map +1 -1
  22. package/package.json +2 -1
  23. package/src/index.ts +0 -2
  24. package/src/native.ts +2 -2
  25. package/src/node/code.ts +103 -0
  26. package/src/node/const.ts +158 -98
  27. package/src/node/index.ts +109 -82
  28. package/src/node/infer.ts +93 -0
  29. package/src/node/node.ts +43 -92
  30. package/src/node/scope.ts +121 -0
  31. package/src/node/types.ts +120 -86
  32. package/src/node/utils.ts +95 -0
  33. package/src/utils/pipeline.ts +4 -5
  34. package/src/utils/program.ts +13 -9
  35. package/src/webgl.ts +1 -1
  36. package/src/webgpu.ts +2 -2
  37. package/dist/index.d.ts +0 -399
  38. package/dist/index.mjs +0 -48
  39. package/dist/index.mjs.map +0 -1
  40. package/dist/native.d.ts +0 -53
  41. package/dist/native.mjs +0 -48
  42. package/dist/native.mjs.map +0 -1
  43. package/dist/react.d.ts +0 -8
  44. package/dist/react.mjs +0 -48
  45. package/dist/react.mjs.map +0 -1
  46. package/dist/solid.d.ts +0 -8
  47. package/dist/solid.mjs +0 -48
  48. package/dist/solid.mjs.map +0 -1
  49. package/src/code/glsl.ts +0 -148
  50. package/src/code/wgsl.ts +0 -134
  51. package/src/node/cache.ts +0 -60
  52. package/src/node/conv.ts +0 -111
  53. package/src/node/uniform.ts +0 -92
package/src/node/const.ts CHANGED
@@ -1,130 +1,190 @@
1
- // 基本型定数
2
- export const TYPES = [
3
- 'float',
4
- 'int',
5
- 'uint',
1
+ export const SWIZZLES = ['x', 'y', 'z', 'w', 'r', 'g', 'b', 'a', 's', 't', 'p', 'q'] as const
2
+
3
+ export const CONSTANTS = [
6
4
  'bool',
7
- 'color',
8
- 'vec2',
9
- 'vec3',
10
- 'vec4',
11
- 'mat2',
12
- 'mat3',
13
- 'mat4',
5
+ 'uint',
6
+ 'int',
7
+ 'float',
8
+ 'bvec2',
9
+ 'bvec3',
10
+ 'bvec4',
14
11
  'ivec2',
15
12
  'ivec3',
16
13
  'ivec4',
17
14
  'uvec2',
18
15
  'uvec3',
19
16
  'uvec4',
20
- 'bvec2',
21
- 'bvec3',
22
- 'bvec4',
17
+ 'vec2',
18
+ 'vec3',
19
+ 'vec4',
20
+ 'color',
21
+ 'mat2',
22
+ 'mat3',
23
+ 'mat4',
23
24
  ] as const
24
25
 
25
- export type NodeType = (typeof TYPES)[number]
26
+ export const CONVERSIONS = [
27
+ 'toFloat',
28
+ 'toInt',
29
+ 'toUint',
30
+ 'toBool',
31
+ 'toVec2',
32
+ 'toVec3',
33
+ 'toVec4',
34
+ 'toIvec2',
35
+ 'toIvec3',
36
+ 'toIvec4',
37
+ 'toUvec2',
38
+ 'toUvec3',
39
+ 'toUvec4',
40
+ 'toBvec2',
41
+ 'toBvec3',
42
+ 'toBvec4',
43
+ 'toMat2',
44
+ 'toMat3',
45
+ 'toMat4',
46
+ 'toColor',
47
+ ] as const
26
48
 
27
- // スウィズル定数
28
- export const SWIZZLES = ['x', 'y', 'z', 'w', 'r', 'g', 'b', 'a', 's', 't', 'p', 'q'] as const
49
+ export const OPERATORS = {
50
+ add: '+',
51
+ sub: '-',
52
+ mul: '*',
53
+ div: '/',
54
+ mod: '%',
55
+ equal: '==',
56
+ notEqual: '!=',
57
+ lessThan: '<',
58
+ lessThanEqual: '<=',
59
+ greaterThan: '>',
60
+ greaterThanEqual: '>=',
61
+ and: '&&',
62
+ or: '||',
63
+ bitAnd: '&',
64
+ bitOr: '|',
65
+ bitXor: '^',
66
+ shiftLeft: '<<',
67
+ shiftRight: '>>',
68
+ } as const
29
69
 
30
- type AllSwizzles<T extends string> = T | `${T}${T}` | `${T}${T}${T}` | `${T}${T}${T}${T}`
31
-
32
- export type Swillzes =
33
- | AllSwizzles<'x' | 'y' | 'z' | 'w'>
34
- | AllSwizzles<'r' | 'g' | 'b' | 'a'>
35
- | AllSwizzles<'p' | 'q'>
36
- | AllSwizzles<'s' | 't'>
37
-
38
- // 演算子定数
39
- export const OPERATORS = [
40
- 'add',
41
- 'sub',
42
- 'mul',
43
- 'div',
44
- 'mod',
45
- 'equal',
46
- 'notEqual',
47
- 'lessThan',
48
- 'lessThanEqual',
49
- 'greaterThan',
50
- 'greaterThanEqual',
51
- 'and',
52
- 'or',
53
- 'not',
54
- 'assign',
55
- 'xor',
56
- 'bitAnd',
57
- 'bitNot',
58
- 'bitOr',
59
- 'bitXor',
60
- 'shiftLeft',
61
- 'shiftRight',
62
- ] as const
70
+ export const OPERATOR_KEYS = Object.keys(OPERATORS) as (keyof typeof OPERATORS)[]
63
71
 
64
- export type Operator = (typeof OPERATORS)[number]
72
+ // Function return type classification
73
+ export const SCALAR_RETURN_FUNCTIONS = ['dot', 'distance', 'length', 'lengthSq', 'determinant', 'luminance'] as const
65
74
 
66
- // 数学関数定数
67
- export const FUNCTIONS = [
75
+ export const BOOL_RETURN_FUNCTIONS = ['all', 'any'] as const
76
+
77
+ export const PRESERVE_TYPE_FUNCTIONS = [
68
78
  'abs',
69
- 'acos',
70
- 'asin',
71
- 'atan',
72
- 'atan2',
79
+ 'sign',
80
+ 'floor',
73
81
  'ceil',
74
- 'clamp',
82
+ 'round',
83
+ 'fract',
84
+ 'trunc',
85
+ 'sin',
75
86
  'cos',
76
- 'cross',
77
- 'degrees',
78
- 'distance',
79
- 'dot',
87
+ 'tan',
88
+ 'asin',
89
+ 'acos',
90
+ 'atan',
80
91
  'exp',
81
92
  'exp2',
93
+ 'log',
94
+ 'log2',
95
+ 'sqrt',
96
+ 'inverseSqrt',
97
+ 'normalize',
98
+ 'oneMinus',
99
+ 'saturate',
100
+ 'negate',
101
+ 'reciprocal',
102
+ 'dFdx',
103
+ 'dFdy',
104
+ 'fwidth',
105
+ ] as const
106
+
107
+ export const VEC3_RETURN_FUNCTIONS = ['cross'] as const
108
+
109
+ export const FIRST_ARG_TYPE_FUNCTIONS = ['reflect', 'refract'] as const
110
+
111
+ export const HIGHEST_TYPE_FUNCTIONS = ['min', 'max', 'mix', 'clamp', 'step', 'smoothstep'] as const
112
+
113
+ export const VEC4_RETURN_FUNCTIONS = ['texture', 'textureLod', 'textureSize', 'cubeTexture'] as const
114
+
115
+ export const ADDITIONAL_FUNCTIONS = [
116
+ 'atan2',
117
+ 'degrees',
82
118
  'faceforward',
83
- 'floor',
84
- 'fract',
85
- 'length',
86
- 'all',
87
- 'any',
88
119
  'bitcast',
89
120
  'cbrt',
90
- 'dFdx',
91
- 'dFdy',
92
121
  'difference',
93
122
  'equals',
94
- 'fwidth',
95
- 'inverseSqrt',
96
- 'lengthSq',
97
- 'log',
98
- 'log2',
99
- 'max',
100
- 'min',
101
- 'mix',
102
- 'negate',
103
- 'normalize',
104
- 'oneMinus',
105
123
  'pow',
106
124
  'pow2',
107
125
  'pow3',
108
126
  'pow4',
109
127
  'radians',
110
- 'reciprocal',
111
- 'reflect',
112
- 'refract',
113
- 'round',
114
- 'saturate',
115
- 'sign',
116
- 'sin',
117
- 'smoothstep',
118
- 'sqrt',
119
- 'step',
120
- 'tan',
121
128
  'transformDirection',
122
- 'trunc',
123
129
  ] as const
124
130
 
125
- export type MathFunction = (typeof FUNCTIONS)[number]
131
+ export const FUNCTIONS = [
132
+ ...SCALAR_RETURN_FUNCTIONS,
133
+ ...BOOL_RETURN_FUNCTIONS,
134
+ ...PRESERVE_TYPE_FUNCTIONS,
135
+ ...VEC3_RETURN_FUNCTIONS,
136
+ ...FIRST_ARG_TYPE_FUNCTIONS,
137
+ ...HIGHEST_TYPE_FUNCTIONS,
138
+ ...VEC4_RETURN_FUNCTIONS,
139
+ ...ADDITIONAL_FUNCTIONS,
140
+ ] as const
141
+
142
+ export const TYPE_MAPPING = {
143
+ float: 'f32',
144
+ int: 'i32',
145
+ uint: 'u32',
146
+ bool: 'bool',
147
+ vec2: 'vec2f',
148
+ vec3: 'vec3f',
149
+ vec4: 'vec4f',
150
+ mat2: 'mat2x2f',
151
+ mat3: 'mat3x3f',
152
+ mat4: 'mat4x4f',
153
+ ivec2: 'vec2i',
154
+ ivec3: 'vec3i',
155
+ ivec4: 'vec4i',
156
+ uvec2: 'vec2u',
157
+ uvec3: 'vec3u',
158
+ uvec4: 'vec4u',
159
+ bvec2: 'vec2<bool>',
160
+ bvec3: 'vec3<bool>',
161
+ bvec4: 'vec4<bool>',
162
+ } as const
163
+
164
+ export const COMPONENT_COUNT_TO_TYPE = {
165
+ 1: 'float',
166
+ 2: 'vec2',
167
+ 3: 'vec3',
168
+ 4: 'vec4',
169
+ 9: 'mat3',
170
+ 16: 'mat4',
171
+ } as const
172
+
173
+ export const BUILTIN_TYPES = {
174
+ gl_FragCoord: 'vec4',
175
+ position: 'vec3',
176
+ normal: 'vec3',
177
+ uv: 'vec2',
178
+ color: 'vec4',
179
+ } as const
180
+
181
+ export const COMPARISON_OPERATORS = [
182
+ 'equal',
183
+ 'notEqual',
184
+ 'lessThan',
185
+ 'lessThanEqual',
186
+ 'greaterThan',
187
+ 'greaterThanEqual',
188
+ ] as const
126
189
 
127
- // キャッシュ用定数
128
- export const CACHE_BOOLS = [true, false] as const
129
- export const CACHE_INTS = [0, 1, 2, 3, 4, 5] as const
130
- export const CACHE_FLOATS = [0.0, 1.0, 0.5, 2.0] as const
190
+ export const LOGICAL_OPERATORS = ['and', 'or'] as const
package/src/node/index.ts CHANGED
@@ -1,93 +1,120 @@
1
- import { float } from './conv'
2
- import { node } from './node'
3
- import { uniform } from './uniform'
1
+ import { f, n, node, u } from './node'
2
+ import { hex2rgb } from './utils'
4
3
  import { is } from '../utils/helpers'
5
- import type { X, FunctionNode, ConditionalNode } from './types'
6
- export type { X, FunctionNode, ConditionalNode }
7
- export * from './cache'
4
+ import type { X } from './types'
5
+ export * from './code'
8
6
  export * from './const'
9
- export * from './conv'
7
+ export * from './infer'
10
8
  export * from './node'
9
+ export * from './scope'
11
10
  export * from './types'
12
- export * from './uniform'
11
+ export * from './utils'
13
12
 
14
- // 関数定義
15
- export const Fn = (jsFunc: Function): FunctionNode => {
16
- const functionNode = (...args: any[]) => {
17
- const inputs = args.map((arg) => {
18
- if (is.obj(arg) && 'type' in arg && arg.type) return arg
19
- return float(arg)
20
- })
21
- const result = jsFunc(inputs)
22
- return result || float(0)
23
- }
24
- functionNode.call = (inputs: X[]) => jsFunc(inputs)
25
- return functionNode as FunctionNode
26
- }
13
+ // Default uniforms
14
+ export const iResolution = u('iResolution', [1280, 800])
15
+ export const iMouse = u('iMouse', [0, 0])
16
+ export const iTime = u('iTime', 0)
17
+ export const position = node('variable', { id: 'gl_FragCoord' })
27
18
 
28
- // 条件分岐
29
- export const If = (condition: X, callback: () => void): ConditionalNode => {
30
- callback()
19
+ // Default attributes
20
+ export const uv = (index = 0) => node('attribute', { id: `uv${index || ''}` })
21
+ export const vertexColor = (index = 0) => node('attribute', { id: `color${index || ''}` })
22
+ export const attribute = (id: string, type?: string) => node('attribute', { id, type })
23
+ export const vertexStage = (value: X) => node('vertex_stage', null, value)
31
24
 
32
- const conditionalNode = {
33
- ElseIf(newCondition: X, newCallback: () => void): ConditionalNode {
34
- newCallback()
35
- return conditionalNode
36
- },
37
- Else(elseCallback: () => void) {
38
- elseCallback()
39
- },
40
- }
25
+ // Buildin Variables
26
+ export const positionLocal = node('builtin', { id: 'positionLocal' })
27
+ export const positionWorld = node('builtin', { id: 'positionWorld' })
28
+ export const positionView = node('builtin', { id: 'positionView' })
29
+ export const normalLocal = node('builtin', { id: 'normalLocal' })
30
+ export const normalWorld = node('builtin', { id: 'normalWorld' })
31
+ export const normalView = node('builtin', { id: 'normalView' })
32
+ export const screenCoordinate = node('builtin', { id: 'screenCoordinate' })
33
+ export const screenUV = node('builtin', { id: 'screenUV' })
41
34
 
42
- return conditionalNode
35
+ // Type constructors
36
+ export const float = (x: X) => n('float', x)
37
+ export const int = (x: X) => n('int', x)
38
+ export const uint = (x: X) => n('uint', x)
39
+ export const bool = (x: X) => n('bool', x)
40
+ export const vec2 = (x?: X, y?: X) => n('vec2', x, y)
41
+ export const vec3 = (x?: X, y?: X, z?: X) => n('vec3', x, y, z)
42
+ export const vec4 = (x?: X, y?: X, z?: X, w?: X) => n('vec4', x, y, z, w)
43
+ export const mat2 = (...args: X[]) => n('mat2', ...args)
44
+ export const mat3 = (...args: X[]) => n('mat3', ...args)
45
+ export const mat4 = (...args: X[]) => n('mat4', ...args)
46
+ export const ivec2 = (x?: X, y?: X) => n('ivec2', x, y)
47
+ export const ivec3 = (x?: X, y?: X, z?: X) => n('ivec3', x, y, z)
48
+ export const ivec4 = (x?: X, y?: X, z?: X, w?: X) => n('ivec4', x, y, z, w)
49
+ export const uvec2 = (x?: X, y?: X) => n('uvec2', x, y)
50
+ export const uvec3 = (x?: X, y?: X, z?: X) => n('uvec3', x, y, z)
51
+ export const uvec4 = (x?: X, y?: X, z?: X, w?: X) => n('uvec4', x, y, z, w)
52
+ export const bvec2 = (x?: X, y?: X) => n('bvec2', x, y)
53
+ export const bvec3 = (x?: X, y?: X, z?: X) => n('bvec3', x, y, z)
54
+ export const bvec4 = (x?: X, y?: X, z?: X, w?: X) => n('bvec4', x, y, z, w)
55
+ export const color = (r?: X, g?: X, b?: X) => {
56
+ if (is.num(r) && is.und(g) && is.und(b)) return vec3(...hex2rgb(r))
57
+ return vec3(r, g, b)
43
58
  }
44
59
 
45
- // 組み込み変数
46
- export const fragCoord = node('vec4', undefined)
47
- export const position = node('vec4', undefined)
48
- export const iTime = uniform(0.0)
49
- export const iResolution = uniform([1920, 1080])
50
- export const iMouse = uniform([0, 0])
51
-
52
- // 数学関数
53
- export const abs = (x: X) => x.abs()
54
- export const sin = (x: X) => x.sin()
55
- export const cos = (x: X) => x.cos()
56
- export const tan = (x: X) => x.tan()
57
- export const sqrt = (x: X) => x.sqrt()
58
- export const floor = (x: X) => x.floor()
59
- export const ceil = (x: X) => x.ceil()
60
- export const fract = (x: X) => x.fract()
61
- export const normalize = (x: X) => x.normalize()
62
- export const length = (x: X) => x.length()
60
+ // Texture Functions
61
+ export const texture = (x: X, y: X, z?: X) => f('texture', x, y, z)
62
+ export const cubeTexture = (x: X, y: X, z?: X) => f('cubeTexture', x, y, z)
63
+ export const textureSize = (x: X, y?: X) => f('textureSize', x, y)
63
64
 
64
- /**
65
- * @TODO FIX
66
- export const min = (a: X, b: X) => {
67
- return node('float', undefined, {
68
- mathFunction: 'min',
69
- children: [a as any, b as any],
70
- })
71
- }
72
-
73
- export const max = (a: X, b: X) => {
74
- return node('float', undefined, {
75
- mathFunction: 'max',
76
- children: [a as any, b as any],
77
- })
78
- }
79
-
80
- export const mix = (a: X, b: X, t: X) => {
81
- return node('float', undefined, {
82
- mathFunction: 'mix',
83
- children: [a as any, b as any, t as any],
84
- })
85
- }
86
-
87
- export const clamp = (x: X, min: X, max: X) => {
88
- return node('float', undefined, {
89
- mathFunction: 'clamp',
90
- children: [x as any, min as any, max as any],
91
- })
92
- }
93
- */
65
+ // Math Functions
66
+ export const abs = (x: X) => f('abs', x)
67
+ export const acos = (x: X) => f('acos', x)
68
+ export const all = (x: X) => f('all', x)
69
+ export const any = (x: X) => f('any', x)
70
+ export const asin = (x: X) => f('asin', x)
71
+ export const atan = (y: X, x?: X) => (x !== undefined ? f('atan', y, x) : f('atan', y))
72
+ export const atan2 = (y: X, x: X) => f('atan', y, x)
73
+ export const bitcast = (x: X, y: X) => f('bitcast', x, y)
74
+ export const cbrt = (x: X) => f('cbrt', x)
75
+ export const ceil = (x: X) => f('ceil', x)
76
+ export const clamp = (x: X, min: X, max: X) => f('clamp', x, min, max)
77
+ export const cos = (x: X) => f('cos', x)
78
+ export const cross = (x: X, y: X) => f('cross', x, y)
79
+ export const dFdx = (p: X) => f('dFdx', p)
80
+ export const dFdy = (p: X) => f('dFdy', p)
81
+ export const degrees = (radians: X) => f('degrees', radians)
82
+ export const difference = (x: X, y: X) => f('difference', x, y)
83
+ export const distance = (x: X, y: X) => f('distance', x, y)
84
+ export const dot = (x: X, y: X) => f('dot', x, y)
85
+ export const equals = (x: X, y: X) => f('equals', x, y)
86
+ export const exp = (x: X) => f('exp', x)
87
+ export const exp2 = (x: X) => f('exp2', x)
88
+ export const faceforward = (N: X, I: X, Nref: X) => f('faceforward', N, I, Nref)
89
+ export const floor = (x: X) => f('floor', x)
90
+ export const fract = (x: X) => f('fract', x)
91
+ export const fwidth = (x: X) => f('fwidth', x)
92
+ export const inverseSqrt = (x: X) => f('inverseSqrt', x)
93
+ export const length = (x: X) => f('length', x)
94
+ export const lengthSq = (x: X) => f('lengthSq', x)
95
+ export const log = (x: X) => f('log', x)
96
+ export const log2 = (x: X) => f('log2', x)
97
+ export const max = (x: X, y: X) => f('max', x, y)
98
+ export const min = (x: X, y: X) => f('min', x, y)
99
+ export const mix = (x: X, y: X, a: X) => f('mix', x, y, a)
100
+ export const negate = (x: X) => f('negate', x)
101
+ export const normalize = (x: X) => f('normalize', x)
102
+ export const oneMinus = (x: X) => f('oneMinus', x)
103
+ export const pow = (x: X, y: X) => f('pow', x, y)
104
+ export const pow2 = (x: X) => f('pow2', x)
105
+ export const pow3 = (x: X) => f('pow3', x)
106
+ export const pow4 = (x: X) => f('pow4', x)
107
+ export const radians = (degrees: X) => f('radians', degrees)
108
+ export const reciprocal = (x: X) => f('reciprocal', x)
109
+ export const reflect = (I: X, N: X) => f('reflect', I, N)
110
+ export const refract = (I: X, N: X, eta: X) => f('refract', I, N, eta)
111
+ export const round = (x: X) => f('round', x)
112
+ export const saturate = (x: X) => f('saturate', x)
113
+ export const sign = (x: X) => f('sign', x)
114
+ export const sin = (x: X) => f('sin', x)
115
+ export const smoothstep = (e0: X, e1: X, x: X) => f('smoothstep', e0, e1, x)
116
+ export const sqrt = (x: X) => f('sqrt', x)
117
+ export const step = (edge: X, x: X) => f('step', edge, x)
118
+ export const tan = (x: X) => f('tan', x)
119
+ export const transformDirection = (dir: X, matrix: X) => f('transformDirection', dir, matrix)
120
+ export const trunc = (x: X) => f('trunc', x)
@@ -0,0 +1,93 @@
1
+ import { is } from '../utils/helpers'
2
+ import { isNodeProxy } from './utils'
3
+ import {
4
+ CONSTANTS,
5
+ SCALAR_RETURN_FUNCTIONS,
6
+ BOOL_RETURN_FUNCTIONS,
7
+ PRESERVE_TYPE_FUNCTIONS,
8
+ VEC3_RETURN_FUNCTIONS,
9
+ FIRST_ARG_TYPE_FUNCTIONS,
10
+ HIGHEST_TYPE_FUNCTIONS,
11
+ VEC4_RETURN_FUNCTIONS,
12
+ COMPARISON_OPERATORS,
13
+ LOGICAL_OPERATORS,
14
+ COMPONENT_COUNT_TO_TYPE,
15
+ BUILTIN_TYPES,
16
+ } from './const'
17
+ import type { Constants, NodeConfig, X } from './types'
18
+
19
+ const inferPrimitiveType = (x: any): Constants => {
20
+ if (is.bol(x)) return 'bool'
21
+ if (is.num(x)) return Number.isInteger(x) ? 'int' : 'float'
22
+ if (is.arr(x)) return COMPONENT_COUNT_TO_TYPE[x.length as keyof typeof COMPONENT_COUNT_TO_TYPE] || 'float'
23
+ return 'float'
24
+ }
25
+
26
+ const inferBinaryOpType = (leftType: string, rightType: string, op: string): Constants => {
27
+ if (COMPARISON_OPERATORS.includes(op as any)) return 'bool'
28
+ if (LOGICAL_OPERATORS.includes(op as any)) return 'bool'
29
+ if (leftType === rightType) return leftType as Constants
30
+ if (leftType.includes('vec') && !rightType.includes('vec')) return leftType as Constants
31
+ if (rightType.includes('vec') && !leftType.includes('vec')) return rightType as Constants
32
+ const leftPriority = CONSTANTS.indexOf(leftType as any)
33
+ const rightPriority = CONSTANTS.indexOf(rightType as any)
34
+ return (leftPriority >= rightPriority ? leftType : rightType) as Constants
35
+ }
36
+
37
+ const getHighestPriorityType = (args: X[]) => {
38
+ return args.reduce((highest, current) => {
39
+ const currentType = infer(current)
40
+ const highestPriority = CONSTANTS.indexOf(highest as any)
41
+ const currentPriority = CONSTANTS.indexOf(currentType as any)
42
+ return currentPriority > highestPriority ? currentType : highest
43
+ }, 'float')
44
+ }
45
+ const inferSwizzleType = (count: number): Constants => {
46
+ return COMPONENT_COUNT_TO_TYPE[count as keyof typeof COMPONENT_COUNT_TO_TYPE] || 'vec4'
47
+ }
48
+
49
+ const inferBuiltinType = (id: string | undefined): Constants => {
50
+ if (!id) return 'vec3'
51
+ return BUILTIN_TYPES[id as keyof typeof BUILTIN_TYPES]!
52
+ }
53
+
54
+ const inferMathType = (funcName: string, args: X[]): Constants => {
55
+ const firstArgType = args.length > 0 ? infer(args[0]) : 'float'
56
+ if (FIRST_ARG_TYPE_FUNCTIONS.includes(funcName as any)) return firstArgType as Constants
57
+ if (SCALAR_RETURN_FUNCTIONS.includes(funcName as any)) return 'float'
58
+ if (BOOL_RETURN_FUNCTIONS.includes(funcName as any)) return 'bool'
59
+ if (PRESERVE_TYPE_FUNCTIONS.includes(funcName as any)) return firstArgType as Constants
60
+ if (VEC3_RETURN_FUNCTIONS.includes(funcName as any)) return 'vec3'
61
+ if (VEC4_RETURN_FUNCTIONS.includes(funcName as any)) return 'vec4'
62
+ if (HIGHEST_TYPE_FUNCTIONS.includes(funcName as any)) return getHighestPriorityType(args) as Constants
63
+ return firstArgType as Constants
64
+ }
65
+
66
+ export const infer = (target: X, c?: NodeConfig): Constants => {
67
+ if (!target) throw ``
68
+ if (!isNodeProxy(target)) return inferPrimitiveType(target)
69
+ const { type, props } = target
70
+ const { id, children = [], value, returnType } = props
71
+ const [x, y, z] = children
72
+ if (
73
+ type === 'uniform' ||
74
+ type === 'variable' ||
75
+ type === 'constant' ||
76
+ type === 'attribute' ||
77
+ type === 'varying'
78
+ )
79
+ return inferPrimitiveType(value)
80
+ if (type === 'conversions') return x as Constants
81
+ if (type === 'operator') return inferBinaryOpType(infer(y, c), infer(z, c), x as string)
82
+ if (type === 'math_fun') return inferMathType(x as string, children.slice(1))
83
+ if (type === 'swizzle') return inferSwizzleType((x as string).length)
84
+ if (type === 'ternary') return inferBinaryOpType(infer(y, c), infer(z, c), 'add')
85
+ if (type === 'fn_run') return returnType!
86
+ if (type === 'fn_def') return returnType!
87
+ if (type === 'builtin') return inferBuiltinType(id)
88
+ return 'float'
89
+ }
90
+
91
+ export const inferParameterTypes = (args: X[], c?: NodeConfig): Constants[] => {
92
+ return args.map((arg) => infer(arg, c))
93
+ }