@bigmistqke/view.gl 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/.github/ISSUE_TEMPLATE/bug-report.yml +31 -0
  3. package/.github/ISSUE_TEMPLATE/feature-request.yml +27 -0
  4. package/.github/workflows/codeql.yml +46 -0
  5. package/.github/workflows/deploy-page.yml +38 -0
  6. package/.github/workflows/format.yml +40 -0
  7. package/README.md +92 -35
  8. package/dev/404.html +19 -0
  9. package/dev/dist/404.html +19 -0
  10. package/dev/dist/assets/bezier-DuLTb2d1.js +294 -0
  11. package/dev/dist/assets/game_of_life-D7qHdFcv.js +202 -0
  12. package/dev/dist/assets/grid-Ie22U_9K.js +173 -0
  13. package/dev/dist/assets/index-0qrXMlfv.js +109 -0
  14. package/dev/dist/assets/index-C2N3u8wj.css +12 -0
  15. package/dev/dist/assets/main-BZ1N6pp6.js +32 -0
  16. package/dev/dist/assets/overview-DAxtMIw5.js +78 -0
  17. package/dev/dist/assets/pix_sim-DIhzM_vu.js +501 -0
  18. package/dev/dist/assets/symbol-BouRL-Ni.js +65 -0
  19. package/dev/dist/assets/tag-C_bg62fD.js +516 -0
  20. package/dev/dist/assets/tetris-IMnkSi9p.js +344 -0
  21. package/dev/dist/assets/utils-CvCgsM08.js +50 -0
  22. package/dev/dist/index.html +51 -0
  23. package/dev/index.html +39 -10
  24. package/dev/{bezier.ts → src/examples/bezier.ts} +1 -1
  25. package/dev/{grid.ts → src/examples/grid.ts} +1 -1
  26. package/dev/{pix_sim.ts → src/examples/pix_sim.ts} +112 -97
  27. package/dev/src/examples/symbol.ts +79 -0
  28. package/dev/{tetris.ts → src/examples/tetris.ts} +1 -0
  29. package/dev/src/index.css +12 -0
  30. package/dev/src/index.ts +69 -0
  31. package/dev/{utils.ts → src/utils.ts} +8 -2
  32. package/dev/vite.config.ts +9 -1
  33. package/dist/index.d.mts +18 -0
  34. package/dist/index.mjs +324 -0
  35. package/dist/index.mjs.map +1 -0
  36. package/dist/tag.d.mts +97 -0
  37. package/dist/tag.mjs +162 -0
  38. package/dist/tag.mjs.map +1 -0
  39. package/dist/types-DoFAJoh-.d.mts +266 -0
  40. package/package.json +24 -10
  41. package/src/index.ts +39 -17
  42. package/src/tag.ts +47 -39
  43. package/src/types.ts +24 -24
  44. package/src/{utils.ts → utils/index.ts} +39 -14
  45. package/src/utils/object.ts +27 -0
  46. package/test/index.test.ts +1017 -0
  47. package/test/mocks/webgl.ts +248 -0
  48. package/test/setup.ts +13 -0
  49. package/test/tag.test.ts +790 -0
  50. package/vitest.config.ts +15 -0
  51. /package/dev/{game_of_life.ts → src/examples/game_of_life.ts} +0 -0
  52. /package/dev/{index.ts → src/examples/overview.ts} +0 -0
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 TName extends string, const TOptions extends Omit<UniformOptions, 'kind'>>(
24
- name: TName,
24
+ <const TKey extends string | symbol, const TOptions extends Omit<UniformOptions, 'kind'>>(
25
+ key: TKey,
25
26
  TOptions: TOptions,
26
- ): Prettify<UniformTag<TName, TKind, TOptions>>
27
- <const TName extends string>(name: TName): Prettify<UniformTag<TName, TKind>>
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 (name: string, options?: Omit<UniformOptions, 'kind'>) => ({
39
+ return (key: string, options?: Omit<UniformOptions, 'kind'>) => ({
39
40
  type: 'uniform',
40
- name,
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 (name: string, options?: Omit<AttributeOptions, 'kind'>) => ({
57
+ return (key: string, options?: Omit<AttributeOptions, 'kind'>) => ({
57
58
  type: 'attribute',
58
- name,
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 TName extends string,
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
- >(name: TName, layout: TLayout, instanced: TOptions): InterleaveTag<TName, TLayout, TOptions>
71
+ >(key: TKey, layout: TLayout, instanced: TOptions): InterleaveTag<TKey, TLayout, TOptions>
71
72
  export function interleave<
72
- const TName extends string,
73
- const TLayout extends Array<AttributeTag<string, AttributeKind, undefined>>,
74
- >(name: TName, layout: TLayout): InterleaveTag<TName, TLayout, { instanced: false }>
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 TName extends string,
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
- >(name: TName, layout: TLayout, { instanced, buffer }?: TOptions = {}) {
80
+ >(key: TKey, layout: TLayout, { instanced, buffer }: Partial<TOptions> = {}) {
80
81
  return {
81
82
  type: 'interleavedAttribute',
82
- name,
83
+ key,
83
84
  // remove instanced- and type-property
84
- layout: layout.map(({ name, kind }) => ({
85
- name,
85
+ layout: layout.map(({ key, kind }) => ({
86
+ key,
86
87
  kind,
87
88
  })),
88
89
  instanced: !!instanced,
89
90
  buffer,
90
- } as InterleaveTag<TName, TLayout, TOptions>
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
- ? hole.layout.reduce(
113
- (a, v) =>
114
- v300 ? `${a}in ${v.kind} ${v.name};\n` : `${a}attribute ${v.kind} ${v.name};\n`,
115
- '',
116
- )
117
- : typeof hole === 'object' && hole.type === 'uniform' && 'size' in hole
118
- ? `${hole.type} ${hole.kind} ${hole.name}[${hole.size}];`
119
- : `${hole.type === 'attribute' && v300 ? 'in' : hole.type} ${hole.kind} ${hole.name};`
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 (typeof resource === 'string' || typeof resource === 'number') {
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
- resources[`${resource.type}s`][resource.name] = resource
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['name']]: Prettify<Omit<K, 'name' | 'type'>>
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['name']]: Prettify<Omit<K, 'name' | 'type'>>
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['name']]: Prettify<
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
- ? B[K]
8
- : never
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
- name: string
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
- TName extends string = string,
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
- name: TName
678
+ key: TKey
679
679
  size: TSize
680
680
  }
681
681
  : {
682
682
  type: 'uniform'
683
683
  kind: TKind
684
- name: TName
684
+ key: TKey
685
685
  }
686
686
 
687
687
  export interface AttributeTag<
688
- TName extends string = string,
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
- name: TName
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
- name: TName,
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>(name: TName): Prettify<AttributeTag<TName, TKey, undefined>>
703
+ <TName extends string | symbol>(key: TName): Prettify<AttributeTag<TName, TKey, undefined>>
704
704
  }
705
705
 
706
706
  export type InterleaveTag<
707
- TName extends string = string,
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
- name: TName
713
+ key: TKey
714
714
  type: 'interleavedAttribute'
715
715
  layout: {
716
- [TKey in keyof TLayout]: Prettify<Pick<TLayout[TKey], 'kind' | 'name'>>
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 './types'
10
-
11
- export function mapObject<T extends Record<string, any>, TReturn>(
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 || a)
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
- return +kind.match(/\d/)![0]
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
+ }