@bigmistqke/view.gl 0.1.1 → 0.1.3
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/.claude/settings.local.json +9 -0
- package/.github/ISSUE_TEMPLATE/bug-report.yml +31 -0
- package/.github/ISSUE_TEMPLATE/feature-request.yml +27 -0
- package/.github/workflows/codeql.yml +46 -0
- package/.github/workflows/deploy-page.yml +38 -0
- package/.github/workflows/format.yml +40 -0
- package/README.md +286 -84
- package/dev/404.html +19 -0
- package/dev/dist/404.html +19 -0
- package/dev/dist/assets/bezier-DuLTb2d1.js +294 -0
- package/dev/dist/assets/game_of_life-D7qHdFcv.js +202 -0
- package/dev/dist/assets/grid-Ie22U_9K.js +173 -0
- package/dev/dist/assets/index-0qrXMlfv.js +109 -0
- package/dev/dist/assets/index-C2N3u8wj.css +12 -0
- package/dev/dist/assets/main-BZ1N6pp6.js +32 -0
- package/dev/dist/assets/overview-DAxtMIw5.js +78 -0
- package/dev/dist/assets/pix_sim-DIhzM_vu.js +501 -0
- package/dev/dist/assets/symbol-BouRL-Ni.js +65 -0
- package/dev/dist/assets/tag-C_bg62fD.js +516 -0
- package/dev/dist/assets/tetris-IMnkSi9p.js +344 -0
- package/dev/dist/assets/utils-CvCgsM08.js +50 -0
- package/dev/dist/index.html +51 -0
- package/dev/index.html +39 -10
- package/dev/{bezier.ts → src/examples/bezier.ts} +1 -1
- package/dev/{grid.ts → src/examples/grid.ts} +1 -1
- package/dev/{pix_sim.ts → src/examples/pix_sim.ts} +112 -97
- package/dev/src/examples/symbol.ts +79 -0
- package/dev/{tetris.ts → src/examples/tetris.ts} +1 -0
- package/dev/src/index.css +12 -0
- package/dev/src/index.ts +69 -0
- package/dev/{utils.ts → src/utils.ts} +8 -2
- package/dev/vite.config.ts +9 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +81 -27
- package/dist/index.mjs.map +1 -1
- package/dist/tag.d.mts +9 -9
- package/dist/tag.mjs +46 -17
- package/dist/tag.mjs.map +1 -1
- package/dist/{types-DxpS9Bae.d.mts → types-DoFAJoh-.d.mts} +18 -18
- package/package.json +20 -7
- package/src/index.ts +39 -17
- package/src/tag.ts +47 -39
- package/src/types.ts +24 -24
- package/src/{utils.ts → utils/index.ts} +39 -14
- package/src/utils/object.ts +27 -0
- package/test/index.test.ts +1017 -0
- package/test/mocks/webgl.ts +248 -0
- package/test/setup.ts +13 -0
- package/test/tag.test.ts +790 -0
- package/vitest.config.ts +15 -0
- /package/dev/{game_of_life.ts → src/examples/game_of_life.ts} +0 -0
- /package/dev/{index.ts → src/examples/overview.ts} +0 -0
package/src/index.ts
CHANGED
|
@@ -17,13 +17,35 @@ import type {
|
|
|
17
17
|
} from './types'
|
|
18
18
|
import {
|
|
19
19
|
assertedNotNullish,
|
|
20
|
+
createUpsertMap,
|
|
20
21
|
isMatKind,
|
|
21
22
|
isSamplerKind,
|
|
22
23
|
kindToSize,
|
|
23
24
|
kindToUniformFnName,
|
|
24
|
-
|
|
25
|
+
ObjectUtils,
|
|
25
26
|
} from './utils'
|
|
26
27
|
|
|
28
|
+
/**********************************************************************************/
|
|
29
|
+
/* */
|
|
30
|
+
/* To ID */
|
|
31
|
+
/* */
|
|
32
|
+
/**********************************************************************************/
|
|
33
|
+
|
|
34
|
+
let index = 0
|
|
35
|
+
const PREFIX = 'VIEW_GL_ALIAS'
|
|
36
|
+
|
|
37
|
+
const SYMBOL_MAP = createUpsertMap(WeakMap<symbol, string>)
|
|
38
|
+
|
|
39
|
+
export function toID(key: string | number | symbol) {
|
|
40
|
+
if (typeof key === 'string') {
|
|
41
|
+
return key
|
|
42
|
+
}
|
|
43
|
+
if (typeof key === 'symbol') {
|
|
44
|
+
return SYMBOL_MAP.getOrInsert(key, () => `${PREFIX}_${index++}`)
|
|
45
|
+
}
|
|
46
|
+
return key.toString()
|
|
47
|
+
}
|
|
48
|
+
|
|
27
49
|
/**********************************************************************************/
|
|
28
50
|
/* */
|
|
29
51
|
/* View */
|
|
@@ -59,7 +81,9 @@ export function uniformView<T extends UniformSchema>(
|
|
|
59
81
|
program: WebGLProgram,
|
|
60
82
|
schema: T,
|
|
61
83
|
): InferUniformView<T> {
|
|
62
|
-
return
|
|
84
|
+
return ObjectUtils.map(schema, ({ kind, size }, key) => {
|
|
85
|
+
const name = toID(key)
|
|
86
|
+
|
|
63
87
|
const location = gl.getUniformLocation(program, name)
|
|
64
88
|
|
|
65
89
|
if (isSamplerKind(kind)) {
|
|
@@ -123,12 +147,14 @@ export function attributeView<T extends AttributeSchema>(
|
|
|
123
147
|
schema: T,
|
|
124
148
|
{ signal }: ViewOptions = {},
|
|
125
149
|
): AttributeView<T> {
|
|
126
|
-
const attributes =
|
|
150
|
+
const attributes = ObjectUtils.map(
|
|
127
151
|
schema,
|
|
128
152
|
(
|
|
129
153
|
{ kind, instanced, buffer = assertedNotNullish(gl.createBuffer()) },
|
|
130
|
-
|
|
154
|
+
key,
|
|
131
155
|
): AttributeMethods => {
|
|
156
|
+
const name = toID(key)
|
|
157
|
+
|
|
132
158
|
const location = gl.getAttribLocation(program, name)
|
|
133
159
|
if (location < 0) {
|
|
134
160
|
throw new Error(`Attribute '${name}' not found`)
|
|
@@ -156,9 +182,7 @@ export function attributeView<T extends AttributeSchema>(
|
|
|
156
182
|
)
|
|
157
183
|
|
|
158
184
|
signal?.addEventListener('abort', function dispose() {
|
|
159
|
-
|
|
160
|
-
attributes[name].dispose()
|
|
161
|
-
}
|
|
185
|
+
ObjectUtils.forEach(attributes, value => value.dispose())
|
|
162
186
|
})
|
|
163
187
|
|
|
164
188
|
return attributes
|
|
@@ -177,16 +201,18 @@ export function interleavedAttributeView<T extends InterleavedAttributeSchema>(
|
|
|
177
201
|
{ signal }: ViewOptions = {},
|
|
178
202
|
): InterleavedAttributeView<T> {
|
|
179
203
|
// Initialize interleaved attributes
|
|
180
|
-
const interleavedAttributes =
|
|
204
|
+
const interleavedAttributes = ObjectUtils.map(schema, ({ layout, instanced }) => {
|
|
181
205
|
// Increment number to keep track of offset
|
|
182
206
|
let index = 0
|
|
183
207
|
|
|
184
208
|
// Calculate layout information
|
|
185
209
|
const handles = layout.map(layout => {
|
|
186
|
-
const
|
|
210
|
+
const name = toID(layout.key)
|
|
211
|
+
|
|
212
|
+
const location = gl.getAttribLocation(program, name)
|
|
187
213
|
|
|
188
214
|
if (location < 0) {
|
|
189
|
-
throw new Error(`Attribute '${
|
|
215
|
+
throw new Error(`Attribute '${name}' not found`)
|
|
190
216
|
}
|
|
191
217
|
|
|
192
218
|
const size = kindToSize(layout.kind)
|
|
@@ -267,9 +293,7 @@ export function interleavedAttributeView<T extends InterleavedAttributeSchema>(
|
|
|
267
293
|
})
|
|
268
294
|
|
|
269
295
|
signal?.addEventListener('abort', function dispose() {
|
|
270
|
-
|
|
271
|
-
interleavedAttributes[name].dispose()
|
|
272
|
-
}
|
|
296
|
+
ObjectUtils.forEach(interleavedAttributes, value => value.dispose())
|
|
273
297
|
})
|
|
274
298
|
|
|
275
299
|
return interleavedAttributes
|
|
@@ -287,7 +311,7 @@ export function bufferView<T extends BufferSchema>(
|
|
|
287
311
|
{ signal }: ViewOptions = {},
|
|
288
312
|
): BufferView<T> {
|
|
289
313
|
// Initialize buffers
|
|
290
|
-
const buffers =
|
|
314
|
+
const buffers = ObjectUtils.map(schema, ({ target = 'ARRAY_BUFFER', usage = 'STATIC_DRAW' }) => {
|
|
291
315
|
const buffer = assertedNotNullish(gl.createBuffer())
|
|
292
316
|
return {
|
|
293
317
|
bind() {
|
|
@@ -304,9 +328,7 @@ export function bufferView<T extends BufferSchema>(
|
|
|
304
328
|
})
|
|
305
329
|
|
|
306
330
|
signal?.addEventListener('abort', function dispose() {
|
|
307
|
-
|
|
308
|
-
buffers[name].dispose()
|
|
309
|
-
}
|
|
331
|
+
ObjectUtils.forEach(buffers, value => value.dispose())
|
|
310
332
|
})
|
|
311
333
|
|
|
312
334
|
return buffers
|
package/src/tag.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { toID } from '.'
|
|
1
2
|
import type {
|
|
2
3
|
AttributeKind,
|
|
3
4
|
AttributeOptions,
|
|
@@ -20,11 +21,11 @@ import { createProgram } from './utils'
|
|
|
20
21
|
/**********************************************************************************/
|
|
21
22
|
|
|
22
23
|
interface UniformTagFn<TKind extends UniformKind> {
|
|
23
|
-
<const
|
|
24
|
-
|
|
24
|
+
<const TKey extends string | symbol, const TOptions extends Omit<UniformOptions, 'kind'>>(
|
|
25
|
+
key: TKey,
|
|
25
26
|
TOptions: TOptions,
|
|
26
|
-
): Prettify<UniformTag<
|
|
27
|
-
<const TName extends string>(
|
|
27
|
+
): Prettify<UniformTag<TKey, TKind, TOptions>>
|
|
28
|
+
<const TName extends string | symbol>(key: TName): Prettify<UniformTag<TName, TKind>>
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
export const uniform = new Proxy(
|
|
@@ -35,9 +36,9 @@ export const uniform = new Proxy(
|
|
|
35
36
|
get(target, property) {
|
|
36
37
|
// @ts-expect-error
|
|
37
38
|
if (typeof property === 'symbol') return target[property]
|
|
38
|
-
return (
|
|
39
|
+
return (key: string, options?: Omit<UniformOptions, 'kind'>) => ({
|
|
39
40
|
type: 'uniform',
|
|
40
|
-
|
|
41
|
+
key,
|
|
41
42
|
kind: property,
|
|
42
43
|
...options,
|
|
43
44
|
})
|
|
@@ -53,9 +54,9 @@ export const attribute = new Proxy(
|
|
|
53
54
|
get(target, property) {
|
|
54
55
|
// @ts-expect-error
|
|
55
56
|
if (typeof property === 'symbol') return target[property]
|
|
56
|
-
return (
|
|
57
|
+
return (key: string, options?: Omit<AttributeOptions, 'kind'>) => ({
|
|
57
58
|
type: 'attribute',
|
|
58
|
-
|
|
59
|
+
key,
|
|
59
60
|
kind: property,
|
|
60
61
|
...options,
|
|
61
62
|
})
|
|
@@ -64,30 +65,30 @@ export const attribute = new Proxy(
|
|
|
64
65
|
)
|
|
65
66
|
|
|
66
67
|
export function interleave<
|
|
67
|
-
const
|
|
68
|
-
const TLayout extends Array<AttributeTag<string, AttributeKind, undefined>>,
|
|
68
|
+
const TKey extends string | symbol,
|
|
69
|
+
const TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>>,
|
|
69
70
|
const TOptions extends Omit<AttributeOptions, 'kind'>,
|
|
70
|
-
>(
|
|
71
|
+
>(key: TKey, layout: TLayout, instanced: TOptions): InterleaveTag<TKey, TLayout, TOptions>
|
|
71
72
|
export function interleave<
|
|
72
|
-
const
|
|
73
|
-
const TLayout extends Array<AttributeTag<string, AttributeKind, undefined>>,
|
|
74
|
-
>(
|
|
73
|
+
const TKey extends string | symbol,
|
|
74
|
+
const TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>>,
|
|
75
|
+
>(key: TKey, layout: TLayout): InterleaveTag<TKey, TLayout, { instanced: false }>
|
|
75
76
|
export function interleave<
|
|
76
|
-
const
|
|
77
|
-
const TLayout extends Array<AttributeTag<string, AttributeKind, undefined>>,
|
|
77
|
+
const TKey extends string | symbol,
|
|
78
|
+
const TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>>,
|
|
78
79
|
const TOptions extends Omit<AttributeOptions, 'kind'>,
|
|
79
|
-
>(
|
|
80
|
+
>(key: TKey, layout: TLayout, { instanced, buffer }: Partial<TOptions> = {}) {
|
|
80
81
|
return {
|
|
81
82
|
type: 'interleavedAttribute',
|
|
82
|
-
|
|
83
|
+
key,
|
|
83
84
|
// remove instanced- and type-property
|
|
84
|
-
layout: layout.map(({
|
|
85
|
-
|
|
85
|
+
layout: layout.map(({ key, kind }) => ({
|
|
86
|
+
key,
|
|
86
87
|
kind,
|
|
87
88
|
})),
|
|
88
89
|
instanced: !!instanced,
|
|
89
90
|
buffer,
|
|
90
|
-
} as InterleaveTag<
|
|
91
|
+
} as unknown as InterleaveTag<TKey, TLayout, TOptions>
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
/**********************************************************************************/
|
|
@@ -99,34 +100,43 @@ export function interleave<
|
|
|
99
100
|
export function glsl<
|
|
100
101
|
Elem extends string,
|
|
101
102
|
Template extends ReadonlyArray<Elem>,
|
|
102
|
-
Hole extends UniformTag | AttributeTag | InterleaveTag | string | number,
|
|
103
|
+
Hole extends UniformTag | AttributeTag | InterleaveTag | string | number | symbol,
|
|
103
104
|
Holes extends Hole[],
|
|
104
105
|
>([initial, ...rest]: Template, ...holes: [...Holes]) {
|
|
105
106
|
const v300 = initial?.startsWith('#version 300 es')
|
|
107
|
+
|
|
106
108
|
const template = rest.reduce((out, templatePart, index) => {
|
|
107
109
|
const hole = holes[index]
|
|
108
110
|
const holePart =
|
|
109
|
-
typeof hole === 'string' || typeof hole === 'number'
|
|
110
|
-
? hole
|
|
111
|
+
typeof hole === 'string' || typeof hole === 'number' || typeof hole === 'symbol'
|
|
112
|
+
? toID(hole)
|
|
111
113
|
: hole.type === 'interleavedAttribute'
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
? hole.layout.reduce(
|
|
115
|
+
(a, v) =>
|
|
116
|
+
v300
|
|
117
|
+
? `${a}in ${v.kind} ${toID(v.key)};\n`
|
|
118
|
+
: `${a}attribute ${v.kind} ${toID(v.key)};\n`,
|
|
119
|
+
'',
|
|
120
|
+
)
|
|
121
|
+
: typeof hole === 'object' && hole.type === 'uniform' && 'size' in hole
|
|
122
|
+
? `${hole.type} ${hole.kind} ${toID(hole.key)}[${hole.size}];`
|
|
123
|
+
: `${hole.type === 'attribute' && v300 ? 'in' : hole.type} ${hole.kind} ${toID(hole.key)};`
|
|
120
124
|
return out + holePart + templatePart
|
|
121
125
|
}, initial || '')
|
|
122
126
|
|
|
123
127
|
return holes.reduce(
|
|
124
128
|
(resources, resource) => {
|
|
125
|
-
if (
|
|
129
|
+
if (
|
|
130
|
+
typeof resource === 'string' ||
|
|
131
|
+
typeof resource === 'number' ||
|
|
132
|
+
typeof resource === 'symbol'
|
|
133
|
+
) {
|
|
126
134
|
return resources
|
|
127
135
|
}
|
|
128
136
|
// @ts-expect-error
|
|
129
|
-
|
|
137
|
+
const { key: name, type, ...rest } = resource
|
|
138
|
+
// @ts-expect-error
|
|
139
|
+
resources[`${type}s`][name] = rest
|
|
130
140
|
return resources
|
|
131
141
|
},
|
|
132
142
|
{
|
|
@@ -137,15 +147,13 @@ export function glsl<
|
|
|
137
147
|
} as {
|
|
138
148
|
template: string
|
|
139
149
|
uniforms: {
|
|
140
|
-
[K in Extract<Holes[number], UniformTag> as K['
|
|
150
|
+
[K in Extract<Holes[number], UniformTag> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>
|
|
141
151
|
}
|
|
142
152
|
attributes: {
|
|
143
|
-
[K in Extract<Holes[number], AttributeTag> as K['
|
|
153
|
+
[K in Extract<Holes[number], AttributeTag> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>
|
|
144
154
|
}
|
|
145
155
|
interleavedAttributes: {
|
|
146
|
-
[K in Extract<Holes[number], InterleaveTag> as K['
|
|
147
|
-
Omit<K, 'name' | 'type'>
|
|
148
|
-
>
|
|
156
|
+
[K in Extract<Holes[number], InterleaveTag> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>
|
|
149
157
|
}
|
|
150
158
|
},
|
|
151
159
|
)
|
package/src/types.ts
CHANGED
|
@@ -4,8 +4,8 @@ export type Merge<A, B> = {
|
|
|
4
4
|
? A[K] | B[K]
|
|
5
5
|
: A[K]
|
|
6
6
|
: K extends keyof B
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
? B[K]
|
|
8
|
+
: never
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export type Prettify<T> = {
|
|
@@ -358,7 +358,7 @@ export interface UniformOptions {
|
|
|
358
358
|
size?: number
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
-
export type UniformSchema = Record<string, UniformOptions>
|
|
361
|
+
export type UniformSchema = Record<string | symbol, UniformOptions>
|
|
362
362
|
|
|
363
363
|
export type UniformMethods<TOptions extends UniformOptions> = TOptions['size'] extends number
|
|
364
364
|
? {
|
|
@@ -426,7 +426,7 @@ export interface AttributeOptions {
|
|
|
426
426
|
buffer?: WebGLBuffer
|
|
427
427
|
}
|
|
428
428
|
|
|
429
|
-
export type AttributeSchema = Record<string, AttributeOptions>
|
|
429
|
+
export type AttributeSchema = Record<string | symbol, AttributeOptions>
|
|
430
430
|
|
|
431
431
|
export interface AttributeMethods<T = AttributeKind> {
|
|
432
432
|
buffer: WebGLBuffer
|
|
@@ -446,7 +446,7 @@ export type AttributeView<T extends AttributeSchema> = {
|
|
|
446
446
|
/**********************************************************************************/
|
|
447
447
|
|
|
448
448
|
export interface InterleavedAttributeLayout {
|
|
449
|
-
|
|
449
|
+
key: string | symbol
|
|
450
450
|
kind: AttributeKind
|
|
451
451
|
}
|
|
452
452
|
|
|
@@ -455,7 +455,7 @@ export interface InterleavedAttributeOptions {
|
|
|
455
455
|
instanced?: boolean
|
|
456
456
|
}
|
|
457
457
|
|
|
458
|
-
export type InterleavedAttributeSchema = Record<string, InterleavedAttributeOptions>
|
|
458
|
+
export type InterleavedAttributeSchema = Record<string | symbol, InterleavedAttributeOptions>
|
|
459
459
|
|
|
460
460
|
export interface InterleavedAttributeMethods<
|
|
461
461
|
T extends InterleavedAttributeLayout[] = InterleavedAttributeLayout[],
|
|
@@ -481,7 +481,7 @@ export interface BufferOptions {
|
|
|
481
481
|
usage?: GLUsage
|
|
482
482
|
}
|
|
483
483
|
|
|
484
|
-
export type BufferSchema = Record<string, BufferOptions>
|
|
484
|
+
export type BufferSchema = Record<string | symbol, BufferOptions>
|
|
485
485
|
|
|
486
486
|
export interface BufferMethods {
|
|
487
487
|
set(data: Float32Array | Uint16Array | Uint32Array): void
|
|
@@ -537,7 +537,7 @@ export type TextureTarget =
|
|
|
537
537
|
| 'TEXTURE_3D' // WebGL2 only
|
|
538
538
|
| 'TEXTURE_2D_ARRAY' // WebGL2 only
|
|
539
539
|
|
|
540
|
-
export type TextureSchema = Record<string, TextureOptions>
|
|
540
|
+
export type TextureSchema = Record<string | symbol, TextureOptions>
|
|
541
541
|
|
|
542
542
|
export interface TextureMethods {
|
|
543
543
|
texture: WebGLTexture
|
|
@@ -662,57 +662,57 @@ export type View<T extends ViewSchema = ViewSchema> = {
|
|
|
662
662
|
|
|
663
663
|
export interface GLSL {
|
|
664
664
|
template: string
|
|
665
|
-
uniforms: Record<string, UniformOptions>
|
|
666
|
-
attributes: Record<string, AttributeOptions>
|
|
667
|
-
interleavedAttributes: Record<string, InterleavedAttributeOptions>
|
|
665
|
+
uniforms: Record<string | symbol, UniformOptions>
|
|
666
|
+
attributes: Record<string | symbol, AttributeOptions>
|
|
667
|
+
interleavedAttributes: Record<string | symbol, InterleavedAttributeOptions>
|
|
668
668
|
}
|
|
669
669
|
|
|
670
670
|
export type UniformTag<
|
|
671
|
-
|
|
671
|
+
TKey extends string | symbol = string | symbol,
|
|
672
672
|
TKind extends UniformKind = UniformKind,
|
|
673
673
|
TOptions extends Partial<UniformOptions> = UniformOptions,
|
|
674
674
|
> = TOptions extends { size: infer TSize }
|
|
675
675
|
? {
|
|
676
676
|
type: 'uniform'
|
|
677
677
|
kind: TKind
|
|
678
|
-
|
|
678
|
+
key: TKey
|
|
679
679
|
size: TSize
|
|
680
680
|
}
|
|
681
681
|
: {
|
|
682
682
|
type: 'uniform'
|
|
683
683
|
kind: TKind
|
|
684
|
-
|
|
684
|
+
key: TKey
|
|
685
685
|
}
|
|
686
686
|
|
|
687
687
|
export interface AttributeTag<
|
|
688
|
-
|
|
688
|
+
TKey extends string | symbol = string | symbol,
|
|
689
689
|
TKind extends AttributeKind = AttributeKind,
|
|
690
690
|
TInstanced extends boolean | undefined = boolean | undefined,
|
|
691
691
|
> {
|
|
692
692
|
type: 'attribute'
|
|
693
693
|
kind: TKind
|
|
694
694
|
instanced: TInstanced
|
|
695
|
-
|
|
695
|
+
key: TKey
|
|
696
696
|
}
|
|
697
697
|
|
|
698
698
|
export interface AttributeTagFn<TKey extends AttributeKind> {
|
|
699
|
-
<TName extends string, TOptions extends Omit<AttributeOptions, 'kind'>>(
|
|
700
|
-
|
|
699
|
+
<TName extends string | symbol, TOptions extends Omit<AttributeOptions, 'kind'>>(
|
|
700
|
+
key: TName,
|
|
701
701
|
options: TOptions,
|
|
702
702
|
): Prettify<AttributeTag<TName, TKey, TOptions['instanced']>>
|
|
703
|
-
<TName extends string>(
|
|
703
|
+
<TName extends string | symbol>(key: TName): Prettify<AttributeTag<TName, TKey, undefined>>
|
|
704
704
|
}
|
|
705
705
|
|
|
706
706
|
export type InterleaveTag<
|
|
707
|
-
|
|
708
|
-
TLayout extends Array<AttributeTag<string, AttributeKind, undefined>> = Array<
|
|
709
|
-
AttributeTag<string, AttributeKind, undefined>
|
|
707
|
+
TKey extends string | symbol = string | symbol,
|
|
708
|
+
TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>> = Array<
|
|
709
|
+
AttributeTag<string | symbol, AttributeKind, undefined>
|
|
710
710
|
>,
|
|
711
711
|
TOptions extends Omit<AttributeOptions, 'kind'> = Omit<AttributeOptions, 'kind'>,
|
|
712
712
|
> = TOptions & {
|
|
713
|
-
|
|
713
|
+
key: TKey
|
|
714
714
|
type: 'interleavedAttribute'
|
|
715
715
|
layout: {
|
|
716
|
-
[TKey in keyof TLayout]: Prettify<Pick<TLayout[TKey], 'kind' | '
|
|
716
|
+
[TKey in keyof TLayout]: Prettify<Pick<TLayout[TKey], 'kind' | 'key'>>
|
|
717
717
|
}
|
|
718
718
|
}
|
|
@@ -6,16 +6,9 @@ import type {
|
|
|
6
6
|
KIND_TO_UNIFORM_FN_NAME_MAP,
|
|
7
7
|
TextureOptions,
|
|
8
8
|
UniformKind,
|
|
9
|
-
} from '
|
|
10
|
-
|
|
11
|
-
export
|
|
12
|
-
value: T,
|
|
13
|
-
callback: (value: T[keyof T], key: Extract<keyof T, string>, index: number) => TReturn,
|
|
14
|
-
): { [TKey in keyof T]: TReturn } {
|
|
15
|
-
return Object.fromEntries(
|
|
16
|
-
Object.entries(value).map(([key, value], index) => [key, callback(value, key, index)]),
|
|
17
|
-
)
|
|
18
|
-
}
|
|
9
|
+
} from '../types'
|
|
10
|
+
|
|
11
|
+
export * as ObjectUtils from './object'
|
|
19
12
|
|
|
20
13
|
export function assertedNotNullish<T>(value: T, message?: string): NonNullable<T> {
|
|
21
14
|
if (value === undefined || value === null) throw new Error(message)
|
|
@@ -111,12 +104,16 @@ export const kindToUniformFnName = <T extends UniformKind>(
|
|
|
111
104
|
export const kindToSize = <T extends UniformKind>(kind: T): KIND_TO_SIZE_MAP[T] => {
|
|
112
105
|
switch (kind[0]) {
|
|
113
106
|
case 'm':
|
|
114
|
-
const [a, b] = kind.match(/\d+/g)!.map(Number)
|
|
115
|
-
return a * (b
|
|
107
|
+
const [a, b] = kind.match(/\d+/g)!.map(Number) as [number, number?]
|
|
108
|
+
return (a * (b ?? a)) as KIND_TO_SIZE_MAP[T]
|
|
116
109
|
case 'v':
|
|
117
|
-
|
|
110
|
+
case 'i':
|
|
111
|
+
case 'b':
|
|
112
|
+
case 'u':
|
|
113
|
+
const match = kind.match(/\d/) as [string] | undefined
|
|
114
|
+
return (match ? +match[0] : 1) as KIND_TO_SIZE_MAP[T]
|
|
118
115
|
default:
|
|
119
|
-
return 1
|
|
116
|
+
return 1 as KIND_TO_SIZE_MAP[T]
|
|
120
117
|
}
|
|
121
118
|
}
|
|
122
119
|
|
|
@@ -264,3 +261,31 @@ export function createFramebuffer(gl: GL, { attachment, texture, ...options }: F
|
|
|
264
261
|
framebuffer,
|
|
265
262
|
}
|
|
266
263
|
}
|
|
264
|
+
|
|
265
|
+
/**********************************************************************************/
|
|
266
|
+
/* */
|
|
267
|
+
/* Create Upsert */
|
|
268
|
+
/* */
|
|
269
|
+
/**********************************************************************************/
|
|
270
|
+
|
|
271
|
+
type UpsertMapKind<T, U> = Map<T, U> | WeakMap<T, U>
|
|
272
|
+
|
|
273
|
+
export function createUpsertMap<T extends UpsertMapKind<any, any> = Map<any, any>>(
|
|
274
|
+
constructor?: new () => T,
|
|
275
|
+
) {
|
|
276
|
+
const map = new (constructor ?? Map)() as T
|
|
277
|
+
return Object.assign(map, {
|
|
278
|
+
getOrInsert(
|
|
279
|
+
key: T extends UpsertMapKind<infer U, any> ? U : never,
|
|
280
|
+
value: T extends UpsertMapKind<any, infer U> ? () => U : never,
|
|
281
|
+
) {
|
|
282
|
+
let result = map.get(key)
|
|
283
|
+
if (result) {
|
|
284
|
+
return result
|
|
285
|
+
}
|
|
286
|
+
result = value()
|
|
287
|
+
map.set(key, result)
|
|
288
|
+
return result
|
|
289
|
+
},
|
|
290
|
+
})
|
|
291
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function forEach<T extends Record<string, any>>(
|
|
2
|
+
value: T,
|
|
3
|
+
callback: (value: T[keyof T], key: keyof T, index: number) => void,
|
|
4
|
+
) {
|
|
5
|
+
let index = 0
|
|
6
|
+
for (const key in value) {
|
|
7
|
+
callback(value[key], key, index)
|
|
8
|
+
index++
|
|
9
|
+
}
|
|
10
|
+
for (const key of Object.getOwnPropertySymbols(value)) {
|
|
11
|
+
callback(value[key as keyof T], key as keyof T, index)
|
|
12
|
+
index++
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function map<T extends Record<string, any>, TReturn>(
|
|
17
|
+
value: T,
|
|
18
|
+
callback: (value: T[keyof T], key: keyof T, index: number) => TReturn,
|
|
19
|
+
): { [TKey in keyof T]: TReturn } {
|
|
20
|
+
const result = {} as { [TKey in keyof T]: TReturn }
|
|
21
|
+
|
|
22
|
+
forEach(value, (value, key, index) => {
|
|
23
|
+
result[key] = callback(value, key, index)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
return result
|
|
27
|
+
}
|