glre 0.27.0 → 0.29.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.
package/src/node/const.ts CHANGED
@@ -1,26 +1,49 @@
1
1
  export const SWIZZLES = ['x', 'y', 'z', 'w', 'r', 'g', 'b', 'a', 's', 't', 'p', 'q'] as const
2
2
 
3
- export const NODE_TYPES = [
4
- 'float',
5
- 'int',
6
- 'uint',
3
+ export const CONSTANTS = [
7
4
  'bool',
8
- 'color',
9
- 'vec2',
10
- 'vec3',
11
- 'vec4',
12
- 'mat2',
13
- 'mat3',
14
- 'mat4',
5
+ 'uint',
6
+ 'int',
7
+ 'float',
8
+ 'bvec2',
9
+ 'bvec3',
10
+ 'bvec4',
15
11
  'ivec2',
16
12
  'ivec3',
17
13
  'ivec4',
18
14
  'uvec2',
19
15
  'uvec3',
20
16
  'uvec4',
21
- 'bvec2',
22
- 'bvec3',
23
- 'bvec4',
17
+ 'vec2',
18
+ 'vec3',
19
+ 'vec4',
20
+ 'color',
21
+ 'mat2',
22
+ 'mat3',
23
+ 'mat4',
24
+ ] as const
25
+
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',
24
47
  ] as const
25
48
 
26
49
  export const OPERATORS = {
@@ -46,62 +69,73 @@ export const OPERATORS = {
46
69
 
47
70
  export const OPERATOR_KEYS = Object.keys(OPERATORS) as (keyof typeof OPERATORS)[]
48
71
 
49
- export const FUNCTIONS = [
72
+ export const SCALAR_RETURN_FUNCTIONS = ['dot', 'distance', 'length', 'lengthSq', 'determinant', 'luminance'] as const
73
+
74
+ export const BOOL_RETURN_FUNCTIONS = ['all', 'any'] as const
75
+
76
+ export const PRESERVE_TYPE_FUNCTIONS = [
50
77
  'abs',
51
- 'acos',
52
- 'asin',
53
- 'atan',
54
- 'atan2',
78
+ 'sign',
79
+ 'floor',
55
80
  'ceil',
56
- 'clamp',
81
+ 'round',
82
+ 'fract',
83
+ 'trunc',
84
+ 'sin',
57
85
  'cos',
58
- 'cross',
59
- 'degrees',
60
- 'distance',
61
- 'dot',
86
+ 'tan',
87
+ 'asin',
88
+ 'acos',
89
+ 'atan',
62
90
  'exp',
63
91
  'exp2',
92
+ 'log',
93
+ 'log2',
94
+ 'sqrt',
95
+ 'inverseSqrt',
96
+ 'normalize',
97
+ 'oneMinus',
98
+ 'saturate',
99
+ 'negate',
100
+ 'reciprocal',
101
+ 'dFdx',
102
+ 'dFdy',
103
+ 'fwidth',
104
+ ] as const
105
+
106
+ export const VEC3_RETURN_FUNCTIONS = ['cross'] as const
107
+
108
+ export const FIRST_ARG_TYPE_FUNCTIONS = ['reflect', 'refract'] as const
109
+
110
+ export const HIGHEST_TYPE_FUNCTIONS = ['min', 'max', 'mix', 'clamp', 'step', 'smoothstep'] as const
111
+
112
+ export const VEC4_RETURN_FUNCTIONS = ['texture', 'textureLod', 'textureSize', 'cubeTexture'] as const
113
+
114
+ export const ADDITIONAL_FUNCTIONS = [
115
+ 'atan2',
116
+ 'degrees',
64
117
  'faceforward',
65
- 'floor',
66
- 'fract',
67
- 'length',
68
- 'all',
69
- 'any',
70
118
  'bitcast',
71
119
  'cbrt',
72
- 'dFdx',
73
- 'dFdy',
74
120
  'difference',
75
121
  'equals',
76
- 'fwidth',
77
- 'inverseSqrt',
78
- 'lengthSq',
79
- 'log',
80
- 'log2',
81
- 'max',
82
- 'min',
83
- 'mix',
84
- 'negate',
85
- 'normalize',
86
- 'oneMinus',
87
122
  'pow',
88
123
  'pow2',
89
124
  'pow3',
90
125
  'pow4',
91
126
  'radians',
92
- 'reciprocal',
93
- 'reflect',
94
- 'refract',
95
- 'round',
96
- 'saturate',
97
- 'sign',
98
- 'sin',
99
- 'smoothstep',
100
- 'sqrt',
101
- 'step',
102
- 'tan',
103
127
  'transformDirection',
104
- 'trunc',
128
+ ] as const
129
+
130
+ export const FUNCTIONS = [
131
+ ...SCALAR_RETURN_FUNCTIONS,
132
+ ...BOOL_RETURN_FUNCTIONS,
133
+ ...PRESERVE_TYPE_FUNCTIONS,
134
+ ...VEC3_RETURN_FUNCTIONS,
135
+ ...FIRST_ARG_TYPE_FUNCTIONS,
136
+ ...HIGHEST_TYPE_FUNCTIONS,
137
+ ...VEC4_RETURN_FUNCTIONS,
138
+ ...ADDITIONAL_FUNCTIONS,
105
139
  ] as const
106
140
 
107
141
  export const TYPE_MAPPING = {
@@ -125,3 +159,71 @@ export const TYPE_MAPPING = {
125
159
  bvec3: 'vec3<bool>',
126
160
  bvec4: 'vec4<bool>',
127
161
  } as const
162
+
163
+ export const COMPONENT_COUNT_TO_TYPE = {
164
+ 1: 'float',
165
+ 2: 'vec2',
166
+ 3: 'vec3',
167
+ 4: 'vec4',
168
+ 9: 'mat3',
169
+ 16: 'mat4',
170
+ } as const
171
+
172
+ export const BUILTIN_TYPES = {
173
+ // WGSL builtin variables
174
+ position: 'vec4',
175
+ vertex_index: 'uint',
176
+ instance_index: 'uint',
177
+ front_facing: 'bool',
178
+ frag_depth: 'float',
179
+ sample_index: 'uint',
180
+ sample_mask: 'uint',
181
+ point_coord: 'vec2',
182
+
183
+ // TSL compatible variables
184
+ positionLocal: 'vec3',
185
+ positionWorld: 'vec3',
186
+ positionView: 'vec3',
187
+ normalLocal: 'vec3',
188
+ normalWorld: 'vec3',
189
+ normalView: 'vec3',
190
+ screenCoordinate: 'vec2',
191
+ screenUV: 'vec2',
192
+
193
+ // Legacy GLSL variables (for backward compatibility)
194
+ gl_FragCoord: 'vec4',
195
+ gl_VertexID: 'uint',
196
+ gl_InstanceID: 'uint',
197
+ gl_FrontFacing: 'bool',
198
+ gl_FragDepth: 'float',
199
+ gl_SampleID: 'uint',
200
+ gl_SampleMask: 'uint',
201
+ gl_PointCoord: 'vec2',
202
+
203
+ // Common variables
204
+ normal: 'vec3',
205
+ uv: 'vec2',
206
+ color: 'vec4',
207
+ } as const
208
+
209
+ export const COMPARISON_OPERATORS = [
210
+ 'equal',
211
+ 'notEqual',
212
+ 'lessThan',
213
+ 'lessThanEqual',
214
+ 'greaterThan',
215
+ 'greaterThanEqual',
216
+ ] as const
217
+
218
+ export const LOGICAL_OPERATORS = ['and', 'or'] as const
219
+
220
+ export const WGSL_TO_GLSL_BUILTIN = {
221
+ position: 'gl_FragCoord',
222
+ vertex_index: 'gl_VertexID',
223
+ instance_index: 'gl_InstanceID',
224
+ front_facing: 'gl_FrontFacing',
225
+ frag_depth: 'gl_FragDepth',
226
+ sample_index: 'gl_SampleID',
227
+ sample_mask: 'gl_SampleMask',
228
+ point_coord: 'gl_PointCoord',
229
+ } as const
package/src/node/index.ts CHANGED
@@ -1,91 +1,137 @@
1
- import { f, n, node, u } from './node'
1
+ import { conversion as c, function_ as f, node } from './node'
2
+ import { hex2rgb } from './utils'
3
+ import { is } from '../utils/helpers'
2
4
  import type { X } from './types'
3
5
  export * from './code'
4
6
  export * from './const'
7
+ export * from './infer'
5
8
  export * from './node'
6
9
  export * from './scope'
7
10
  export * from './types'
8
11
  export * from './utils'
9
12
 
13
+ // x ? y : z
14
+ export const select = (x: X, y: X, z: X) => node('ternary', null, x, y, z)
15
+
16
+ // uniform and attribute
17
+ export const uniform = (value: number | number[], id?: string) => node('uniform', { id, value })
18
+ export const varying = (value: number | number[], id?: string) => node('varying', { id, value })
19
+ export const attribute = (value: number | number[], id?: string) => node('varying', { id, value })
20
+ export const variable = (id: string) => node('variable', { id })
21
+ export const builtin = (id: string) => node('builtin', { id })
22
+
10
23
  // Default uniforms
11
- export const iResolution = u('iResolution', [1280, 800])
12
- export const iMouse = u('iMouse', [0, 0])
13
- export const iTime = u('iTime', 0)
14
- export const fragCoord = node('variable', { id: 'fragCoord' })
24
+ export const iResolution = uniform([1280, 800], 'iResolution')
25
+ export const iMouse = uniform([0, 0], 'iMouse')
26
+ export const iTime = uniform(0, 'iTime')
27
+
28
+ // Builtin Variables
29
+ export const position = node('builtin', { id: 'position' })
30
+ export const vertexIndex = node('builtin', { id: 'vertex_index' })
31
+ export const instanceIndex = node('builtin', { id: 'instance_index' })
32
+ export const frontFacing = node('builtin', { id: 'front_facing' })
33
+ export const fragDepth = node('builtin', { id: 'frag_depth' })
34
+ export const sampleIndex = node('builtin', { id: 'sample_index' })
35
+ export const sampleMask = node('builtin', { id: 'sample_mask' })
36
+ export const pointCoord = node('builtin', { id: 'point_coord' })
37
+
38
+ // TSL Compatible Builtin Variables
39
+ export const positionLocal = node('builtin', { id: 'position' })
40
+ export const positionWorld = node('builtin', { id: 'positionWorld' })
41
+ export const positionView = node('builtin', { id: 'positionView' })
42
+ export const normalLocal = node('builtin', { id: 'normalLocal' })
43
+ export const normalWorld = node('builtin', { id: 'normalWorld' })
44
+ export const normalView = node('builtin', { id: 'normalView' })
45
+ export const screenCoordinate = node('builtin', { id: 'screenCoordinate' })
46
+ export const screenUV = node('builtin', { id: 'screenUV' })
47
+
48
+ // Legacy aliases for backward compatibility
49
+ export const fragCoord = position
50
+ export const vertexId = vertexIndex
15
51
 
16
52
  // Type constructors
17
- export const float = (x: X) => n('float', x)
18
- export const int = (x: X) => n('int', x)
19
- export const uint = (x: X) => n('uint', x)
20
- export const bool = (x: X) => n('bool', x)
21
- export const vec2 = (x?: X, y?: X) => n('vec2', x, y)
22
- export const vec3 = (x?: X, y?: X, z?: X) => n('vec3', x, y, z)
23
- export const vec4 = (x?: X, y?: X, z?: X, w?: X) => n('vec4', x, y, z, w)
24
- export const mat2 = (...args: X[]) => n('mat2', ...args)
25
- export const mat3 = (...args: X[]) => n('mat3', ...args)
26
- export const mat4 = (...args: X[]) => n('mat4', ...args)
27
- export const ivec2 = (x?: X, y?: X) => n('ivec2', x, y)
28
- export const ivec3 = (x?: X, y?: X, z?: X) => n('ivec3', x, y, z)
29
- export const ivec4 = (x?: X, y?: X, z?: X, w?: X) => n('ivec4', x, y, z, w)
30
- export const uvec2 = (x?: X, y?: X) => n('uvec2', x, y)
31
- export const uvec3 = (x?: X, y?: X, z?: X) => n('uvec3', x, y, z)
32
- export const uvec4 = (x?: X, y?: X, z?: X, w?: X) => n('uvec4', x, y, z, w)
33
- export const bvec2 = (x?: X, y?: X) => n('bvec2', x, y)
34
- export const bvec3 = (x?: X, y?: X, z?: X) => n('bvec3', x, y, z)
35
- export const bvec4 = (x?: X, y?: X, z?: X, w?: X) => n('bvec4', x, y, z, w)
53
+ export const float = (x: X) => c('float', x)
54
+ export const int = (x: X) => c('int', x)
55
+ export const uint = (x: X) => c('uint', x)
56
+ export const bool = (x: X) => c('bool', x)
57
+ export const vec2 = (x?: X, y?: X) => c('vec2', x, y)
58
+ export const vec3 = (x?: X, y?: X, z?: X) => c('vec3', x, y, z)
59
+ export const vec4 = (x?: X, y?: X, z?: X, w?: X) => c('vec4', x, y, z, w)
60
+ export const mat2 = (...args: X[]) => c('mat2', ...args)
61
+ export const mat3 = (...args: X[]) => c('mat3', ...args)
62
+ export const mat4 = (...args: X[]) => c('mat4', ...args)
63
+ export const ivec2 = (x?: X, y?: X) => c('ivec2', x, y)
64
+ export const ivec3 = (x?: X, y?: X, z?: X) => c('ivec3', x, y, z)
65
+ export const ivec4 = (x?: X, y?: X, z?: X, w?: X) => c('ivec4', x, y, z, w)
66
+ export const uvec2 = (x?: X, y?: X) => c('uvec2', x, y)
67
+ export const uvec3 = (x?: X, y?: X, z?: X) => c('uvec3', x, y, z)
68
+ export const uvec4 = (x?: X, y?: X, z?: X, w?: X) => c('uvec4', x, y, z, w)
69
+ export const bvec2 = (x?: X, y?: X) => c('bvec2', x, y)
70
+ export const bvec3 = (x?: X, y?: X, z?: X) => c('bvec3', x, y, z)
71
+ export const bvec4 = (x?: X, y?: X, z?: X, w?: X) => c('bvec4', x, y, z, w)
72
+ export const color = (r?: X, g?: X, b?: X) => {
73
+ if (is.num(r) && is.und(g) && is.und(b)) return vec3(...hex2rgb(r))
74
+ return vec3(r, g, b)
75
+ }
76
+
77
+ // Texture Functions
78
+ export const texture = (x: X, y: X, z?: X) => f('texture', x, y, z)
79
+ export const cubeTexture = (x: X, y: X, z?: X) => f('cubeTexture', x, y, z)
80
+ export const textureSize = (x: X, y?: X) => f('textureSize', x, y)
36
81
 
37
82
  // Math Functions
38
- export const abs = (x: X) => f('abs', x) // Return the absolute value of the parameter.
39
- export const acos = (x: X) => f('acos', x) // Return the arccosine of the parameter.
40
- export const all = (x: X) => f('all', x) // Return true if all components of x are true.
41
- export const any = (x: X) => f('any', x) // Return true if any component of x is true.
42
- export const asin = (x: X) => f('asin', x) // Return the arcsine of the parameter.
43
- export const atan = (y: X, x: X) => f('atan', y, x) // Return the arc-tangent of the parameters.
44
- export const bitcast = (x: X, y: X) => f('bitcast', x, y) // Reinterpret the bits of a value as a different type.
45
- export const cbrt = (x: X) => f('cbrt', x) // Return the cube root of the parameter.
46
- export const ceil = (x: X) => f('ceil', x) // Find the nearest integer that is greater than or equal to the parameter.
47
- export const clamp = (x: X, min: X, max: X) => f('clamp', x, min, max) // Constrain a value to lie between two further values.
48
- export const cos = (x: X) => f('cos', x) // Return the cosine of the parameter.
49
- export const cross = (x: X, y: X) => f('cross', x, y) // Calculate the cross product of two vectors.
50
- export const dFdx = (p: X) => f('dFdx', p) // Return the partial derivative of an argument with respect to x.
51
- export const dFdy = (p: X) => f('dFdy', p) // Return the partial derivative of an argument with respect to y.
52
- export const degrees = (radians: X) => f('degrees', radians) // Convert a quantity in radians to degrees.
53
- export const difference = (x: X, y: X) => f('difference', x, y) // Calculate the absolute difference between two values.
54
- export const distance = (x: X, y: X) => f('distance', x, y) // Calculate the distance between two points.
55
- export const dot = (x: X, y: X) => f('dot', x, y) // Calculate the dot product of two vectors.
56
- export const equals = (x: X, y: X) => f('equals', x, y) // Return true if x equals y.
57
- export const exp = (x: X) => f('exp', x) // Return the natural exponentiation of the parameter.
58
- export const exp2 = (x: X) => f('exp2', x) // Return 2 raised to the power of the parameter.
59
- export const faceforward = (N: X, I: X, Nref: X) => f('faceforward', N, I, Nref) // Return a vector pointing in the same direction as another.
60
- export const floor = (x: X) => f('floor', x) // Find the nearest integer less than or equal to the parameter.
61
- export const fract = (x: X) => f('fract', x) // Compute the fractional part of the argument.
62
- export const fwidth = (x: X) => f('fwidth', x) // Return the sum of the absolute derivatives in x and y.
63
- export const inverseSqrt = (x: X) => f('inverseSqrt', x) // Return the inverse of the square root of the parameter.
64
- export const length = (x: X) => f('length', x) // Calculate the length of a vector.
65
- export const lengthSq = (x: X) => f('lengthSq', x) // Calculate the squared length of a vector.
66
- export const log = (x: X) => f('log', x) // Return the natural logarithm of the parameter.
67
- export const log2 = (x: X) => f('log2', x) // Return the base 2 logarithm of the parameter.
68
- export const max = (x: X, y: X) => f('max', x, y) // Return the greater of two values.
69
- export const min = (x: X, y: X) => f('min', x, y) // Return the lesser of two values.
70
- export const mix = (x: X, y: X, a: X) => f('mix', x, y, a) // Linearly interpolate between two values.
71
- export const negate = (x: X) => f('negate', x) // Negate the value of the parameter ( -x ).
72
- export const normalize = (x: X) => f('normalize', x) // Calculate the unit vector in the same direction as the original vector.
73
- export const oneMinus = (x: X) => f('oneMinus', x) // Return 1 minus the parameter.
74
- export const pow = (x: X, y: X) => f('pow', x, y) // Return the value of the first parameter raised to the power of the second.
75
- export const pow2 = (x: X) => f('pow2', x) // Return the square of the parameter.
76
- export const pow3 = (x: X) => f('pow3', x) // Return the cube of the parameter.
77
- export const pow4 = (x: X) => f('pow4', x) // Return the fourth power of the parameter.
78
- export const radians = (degrees: X) => f('radians', degrees) // Convert a quantity in degrees to radians.
79
- export const reciprocal = (x: X) => f('reciprocal', x) // Return the reciprocal of the parameter (1/x).
80
- export const reflect = (I: X, N: X) => f('reflect', I, N) // Calculate the reflection direction for an incident vector.
81
- export const refract = (I: X, N: X, eta: X) => f('refract', I, N, eta) // Calculate the refraction direction for an incident vector.
82
- export const round = (x: X) => f('round', x) // Round the parameter to the nearest integer.
83
- export const saturate = (x: X) => f('saturate', x) // Constrain a value between 0 and 1.
84
- export const sign = (x: X) => f('sign', x) // Extract the sign of the parameter.
85
- export const sin = (x: X) => f('sin', x) // Return the sine of the parameter.
86
- export const smoothstep = (e0: X, e1: X, x: X) => f('smoothstep', e0, e1, x) // Perform Hermite interpolation between two values.
87
- export const sqrt = (x: X) => f('sqrt', x) // Return the square root of the parameter.
88
- export const step = (edge: X, x: X) => f('step', edge, x) // Generate a step function by comparing two values.
89
- export const tan = (x: X) => f('tan', x) // Return the tangent of the parameter.
90
- export const transformDirection = (dir: X, matrix: X) => f('transformDirection', dir, matrix) // Transform the direction of a vector by a matrix and then normalize the result.
91
- export const trunc = (x: X) => f('trunc', x) // Truncate the parameter, removing the fractional part.
83
+ export const abs = (x: X) => f('abs', x)
84
+ export const acos = (x: X) => f('acos', x)
85
+ export const all = (x: X) => f('all', x)
86
+ export const any = (x: X) => f('any', x)
87
+ export const asin = (x: X) => f('asin', x)
88
+ export const atan = (y: X, x?: X) => (x !== undefined ? f('atan', y, x) : f('atan', y))
89
+ export const atan2 = (y: X, x: X) => f('atan', y, x)
90
+ export const bitcast = (x: X, y: X) => f('bitcast', x, y)
91
+ export const cbrt = (x: X) => f('cbrt', x)
92
+ export const ceil = (x: X) => f('ceil', x)
93
+ export const clamp = (x: X, min: X, max: X) => f('clamp', x, min, max)
94
+ export const cos = (x: X) => f('cos', x)
95
+ export const cross = (x: X, y: X) => f('cross', x, y)
96
+ export const dFdx = (p: X) => f('dFdx', p)
97
+ export const dFdy = (p: X) => f('dFdy', p)
98
+ export const degrees = (radians: X) => f('degrees', radians)
99
+ export const difference = (x: X, y: X) => f('difference', x, y)
100
+ export const distance = (x: X, y: X) => f('distance', x, y)
101
+ export const dot = (x: X, y: X) => f('dot', x, y)
102
+ export const equals = (x: X, y: X) => f('equals', x, y)
103
+ export const exp = (x: X) => f('exp', x)
104
+ export const exp2 = (x: X) => f('exp2', x)
105
+ export const faceforward = (N: X, I: X, Nref: X) => f('faceforward', N, I, Nref)
106
+ export const floor = (x: X) => f('floor', x)
107
+ export const fract = (x: X) => f('fract', x)
108
+ export const fwidth = (x: X) => f('fwidth', x)
109
+ export const inverseSqrt = (x: X) => f('inverseSqrt', x)
110
+ export const length = (x: X) => f('length', x)
111
+ export const lengthSq = (x: X) => f('lengthSq', x)
112
+ export const log = (x: X) => f('log', x)
113
+ export const log2 = (x: X) => f('log2', x)
114
+ export const max = (x: X, y: X) => f('max', x, y)
115
+ export const min = (x: X, y: X) => f('min', x, y)
116
+ export const mix = (x: X, y: X, a: X) => f('mix', x, y, a)
117
+ export const negate = (x: X) => f('negate', x)
118
+ export const normalize = (x: X) => f('normalize', x)
119
+ export const oneMinus = (x: X) => f('oneMinus', x)
120
+ export const pow = (x: X, y: X) => f('pow', x, y)
121
+ export const pow2 = (x: X) => f('pow2', x)
122
+ export const pow3 = (x: X) => f('pow3', x)
123
+ export const pow4 = (x: X) => f('pow4', x)
124
+ export const radians = (degrees: X) => f('radians', degrees)
125
+ export const reciprocal = (x: X) => f('reciprocal', x)
126
+ export const reflect = (I: X, N: X) => f('reflect', I, N)
127
+ export const refract = (I: X, N: X, eta: X) => f('refract', I, N, eta)
128
+ export const round = (x: X) => f('round', x)
129
+ export const saturate = (x: X) => f('saturate', x)
130
+ export const sign = (x: X) => f('sign', x)
131
+ export const sin = (x: X) => f('sin', x)
132
+ export const smoothstep = (e0: X, e1: X, x: X) => f('smoothstep', e0, e1, x)
133
+ export const sqrt = (x: X) => f('sqrt', x)
134
+ export const step = (edge: X, x: X) => f('step', edge, x)
135
+ export const tan = (x: X) => f('tan', x)
136
+ export const transformDirection = (dir: X, matrix: X) => f('transformDirection', dir, matrix)
137
+ export const trunc = (x: X) => f('trunc', x)
@@ -0,0 +1,96 @@
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, NodeProxy, X } from './types'
18
+
19
+ const inferPrimitiveType = (x: any): Constants => {
20
+ if (is.bol(x)) return 'bool'
21
+ if (is.num(x)) return 'float' // Number.isInteger(x) ? 'int' : 'float' // @TODO FIX
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[], c: NodeConfig) => {
38
+ return args.reduce((highest, current) => {
39
+ const currentType = infer(current, c)
40
+ const highestPriority = CONSTANTS.indexOf(highest as any)
41
+ const currentPriority = CONSTANTS.indexOf(currentType as any)
42
+ return currentPriority > highestPriority ? currentType : highest
43
+ }, 'float') as Constants
44
+ }
45
+
46
+ const inferSwizzleType = (count: number): Constants => {
47
+ return COMPONENT_COUNT_TO_TYPE[count as keyof typeof COMPONENT_COUNT_TO_TYPE]!
48
+ }
49
+
50
+ const inferBuiltinType = (id: string | undefined): Constants => {
51
+ return BUILTIN_TYPES[id as keyof typeof BUILTIN_TYPES]!
52
+ }
53
+
54
+ const inferMathType = (funcName: string, args: X[], c: NodeConfig): Constants => {
55
+ const firstArgType = args.length > 0 ? infer(args[0], c) : 'float'
56
+ if (FIRST_ARG_TYPE_FUNCTIONS.includes(funcName as any)) return firstArgType
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
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, c)
63
+ return firstArgType
64
+ }
65
+
66
+ export const inferImpl = (target: NodeProxy, c: NodeConfig): Constants => {
67
+ const { type, props } = target
68
+ const { id, children = [], value } = props
69
+ const [x, y, z] = children
70
+ if (
71
+ type === 'uniform' ||
72
+ type === 'variable' ||
73
+ type === 'constant' ||
74
+ type === 'attribute' ||
75
+ type === 'varying'
76
+ )
77
+ return inferPrimitiveType(value)
78
+ if (type === 'conversion') return x as Constants
79
+ if (type === 'operator') return inferBinaryOpType(infer(y, c), infer(z, c), x as string)
80
+ if (type === 'function') return inferMathType(x as string, children.slice(1), c)
81
+ if (type === 'swizzle') return inferSwizzleType((x as string).length)
82
+ if (type === 'ternary') return inferBinaryOpType(infer(y, c), infer(z, c), 'add')
83
+ if (type === 'define') return y ? infer(y, c) : 'void'
84
+ if (type === 'builtin') return inferBuiltinType(id)
85
+ return 'float'
86
+ }
87
+
88
+ export const infer = (target: X, c: NodeConfig | null): Constants => {
89
+ if (!c) c = {}
90
+ if (!isNodeProxy(target)) return inferPrimitiveType(target)
91
+ if (!c.infers) c.infers = new WeakMap<NodeProxy, Constants>()
92
+ if (c.infers.has(target)) return c.infers.get(target)!
93
+ const ret = inferImpl(target, c)
94
+ c.infers.set(target, ret)
95
+ return ret
96
+ }
package/src/node/node.ts CHANGED
@@ -1,46 +1,42 @@
1
1
  import { code } from './code'
2
2
  import { assign, toVar } from './scope'
3
- import { getId, isFunction, isOperator, isSwizzle } from './utils'
3
+ import { getId, isConversion, isFunction, isOperator, isSwizzle } from './utils'
4
4
  import type { Functions, NodeProps, NodeProxy, NodeTypes, Operators, Swizzles, X } from './types'
5
5
 
6
- const toPrimitive = (x: X) => {
7
- return (hint: string) => {
8
- if (hint === 'string') return code(x)
9
- }
6
+ const toPrimitive = (x: X, hint: string) => {
7
+ if (hint === 'string') return code(x)
10
8
  }
11
9
 
12
10
  export const node = (type: NodeTypes, props?: NodeProps | null, ...args: X[]) => {
13
11
  if (!props) props = {}
14
12
  if (args.length) props.children = args
15
- const x = new Proxy(() => {}, {
16
- get(_, key) {
17
- if (key === 'type') return type
18
- if (key === 'props') return props
19
- if (key === 'toVar') return toVar(x)
20
- if (key === 'assign') return assign(x)
21
- if (key === 'isProxy') return true
22
- if (key === 'toString') return code.bind(null, x)
23
- if (key === Symbol.toPrimitive) return toPrimitive(x)
24
- if (isSwizzle(key)) return s(key, x)
25
- if (isOperator(key)) return (...y: X[]) => o(key, x, ...y)
26
- if (isFunction(key)) return (...y: X[]) => f(key, x, ...y)
27
- return toVar(x)('')
28
- },
29
- set(_, key, value) {
30
- if (isSwizzle(key)) {
31
- s(key, x).assign(value)
32
- return true
33
- }
34
- return false
35
- },
36
- }) as unknown as NodeProxy
13
+ const get = (_: unknown, key: string | Symbol) => {
14
+ if (key === 'type') return type
15
+ if (key === 'props') return props
16
+ if (key === 'toVar') return toVar.bind(null, x)
17
+ if (key === 'assign') return assign.bind(null, x)
18
+ if (key === 'isProxy') return true
19
+ if (key === 'toString') return code.bind(null, x)
20
+ if (key === Symbol.toPrimitive) return toPrimitive.bind(null, x)
21
+ if (isSwizzle(key)) return swizzle(key, x)
22
+ if (isOperator(key)) return (...y: X[]) => operator(key, x, ...y)
23
+ if (isFunction(key)) return (...y: X[]) => function_(key, x, ...y)
24
+ if (isConversion(key)) return conversion(key, x)
25
+ }
26
+ const set = (_: unknown, key: string, value: X) => {
27
+ if (isSwizzle(key)) {
28
+ swizzle(key, x).assign(value)
29
+ return true
30
+ }
31
+ return false
32
+ }
33
+ const x = new Proxy({}, { get, set }) as unknown as NodeProxy
37
34
  return x
38
35
  }
39
36
 
40
37
  // Node shorthands
41
- export const v = (...args: X[]) => node('variable', { id: getId() }, ...args)
42
- export const u = (key: string, defaultValue?: number | number[]) => node('uniform', { defaultValue }, key)
43
- export const s = (key: Swizzles, arg: X) => node('swizzle', null, key, arg)
44
- export const n = (key: string, ...args: X[]) => node('node_type', null, key, ...args)
45
- export const o = (key: Operators, ...args: X[]) => node('operator', null, key, ...args)
46
- export const f = (key: Functions, ...args: X[]) => node('math_fun', null, key, ...args)
38
+ export const variable = (...args: X[]) => node('variable', { id: getId() }, ...args)
39
+ export const swizzle = (key: Swizzles, arg: X) => node('swizzle', null, key, arg)
40
+ export const operator = (key: Operators, ...args: X[]) => node('operator', null, key, ...args)
41
+ export const function_ = (key: Functions, ...args: X[]) => node('function', null, key, ...args)
42
+ export const conversion = (key: string, ...args: X[]) => node('conversion', null, key, ...args)