glre 0.32.0 → 0.34.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/parse.ts CHANGED
@@ -1,12 +1,20 @@
1
- import { infer } from './infer'
2
- import { formatConversions, joins } from './utils'
1
+ import { is } from '../utils/helpers'
3
2
  import { code } from './code'
4
- import type { Constants, NodeContext, NodeProps, X } from './types'
3
+ import { infer } from './infer'
4
+ import { formatConversions, addDependency } from './utils'
5
+ import type { Constants, NodeContext, NodeProps, NodeProxy, X } from './types'
6
+
7
+ export const parseArray = (children: X[], c: NodeContext) => {
8
+ return children
9
+ .filter((x) => !is.und(x) && !is.nul(x))
10
+ .map((x) => code(x, c))
11
+ .join(', ')
12
+ }
5
13
 
6
14
  export const parseTexture = (c: NodeContext, y: X, z: X, w: X) => {
7
15
  if (c.isWebGL) {
8
16
  const args = w ? [y, z, w] : [y, z]
9
- return `texture(${joins(args, c)})`
17
+ return `texture(${parseArray(args, c)})`
10
18
  }
11
19
  const _y = code(y, c)
12
20
  const args = [_y, _y + 'Sampler', code(z, c)]
@@ -43,10 +51,10 @@ export const parseSwitch = (c: NodeContext, x: X, children: X[]) => {
43
51
  }
44
52
 
45
53
  export const parseDeclare = (c: NodeContext, x: X, y: X) => {
46
- const varType = infer(x, c)
54
+ const type = infer(x, c)
47
55
  const varName = (y as any)?.props?.id
48
- if (c.isWebGL) return `${varType} ${varName} = ${code(x, c)};`
49
- const wgslType = formatConversions(varType)
56
+ if (c.isWebGL) return `${type} ${varName} = ${code(x, c)};`
57
+ const wgslType = formatConversions(type)
50
58
  return `var ${varName}: ${wgslType} = ${code(x, c)};`
51
59
  }
52
60
 
@@ -65,10 +73,14 @@ export const parseDefine = (c: NodeContext, props: NodeProps, returnType: Consta
65
73
  }
66
74
  const ret = []
67
75
  if (c?.isWebGL) {
68
- for (const [id, type] of argParams) params.push(`${type} ${id}`)
76
+ for (const [paramId, type] of argParams) {
77
+ addDependency(c, id!, type)
78
+ params.push(`${type} ${paramId}`)
79
+ }
80
+ addDependency(c, id!, returnType)
69
81
  ret.push(`${returnType} ${id}(${params}) {`)
70
82
  } else {
71
- for (const [id, type] of argParams) params.push(`${id}: ${formatConversions(type, c)}`)
83
+ for (const [paramId, type] of argParams) params.push(`${paramId}: ${formatConversions(type, c)}`)
72
84
  ret.push(`fn ${id}(${params}) -> ${formatConversions(returnType, c)} {`)
73
85
  }
74
86
  const scopeCode = code(x, c)
@@ -77,42 +89,74 @@ export const parseDefine = (c: NodeContext, props: NodeProps, returnType: Consta
77
89
  return ret.join('\n')
78
90
  }
79
91
 
92
+ export const parseStructHead = (c: NodeContext, id: string, fields: Record<string, NodeProxy> = {}) => {
93
+ const lines: string[] = []
94
+ for (const key in fields) {
95
+ const fieldType = fields[key]
96
+ const type = infer(fieldType, c)
97
+ if (c.isWebGL) addDependency(c, id, type)
98
+ lines.push(c.isWebGL ? `${type} ${key};` : `${key}: ${formatConversions(type, c)},`)
99
+ }
100
+ const ret = lines.join('\n ')
101
+ return `struct ${id} {\n ${ret}\n};`
102
+ }
103
+
104
+ export const parseStruct = (
105
+ c: NodeContext,
106
+ id: string,
107
+ instanceId = '',
108
+ fields?: Record<string, NodeProxy>,
109
+ initialValues?: Record<string, NodeProxy>
110
+ ) => {
111
+ if (c.isWebGL) {
112
+ if (initialValues) {
113
+ const ordered = []
114
+ for (const key in fields) ordered.push(initialValues[key])
115
+ return `${id} ${instanceId} = ${id}(${parseArray(ordered, c)});`
116
+ } else return `${id} ${instanceId};`
117
+ } else {
118
+ if (initialValues) {
119
+ const ordered = []
120
+ for (const key in fields) ordered.push(initialValues[key])
121
+ return `var ${instanceId}: ${id} = ${id}(${parseArray(ordered, c)});`
122
+ } else return `var ${instanceId}: ${id};`
123
+ }
124
+ }
125
+
80
126
  /**
81
127
  * headers
82
128
  */
83
- export const parseVaryingHead = (c: NodeContext, id: string, varType: string) => {
129
+ export const parseVaryingHead = (c: NodeContext, id: string, type: string) => {
84
130
  return c.isWebGL
85
- ? `${varType} ${id};`
86
- : `@location(${c.vertVaryings!.size}) ${id}: ${formatConversions(varType, c)}`
131
+ ? `${type} ${id};`
132
+ : `@location(${c.code?.vertVaryings?.size || 0}) ${id}: ${formatConversions(type, c)}`
87
133
  }
88
134
 
89
- export const parseUniformHead = (c: NodeContext, id: string, varType: Constants) => {
90
- const isTexture = varType === 'sampler2D' || varType === 'texture'
135
+ export const parseUniformHead = (c: NodeContext, id: string, type: Constants) => {
136
+ const isTexture = type === 'sampler2D' || type === 'texture'
91
137
  if (c.isWebGL)
92
138
  return isTexture //
93
139
  ? `uniform sampler2D ${id};`
94
- : `uniform ${varType} ${id};`
140
+ : `uniform ${type} ${id};`
95
141
  if (isTexture) {
96
- const { group = 1, binding = 0 } = c.webgpu?.textures.map.get(id) || {}
142
+ const { group = 1, binding = 0 } = c.gl?.webgpu?.textures.map.get(id) || {}
97
143
  return (
98
144
  `@group(${group}) @binding(${binding}) var ${id}Sampler: sampler;\n` +
99
145
  `@group(${group}) @binding(${binding + 1}) var ${id}: texture_2d<f32>;`
100
146
  )
101
147
  }
102
- const { group = 0, binding = 0 } = c.webgpu?.uniforms.map.get(id) || {}
103
- const wgslType = formatConversions(varType, c)
148
+ const { group = 0, binding = 0 } = c.gl?.webgpu?.uniforms.map.get(id) || {}
149
+ const wgslType = formatConversions(type, c)
104
150
  return `@group(${group}) @binding(${binding}) var<uniform> ${id}: ${wgslType};`
105
151
  }
106
152
 
107
- export const parseAttribHead = (c: NodeContext, id: string, varType: Constants) => {
108
- if (c.isWebGL) return `${varType} ${id};`
109
- const { location = 0 } = c.webgpu?.attribs.map.get(id) || {}
110
- const wgslType = formatConversions(varType, c)
153
+ export const parseAttribHead = (c: NodeContext, id: string, type: Constants) => {
154
+ if (c.isWebGL) return `${type} ${id};`
155
+ const { location = 0 } = c.gl?.webgpu?.attribs.map.get(id) || {}
156
+ const wgslType = formatConversions(type, c)
111
157
  return `@location(${location}) ${id}: ${wgslType}`
112
158
  }
113
159
 
114
- export const parseConstantHead = (c: NodeContext, id: string, varType: Constants, value: string) => {
115
- return c.isWebGL
116
- ? `const ${varType} ${id} = ${value};`
117
- : `const ${id}: ${formatConversions(varType, c)} = ${value};`
160
+ export const parseConstantHead = (c: NodeContext, id: string, type: Constants, value: string) => {
161
+ return c.isWebGL ? `const ${type} ${id} = ${value};` : `const ${id}: ${formatConversions(type, c)} = ${value};`
118
162
  }
package/src/node/scope.ts CHANGED
@@ -1,7 +1,6 @@
1
- import { int } from '.'
2
1
  import { conversion, node } from './node'
3
2
  import { getId } from './utils'
4
- import type { FnLayout, NodeProps, NodeProxy, X } from './types'
3
+ import type { FnLayout, NodeProps, NodeProxy, X, Constants, Int } from './types'
5
4
 
6
5
  let scope: NodeProxy | null = null
7
6
  let define: NodeProxy | null = null
@@ -16,26 +15,35 @@ const addToScope = (x: NodeProxy) => {
16
15
  props.inferFrom.push(x)
17
16
  }
18
17
 
19
- export const toVar = (x: X, id?: string) => {
18
+ export const toVar = <T extends Constants>(x: X<T>, id?: string): NodeProxy<T> => {
20
19
  if (!id) id = getId()
21
- const y = node('variable', { id, inferFrom: [x] })
20
+ const y = node<T>('variable', { id, inferFrom: [x] })
22
21
  const z = node('declare', null, x, y)
23
22
  addToScope(z)
24
23
  return y
25
24
  }
26
25
 
27
- export const assign = (x: X, y: X) => {
26
+ export const assign = <T extends Constants>(x: X<T>, y: X<T>): X<T> => {
28
27
  const z = node('assign', null, x, y)
29
28
  addToScope(z)
30
29
  return x
31
30
  }
32
31
 
33
- export const Return = (x: X) => {
34
- const y = node('return', { inferFrom: [x] }, x)
32
+ export const Return = <T extends Constants>(x: X<T>): NodeProxy<T> => {
33
+ const y = node<T>('return', { inferFrom: [x] }, x)
35
34
  addToScope(y)
36
35
  return y
37
36
  }
38
37
 
38
+ export const struct = <T extends Record<string, NodeProxy>>(fields: T, id = getId()) => {
39
+ return (initialValues: T = {} as T, instanceId = getId()) => {
40
+ const x = node('variable', { id: instanceId, inferFrom: [id] })
41
+ const y = node('struct', { id, fields, initialValues }, x)
42
+ addToScope(y)
43
+ return x
44
+ }
45
+ }
46
+
39
47
  const scoped = (x: NodeProxy, fun: () => NodeProxy | void, y = define) => {
40
48
  // cache to revert
41
49
  const _scope = scope
@@ -51,7 +59,7 @@ const scoped = (x: NodeProxy, fun: () => NodeProxy | void, y = define) => {
51
59
  define = _define
52
60
  }
53
61
 
54
- export const If = (x: X, fun: () => void) => {
62
+ export const If = (x: NodeProxy, fun: () => void) => {
55
63
  const y = node('scope')
56
64
  scoped(y, fun)
57
65
  const ifNode = node('if', null, x, y)
@@ -72,15 +80,15 @@ export const If = (x: X, fun: () => void) => {
72
80
  return ret()
73
81
  }
74
82
 
75
- export const Loop = (x: X, fun: (params: { i: NodeProxy }) => void) => {
83
+ export const Loop = (x: NodeProxy, fun: (params: { i: Int }) => void) => {
76
84
  const y = node('scope')
77
- scoped(y, () => fun({ i: node('variable', { id: 'i', inferFrom: [int(0)] }) }))
85
+ scoped(y, () => fun({ i: node<'int'>('variable', { id: 'i', inferFrom: [conversion('int', 0)] }) }))
78
86
  const ret = node('loop', null, x, y)
79
87
  addToScope(ret)
80
88
  return ret
81
89
  }
82
90
 
83
- export const Switch = (x: X) => {
91
+ export const Switch = (x: NodeProxy) => {
84
92
  const switchNode = node('switch', null, x)
85
93
  addToScope(switchNode)
86
94
  const ret = () => ({
@@ -98,14 +106,16 @@ export const Switch = (x: X) => {
98
106
  switchNode.props.children!.push(scope)
99
107
  },
100
108
  })
101
-
102
109
  return ret()
103
110
  }
104
111
 
105
- export const Fn = (fun: (paramVars: NodeProxy[]) => NodeProxy) => {
112
+ export const Fn = <ReturnType extends Constants, Args extends Constants[]>(
113
+ fun: (paramVars: NodeProxy[]) => NodeProxy<ReturnType> | void,
114
+ defaultId = getId()
115
+ ) => {
106
116
  let layout: FnLayout
107
- const ret = (...args: X[]) => {
108
- const id = layout?.name || getId()
117
+ const ret = (...args: X<Args[number]>[]): NodeProxy<ReturnType> => {
118
+ const id = layout?.name || defaultId
109
119
  const x = node('scope')
110
120
  const paramVars: NodeProxy[] = []
111
121
  const paramDefs: NodeProps[] = []
@@ -118,12 +128,12 @@ export const Fn = (fun: (paramVars: NodeProxy[]) => NodeProxy) => {
118
128
  paramDefs.push({ id: `p${i}`, inferFrom: [args[i]] })
119
129
  }
120
130
  for (const props of paramDefs) paramVars.push(node('variable', props))
121
- const y = node('define', { id, layout }, x, ...args)
131
+ const y = node<ReturnType>('define', { id, layout }, x, ...args)
122
132
  scoped(x, () => fun(paramVars), y)
123
133
  return y
124
134
  }
125
- ret.setLayout = (newLayout: FnLayout) => {
126
- layout = newLayout
135
+ ret.setLayout = (_layout: FnLayout) => {
136
+ layout = _layout
127
137
  return ret
128
138
  }
129
139
  return ret
package/src/node/types.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { WebGPUState } from '../types'
1
+ import { GL } from '../types'
2
+
2
3
  import { CONSTANTS, CONVERSIONS, FUNCTIONS, OPERATOR_KEYS } from './const'
3
4
 
4
5
  export type Constants = (typeof CONSTANTS)[number] | 'void'
@@ -29,12 +30,14 @@ export type NodeTypes =
29
30
  // variables
30
31
  | 'variable'
31
32
  | 'varying'
32
- | 'swizzle'
33
33
  | 'ternary'
34
34
  | 'builtin'
35
35
  | 'conversion'
36
36
  | 'operator'
37
37
  | 'function'
38
+ // struct
39
+ | 'struct'
40
+ | 'member'
38
41
  // scopes
39
42
  | 'scope'
40
43
  | 'assign'
@@ -45,32 +48,79 @@ export type NodeTypes =
45
48
  | 'declare'
46
49
  | 'return'
47
50
 
48
- export interface NodeProps {
51
+ export interface NodeProps<T extends Record<string, NodeProxy> = {}> {
49
52
  id?: string
50
- args?: X[]
53
+ args?: any[]
51
54
  type?: string
52
- children?: X[]
53
- inferFrom?: X[]
55
+ children?: any[]
56
+ inferFrom?: any[]
54
57
  layout?: FnLayout
55
58
  parent?: NodeProxy
59
+ // for struct
60
+ fields?: T
61
+ initialValues?: T
56
62
  }
57
63
 
58
64
  export interface NodeContext {
65
+ gl?: Partial<GL>
59
66
  isFrag?: boolean
60
67
  isWebGL?: boolean
61
68
  binding?: number
62
69
  infers?: WeakMap<NodeProxy, Constants>
63
70
  onMount?: (name: string) => void
64
- webgpu?: WebGPUState
65
- headers?: Map<string, string>
66
- fragInputs?: Map<string, string>
67
- vertInputs?: Map<string, string>
68
- vertOutputs?: Map<string, string>
69
- vertVaryings?: Map<string, string>
71
+ code?: {
72
+ headers: Map<string, string>
73
+ fragInputs: Map<string, string>
74
+ vertInputs: Map<string, string>
75
+ vertOutputs: Map<string, string>
76
+ vertVaryings: Map<string, string>
77
+ dependencies: Map<string, Set<string>>
78
+ }
70
79
  }
71
80
 
72
81
  /**
73
- * NodeProxy
82
+ * infer
83
+ */
84
+ // Unified logic with infer.ts inferOperator function
85
+ // prettier-ignore
86
+ type InferOperator<L extends Constants, R extends Constants> =
87
+ L extends R ? L :
88
+ // broadcast
89
+ L extends 'float' | 'int' ? R :
90
+ R extends 'float' | 'int' ? L :
91
+ // mat * vec → vec
92
+ L extends 'mat4' ? R extends 'vec4' ? R /* default */ : L :
93
+ L extends 'mat3' ? R extends 'vec3' ? R /* default */ : L :
94
+ L extends 'mat2' ? R extends 'vec2' ? R /* default */ : L :
95
+ // vec * mat → vec
96
+ L extends 'vec4' ? R extends 'mat4' ? L /* default */ : L :
97
+ L extends 'vec3' ? R extends 'mat3' ? L /* default */ : L :
98
+ L extends 'vec2' ? R extends 'mat2' ? L /* default */ : L : L
99
+
100
+ type _StringLength<S extends string> = S extends `${infer _}${infer Rest}`
101
+ ? Rest extends ''
102
+ ? 1
103
+ : Rest extends `${infer _}${infer Rest2}`
104
+ ? Rest2 extends ''
105
+ ? 2
106
+ : Rest2 extends `${infer _}${infer Rest3}`
107
+ ? Rest3 extends ''
108
+ ? 3
109
+ : 4
110
+ : never
111
+ : never
112
+ : 0
113
+
114
+ type InferSwizzleType<S extends string> = _StringLength<S> extends 4
115
+ ? 'vec4'
116
+ : _StringLength<S> extends 3
117
+ ? 'vec3'
118
+ : _StringLength<S> extends 2
119
+ ? 'vec2'
120
+ : 'float'
121
+
122
+ /**
123
+ * Swizzles
74
124
  */
75
125
  type _Swizzles<T extends string> = T | `${T}${T}` | `${T}${T}${T}` | `${T}${T}${T}${T}`
76
126
 
@@ -93,104 +143,187 @@ type NodeProxyMethods =
93
143
  | 'toVar'
94
144
  | 'toString'
95
145
 
96
- export type DynamicProperties = {
97
- [K in string as K extends NodeProxyMethods ? never : K]: NodeProxy
98
- }
99
-
100
- export interface BaseNodeProxy extends Record<Swizzles, NodeProxy> {
146
+ export interface BaseNodeProxy<T extends Constants> {
101
147
  // System properties
102
- assign(n: X): NodeProxy
103
- toVar(name?: string): NodeProxy
148
+ assign(x: any): NodeProxy<T>
149
+ toVar(name?: string): NodeProxy<T>
104
150
  toString(c?: NodeContext): string
105
151
  type: NodeTypes
106
152
  props: NodeProps
107
153
  isProxy: true
154
+ listeners: Set<(value: any) => void>
108
155
 
109
156
  // Operators methods
110
- add(n: X): NodeProxy
111
- sub(n: X): NodeProxy
112
- mul(n: X): NodeProxy
113
- div(n: X): NodeProxy
114
- mod(n: X): NodeProxy
115
- equal(n: X): NodeProxy
116
- notEqual(n: X): NodeProxy
117
- lessThan(n: X): NodeProxy
118
- lessThanEqual(n: X): NodeProxy
119
- greaterThan(n: X): NodeProxy
120
- greaterThanEqual(n: X): NodeProxy
121
- and(n: X): NodeProxy
122
- or(n: X): NodeProxy
123
- not(): NodeProxy
124
-
125
- // Conversations methods
126
- toBool(): NodeProxy
127
- toUint(): NodeProxy
128
- toInt(): NodeProxy
129
- toFloat(): NodeProxy
130
- toBvec2(): NodeProxy
131
- toIvec2(): NodeProxy
132
- toUvec2(): NodeProxy
133
- toVec2(): NodeProxy
134
- toBvec3(): NodeProxy
135
- toIvec3(): NodeProxy
136
- toUvec3(): NodeProxy
137
- toVec3(): NodeProxy
138
- toBvec4(): NodeProxy
139
- toIvec4(): NodeProxy
140
- toUvec4(): NodeProxy
141
- toVec4(): NodeProxy
142
- toColor(): NodeProxy
143
- toMat2(): NodeProxy
144
- toMat3(): NodeProxy
145
- toMat4(): NodeProxy
146
-
147
- // Function methods
148
- abs(): NodeProxy
149
- sin(): NodeProxy
150
- cos(): NodeProxy
151
- tan(): NodeProxy
152
- asin(): NodeProxy
153
- acos(): NodeProxy
154
- atan(): NodeProxy
155
- atan2(x: X): NodeProxy
156
- pow(y: X): NodeProxy
157
- pow2(): NodeProxy
158
- pow3(): NodeProxy
159
- pow4(): NodeProxy
160
- sqrt(): NodeProxy
161
- inverseSqrt(): NodeProxy
162
- exp(): NodeProxy
163
- exp2(): NodeProxy
164
- log(): NodeProxy
165
- log2(): NodeProxy
166
- floor(): NodeProxy
167
- ceil(): NodeProxy
168
- round(): NodeProxy
169
- fract(): NodeProxy
170
- trunc(): NodeProxy
171
- min(y: X): NodeProxy
172
- max(y: X): NodeProxy
173
- clamp(min: X, max: X): NodeProxy
174
- saturate(): NodeProxy
175
- mix(y: X, a: X): NodeProxy
176
- step(edge: X): NodeProxy
177
- smoothstep(edge0: X, edge1: X): NodeProxy
178
- length(): NodeProxy
179
- distance(y: X): NodeProxy
180
- dot(y: X): NodeProxy
181
- cross(y: X): NodeProxy
182
- normalize(): NodeProxy
183
- reflect(N: X): NodeProxy
184
- refract(N: X, eta: X): NodeProxy
185
- sign(): NodeProxy
186
- oneMinus(): NodeProxy
187
- reciprocal(): NodeProxy
188
- negate(): NodeProxy
189
- dFdx(): NodeProxy
190
- dFdy(): NodeProxy
191
- fwidth(): NodeProxy
157
+ add<U extends Constants>(x: X<U>): NodeProxy<InferOperator<T, U>>
158
+ sub<U extends Constants>(x: X<U>): NodeProxy<InferOperator<T, U>>
159
+ mul<U extends Constants>(x: X<U>): NodeProxy<InferOperator<T, U>>
160
+ div<U extends Constants>(x: X<U>): NodeProxy<InferOperator<T, U>>
161
+ mod<U extends Constants>(x: X<U>): NodeProxy<InferOperator<T, U>>
162
+ equal<U extends Constants>(x: X<U>): Bool
163
+ notEqual<U extends Constants>(x: X<U>): Bool
164
+ lessThan<U extends Constants>(x: X<U>): Bool
165
+ lessThanEqual<U extends Constants>(x: X<U>): Bool
166
+ greaterThan<U extends Constants>(x: X<U>): Bool
167
+ greaterThanEqual<U extends Constants>(x: X<U>): Bool
168
+ and(x: X<'bool'>): Bool
169
+ or(x: X<'bool'>): Bool
170
+ not(): Bool
171
+
172
+ // Bitwise operators
173
+ bitAnd(x: X<T>): NodeProxy<T>
174
+ bitOr(x: X<T>): NodeProxy<T>
175
+ bitXor(x: X<T>): NodeProxy<T>
176
+ bitNot(): NodeProxy<T>
177
+ shiftLeft<U extends Constants>(x: X<U>): NodeProxy<InferOperator<T, U>>
178
+ shiftRight<U extends Constants>(x: X<U>): NodeProxy<InferOperator<T, U>>
179
+
180
+ // Conversion methods
181
+ toBool(): Bool
182
+ toUint(): UInt
183
+ toInt(): Int
184
+ toFloat(): Float
185
+ toBvec2(): BVec2
186
+ toIvec2(): IVec2
187
+ toUvec2(): UVec2
188
+ toVec2(): Vec2
189
+ toBvec3(): BVec3
190
+ toIvec3(): IVec3
191
+ toUvec3(): UVec3
192
+ toVec3(): Vec3
193
+ toBvec4(): BVec4
194
+ toIvec4(): IVec4
195
+ toUvec4(): UVec4
196
+ toVec4(): Vec4
197
+ toColor(): Color
198
+ toMat2(): Mat2
199
+ toMat3(): Mat3
200
+ toMat4(): Mat4
201
+
202
+ // Mathematical function methods (preserve type functions)
203
+ abs(): NodeProxy<T>
204
+ sign(): NodeProxy<T>
205
+ floor(): NodeProxy<T>
206
+ ceil(): NodeProxy<T>
207
+ round(): NodeProxy<T>
208
+ fract(): NodeProxy<T>
209
+ trunc(): NodeProxy<T>
210
+ sin(): NodeProxy<T>
211
+ cos(): NodeProxy<T>
212
+ tan(): NodeProxy<T>
213
+ asin(): NodeProxy<T>
214
+ acos(): NodeProxy<T>
215
+ atan(): NodeProxy<T>
216
+ exp(): NodeProxy<T>
217
+ exp2(): NodeProxy<T>
218
+ log(): NodeProxy<T>
219
+ log2(): NodeProxy<T>
220
+ sqrt(): NodeProxy<T>
221
+ inverseSqrt(): NodeProxy<T>
222
+ normalize(): NodeProxy<T>
223
+ oneMinus(): NodeProxy<T>
224
+ saturate(): NodeProxy<T>
225
+ negate(): NodeProxy<T>
226
+ reciprocal(): NodeProxy<T>
227
+ dFdx(): NodeProxy<T>
228
+ dFdy(): NodeProxy<T>
229
+ fwidth(): NodeProxy<T>
230
+
231
+ // Scalar return functions
232
+ length(): Float
233
+ lengthSq(): Float
234
+ determinant(): Float
235
+ luminance(): Float
236
+
237
+ // Bool return functions
238
+ all(): Bool
239
+ any(): Bool
240
+
241
+ // Specific return type functions
242
+ cross<U extends Constants>(y: X<U>): Vec3
243
+
244
+ // Two argument functions with variable return types
245
+ atan2<U extends Constants>(x: X<U>): NodeProxy<T>
246
+ pow<U extends Constants>(y: X<U>): NodeProxy<T>
247
+ distance<U extends Constants>(y: X<U>): Float
248
+ dot<U extends Constants>(y: X<U>): Float
249
+ reflect<U extends Constants>(N: X<U>): NodeProxy<T>
250
+ refract<U extends Constants>(N: X<U>, eta: any): NodeProxy<T>
251
+
252
+ // Multi-argument functions that return highest priority type
253
+ min<U extends Constants>(y: X<U>): NodeProxy<InferOperator<T, U>>
254
+ max<U extends Constants>(y: X<U>): NodeProxy<InferOperator<T, U>>
255
+ mix<U extends Constants, V>(y: X<U>, a: V): NodeProxy<InferOperator<T, U>>
256
+ clamp<U extends Constants, V>(mix: X<U>, max: V): NodeProxy<InferOperator<T, U>>
257
+ step<U extends Constants>(edge: X<U>): NodeProxy<InferOperator<T, U>>
258
+ smoothstep<U extends Constants, V>(edge0: X<U>, edge1: V): NodeProxy<InferOperator<T, U>>
259
+
260
+ // Power functions
261
+ pow2(): NodeProxy<T>
262
+ pow3(): NodeProxy<T>
263
+ pow4(): NodeProxy<T>
264
+ }
265
+
266
+ type ReadNodeProxy = {
267
+ [K in string as K extends NodeProxyMethods ? never : K]: any
268
+ } & {
269
+ [K in Swizzles]: NodeProxy<InferSwizzleType<K>>
270
+ }
271
+
272
+ // Internal NodeProxy implementation (renamed from original)
273
+ type NodeProxyImpl<T extends Constants = string> = BaseNodeProxy<T> & ReadNodeProxy
274
+
275
+ export type Bool = NodeProxyImpl<'bool'>
276
+ export type UInt = NodeProxyImpl<'uint'>
277
+ export type Int = NodeProxyImpl<'int'>
278
+ export type Float = NodeProxyImpl<'float'>
279
+ export type BVec2 = NodeProxyImpl<'bvec2'>
280
+ export type IVec2 = NodeProxyImpl<'ivec2'>
281
+ export type UVec2 = NodeProxyImpl<'uvec2'>
282
+ export type Vec2 = NodeProxyImpl<'vec2'>
283
+ export type BVec3 = NodeProxyImpl<'bvec3'>
284
+ export type IVec3 = NodeProxyImpl<'ivec3'>
285
+ export type UVec3 = NodeProxyImpl<'uvec3'>
286
+ export type Vec3 = NodeProxyImpl<'vec3'>
287
+ export type BVec4 = NodeProxyImpl<'bvec4'>
288
+ export type IVec4 = NodeProxyImpl<'ivec4'>
289
+ export type UVec4 = NodeProxyImpl<'uvec4'>
290
+ export type Vec4 = NodeProxyImpl<'vec4'>
291
+ export type Color = NodeProxyImpl<'color'>
292
+ export type Mat2 = NodeProxyImpl<'mat2'>
293
+ export type Mat3 = NodeProxyImpl<'mat3'>
294
+ export type Mat4 = NodeProxyImpl<'mat4'>
295
+ export type Texture = NodeProxyImpl<'texture'>
296
+ export type Sampler2D = NodeProxyImpl<'sampler2D'>
297
+ export type Struct = NodeProxyImpl<'struct'>
298
+
299
+ export interface ConstantsToType {
300
+ bool: Bool
301
+ uint: UInt
302
+ int: Int
303
+ float: Float
304
+ bvec2: BVec2
305
+ ivec2: IVec2
306
+ uvec2: UVec2
307
+ vec2: Vec2
308
+ bvec3: BVec3
309
+ ivec3: IVec3
310
+ uvec3: UVec3
311
+ vec3: Vec3
312
+ bvec4: BVec4
313
+ ivec4: IVec4
314
+ uvec4: UVec4
315
+ vec4: Vec4
316
+ color: Color
317
+ mat2: Mat2
318
+ mat3: Mat3
319
+ mat4: Mat4
320
+ texture: Texture
321
+ sampler2D: Sampler2D
322
+ struct: Struct
192
323
  }
193
324
 
194
- export type NodeProxy = BaseNodeProxy & DynamicProperties
325
+ export type NodeProxy<T extends Constants = string> = T extends keyof ConstantsToType
326
+ ? ConstantsToType[T]
327
+ : NodeProxyImpl<T>
195
328
 
196
- export type X = NodeProxy | number | string | boolean | undefined
329
+ export type X<T extends Constants = string> = number | string | boolean | undefined | NodeProxy<T> | X[]