@motion-core/motion-gpu 0.4.1 → 0.5.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.
Files changed (228) hide show
  1. package/README.md +99 -0
  2. package/dist/advanced.d.ts +1 -0
  3. package/dist/advanced.d.ts.map +1 -0
  4. package/dist/advanced.js +14 -6
  5. package/dist/core/advanced.d.ts +1 -0
  6. package/dist/core/advanced.d.ts.map +1 -0
  7. package/dist/core/advanced.js +14 -5
  8. package/dist/core/compute-shader.d.ts +87 -0
  9. package/dist/core/compute-shader.d.ts.map +1 -0
  10. package/dist/core/compute-shader.js +205 -0
  11. package/dist/core/compute-shader.js.map +1 -0
  12. package/dist/core/current-value.d.ts +1 -0
  13. package/dist/core/current-value.d.ts.map +1 -0
  14. package/dist/core/current-value.js +35 -34
  15. package/dist/core/current-value.js.map +1 -0
  16. package/dist/core/error-diagnostics.d.ts +1 -0
  17. package/dist/core/error-diagnostics.d.ts.map +1 -0
  18. package/dist/core/error-diagnostics.js +70 -137
  19. package/dist/core/error-diagnostics.js.map +1 -0
  20. package/dist/core/error-report.d.ts +2 -1
  21. package/dist/core/error-report.d.ts.map +1 -0
  22. package/dist/core/error-report.js +247 -233
  23. package/dist/core/error-report.js.map +1 -0
  24. package/dist/core/frame-registry.d.ts +1 -0
  25. package/dist/core/frame-registry.d.ts.map +1 -0
  26. package/dist/core/frame-registry.js +546 -662
  27. package/dist/core/frame-registry.js.map +1 -0
  28. package/dist/core/index.d.ts +6 -2
  29. package/dist/core/index.d.ts.map +1 -0
  30. package/dist/core/index.js +13 -12
  31. package/dist/core/material-preprocess.d.ts +1 -0
  32. package/dist/core/material-preprocess.d.ts.map +1 -0
  33. package/dist/core/material-preprocess.js +131 -152
  34. package/dist/core/material-preprocess.js.map +1 -0
  35. package/dist/core/material.d.ts +23 -6
  36. package/dist/core/material.d.ts.map +1 -0
  37. package/dist/core/material.js +290 -317
  38. package/dist/core/material.js.map +1 -0
  39. package/dist/core/recompile-policy.d.ts +1 -0
  40. package/dist/core/recompile-policy.d.ts.map +1 -0
  41. package/dist/core/recompile-policy.js +18 -13
  42. package/dist/core/recompile-policy.js.map +1 -0
  43. package/dist/core/render-graph.d.ts +8 -3
  44. package/dist/core/render-graph.d.ts.map +1 -0
  45. package/dist/core/render-graph.js +77 -68
  46. package/dist/core/render-graph.js.map +1 -0
  47. package/dist/core/render-targets.d.ts +1 -0
  48. package/dist/core/render-targets.d.ts.map +1 -0
  49. package/dist/core/render-targets.js +52 -53
  50. package/dist/core/render-targets.js.map +1 -0
  51. package/dist/core/renderer.d.ts +1 -0
  52. package/dist/core/renderer.d.ts.map +1 -0
  53. package/dist/core/renderer.js +1337 -1081
  54. package/dist/core/renderer.js.map +1 -0
  55. package/dist/core/runtime-loop.d.ts +3 -2
  56. package/dist/core/runtime-loop.d.ts.map +1 -0
  57. package/dist/core/runtime-loop.js +353 -362
  58. package/dist/core/runtime-loop.js.map +1 -0
  59. package/dist/core/scheduler-helpers.d.ts +1 -0
  60. package/dist/core/scheduler-helpers.d.ts.map +1 -0
  61. package/dist/core/scheduler-helpers.js +52 -51
  62. package/dist/core/scheduler-helpers.js.map +1 -0
  63. package/dist/core/shader.d.ts +10 -1
  64. package/dist/core/shader.d.ts.map +1 -0
  65. package/dist/core/shader.js +109 -115
  66. package/dist/core/shader.js.map +1 -0
  67. package/dist/core/storage-buffers.d.ts +37 -0
  68. package/dist/core/storage-buffers.d.ts.map +1 -0
  69. package/dist/core/storage-buffers.js +95 -0
  70. package/dist/core/storage-buffers.js.map +1 -0
  71. package/dist/core/texture-loader.d.ts +1 -0
  72. package/dist/core/texture-loader.d.ts.map +1 -0
  73. package/dist/core/texture-loader.js +209 -273
  74. package/dist/core/texture-loader.js.map +1 -0
  75. package/dist/core/textures.d.ts +13 -0
  76. package/dist/core/textures.d.ts.map +1 -0
  77. package/dist/core/textures.js +111 -116
  78. package/dist/core/textures.js.map +1 -0
  79. package/dist/core/types.d.ts +147 -4
  80. package/dist/core/types.d.ts.map +1 -0
  81. package/dist/core/types.js +0 -4
  82. package/dist/core/uniforms.d.ts +1 -0
  83. package/dist/core/uniforms.d.ts.map +1 -0
  84. package/dist/core/uniforms.js +170 -191
  85. package/dist/core/uniforms.js.map +1 -0
  86. package/dist/index.d.ts +1 -0
  87. package/dist/index.d.ts.map +1 -0
  88. package/dist/index.js +13 -6
  89. package/dist/passes/BlitPass.d.ts +1 -0
  90. package/dist/passes/BlitPass.d.ts.map +1 -0
  91. package/dist/passes/BlitPass.js +23 -18
  92. package/dist/passes/BlitPass.js.map +1 -0
  93. package/dist/passes/ComputePass.d.ts +83 -0
  94. package/dist/passes/ComputePass.d.ts.map +1 -0
  95. package/dist/passes/ComputePass.js +92 -0
  96. package/dist/passes/ComputePass.js.map +1 -0
  97. package/dist/passes/CopyPass.d.ts +1 -0
  98. package/dist/passes/CopyPass.d.ts.map +1 -0
  99. package/dist/passes/CopyPass.js +58 -52
  100. package/dist/passes/CopyPass.js.map +1 -0
  101. package/dist/passes/FullscreenPass.d.ts +1 -0
  102. package/dist/passes/FullscreenPass.d.ts.map +1 -0
  103. package/dist/passes/FullscreenPass.js +127 -130
  104. package/dist/passes/FullscreenPass.js.map +1 -0
  105. package/dist/passes/PingPongComputePass.d.ts +104 -0
  106. package/dist/passes/PingPongComputePass.d.ts.map +1 -0
  107. package/dist/passes/PingPongComputePass.js +132 -0
  108. package/dist/passes/PingPongComputePass.js.map +1 -0
  109. package/dist/passes/ShaderPass.d.ts +1 -0
  110. package/dist/passes/ShaderPass.d.ts.map +1 -0
  111. package/dist/passes/ShaderPass.js +41 -37
  112. package/dist/passes/ShaderPass.js.map +1 -0
  113. package/dist/passes/index.d.ts +3 -0
  114. package/dist/passes/index.d.ts.map +1 -0
  115. package/dist/passes/index.js +6 -3
  116. package/dist/react/FragCanvas.d.ts +3 -2
  117. package/dist/react/FragCanvas.d.ts.map +1 -0
  118. package/dist/react/FragCanvas.js +234 -211
  119. package/dist/react/FragCanvas.js.map +1 -0
  120. package/dist/react/MotionGPUErrorOverlay.d.ts +1 -0
  121. package/dist/react/MotionGPUErrorOverlay.d.ts.map +1 -0
  122. package/dist/react/MotionGPUErrorOverlay.js +200 -14
  123. package/dist/react/MotionGPUErrorOverlay.js.map +1 -0
  124. package/dist/react/Portal.d.ts +1 -0
  125. package/dist/react/Portal.d.ts.map +1 -0
  126. package/dist/react/Portal.js +18 -21
  127. package/dist/react/Portal.js.map +1 -0
  128. package/dist/react/advanced.d.ts +1 -0
  129. package/dist/react/advanced.d.ts.map +1 -0
  130. package/dist/react/advanced.js +14 -6
  131. package/dist/react/frame-context.d.ts +1 -0
  132. package/dist/react/frame-context.d.ts.map +1 -0
  133. package/dist/react/frame-context.js +88 -94
  134. package/dist/react/frame-context.js.map +1 -0
  135. package/dist/react/index.d.ts +6 -2
  136. package/dist/react/index.d.ts.map +1 -0
  137. package/dist/react/index.js +12 -9
  138. package/dist/react/motiongpu-context.d.ts +1 -0
  139. package/dist/react/motiongpu-context.d.ts.map +1 -0
  140. package/dist/react/motiongpu-context.js +18 -15
  141. package/dist/react/motiongpu-context.js.map +1 -0
  142. package/dist/react/use-motiongpu-user-context.d.ts +1 -0
  143. package/dist/react/use-motiongpu-user-context.d.ts.map +1 -0
  144. package/dist/react/use-motiongpu-user-context.js +83 -82
  145. package/dist/react/use-motiongpu-user-context.js.map +1 -0
  146. package/dist/react/use-texture.d.ts +1 -0
  147. package/dist/react/use-texture.d.ts.map +1 -0
  148. package/dist/react/use-texture.js +132 -152
  149. package/dist/react/use-texture.js.map +1 -0
  150. package/dist/svelte/FragCanvas.svelte +2 -2
  151. package/dist/svelte/FragCanvas.svelte.d.ts +3 -2
  152. package/dist/svelte/FragCanvas.svelte.d.ts.map +1 -0
  153. package/dist/svelte/MotionGPUErrorOverlay.svelte +137 -7
  154. package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts +1 -0
  155. package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts.map +1 -0
  156. package/dist/svelte/Portal.svelte.d.ts +1 -0
  157. package/dist/svelte/Portal.svelte.d.ts.map +1 -0
  158. package/dist/svelte/advanced.d.ts +1 -0
  159. package/dist/svelte/advanced.d.ts.map +1 -0
  160. package/dist/svelte/advanced.js +13 -6
  161. package/dist/svelte/frame-context.d.ts +1 -0
  162. package/dist/svelte/frame-context.d.ts.map +1 -0
  163. package/dist/svelte/frame-context.js +27 -27
  164. package/dist/svelte/frame-context.js.map +1 -0
  165. package/dist/svelte/index.d.ts +6 -2
  166. package/dist/svelte/index.d.ts.map +1 -0
  167. package/dist/svelte/index.js +12 -9
  168. package/dist/svelte/motiongpu-context.d.ts +1 -0
  169. package/dist/svelte/motiongpu-context.d.ts.map +1 -0
  170. package/dist/svelte/motiongpu-context.js +24 -21
  171. package/dist/svelte/motiongpu-context.js.map +1 -0
  172. package/dist/svelte/use-motiongpu-user-context.d.ts +1 -0
  173. package/dist/svelte/use-motiongpu-user-context.d.ts.map +1 -0
  174. package/dist/svelte/use-motiongpu-user-context.js +69 -70
  175. package/dist/svelte/use-motiongpu-user-context.js.map +1 -0
  176. package/dist/svelte/use-texture.d.ts +1 -0
  177. package/dist/svelte/use-texture.d.ts.map +1 -0
  178. package/dist/svelte/use-texture.js +125 -147
  179. package/dist/svelte/use-texture.js.map +1 -0
  180. package/package.json +12 -7
  181. package/src/lib/advanced.ts +6 -0
  182. package/src/lib/core/advanced.ts +12 -0
  183. package/src/lib/core/compute-shader.ts +326 -0
  184. package/src/lib/core/current-value.ts +64 -0
  185. package/src/lib/core/error-diagnostics.ts +236 -0
  186. package/src/lib/core/error-report.ts +535 -0
  187. package/src/lib/core/frame-registry.ts +1190 -0
  188. package/src/lib/core/index.ts +94 -0
  189. package/src/lib/core/material-preprocess.ts +295 -0
  190. package/src/lib/core/material.ts +748 -0
  191. package/src/lib/core/recompile-policy.ts +31 -0
  192. package/src/lib/core/render-graph.ts +173 -0
  193. package/src/lib/core/render-targets.ts +107 -0
  194. package/src/lib/core/renderer.ts +2161 -0
  195. package/src/lib/core/runtime-loop.ts +537 -0
  196. package/src/lib/core/scheduler-helpers.ts +136 -0
  197. package/src/lib/core/shader.ts +301 -0
  198. package/src/lib/core/storage-buffers.ts +142 -0
  199. package/src/lib/core/texture-loader.ts +482 -0
  200. package/src/lib/core/textures.ts +257 -0
  201. package/src/lib/core/types.ts +743 -0
  202. package/src/lib/core/uniforms.ts +282 -0
  203. package/src/lib/index.ts +6 -0
  204. package/src/lib/passes/BlitPass.ts +54 -0
  205. package/src/lib/passes/ComputePass.ts +136 -0
  206. package/src/lib/passes/CopyPass.ts +80 -0
  207. package/src/lib/passes/FullscreenPass.ts +173 -0
  208. package/src/lib/passes/PingPongComputePass.ts +180 -0
  209. package/src/lib/passes/ShaderPass.ts +89 -0
  210. package/src/lib/passes/index.ts +9 -0
  211. package/src/lib/react/FragCanvas.tsx +345 -0
  212. package/src/lib/react/MotionGPUErrorOverlay.tsx +524 -0
  213. package/src/lib/react/Portal.tsx +34 -0
  214. package/src/lib/react/advanced.ts +36 -0
  215. package/src/lib/react/frame-context.ts +169 -0
  216. package/src/lib/react/index.ts +68 -0
  217. package/src/lib/react/motiongpu-context.ts +88 -0
  218. package/src/lib/react/use-motiongpu-user-context.ts +186 -0
  219. package/src/lib/react/use-texture.ts +233 -0
  220. package/src/lib/svelte/FragCanvas.svelte +249 -0
  221. package/src/lib/svelte/MotionGPUErrorOverlay.svelte +512 -0
  222. package/src/lib/svelte/Portal.svelte +31 -0
  223. package/src/lib/svelte/advanced.ts +32 -0
  224. package/src/lib/svelte/frame-context.ts +87 -0
  225. package/src/lib/svelte/index.ts +68 -0
  226. package/src/lib/svelte/motiongpu-context.ts +97 -0
  227. package/src/lib/svelte/use-motiongpu-user-context.ts +145 -0
  228. package/src/lib/svelte/use-texture.ts +232 -0
@@ -0,0 +1,95 @@
1
+ import { assertUniformName } from "./uniforms.js";
2
+ //#region src/lib/core/storage-buffers.ts
3
+ /**
4
+ * Valid WGSL storage buffer element types.
5
+ */
6
+ var VALID_STORAGE_BUFFER_TYPES = new Set([
7
+ "array<f32>",
8
+ "array<vec2f>",
9
+ "array<vec3f>",
10
+ "array<vec4f>",
11
+ "array<u32>",
12
+ "array<i32>",
13
+ "array<vec4u>",
14
+ "array<vec4i>"
15
+ ]);
16
+ /**
17
+ * Storage-compatible texture formats for `texture_storage_2d`.
18
+ */
19
+ var STORAGE_TEXTURE_FORMATS = new Set([
20
+ "r32float",
21
+ "r32sint",
22
+ "r32uint",
23
+ "rg32float",
24
+ "rg32sint",
25
+ "rg32uint",
26
+ "rgba8unorm",
27
+ "rgba8snorm",
28
+ "rgba8uint",
29
+ "rgba8sint",
30
+ "rgba16float",
31
+ "rgba16uint",
32
+ "rgba16sint",
33
+ "rgba32float",
34
+ "rgba32uint",
35
+ "rgba32sint",
36
+ "bgra8unorm"
37
+ ]);
38
+ /**
39
+ * Validates a single storage buffer definition.
40
+ *
41
+ * @param name - Buffer identifier.
42
+ * @param definition - Storage buffer definition to validate.
43
+ * @throws {Error} When any field is invalid.
44
+ */
45
+ function assertStorageBufferDefinition(name, definition) {
46
+ assertUniformName(name);
47
+ if (!Number.isFinite(definition.size) || definition.size <= 0) throw new Error(`Storage buffer "${name}" size must be a finite number greater than 0, got ${definition.size}`);
48
+ if (definition.size % 4 !== 0) throw new Error(`Storage buffer "${name}" size must be a multiple of 4, got ${definition.size}`);
49
+ if (!VALID_STORAGE_BUFFER_TYPES.has(definition.type)) throw new Error(`Storage buffer "${name}" has unknown type "${definition.type}". Supported types: ${[...VALID_STORAGE_BUFFER_TYPES].join(", ")}`);
50
+ if (definition.access !== void 0 && definition.access !== "read" && definition.access !== "read-write") throw new Error(`Storage buffer "${name}" has invalid access mode "${definition.access}". Use 'read' or 'read-write'.`);
51
+ if (definition.initialData !== void 0) {
52
+ if (definition.initialData.byteLength > definition.size) throw new Error(`Storage buffer "${name}" initialData byte length (${definition.initialData.byteLength}) exceeds buffer size (${definition.size})`);
53
+ }
54
+ }
55
+ /**
56
+ * Validates and returns sorted storage buffer keys.
57
+ *
58
+ * @param definitions - Storage buffer definition map.
59
+ * @returns Lexicographically sorted buffer keys.
60
+ */
61
+ function resolveStorageBufferKeys(definitions) {
62
+ const keys = Object.keys(definitions).sort();
63
+ for (const key of keys) {
64
+ const definition = definitions[key];
65
+ if (definition) assertStorageBufferDefinition(key, definition);
66
+ }
67
+ return keys;
68
+ }
69
+ /**
70
+ * Normalizes a storage buffer definition with defaults applied.
71
+ *
72
+ * @param definition - Raw definition.
73
+ * @returns Normalized definition with access default.
74
+ */
75
+ function normalizeStorageBufferDefinition(definition) {
76
+ return {
77
+ size: definition.size,
78
+ type: definition.type,
79
+ access: definition.access ?? "read-write"
80
+ };
81
+ }
82
+ /**
83
+ * Validates that a texture format is storage-compatible.
84
+ *
85
+ * @param name - Texture identifier.
86
+ * @param format - GPU texture format.
87
+ * @throws {Error} When format is not storage-compatible.
88
+ */
89
+ function assertStorageTextureFormat(name, format) {
90
+ if (!STORAGE_TEXTURE_FORMATS.has(format)) throw new Error(`Texture "${name}" with storage:true requires a storage-compatible format, but got "${format}". Supported formats: ${[...STORAGE_TEXTURE_FORMATS].join(", ")}`);
91
+ }
92
+ //#endregion
93
+ export { STORAGE_TEXTURE_FORMATS, assertStorageBufferDefinition, assertStorageTextureFormat, normalizeStorageBufferDefinition, resolveStorageBufferKeys };
94
+
95
+ //# sourceMappingURL=storage-buffers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-buffers.js","names":[],"sources":["../../src/lib/core/storage-buffers.ts"],"sourcesContent":["import { assertUniformName } from './uniforms.js';\nimport type {\n\tStorageBufferDefinition,\n\tStorageBufferDefinitionMap,\n\tStorageBufferType\n} from './types.js';\n\n/**\n * Valid WGSL storage buffer element types.\n */\nconst VALID_STORAGE_BUFFER_TYPES: ReadonlySet<string> = new Set<StorageBufferType>([\n\t'array<f32>',\n\t'array<vec2f>',\n\t'array<vec3f>',\n\t'array<vec4f>',\n\t'array<u32>',\n\t'array<i32>',\n\t'array<vec4u>',\n\t'array<vec4i>'\n]);\n\n/**\n * Storage-compatible texture formats for `texture_storage_2d`.\n */\nexport const STORAGE_TEXTURE_FORMATS: ReadonlySet<GPUTextureFormat> = new Set([\n\t'r32float',\n\t'r32sint',\n\t'r32uint',\n\t'rg32float',\n\t'rg32sint',\n\t'rg32uint',\n\t'rgba8unorm',\n\t'rgba8snorm',\n\t'rgba8uint',\n\t'rgba8sint',\n\t'rgba16float',\n\t'rgba16uint',\n\t'rgba16sint',\n\t'rgba32float',\n\t'rgba32uint',\n\t'rgba32sint',\n\t'bgra8unorm'\n] as GPUTextureFormat[]);\n\n/**\n * Validates a single storage buffer definition.\n *\n * @param name - Buffer identifier.\n * @param definition - Storage buffer definition to validate.\n * @throws {Error} When any field is invalid.\n */\nexport function assertStorageBufferDefinition(\n\tname: string,\n\tdefinition: StorageBufferDefinition\n): void {\n\tassertUniformName(name);\n\n\tif (!Number.isFinite(definition.size) || definition.size <= 0) {\n\t\tthrow new Error(\n\t\t\t`Storage buffer \"${name}\" size must be a finite number greater than 0, got ${definition.size}`\n\t\t);\n\t}\n\n\tif (definition.size % 4 !== 0) {\n\t\tthrow new Error(\n\t\t\t`Storage buffer \"${name}\" size must be a multiple of 4, got ${definition.size}`\n\t\t);\n\t}\n\n\tif (!VALID_STORAGE_BUFFER_TYPES.has(definition.type)) {\n\t\tthrow new Error(\n\t\t\t`Storage buffer \"${name}\" has unknown type \"${definition.type}\". Supported types: ${[...VALID_STORAGE_BUFFER_TYPES].join(', ')}`\n\t\t);\n\t}\n\n\tif (\n\t\tdefinition.access !== undefined &&\n\t\tdefinition.access !== 'read' &&\n\t\tdefinition.access !== 'read-write'\n\t) {\n\t\tthrow new Error(\n\t\t\t`Storage buffer \"${name}\" has invalid access mode \"${definition.access}\". Use 'read' or 'read-write'.`\n\t\t);\n\t}\n\n\tif (definition.initialData !== undefined) {\n\t\tif (definition.initialData.byteLength > definition.size) {\n\t\t\tthrow new Error(\n\t\t\t\t`Storage buffer \"${name}\" initialData byte length (${definition.initialData.byteLength}) exceeds buffer size (${definition.size})`\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Validates and returns sorted storage buffer keys.\n *\n * @param definitions - Storage buffer definition map.\n * @returns Lexicographically sorted buffer keys.\n */\nexport function resolveStorageBufferKeys(definitions: StorageBufferDefinitionMap): string[] {\n\tconst keys = Object.keys(definitions).sort();\n\tfor (const key of keys) {\n\t\tconst definition = definitions[key];\n\t\tif (definition) {\n\t\t\tassertStorageBufferDefinition(key, definition);\n\t\t}\n\t}\n\treturn keys;\n}\n\n/**\n * Normalizes a storage buffer definition with defaults applied.\n *\n * @param definition - Raw definition.\n * @returns Normalized definition with access default.\n */\nexport function normalizeStorageBufferDefinition(\n\tdefinition: StorageBufferDefinition\n): Required<Pick<StorageBufferDefinition, 'size' | 'type' | 'access'>> {\n\treturn {\n\t\tsize: definition.size,\n\t\ttype: definition.type,\n\t\taccess: definition.access ?? 'read-write'\n\t};\n}\n\n/**\n * Validates that a texture format is storage-compatible.\n *\n * @param name - Texture identifier.\n * @param format - GPU texture format.\n * @throws {Error} When format is not storage-compatible.\n */\nexport function assertStorageTextureFormat(name: string, format: GPUTextureFormat): void {\n\tif (!STORAGE_TEXTURE_FORMATS.has(format)) {\n\t\tthrow new Error(\n\t\t\t`Texture \"${name}\" with storage:true requires a storage-compatible format, but got \"${format}\". ` +\n\t\t\t\t`Supported formats: ${[...STORAGE_TEXTURE_FORMATS].join(', ')}`\n\t\t);\n\t}\n}\n"],"mappings":";;;;;AAUA,IAAM,6BAAkD,IAAI,IAAuB;CAClF;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;;;;AAKF,IAAa,0BAAyD,IAAI,IAAI;CAC7E;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,CAAuB;;;;;;;;AASxB,SAAgB,8BACf,MACA,YACO;AACP,mBAAkB,KAAK;AAEvB,KAAI,CAAC,OAAO,SAAS,WAAW,KAAK,IAAI,WAAW,QAAQ,EAC3D,OAAM,IAAI,MACT,mBAAmB,KAAK,qDAAqD,WAAW,OACxF;AAGF,KAAI,WAAW,OAAO,MAAM,EAC3B,OAAM,IAAI,MACT,mBAAmB,KAAK,sCAAsC,WAAW,OACzE;AAGF,KAAI,CAAC,2BAA2B,IAAI,WAAW,KAAK,CACnD,OAAM,IAAI,MACT,mBAAmB,KAAK,sBAAsB,WAAW,KAAK,sBAAsB,CAAC,GAAG,2BAA2B,CAAC,KAAK,KAAK,GAC9H;AAGF,KACC,WAAW,WAAW,UACtB,WAAW,WAAW,UACtB,WAAW,WAAW,aAEtB,OAAM,IAAI,MACT,mBAAmB,KAAK,6BAA6B,WAAW,OAAO,gCACvE;AAGF,KAAI,WAAW,gBAAgB,QAC9B;MAAI,WAAW,YAAY,aAAa,WAAW,KAClD,OAAM,IAAI,MACT,mBAAmB,KAAK,6BAA6B,WAAW,YAAY,WAAW,yBAAyB,WAAW,KAAK,GAChI;;;;;;;;;AAWJ,SAAgB,yBAAyB,aAAmD;CAC3F,MAAM,OAAO,OAAO,KAAK,YAAY,CAAC,MAAM;AAC5C,MAAK,MAAM,OAAO,MAAM;EACvB,MAAM,aAAa,YAAY;AAC/B,MAAI,WACH,+BAA8B,KAAK,WAAW;;AAGhD,QAAO;;;;;;;;AASR,SAAgB,iCACf,YACsE;AACtE,QAAO;EACN,MAAM,WAAW;EACjB,MAAM,WAAW;EACjB,QAAQ,WAAW,UAAU;EAC7B;;;;;;;;;AAUF,SAAgB,2BAA2B,MAAc,QAAgC;AACxF,KAAI,CAAC,wBAAwB,IAAI,OAAO,CACvC,OAAM,IAAI,MACT,YAAY,KAAK,qEAAqE,OAAO,wBACtE,CAAC,GAAG,wBAAwB,CAAC,KAAK,KAAK,GAC9D"}
@@ -127,3 +127,4 @@ export declare function loadTextureFromUrl(url: string, options?: TextureLoadOpt
127
127
  * @returns Promise resolving to loaded textures in input order.
128
128
  */
129
129
  export declare function loadTexturesFromUrls(urls: string[], options?: TextureLoadOptions): Promise<LoadedTexture[]>;
130
+ //# sourceMappingURL=texture-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"texture-loader.d.ts","sourceRoot":"","sources":["../../src/lib/core/texture-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC;;OAEG;IACH,oBAAoB,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1C;;OAEG;IACH,gBAAgB,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,aAAa,CAAC;IACtD;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC/B;;OAEG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;OAEG;IACH,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;OAEG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,MAAM,EAAE,WAAW,CAAC;IACpB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,UAAU,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC9B;;OAEG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;CACpB;AAiCD;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAKpD;AA+FD;;GAEG;AACH,wBAAgB,4BAA4B,CAC3C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,kBAAuB,GAC9B,MAAM,CAQR;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAO5C;AAsGD;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,kBAAuB,GAC9B,OAAO,CAAC,aAAa,CAAC,CAsExB;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACzC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,kBAAuB,GAC9B,OAAO,CAAC,aAAa,EAAE,CAAC,CAsB1B"}
@@ -1,295 +1,231 @@
1
- const resourceCache = new Map();
1
+ //#region src/lib/core/texture-loader.ts
2
+ var resourceCache = /* @__PURE__ */ new Map();
2
3
  function createAbortError() {
3
- try {
4
- return new DOMException('Texture request was aborted', 'AbortError');
5
- }
6
- catch {
7
- const error = new Error('Texture request was aborted');
8
- error.name = 'AbortError';
9
- return error;
10
- }
4
+ try {
5
+ return new DOMException("Texture request was aborted", "AbortError");
6
+ } catch {
7
+ const error = /* @__PURE__ */ new Error("Texture request was aborted");
8
+ error.name = "AbortError";
9
+ return error;
10
+ }
11
11
  }
12
12
  /**
13
- * Checks whether error represents abort cancellation.
14
- */
15
- export function isAbortError(error) {
16
- return (error instanceof Error &&
17
- (error.name === 'AbortError' || error.message.toLowerCase().includes('aborted')));
13
+ * Checks whether error represents abort cancellation.
14
+ */
15
+ function isAbortError(error) {
16
+ return error instanceof Error && (error.name === "AbortError" || error.message.toLowerCase().includes("aborted"));
18
17
  }
19
18
  function toBodyFingerprint(body) {
20
- if (body == null) {
21
- return null;
22
- }
23
- if (typeof body === 'string') {
24
- return `string:${body}`;
25
- }
26
- if (body instanceof URLSearchParams) {
27
- return `urlsearchparams:${body.toString()}`;
28
- }
29
- if (typeof FormData !== 'undefined' && body instanceof FormData) {
30
- const entries = Array.from(body.entries()).map(([key, value]) => `${key}:${String(value)}`);
31
- return `formdata:${entries.join('&')}`;
32
- }
33
- if (body instanceof Blob) {
34
- return `blob:${body.type}:${body.size}`;
35
- }
36
- if (body instanceof ArrayBuffer) {
37
- return `arraybuffer:${body.byteLength}`;
38
- }
39
- if (ArrayBuffer.isView(body)) {
40
- return `view:${body.byteLength}`;
41
- }
42
- return `opaque:${Object.prototype.toString.call(body)}`;
19
+ if (body == null) return null;
20
+ if (typeof body === "string") return `string:${body}`;
21
+ if (body instanceof URLSearchParams) return `urlsearchparams:${body.toString()}`;
22
+ if (typeof FormData !== "undefined" && body instanceof FormData) return `formdata:${Array.from(body.entries()).map(([key, value]) => `${key}:${String(value)}`).join("&")}`;
23
+ if (body instanceof Blob) return `blob:${body.type}:${body.size}`;
24
+ if (body instanceof ArrayBuffer) return `arraybuffer:${body.byteLength}`;
25
+ if (ArrayBuffer.isView(body)) return `view:${body.byteLength}`;
26
+ return `opaque:${Object.prototype.toString.call(body)}`;
43
27
  }
44
28
  function normalizeRequestInit(requestInit) {
45
- if (!requestInit) {
46
- return {};
47
- }
48
- const headers = new Headers(requestInit.headers);
49
- const headerEntries = Array.from(headers.entries()).sort(([a], [b]) => a.localeCompare(b));
50
- const normalized = {};
51
- normalized.method = (requestInit.method ?? 'GET').toUpperCase();
52
- normalized.mode = requestInit.mode ?? null;
53
- normalized.cache = requestInit.cache ?? null;
54
- normalized.credentials = requestInit.credentials ?? null;
55
- normalized.redirect = requestInit.redirect ?? null;
56
- normalized.referrer = requestInit.referrer ?? null;
57
- normalized.referrerPolicy = requestInit.referrerPolicy ?? null;
58
- normalized.integrity = requestInit.integrity ?? null;
59
- normalized.keepalive = requestInit.keepalive ?? false;
60
- normalized.priority = requestInit.priority ?? null;
61
- normalized.headers = headerEntries;
62
- normalized.body = toBodyFingerprint(requestInit.body);
63
- return normalized;
29
+ if (!requestInit) return {};
30
+ const headers = new Headers(requestInit.headers);
31
+ const headerEntries = Array.from(headers.entries()).sort(([a], [b]) => a.localeCompare(b));
32
+ const normalized = {};
33
+ normalized.method = (requestInit.method ?? "GET").toUpperCase();
34
+ normalized.mode = requestInit.mode ?? null;
35
+ normalized.cache = requestInit.cache ?? null;
36
+ normalized.credentials = requestInit.credentials ?? null;
37
+ normalized.redirect = requestInit.redirect ?? null;
38
+ normalized.referrer = requestInit.referrer ?? null;
39
+ normalized.referrerPolicy = requestInit.referrerPolicy ?? null;
40
+ normalized.integrity = requestInit.integrity ?? null;
41
+ normalized.keepalive = requestInit.keepalive ?? false;
42
+ normalized.priority = requestInit.priority ?? null;
43
+ normalized.headers = headerEntries;
44
+ normalized.body = toBodyFingerprint(requestInit.body);
45
+ return normalized;
64
46
  }
65
47
  function normalizeTextureLoadOptions(options) {
66
- const colorSpace = options.colorSpace ?? 'srgb';
67
- const normalized = {
68
- colorSpace,
69
- decode: {
70
- colorSpaceConversion: options.decode?.colorSpaceConversion ?? (colorSpace === 'linear' ? 'none' : 'default'),
71
- premultiplyAlpha: options.decode?.premultiplyAlpha ?? 'default',
72
- imageOrientation: options.decode?.imageOrientation ?? 'none'
73
- }
74
- };
75
- if (options.requestInit !== undefined) {
76
- normalized.requestInit = options.requestInit;
77
- }
78
- if (options.signal !== undefined) {
79
- normalized.signal = options.signal;
80
- }
81
- if (options.update !== undefined) {
82
- normalized.update = options.update;
83
- }
84
- if (options.flipY !== undefined) {
85
- normalized.flipY = options.flipY;
86
- }
87
- if (options.premultipliedAlpha !== undefined) {
88
- normalized.premultipliedAlpha = options.premultipliedAlpha;
89
- }
90
- if (options.generateMipmaps !== undefined) {
91
- normalized.generateMipmaps = options.generateMipmaps;
92
- }
93
- return normalized;
48
+ const colorSpace = options.colorSpace ?? "srgb";
49
+ const normalized = {
50
+ colorSpace,
51
+ decode: {
52
+ colorSpaceConversion: options.decode?.colorSpaceConversion ?? (colorSpace === "linear" ? "none" : "default"),
53
+ premultiplyAlpha: options.decode?.premultiplyAlpha ?? "default",
54
+ imageOrientation: options.decode?.imageOrientation ?? "none"
55
+ }
56
+ };
57
+ if (options.requestInit !== void 0) normalized.requestInit = options.requestInit;
58
+ if (options.signal !== void 0) normalized.signal = options.signal;
59
+ if (options.update !== void 0) normalized.update = options.update;
60
+ if (options.flipY !== void 0) normalized.flipY = options.flipY;
61
+ if (options.premultipliedAlpha !== void 0) normalized.premultipliedAlpha = options.premultipliedAlpha;
62
+ if (options.generateMipmaps !== void 0) normalized.generateMipmaps = options.generateMipmaps;
63
+ return normalized;
94
64
  }
95
65
  /**
96
- * Builds deterministic resource cache key from full URL IO config.
97
- */
98
- export function buildTextureResourceCacheKey(url, options = {}) {
99
- const normalized = normalizeTextureLoadOptions(options);
100
- return JSON.stringify({
101
- url,
102
- colorSpace: normalized.colorSpace,
103
- requestInit: normalizeRequestInit(normalized.requestInit),
104
- decode: normalized.decode
105
- });
66
+ * Builds deterministic resource cache key from full URL IO config.
67
+ */
68
+ function buildTextureResourceCacheKey(url, options = {}) {
69
+ const normalized = normalizeTextureLoadOptions(options);
70
+ return JSON.stringify({
71
+ url,
72
+ colorSpace: normalized.colorSpace,
73
+ requestInit: normalizeRequestInit(normalized.requestInit),
74
+ decode: normalized.decode
75
+ });
106
76
  }
107
77
  /**
108
- * Clears the internal texture resource cache.
109
- */
110
- export function clearTextureBlobCache() {
111
- for (const entry of resourceCache.values()) {
112
- if (!entry.settled) {
113
- entry.controller.abort();
114
- }
115
- }
116
- resourceCache.clear();
78
+ * Clears the internal texture resource cache.
79
+ */
80
+ function clearTextureBlobCache() {
81
+ for (const entry of resourceCache.values()) if (!entry.settled) entry.controller.abort();
82
+ resourceCache.clear();
117
83
  }
118
84
  function acquireTextureBlob(url, options) {
119
- const key = buildTextureResourceCacheKey(url, options);
120
- const existing = resourceCache.get(key);
121
- if (existing) {
122
- existing.refs += 1;
123
- let released = false;
124
- return {
125
- entry: existing,
126
- release: () => {
127
- if (released) {
128
- return;
129
- }
130
- released = true;
131
- existing.refs = Math.max(0, existing.refs - 1);
132
- if (existing.refs === 0) {
133
- if (!existing.settled) {
134
- existing.controller.abort();
135
- }
136
- resourceCache.delete(key);
137
- }
138
- }
139
- };
140
- }
141
- const normalized = normalizeTextureLoadOptions(options);
142
- const controller = new AbortController();
143
- const requestInit = {
144
- ...(normalized.requestInit ?? {}),
145
- signal: controller.signal
146
- };
147
- const entry = {
148
- key,
149
- refs: 1,
150
- controller,
151
- settled: false,
152
- blobPromise: fetch(url, requestInit)
153
- .then(async (response) => {
154
- if (!response.ok) {
155
- throw new Error(`Texture request failed (${response.status}) for ${url}`);
156
- }
157
- return response.blob();
158
- })
159
- .then((blob) => {
160
- entry.settled = true;
161
- return blob;
162
- })
163
- .catch((error) => {
164
- resourceCache.delete(key);
165
- throw error;
166
- })
167
- };
168
- resourceCache.set(key, entry);
169
- let released = false;
170
- return {
171
- entry,
172
- release: () => {
173
- if (released) {
174
- return;
175
- }
176
- released = true;
177
- entry.refs = Math.max(0, entry.refs - 1);
178
- if (entry.refs === 0) {
179
- if (!entry.settled) {
180
- entry.controller.abort();
181
- }
182
- resourceCache.delete(key);
183
- }
184
- }
185
- };
85
+ const key = buildTextureResourceCacheKey(url, options);
86
+ const existing = resourceCache.get(key);
87
+ if (existing) {
88
+ existing.refs += 1;
89
+ let released = false;
90
+ return {
91
+ entry: existing,
92
+ release: () => {
93
+ if (released) return;
94
+ released = true;
95
+ existing.refs = Math.max(0, existing.refs - 1);
96
+ if (existing.refs === 0) {
97
+ if (!existing.settled) existing.controller.abort();
98
+ resourceCache.delete(key);
99
+ }
100
+ }
101
+ };
102
+ }
103
+ const normalized = normalizeTextureLoadOptions(options);
104
+ const controller = new AbortController();
105
+ const requestInit = {
106
+ ...normalized.requestInit ?? {},
107
+ signal: controller.signal
108
+ };
109
+ const entry = {
110
+ key,
111
+ refs: 1,
112
+ controller,
113
+ settled: false,
114
+ blobPromise: fetch(url, requestInit).then(async (response) => {
115
+ if (!response.ok) throw new Error(`Texture request failed (${response.status}) for ${url}`);
116
+ return response.blob();
117
+ }).then((blob) => {
118
+ entry.settled = true;
119
+ return blob;
120
+ }).catch((error) => {
121
+ resourceCache.delete(key);
122
+ throw error;
123
+ })
124
+ };
125
+ resourceCache.set(key, entry);
126
+ let released = false;
127
+ return {
128
+ entry,
129
+ release: () => {
130
+ if (released) return;
131
+ released = true;
132
+ entry.refs = Math.max(0, entry.refs - 1);
133
+ if (entry.refs === 0) {
134
+ if (!entry.settled) entry.controller.abort();
135
+ resourceCache.delete(key);
136
+ }
137
+ }
138
+ };
186
139
  }
187
140
  async function awaitWithAbort(promise, signal) {
188
- if (!signal) {
189
- return promise;
190
- }
191
- if (signal.aborted) {
192
- throw createAbortError();
193
- }
194
- return new Promise((resolve, reject) => {
195
- const onAbort = () => {
196
- reject(createAbortError());
197
- };
198
- signal.addEventListener('abort', onAbort, { once: true });
199
- promise.then(resolve, reject).finally(() => {
200
- signal.removeEventListener('abort', onAbort);
201
- });
202
- });
141
+ if (!signal) return promise;
142
+ if (signal.aborted) throw createAbortError();
143
+ return new Promise((resolve, reject) => {
144
+ const onAbort = () => {
145
+ reject(createAbortError());
146
+ };
147
+ signal.addEventListener("abort", onAbort, { once: true });
148
+ promise.then(resolve, reject).finally(() => {
149
+ signal.removeEventListener("abort", onAbort);
150
+ });
151
+ });
203
152
  }
204
153
  /**
205
- * Loads a single texture from URL and converts it to an `ImageBitmap`.
206
- *
207
- * @param url - Texture URL.
208
- * @param options - Loading options.
209
- * @returns Loaded texture object.
210
- * @throws {Error} When runtime does not support `createImageBitmap` or request fails.
211
- */
212
- export async function loadTextureFromUrl(url, options = {}) {
213
- if (typeof createImageBitmap !== 'function') {
214
- throw new Error('createImageBitmap is not available in this runtime');
215
- }
216
- const normalized = normalizeTextureLoadOptions(options);
217
- const { entry, release } = acquireTextureBlob(url, options);
218
- let bitmap = null;
219
- try {
220
- const blob = await awaitWithAbort(entry.blobPromise, normalized.signal);
221
- const bitmapOptions = {
222
- colorSpaceConversion: normalized.decode.colorSpaceConversion,
223
- premultiplyAlpha: normalized.decode.premultiplyAlpha,
224
- imageOrientation: normalized.decode.imageOrientation
225
- };
226
- const allDefaults = bitmapOptions.colorSpaceConversion === 'default' &&
227
- bitmapOptions.premultiplyAlpha === 'default' &&
228
- bitmapOptions.imageOrientation === 'none';
229
- bitmap = allDefaults
230
- ? await createImageBitmap(blob)
231
- : await createImageBitmap(blob, bitmapOptions);
232
- if (normalized.signal?.aborted) {
233
- bitmap.close();
234
- throw createAbortError();
235
- }
236
- const loaded = {
237
- url,
238
- source: bitmap,
239
- width: bitmap.width,
240
- height: bitmap.height,
241
- colorSpace: normalized.colorSpace,
242
- dispose: () => {
243
- bitmap?.close();
244
- }
245
- };
246
- if (normalized.update !== undefined) {
247
- loaded.update = normalized.update;
248
- }
249
- if (normalized.flipY !== undefined) {
250
- loaded.flipY = normalized.flipY;
251
- }
252
- if (normalized.premultipliedAlpha !== undefined) {
253
- loaded.premultipliedAlpha = normalized.premultipliedAlpha;
254
- }
255
- if (normalized.generateMipmaps !== undefined) {
256
- loaded.generateMipmaps = normalized.generateMipmaps;
257
- }
258
- return loaded;
259
- }
260
- catch (error) {
261
- if (bitmap) {
262
- bitmap.close();
263
- }
264
- throw error;
265
- }
266
- finally {
267
- release();
268
- }
154
+ * Loads a single texture from URL and converts it to an `ImageBitmap`.
155
+ *
156
+ * @param url - Texture URL.
157
+ * @param options - Loading options.
158
+ * @returns Loaded texture object.
159
+ * @throws {Error} When runtime does not support `createImageBitmap` or request fails.
160
+ */
161
+ async function loadTextureFromUrl(url, options = {}) {
162
+ if (typeof createImageBitmap !== "function") throw new Error("createImageBitmap is not available in this runtime");
163
+ const normalized = normalizeTextureLoadOptions(options);
164
+ const { entry, release } = acquireTextureBlob(url, options);
165
+ let bitmap = null;
166
+ try {
167
+ const blob = await awaitWithAbort(entry.blobPromise, normalized.signal);
168
+ const bitmapOptions = {
169
+ colorSpaceConversion: normalized.decode.colorSpaceConversion,
170
+ premultiplyAlpha: normalized.decode.premultiplyAlpha,
171
+ imageOrientation: normalized.decode.imageOrientation
172
+ };
173
+ bitmap = bitmapOptions.colorSpaceConversion === "default" && bitmapOptions.premultiplyAlpha === "default" && bitmapOptions.imageOrientation === "none" ? await createImageBitmap(blob) : await createImageBitmap(blob, bitmapOptions);
174
+ if (normalized.signal?.aborted) {
175
+ bitmap.close();
176
+ throw createAbortError();
177
+ }
178
+ let disposed = false;
179
+ const loaded = {
180
+ url,
181
+ source: bitmap,
182
+ width: bitmap.width,
183
+ height: bitmap.height,
184
+ colorSpace: normalized.colorSpace,
185
+ dispose: () => {
186
+ if (disposed) return;
187
+ disposed = true;
188
+ bitmap?.close();
189
+ bitmap = null;
190
+ }
191
+ };
192
+ if (normalized.update !== void 0) loaded.update = normalized.update;
193
+ if (normalized.flipY !== void 0) loaded.flipY = normalized.flipY;
194
+ if (normalized.premultipliedAlpha !== void 0) loaded.premultipliedAlpha = normalized.premultipliedAlpha;
195
+ if (normalized.generateMipmaps !== void 0) loaded.generateMipmaps = normalized.generateMipmaps;
196
+ return loaded;
197
+ } catch (error) {
198
+ if (bitmap) bitmap.close();
199
+ throw error;
200
+ } finally {
201
+ release();
202
+ }
269
203
  }
270
204
  /**
271
- * Loads many textures in parallel from URLs.
272
- *
273
- * @param urls - Texture URLs.
274
- * @param options - Shared loading options.
275
- * @returns Promise resolving to loaded textures in input order.
276
- */
277
- export async function loadTexturesFromUrls(urls, options = {}) {
278
- const settled = await Promise.allSettled(urls.map((url) => loadTextureFromUrl(url, options)));
279
- const loaded = [];
280
- let firstError = null;
281
- for (const entry of settled) {
282
- if (entry.status === 'fulfilled') {
283
- loaded.push(entry.value);
284
- continue;
285
- }
286
- firstError ??= entry.reason;
287
- }
288
- if (firstError) {
289
- for (const texture of loaded) {
290
- texture.dispose();
291
- }
292
- throw firstError;
293
- }
294
- return loaded;
205
+ * Loads many textures in parallel from URLs.
206
+ *
207
+ * @param urls - Texture URLs.
208
+ * @param options - Shared loading options.
209
+ * @returns Promise resolving to loaded textures in input order.
210
+ */
211
+ async function loadTexturesFromUrls(urls, options = {}) {
212
+ const settled = await Promise.allSettled(urls.map((url) => loadTextureFromUrl(url, options)));
213
+ const loaded = [];
214
+ let firstError = null;
215
+ for (const entry of settled) {
216
+ if (entry.status === "fulfilled") {
217
+ loaded.push(entry.value);
218
+ continue;
219
+ }
220
+ firstError ??= entry.reason;
221
+ }
222
+ if (firstError) {
223
+ for (const texture of loaded) texture.dispose();
224
+ throw firstError;
225
+ }
226
+ return loaded;
295
227
  }
228
+ //#endregion
229
+ export { buildTextureResourceCacheKey, clearTextureBlobCache, isAbortError, loadTextureFromUrl, loadTexturesFromUrls };
230
+
231
+ //# sourceMappingURL=texture-loader.js.map