glre 0.33.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/node.ts CHANGED
@@ -2,13 +2,13 @@ import { is } from '../utils/helpers'
2
2
  import { code } from './code'
3
3
  import { assign, toVar } from './scope'
4
4
  import { conversionToConstant, isConversion, isFunction, isOperator, getId } from './utils'
5
- import type { Functions, NodeProps, NodeProxy, NodeTypes, Operators, X } from './types'
5
+ import type { Functions, NodeProps, NodeProxy, NodeTypes, Operators, X, Constants as C } from './types'
6
6
 
7
7
  const toPrimitive = (x: X, hint: string) => {
8
8
  if (hint === 'string') return code(x)
9
9
  }
10
10
 
11
- export const node = (type: NodeTypes, props?: NodeProps | null, ...args: X[]) => {
11
+ export const node = <T extends C>(type: NodeTypes, props?: NodeProps | null, ...args: X[]) => {
12
12
  if (!props) props = {}
13
13
  if (args.length) props.children = args
14
14
  const listeners = new Set<(value: any) => void>()
@@ -24,28 +24,30 @@ export const node = (type: NodeTypes, props?: NodeProps | null, ...args: X[]) =>
24
24
  if (isOperator(key)) return (...y: X[]) => operator(key, x, ...y)
25
25
  if (isFunction(key)) return (...y: X[]) => function_(key, x, ...y)
26
26
  if (isConversion(key)) return () => conversion(conversionToConstant(key), x)
27
- if (is.str(key)) return member(key, x) // for struct
27
+ if (is.str(key)) return member(key, x) // for struct and swizzling
28
28
  }
29
29
  const set = (_: unknown, key: string, y: X) => {
30
30
  if (key === 'value') listeners.forEach((fun) => fun(y))
31
31
  if (is.str(key)) member(key, x).assign(y)
32
32
  return true
33
33
  }
34
- const x = new Proxy({}, { get, set }) as unknown as NodeProxy
34
+ const x = new Proxy({}, { get, set }) as unknown as NodeProxy<T>
35
35
  return x
36
36
  }
37
37
 
38
- // headers
39
- export const attribute = (x: X, id = getId()) => node('attribute', { id }, x)
40
- export const constant = (x: X, id = getId()) => node('constant', { id }, x)
41
- export const uniform = (x: X, id = getId()) => node('uniform', { id }, x)
42
- export const variable = (id = getId()) => node('variable', { id })
43
- export const builtin = (id = getId()) => node('builtin', { id })
44
- export const vertexStage = (x: X, id = getId()) => node('varying', { id, inferFrom: [x] }, x)
38
+ // headers with proper type inference
39
+ export const attribute = <T extends C>(x: X, id = getId()) => node<T>('attribute', { id }, x)
40
+ export const constant = <T extends C>(x: X<T>, id = getId()) => node<T>('constant', { id }, x)
41
+ export const uniform = <T extends C>(x: X<T>, id = getId()) => node<T>('uniform', { id }, x)
42
+ export const variable = <T extends C>(id = getId()) => node<T>('variable', { id })
43
+ export const builtin = <T extends C>(id = getId()) => node<T>('builtin', { id })
44
+ export const vertexStage = <T extends C>(x: X<T>, id = getId()) => {
45
+ return node<T>('varying', { id, inferFrom: [x] }, x)
46
+ }
45
47
 
46
- // Node shorthands
47
- export const operator = (key: Operators, ...x: X[]) => node('operator', null, key, ...x)
48
- export const function_ = (key: Functions, ...x: X[]) => node('function', null, key, ...x)
49
- export const conversion = (key: string, ...x: X[]) => node('conversion', null, key, ...x)
50
- export const member = (key: string, x: X) => node('member', null, key, x)
51
- export const select = (x: X, y: X, z: X) => node('ternary', null, x, y, z) // x ? y : z @TODO REMOVE
48
+ // Node shorthands with proper typing
49
+ export const member = <T extends C>(key: string, x: X) => node<T>('member', null, key, x)
50
+ export const select = <T extends C>(x: X<T>, y: X<T>, z: X) => node<T>('ternary', null, x, y, z) // z ? x : y @TODO REMOVE
51
+ export const operator = <T extends C>(key: Operators, ...x: X[]) => node<T>('operator', null, key, ...x)
52
+ export const function_ = <T extends C>(key: Functions, ...x: X[]) => node<T>('function', null, key, ...x)
53
+ export const conversion = <T extends C>(key: T, ...x: X[]) => node<T>('conversion', null, key, ...x)
package/src/node/parse.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { is } from '../utils/helpers'
2
2
  import { code } from './code'
3
3
  import { infer } from './infer'
4
- import { formatConversions, isConstants, addDependency } from './utils'
4
+ import { formatConversions, addDependency } from './utils'
5
5
  import type { Constants, NodeContext, NodeProps, NodeProxy, X } from './types'
6
6
 
7
7
  export const parseArray = (children: X[], c: NodeContext) => {
@@ -58,7 +58,7 @@ export const parseDeclare = (c: NodeContext, x: X, y: X) => {
58
58
  return `var ${varName}: ${wgslType} = ${code(x, c)};`
59
59
  }
60
60
 
61
- export const parseDefine = (c: NodeContext, props: NodeProps, returnType: Constants | string) => {
61
+ export const parseDefine = (c: NodeContext, props: NodeProps, returnType: Constants) => {
62
62
  const { id, children = [], layout } = props
63
63
  const [x, ...args] = children
64
64
  const argParams: [name: string, type: string][] = []
@@ -127,7 +127,9 @@ export const parseStruct = (
127
127
  * headers
128
128
  */
129
129
  export const parseVaryingHead = (c: NodeContext, id: string, type: string) => {
130
- return c.isWebGL ? `${type} ${id};` : `@location(${c.code?.vertVaryings?.size || 0}) ${id}: ${formatConversions(type, c)}`
130
+ return c.isWebGL
131
+ ? `${type} ${id};`
132
+ : `@location(${c.code?.vertVaryings?.size || 0}) ${id}: ${formatConversions(type, c)}`
131
133
  }
132
134
 
133
135
  export const parseUniformHead = (c: NodeContext, id: string, type: Constants) => {
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,29 +15,28 @@ 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
 
39
- // Struct functions
40
- export const struct = (fields: Record<string, NodeProxy>, id = getId()) => {
41
- return (initialValues: Record<string, NodeProxy> = {}, instanceId = getId()) => {
38
+ export const struct = <T extends Record<string, NodeProxy>>(fields: T, id = getId()) => {
39
+ return (initialValues: T = {} as T, instanceId = getId()) => {
42
40
  const x = node('variable', { id: instanceId, inferFrom: [id] })
43
41
  const y = node('struct', { id, fields, initialValues }, x)
44
42
  addToScope(y)
@@ -61,7 +59,7 @@ const scoped = (x: NodeProxy, fun: () => NodeProxy | void, y = define) => {
61
59
  define = _define
62
60
  }
63
61
 
64
- export const If = (x: X, fun: () => void) => {
62
+ export const If = (x: NodeProxy, fun: () => void) => {
65
63
  const y = node('scope')
66
64
  scoped(y, fun)
67
65
  const ifNode = node('if', null, x, y)
@@ -82,15 +80,15 @@ export const If = (x: X, fun: () => void) => {
82
80
  return ret()
83
81
  }
84
82
 
85
- export const Loop = (x: X, fun: (params: { i: NodeProxy }) => void) => {
83
+ export const Loop = (x: NodeProxy, fun: (params: { i: Int }) => void) => {
86
84
  const y = node('scope')
87
- 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)] }) }))
88
86
  const ret = node('loop', null, x, y)
89
87
  addToScope(ret)
90
88
  return ret
91
89
  }
92
90
 
93
- export const Switch = (x: X) => {
91
+ export const Switch = (x: NodeProxy) => {
94
92
  const switchNode = node('switch', null, x)
95
93
  addToScope(switchNode)
96
94
  const ret = () => ({
@@ -111,10 +109,13 @@ export const Switch = (x: X) => {
111
109
  return ret()
112
110
  }
113
111
 
114
- 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
+ ) => {
115
116
  let layout: FnLayout
116
- const ret = (...args: X[]) => {
117
- const id = layout?.name || getId()
117
+ const ret = (...args: X<Args[number]>[]): NodeProxy<ReturnType> => {
118
+ const id = layout?.name || defaultId
118
119
  const x = node('scope')
119
120
  const paramVars: NodeProxy[] = []
120
121
  const paramDefs: NodeProps[] = []
@@ -127,10 +128,13 @@ export const Fn = (fun: (paramVars: NodeProxy[]) => NodeProxy) => {
127
128
  paramDefs.push({ id: `p${i}`, inferFrom: [args[i]] })
128
129
  }
129
130
  for (const props of paramDefs) paramVars.push(node('variable', props))
130
- const y = node('define', { id, layout }, x, ...args)
131
+ const y = node<ReturnType>('define', { id, layout }, x, ...args)
131
132
  scoped(x, () => fun(paramVars), y)
132
133
  return y
133
134
  }
134
- ret.setLayout = (_layout: FnLayout) => void (layout = _layout)
135
+ ret.setLayout = (_layout: FnLayout) => {
136
+ layout = _layout
137
+ return ret
138
+ }
135
139
  return ret
136
140
  }
package/src/node/types.ts CHANGED
@@ -1,4 +1,5 @@
1
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'
@@ -47,17 +48,17 @@ export type NodeTypes =
47
48
  | 'declare'
48
49
  | 'return'
49
50
 
50
- export interface NodeProps {
51
+ export interface NodeProps<T extends Record<string, NodeProxy> = {}> {
51
52
  id?: string
52
- args?: X[]
53
+ args?: any[]
53
54
  type?: string
54
- children?: X[]
55
- inferFrom?: X[]
55
+ children?: any[]
56
+ inferFrom?: any[]
56
57
  layout?: FnLayout
57
58
  parent?: NodeProxy
58
59
  // for struct
59
- fields?: Record<string, NodeProxy>
60
- initialValues?: Record<string, NodeProxy>
60
+ fields?: T
61
+ initialValues?: T
61
62
  }
62
63
 
63
64
  export interface NodeContext {
@@ -78,7 +79,48 @@ export interface NodeContext {
78
79
  }
79
80
 
80
81
  /**
81
- * 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
82
124
  */
83
125
  type _Swizzles<T extends string> = T | `${T}${T}` | `${T}${T}${T}` | `${T}${T}${T}${T}`
84
126
 
@@ -101,14 +143,10 @@ type NodeProxyMethods =
101
143
  | 'toVar'
102
144
  | 'toString'
103
145
 
104
- export type ReadNodeProxy = {
105
- [K in string as K extends NodeProxyMethods ? never : K]: X
106
- }
107
-
108
- export interface BaseNodeProxy extends Record<Swizzles, NodeProxy> {
146
+ export interface BaseNodeProxy<T extends Constants> {
109
147
  // System properties
110
- assign(n: X): NodeProxy
111
- toVar(name?: string): NodeProxy
148
+ assign(x: any): NodeProxy<T>
149
+ toVar(name?: string): NodeProxy<T>
112
150
  toString(c?: NodeContext): string
113
151
  type: NodeTypes
114
152
  props: NodeProps
@@ -116,90 +154,176 @@ export interface BaseNodeProxy extends Record<Swizzles, NodeProxy> {
116
154
  listeners: Set<(value: any) => void>
117
155
 
118
156
  // Operators methods
119
- add(n: X): NodeProxy
120
- sub(n: X): NodeProxy
121
- mul(n: X): NodeProxy
122
- div(n: X): NodeProxy
123
- mod(n: X): NodeProxy
124
- equal(n: X): NodeProxy
125
- notEqual(n: X): NodeProxy
126
- lessThan(n: X): NodeProxy
127
- lessThanEqual(n: X): NodeProxy
128
- greaterThan(n: X): NodeProxy
129
- greaterThanEqual(n: X): NodeProxy
130
- and(n: X): NodeProxy
131
- or(n: X): NodeProxy
132
- not(): NodeProxy
133
-
134
- // Conversations methods
135
- toBool(): NodeProxy
136
- toUint(): NodeProxy
137
- toInt(): NodeProxy
138
- toFloat(): NodeProxy
139
- toBvec2(): NodeProxy
140
- toIvec2(): NodeProxy
141
- toUvec2(): NodeProxy
142
- toVec2(): NodeProxy
143
- toBvec3(): NodeProxy
144
- toIvec3(): NodeProxy
145
- toUvec3(): NodeProxy
146
- toVec3(): NodeProxy
147
- toBvec4(): NodeProxy
148
- toIvec4(): NodeProxy
149
- toUvec4(): NodeProxy
150
- toVec4(): NodeProxy
151
- toColor(): NodeProxy
152
- toMat2(): NodeProxy
153
- toMat3(): NodeProxy
154
- toMat4(): NodeProxy
155
-
156
- // Function methods
157
- abs(): NodeProxy
158
- sin(): NodeProxy
159
- cos(): NodeProxy
160
- tan(): NodeProxy
161
- asin(): NodeProxy
162
- acos(): NodeProxy
163
- atan(): NodeProxy
164
- atan2(x: X): NodeProxy
165
- pow(y: X): NodeProxy
166
- pow2(): NodeProxy
167
- pow3(): NodeProxy
168
- pow4(): NodeProxy
169
- sqrt(): NodeProxy
170
- inverseSqrt(): NodeProxy
171
- exp(): NodeProxy
172
- exp2(): NodeProxy
173
- log(): NodeProxy
174
- log2(): NodeProxy
175
- floor(): NodeProxy
176
- ceil(): NodeProxy
177
- round(): NodeProxy
178
- fract(): NodeProxy
179
- trunc(): NodeProxy
180
- min(y: X): NodeProxy
181
- max(y: X): NodeProxy
182
- clamp(min: X, max: X): NodeProxy
183
- saturate(): NodeProxy
184
- mix(y: X, a: X): NodeProxy
185
- step(edge: X): NodeProxy
186
- smoothstep(edge0: X, edge1: X): NodeProxy
187
- length(): NodeProxy
188
- distance(y: X): NodeProxy
189
- dot(y: X): NodeProxy
190
- cross(y: X): NodeProxy
191
- normalize(): NodeProxy
192
- reflect(N: X): NodeProxy
193
- refract(N: X, eta: X): NodeProxy
194
- sign(): NodeProxy
195
- oneMinus(): NodeProxy
196
- reciprocal(): NodeProxy
197
- negate(): NodeProxy
198
- dFdx(): NodeProxy
199
- dFdy(): NodeProxy
200
- 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
201
323
  }
202
324
 
203
- export type NodeProxy = BaseNodeProxy & ReadNodeProxy
325
+ export type NodeProxy<T extends Constants = string> = T extends keyof ConstantsToType
326
+ ? ConstantsToType[T]
327
+ : NodeProxyImpl<T>
204
328
 
205
- export type X = X[] | (NodeProxy | number | string | boolean | undefined)
329
+ export type X<T extends Constants = string> = number | string | boolean | undefined | NodeProxy<T> | X[]
package/src/node/utils.ts CHANGED
@@ -26,7 +26,7 @@ export const isConversion = (key: unknown): key is Conversions => {
26
26
  return CONVERSIONS.includes(key as Conversions)
27
27
  }
28
28
 
29
- export const isNodeProxy = (x: unknown): x is NodeProxy => {
29
+ export const isNodeProxy = <T extends Constants>(x: unknown): x is NodeProxy<T> => {
30
30
  if (!x) return false
31
31
  if (typeof x !== 'object') return false // @ts-ignore
32
32
  return x.isProxy
@@ -48,13 +48,13 @@ let count = 0
48
48
 
49
49
  export const getId = () => `i${count++}`
50
50
 
51
- export const formatConversions = (x: X, c?: NodeContext) => {
51
+ export const formatConversions = <T extends Constants>(x: X<T>, c?: NodeContext) => {
52
52
  if (!is.str(x)) return ''
53
53
  if (c?.isWebGL) return x
54
54
  return TYPE_MAPPING[x as keyof typeof TYPE_MAPPING] || x // for struct type
55
55
  }
56
56
 
57
- export const getOperator = (op: X) => {
57
+ export const getOperator = (op: X<string>) => {
58
58
  return OPERATORS[op as keyof typeof OPERATORS] || op
59
59
  }
60
60
 
@@ -78,7 +78,7 @@ export const getEventFun = (c: NodeContext, id: string, isAttribute = false, isT
78
78
  return (value: any) => c.gl?._uniform?.(id, value)
79
79
  }
80
80
 
81
- export const safeEventCall = (x: X, fun: (value: unknown) => void) => {
81
+ export const safeEventCall = <T extends Constants>(x: X<T>, fun: (value: unknown) => void) => {
82
82
  if (!x) return
83
83
  if (!isNodeProxy(x)) return fun(x) // for uniform(1)
84
84
  if (x.type !== 'conversion') return
package/src/types.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { EventState, Nested } from 'reev'
2
2
  import type { Fun, Queue, Frame } from 'refr'
3
- import type { NodeProxy } from './node'
3
+ import type { NodeProxy, Vec4 } from './node'
4
4
  export type { Fun, Queue, Frame }
5
5
  export type PrecisionMode = 'highp' | 'mediump' | 'lowp'
6
6
  export type GLClearMode = 'COLOR_BUFFER_BIT' | 'DEPTH_BUFFER_BIT' | 'STENCIL_BUFFER_BIT'
@@ -67,12 +67,12 @@ export type GL = EventState<{
67
67
  mouse: [number, number]
68
68
  count: number
69
69
  el: HTMLCanvasElement
70
- vs: string | NodeProxy
71
- fs: string | NodeProxy
72
- vert: string | NodeProxy
73
- frag: string | NodeProxy
74
- vertex: string | NodeProxy
75
- fragment: string | NodeProxy
70
+ vs: string | Vec4
71
+ fs: string | Vec4
72
+ vert: string | Vec4
73
+ frag: string | Vec4
74
+ vertex: string | Vec4
75
+ fragment: string | Vec4
76
76
 
77
77
  /**
78
78
  * core state