@bloopjs/toodle 0.0.102 → 0.0.103
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/dist/mod.d.ts +1 -0
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +307 -132
- package/dist/mod.js.map +5 -4
- package/dist/textures/AssetManager.d.ts +10 -2
- package/dist/textures/AssetManager.d.ts.map +1 -1
- package/dist/textures/Bundles.d.ts +183 -0
- package/dist/textures/Bundles.d.ts.map +1 -0
- package/dist/textures/mod.d.ts +2 -0
- package/dist/textures/mod.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/mod.ts +1 -0
- package/src/textures/AssetManager.ts +42 -194
- package/src/textures/Bundles.ts +541 -0
- package/src/textures/mod.ts +2 -0
package/dist/mod.d.ts
CHANGED
|
@@ -14,4 +14,5 @@ export * as Text from "./text/mod";
|
|
|
14
14
|
export * as Textures from "./textures/mod";
|
|
15
15
|
export * as Utils from "./utils/mod";
|
|
16
16
|
export { AssetManager } from "./textures/AssetManager";
|
|
17
|
+
export { Bundles } from "./textures/Bundles";
|
|
17
18
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAEA,mBAAmB,iBAAiB,CAAC;AAErC,mBAAmB,kBAAkB,CAAC;AACtC,mBAAmB,mBAAmB,CAAC;AACvC,mBAAmB,sBAAsB,CAAC;AAC1C,mBAAmB,iBAAiB,CAAC;AAErC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AAEzB,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,OAAO,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,OAAO,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAEA,mBAAmB,iBAAiB,CAAC;AAErC,mBAAmB,kBAAkB,CAAC;AACtC,mBAAmB,mBAAmB,CAAC;AACvC,mBAAmB,sBAAsB,CAAC;AAC1C,mBAAmB,iBAAiB,CAAC;AAErC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AAEzB,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,OAAO,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,OAAO,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/mod.js
CHANGED
|
@@ -18088,6 +18088,276 @@ class Pool {
|
|
|
18088
18088
|
this.#index = 0;
|
|
18089
18089
|
}
|
|
18090
18090
|
}
|
|
18091
|
+
// src/textures/Bundles.ts
|
|
18092
|
+
class Bundles {
|
|
18093
|
+
#bundles = new Map;
|
|
18094
|
+
#textures = new Map;
|
|
18095
|
+
#atlasSize;
|
|
18096
|
+
constructor(options = {}) {
|
|
18097
|
+
this.#atlasSize = options.atlasSize ?? 4096;
|
|
18098
|
+
}
|
|
18099
|
+
async registerAtlasBundle(bundleId, opts) {
|
|
18100
|
+
const atlases = [];
|
|
18101
|
+
for (const atlas of opts.atlases) {
|
|
18102
|
+
const jsonUrl = atlas.json ?? new URL(atlas.png.toString().replace(".png", ".json"), atlas.png.origin);
|
|
18103
|
+
const pngUrl = atlas.png ?? new URL(atlas.json.toString().replace(".json", ".png"), atlas.json.origin);
|
|
18104
|
+
const atlasDef = await (await fetch(jsonUrl)).json();
|
|
18105
|
+
const bitmap = !opts.rg8 ? await this.#getBitmapFromUrl(pngUrl) : await createImageBitmap(new ImageData(1, 1));
|
|
18106
|
+
let rg8Bytes;
|
|
18107
|
+
if (opts.rg8) {
|
|
18108
|
+
const rg8url = new URL(pngUrl.toString().replace(".png", ".rg8.gz"), pngUrl.origin);
|
|
18109
|
+
rg8Bytes = await this.#fetchRg8Bytes(rg8url);
|
|
18110
|
+
}
|
|
18111
|
+
const cpuTextureAtlas = {
|
|
18112
|
+
texture: bitmap,
|
|
18113
|
+
rg8Bytes,
|
|
18114
|
+
textureRegions: new Map,
|
|
18115
|
+
width: opts.rg8 ? this.#atlasSize : bitmap.width,
|
|
18116
|
+
height: opts.rg8 ? this.#atlasSize : bitmap.height
|
|
18117
|
+
};
|
|
18118
|
+
for (const [assetId, frame] of Object.entries(atlasDef.frames)) {
|
|
18119
|
+
const textureRegion = this.#parsePixiFrame(frame, cpuTextureAtlas.width, cpuTextureAtlas.height);
|
|
18120
|
+
cpuTextureAtlas.textureRegions.set(assetId, textureRegion);
|
|
18121
|
+
}
|
|
18122
|
+
atlases.push(cpuTextureAtlas);
|
|
18123
|
+
}
|
|
18124
|
+
this.#bundles.set(bundleId, {
|
|
18125
|
+
atlases,
|
|
18126
|
+
atlasIndices: [],
|
|
18127
|
+
isLoaded: false
|
|
18128
|
+
});
|
|
18129
|
+
return bundleId;
|
|
18130
|
+
}
|
|
18131
|
+
registerDynamicBundle(bundleId, atlases) {
|
|
18132
|
+
this.#bundles.set(bundleId, {
|
|
18133
|
+
atlases,
|
|
18134
|
+
atlasIndices: [],
|
|
18135
|
+
isLoaded: false
|
|
18136
|
+
});
|
|
18137
|
+
}
|
|
18138
|
+
hasBundle(bundleId) {
|
|
18139
|
+
return this.#bundles.has(bundleId);
|
|
18140
|
+
}
|
|
18141
|
+
isBundleLoaded(bundleId) {
|
|
18142
|
+
const bundle = this.#bundles.get(bundleId);
|
|
18143
|
+
return bundle?.isLoaded ?? false;
|
|
18144
|
+
}
|
|
18145
|
+
getBundleAtlasIndices(bundleId) {
|
|
18146
|
+
const bundle = this.#bundles.get(bundleId);
|
|
18147
|
+
return bundle?.atlasIndices ?? [];
|
|
18148
|
+
}
|
|
18149
|
+
setBundleLoaded(bundleId, atlasIndices) {
|
|
18150
|
+
const bundle = this.#bundles.get(bundleId);
|
|
18151
|
+
if (!bundle) {
|
|
18152
|
+
throw new Error(`Bundle ${bundleId} not found`);
|
|
18153
|
+
}
|
|
18154
|
+
bundle.atlasIndices = atlasIndices;
|
|
18155
|
+
bundle.isLoaded = true;
|
|
18156
|
+
}
|
|
18157
|
+
markBundleLoaded(bundleId, atlasIndices) {
|
|
18158
|
+
const bundle = this.#bundles.get(bundleId);
|
|
18159
|
+
if (!bundle) {
|
|
18160
|
+
throw new Error(`Bundle ${bundleId} not found`);
|
|
18161
|
+
}
|
|
18162
|
+
if (bundle.isLoaded) {
|
|
18163
|
+
console.warn(`Bundle ${bundleId} is already loaded.`);
|
|
18164
|
+
return;
|
|
18165
|
+
}
|
|
18166
|
+
const indices = atlasIndices ?? bundle.atlases.map(() => this.#getNextAtlasIndex());
|
|
18167
|
+
if (indices.length !== bundle.atlases.length) {
|
|
18168
|
+
throw new Error(`Expected ${bundle.atlases.length} atlas indices, got ${indices.length}`);
|
|
18169
|
+
}
|
|
18170
|
+
for (let i3 = 0;i3 < bundle.atlases.length; i3++) {
|
|
18171
|
+
const atlas = bundle.atlases[i3];
|
|
18172
|
+
const atlasIndex = indices[i3];
|
|
18173
|
+
bundle.atlasIndices.push(atlasIndex);
|
|
18174
|
+
for (const [id, region] of atlas.textureRegions) {
|
|
18175
|
+
const coords = { ...region, atlasIndex };
|
|
18176
|
+
const existing = this.#textures.get(id);
|
|
18177
|
+
if (existing) {
|
|
18178
|
+
existing.push(coords);
|
|
18179
|
+
} else {
|
|
18180
|
+
this.#textures.set(id, [coords]);
|
|
18181
|
+
}
|
|
18182
|
+
}
|
|
18183
|
+
}
|
|
18184
|
+
bundle.isLoaded = true;
|
|
18185
|
+
}
|
|
18186
|
+
unloadBundle(bundleId) {
|
|
18187
|
+
const bundle = this.#bundles.get(bundleId);
|
|
18188
|
+
if (!bundle) {
|
|
18189
|
+
throw new Error(`Bundle ${bundleId} not found`);
|
|
18190
|
+
}
|
|
18191
|
+
if (!bundle.isLoaded) {
|
|
18192
|
+
console.warn(`Bundle ${bundleId} is not loaded.`);
|
|
18193
|
+
return;
|
|
18194
|
+
}
|
|
18195
|
+
for (const atlasIndex of bundle.atlasIndices) {
|
|
18196
|
+
for (const [id, coords] of this.#textures.entries()) {
|
|
18197
|
+
const indexToRemove = coords.findIndex((coord) => coord.atlasIndex === atlasIndex);
|
|
18198
|
+
if (indexToRemove !== -1) {
|
|
18199
|
+
coords.splice(indexToRemove, 1);
|
|
18200
|
+
}
|
|
18201
|
+
if (!coords.length) {
|
|
18202
|
+
this.#textures.delete(id);
|
|
18203
|
+
}
|
|
18204
|
+
}
|
|
18205
|
+
}
|
|
18206
|
+
bundle.isLoaded = false;
|
|
18207
|
+
bundle.atlasIndices = [];
|
|
18208
|
+
}
|
|
18209
|
+
get textures() {
|
|
18210
|
+
return this.#textures;
|
|
18211
|
+
}
|
|
18212
|
+
get textureIds() {
|
|
18213
|
+
return Array.from(this.#textures.keys());
|
|
18214
|
+
}
|
|
18215
|
+
getAtlasCoords(id) {
|
|
18216
|
+
const coords = this.#textures.get(id);
|
|
18217
|
+
if (!coords) {
|
|
18218
|
+
throw new Error(`Texture ${id} not found. Have you registered and loaded a bundle containing this texture?`);
|
|
18219
|
+
}
|
|
18220
|
+
return coords;
|
|
18221
|
+
}
|
|
18222
|
+
setAtlasCoords(id, coords) {
|
|
18223
|
+
const oldCoords = this.#textures.get(id);
|
|
18224
|
+
if (!oldCoords)
|
|
18225
|
+
return;
|
|
18226
|
+
const indexToModify = oldCoords.findIndex((coord) => coord.atlasIndex === coords.atlasIndex);
|
|
18227
|
+
if (indexToModify === -1)
|
|
18228
|
+
return;
|
|
18229
|
+
oldCoords[indexToModify] = coords;
|
|
18230
|
+
this.#textures.set(id, oldCoords);
|
|
18231
|
+
}
|
|
18232
|
+
addTextureEntry(id, coords) {
|
|
18233
|
+
const existing = this.#textures.get(id);
|
|
18234
|
+
if (existing) {
|
|
18235
|
+
existing.push(coords);
|
|
18236
|
+
} else {
|
|
18237
|
+
this.#textures.set(id, [coords]);
|
|
18238
|
+
}
|
|
18239
|
+
}
|
|
18240
|
+
removeTextureEntriesForAtlas(atlasIndex) {
|
|
18241
|
+
for (const [id, coords] of this.#textures.entries()) {
|
|
18242
|
+
const indexToRemove = coords.findIndex((coord) => coord.atlasIndex === atlasIndex);
|
|
18243
|
+
if (indexToRemove !== -1) {
|
|
18244
|
+
coords.splice(indexToRemove, 1);
|
|
18245
|
+
}
|
|
18246
|
+
if (!coords.length) {
|
|
18247
|
+
this.#textures.delete(id);
|
|
18248
|
+
}
|
|
18249
|
+
}
|
|
18250
|
+
}
|
|
18251
|
+
getTextureRegion(id) {
|
|
18252
|
+
const coords = this.#textures.get(id);
|
|
18253
|
+
if (!coords || coords.length === 0)
|
|
18254
|
+
return;
|
|
18255
|
+
const { atlasIndex: _3, ...region } = coords[0];
|
|
18256
|
+
return region;
|
|
18257
|
+
}
|
|
18258
|
+
getTextureOffset(id) {
|
|
18259
|
+
const coords = this.#textures.get(id);
|
|
18260
|
+
if (!coords) {
|
|
18261
|
+
throw new Error(`Texture ${id} not found. Have you registered and loaded a bundle containing this texture?`);
|
|
18262
|
+
}
|
|
18263
|
+
return coords[0].cropOffset;
|
|
18264
|
+
}
|
|
18265
|
+
getSize(id) {
|
|
18266
|
+
const coords = this.getAtlasCoords(id);
|
|
18267
|
+
const uvScale = coords[0].uvScale;
|
|
18268
|
+
return {
|
|
18269
|
+
width: uvScale.width * this.#atlasSize,
|
|
18270
|
+
height: uvScale.height * this.#atlasSize
|
|
18271
|
+
};
|
|
18272
|
+
}
|
|
18273
|
+
getCroppedSize(id) {
|
|
18274
|
+
const coords = this.getAtlasCoords(id);
|
|
18275
|
+
const uvScaleCropped = coords[0].uvScaleCropped;
|
|
18276
|
+
if (uvScaleCropped) {
|
|
18277
|
+
return {
|
|
18278
|
+
width: uvScaleCropped.width * this.#atlasSize,
|
|
18279
|
+
height: uvScaleCropped.height * this.#atlasSize
|
|
18280
|
+
};
|
|
18281
|
+
}
|
|
18282
|
+
return this.getSize(id);
|
|
18283
|
+
}
|
|
18284
|
+
hasTexture(id) {
|
|
18285
|
+
return this.#textures.has(id);
|
|
18286
|
+
}
|
|
18287
|
+
getRegisteredBundleIds() {
|
|
18288
|
+
return Array.from(this.#bundles.keys());
|
|
18289
|
+
}
|
|
18290
|
+
getLoadedBundleIds() {
|
|
18291
|
+
return Array.from(this.#bundles.entries()).filter(([, bundle]) => bundle.isLoaded).map(([id]) => id);
|
|
18292
|
+
}
|
|
18293
|
+
getBundleAtlases(bundleId) {
|
|
18294
|
+
const bundle = this.#bundles.get(bundleId);
|
|
18295
|
+
if (!bundle) {
|
|
18296
|
+
throw new Error(`Bundle ${bundleId} not found`);
|
|
18297
|
+
}
|
|
18298
|
+
return bundle.atlases;
|
|
18299
|
+
}
|
|
18300
|
+
get atlasSize() {
|
|
18301
|
+
return this.#atlasSize;
|
|
18302
|
+
}
|
|
18303
|
+
#parsePixiFrame(frame, atlasWidth, atlasHeight) {
|
|
18304
|
+
const leftCrop = frame.spriteSourceSize.x;
|
|
18305
|
+
const rightCrop = frame.sourceSize.w - frame.spriteSourceSize.x - frame.spriteSourceSize.w;
|
|
18306
|
+
const topCrop = frame.spriteSourceSize.y;
|
|
18307
|
+
const bottomCrop = frame.sourceSize.h - frame.spriteSourceSize.y - frame.spriteSourceSize.h;
|
|
18308
|
+
return {
|
|
18309
|
+
cropOffset: {
|
|
18310
|
+
x: leftCrop - rightCrop,
|
|
18311
|
+
y: bottomCrop - topCrop
|
|
18312
|
+
},
|
|
18313
|
+
originalSize: {
|
|
18314
|
+
width: frame.sourceSize.w,
|
|
18315
|
+
height: frame.sourceSize.h
|
|
18316
|
+
},
|
|
18317
|
+
uvOffset: {
|
|
18318
|
+
x: frame.frame.x / atlasWidth,
|
|
18319
|
+
y: frame.frame.y / atlasHeight
|
|
18320
|
+
},
|
|
18321
|
+
uvScale: {
|
|
18322
|
+
width: frame.sourceSize.w / atlasWidth,
|
|
18323
|
+
height: frame.sourceSize.h / atlasHeight
|
|
18324
|
+
},
|
|
18325
|
+
uvScaleCropped: {
|
|
18326
|
+
width: frame.frame.w / atlasWidth,
|
|
18327
|
+
height: frame.frame.h / atlasHeight
|
|
18328
|
+
}
|
|
18329
|
+
};
|
|
18330
|
+
}
|
|
18331
|
+
async#getBitmapFromUrl(url) {
|
|
18332
|
+
const response = await fetch(url);
|
|
18333
|
+
const blob = await response.blob();
|
|
18334
|
+
return createImageBitmap(blob);
|
|
18335
|
+
}
|
|
18336
|
+
async#fetchRg8Bytes(url) {
|
|
18337
|
+
const response = await fetch(url);
|
|
18338
|
+
const enc = (response.headers.get("content-encoding") || "").toLowerCase();
|
|
18339
|
+
if (enc.includes("gzip") || enc.includes("br") || enc.includes("deflate")) {
|
|
18340
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
18341
|
+
}
|
|
18342
|
+
if (!response.body) {
|
|
18343
|
+
throw new Error("Response body of rg8 file is null");
|
|
18344
|
+
}
|
|
18345
|
+
const ds = new DecompressionStream("gzip");
|
|
18346
|
+
const ab = await new Response(response.body.pipeThrough(ds)).arrayBuffer();
|
|
18347
|
+
return new Uint8Array(ab);
|
|
18348
|
+
}
|
|
18349
|
+
#getNextAtlasIndex() {
|
|
18350
|
+
let maxIndex = -1;
|
|
18351
|
+
for (const bundle of this.#bundles.values()) {
|
|
18352
|
+
for (const idx of bundle.atlasIndices) {
|
|
18353
|
+
if (idx > maxIndex)
|
|
18354
|
+
maxIndex = idx;
|
|
18355
|
+
}
|
|
18356
|
+
}
|
|
18357
|
+
return maxIndex + 1;
|
|
18358
|
+
}
|
|
18359
|
+
}
|
|
18360
|
+
|
|
18091
18361
|
// src/textures/pixel-scraping.wgsl.ts
|
|
18092
18362
|
var pixel_scraping_wgsl_default = `
|
|
18093
18363
|
// ==============================
|
|
@@ -18650,18 +18920,19 @@ async function textureToBitmap(device, texture, width, height) {
|
|
|
18650
18920
|
// src/textures/AssetManager.ts
|
|
18651
18921
|
class AssetManager {
|
|
18652
18922
|
textureAtlas;
|
|
18923
|
+
bundles;
|
|
18653
18924
|
#device;
|
|
18654
18925
|
#presentationFormat;
|
|
18655
|
-
#bundles = new Map;
|
|
18656
|
-
#textures = new Map;
|
|
18657
18926
|
#fonts = new Map;
|
|
18658
18927
|
#cropComputeShader;
|
|
18659
18928
|
#limits;
|
|
18660
18929
|
#availableIndices = new Set;
|
|
18661
|
-
constructor(device, presentationFormat, limits,
|
|
18930
|
+
constructor(device, presentationFormat, limits, options = {}) {
|
|
18662
18931
|
this.#device = device;
|
|
18663
18932
|
this.#presentationFormat = presentationFormat;
|
|
18664
18933
|
this.#limits = limits;
|
|
18934
|
+
this.bundles = options.bundles ?? new Bundles({ atlasSize: limits.textureSize });
|
|
18935
|
+
const format = options.format ?? "rgba8unorm";
|
|
18665
18936
|
this.textureAtlas = device.createTexture({
|
|
18666
18937
|
label: "Asset Manager Atlas Texture",
|
|
18667
18938
|
size: [
|
|
@@ -18694,16 +18965,16 @@ class AssetManager {
|
|
|
18694
18965
|
return this.getSize(id);
|
|
18695
18966
|
}
|
|
18696
18967
|
isCropped(id) {
|
|
18697
|
-
if (!this
|
|
18968
|
+
if (!this.bundles.hasTexture(id)) {
|
|
18698
18969
|
throw new Error(`Texture ${id} not found in atlas. Have you called toodle.loadTextures with this id or toodle.loadBundle with a bundle that contains it?`);
|
|
18699
18970
|
}
|
|
18700
|
-
return this
|
|
18971
|
+
return this.bundles.getAtlasCoords(id)[0].uvScaleCropped === undefined;
|
|
18701
18972
|
}
|
|
18702
18973
|
get textures() {
|
|
18703
|
-
return this
|
|
18974
|
+
return this.bundles.textures;
|
|
18704
18975
|
}
|
|
18705
18976
|
get textureIds() {
|
|
18706
|
-
return
|
|
18977
|
+
return this.bundles.textureIds;
|
|
18707
18978
|
}
|
|
18708
18979
|
async loadTextures(opts) {
|
|
18709
18980
|
await Promise.all(Object.entries(opts).map(([id, url]) => this.loadTexture(id, url, opts)));
|
|
@@ -18730,7 +19001,7 @@ class AssetManager {
|
|
|
18730
19001
|
},
|
|
18731
19002
|
atlasIndex
|
|
18732
19003
|
};
|
|
18733
|
-
this
|
|
19004
|
+
this.bundles.addTextureEntry(id, coords);
|
|
18734
19005
|
this.#availableIndices.delete(atlasIndex);
|
|
18735
19006
|
textureWrapper.texture.destroy();
|
|
18736
19007
|
return { id, coords };
|
|
@@ -18747,32 +19018,32 @@ class AssetManager {
|
|
|
18747
19018
|
return bundleId;
|
|
18748
19019
|
}
|
|
18749
19020
|
async loadBundle(bundleId) {
|
|
18750
|
-
|
|
18751
|
-
if (!bundle) {
|
|
19021
|
+
if (!this.bundles.hasBundle(bundleId)) {
|
|
18752
19022
|
throw new Error(`Bundle ${bundleId} not found`);
|
|
18753
19023
|
}
|
|
18754
|
-
if (
|
|
19024
|
+
if (this.bundles.isBundleLoaded(bundleId)) {
|
|
18755
19025
|
console.warn(`Bundle ${bundleId} is already loaded.`);
|
|
18756
19026
|
return;
|
|
18757
19027
|
}
|
|
18758
|
-
|
|
19028
|
+
const atlases = this.bundles.getBundleAtlases(bundleId);
|
|
19029
|
+
const atlasIndices = [];
|
|
19030
|
+
for (const atlas of atlases) {
|
|
18759
19031
|
const atlasIndex = await this.extra.loadAtlas(atlas);
|
|
18760
|
-
|
|
19032
|
+
atlasIndices.push(atlasIndex);
|
|
18761
19033
|
}
|
|
18762
|
-
|
|
19034
|
+
this.bundles.setBundleLoaded(bundleId, atlasIndices);
|
|
18763
19035
|
}
|
|
18764
19036
|
async unloadBundle(bundleId) {
|
|
18765
|
-
|
|
18766
|
-
if (!bundle) {
|
|
19037
|
+
if (!this.bundles.hasBundle(bundleId)) {
|
|
18767
19038
|
throw new Error(`Bundle ${bundleId} not found`);
|
|
18768
19039
|
}
|
|
18769
|
-
if (!
|
|
19040
|
+
if (!this.bundles.isBundleLoaded(bundleId)) {
|
|
18770
19041
|
console.warn(`Bundle ${bundleId} is not loaded.`);
|
|
18771
19042
|
return;
|
|
18772
19043
|
}
|
|
18773
|
-
|
|
18774
|
-
|
|
18775
|
-
|
|
19044
|
+
const atlasIndices = this.bundles.getBundleAtlasIndices(bundleId);
|
|
19045
|
+
await Promise.all(atlasIndices.map((atlasIndex) => this.extra.unloadAtlas(atlasIndex)));
|
|
19046
|
+
this.bundles.unloadBundle(bundleId);
|
|
18776
19047
|
}
|
|
18777
19048
|
async loadFont(id, url, fallbackCharacter = "_") {
|
|
18778
19049
|
const font = await MsdfFont.create(id, url);
|
|
@@ -18791,22 +19062,14 @@ class AssetManager {
|
|
|
18791
19062
|
validateTextureReference(node) {
|
|
18792
19063
|
if (!(node instanceof QuadNode) || node.isPrimitive || node instanceof JumboQuadNode)
|
|
18793
19064
|
return;
|
|
18794
|
-
|
|
18795
|
-
if (!coords || !coords.length) {
|
|
19065
|
+
if (!this.bundles.hasTexture(node.textureId)) {
|
|
18796
19066
|
throw new Error(`Node ${node.id} references an invalid texture ${node.textureId}.`);
|
|
18797
19067
|
}
|
|
19068
|
+
const coords = this.bundles.getAtlasCoords(node.textureId);
|
|
18798
19069
|
if (coords.find((coord) => coord.atlasIndex === node.atlasCoords.atlasIndex))
|
|
18799
19070
|
return;
|
|
18800
19071
|
node.extra.setAtlasCoords(coords[0]);
|
|
18801
19072
|
}
|
|
18802
|
-
#addTexture(id, textureRegion, atlasIndex) {
|
|
18803
|
-
this.#textures.set(id, [
|
|
18804
|
-
{
|
|
18805
|
-
...textureRegion,
|
|
18806
|
-
atlasIndex
|
|
18807
|
-
}
|
|
18808
|
-
]);
|
|
18809
|
-
}
|
|
18810
19073
|
#createTextureFromImageBitmap(bitmap, name) {
|
|
18811
19074
|
const texture = this.#device.createTexture({
|
|
18812
19075
|
label: `${name} Intermediary Texture`,
|
|
@@ -18835,106 +19098,26 @@ class AssetManager {
|
|
|
18835
19098
|
images.set(id, textureWrapper);
|
|
18836
19099
|
}));
|
|
18837
19100
|
const atlases = await packBitmapsToAtlas(images, this.#limits.textureSize, this.#device);
|
|
18838
|
-
this
|
|
18839
|
-
atlases,
|
|
18840
|
-
atlasIndices: [],
|
|
18841
|
-
isLoaded: false
|
|
18842
|
-
});
|
|
19101
|
+
this.bundles.registerDynamicBundle(bundleId, atlases);
|
|
18843
19102
|
}
|
|
18844
19103
|
async#registerBundleFromAtlases(bundleId, opts) {
|
|
18845
|
-
|
|
18846
|
-
for (const atlas of opts.atlases) {
|
|
18847
|
-
const jsonUrl = atlas.json ?? new URL(atlas.png.toString().replace(".png", ".json"), atlas.png.origin);
|
|
18848
|
-
const pngUrl = atlas.png ?? new URL(atlas.json.toString().replace(".json", ".png"), atlas.json.origin);
|
|
18849
|
-
const atlasDef = await (await fetch(jsonUrl)).json();
|
|
18850
|
-
const bitmap = !opts.rg8 ? await getBitmapFromUrl(pngUrl) : await createImageBitmap(new ImageData(1, 1));
|
|
18851
|
-
let rg8Bytes;
|
|
18852
|
-
if (opts.rg8) {
|
|
18853
|
-
const rg8url = new URL(pngUrl.toString().replace(".png", ".rg8.gz"), pngUrl.origin);
|
|
18854
|
-
const rgBytes = await fetch(rg8url).then(async (r3) => {
|
|
18855
|
-
const enc = (r3.headers.get("content-encoding") || "").toLowerCase();
|
|
18856
|
-
if (enc.includes("gzip") || enc.includes("br") || enc.includes("deflate")) {
|
|
18857
|
-
return new Uint8Array(await r3.arrayBuffer());
|
|
18858
|
-
}
|
|
18859
|
-
assert(r3.body, "Response body of rg8 file is null");
|
|
18860
|
-
const ds = new DecompressionStream("gzip");
|
|
18861
|
-
const ab = await new Response(r3.body.pipeThrough(ds)).arrayBuffer();
|
|
18862
|
-
return new Uint8Array(ab);
|
|
18863
|
-
});
|
|
18864
|
-
rg8Bytes = rgBytes;
|
|
18865
|
-
}
|
|
18866
|
-
const cpuTextureAtlas = {
|
|
18867
|
-
texture: bitmap,
|
|
18868
|
-
rg8Bytes,
|
|
18869
|
-
textureRegions: new Map,
|
|
18870
|
-
width: opts.rg8 ? this.#limits.textureSize : bitmap.width,
|
|
18871
|
-
height: opts.rg8 ? this.#limits.textureSize : bitmap.height
|
|
18872
|
-
};
|
|
18873
|
-
for (const [assetId, frame] of Object.entries(atlasDef.frames)) {
|
|
18874
|
-
const leftCrop = frame.spriteSourceSize.x;
|
|
18875
|
-
const rightCrop = frame.sourceSize.w - frame.spriteSourceSize.x - frame.spriteSourceSize.w;
|
|
18876
|
-
const topCrop = frame.spriteSourceSize.y;
|
|
18877
|
-
const bottomCrop = frame.sourceSize.h - frame.spriteSourceSize.y - frame.spriteSourceSize.h;
|
|
18878
|
-
cpuTextureAtlas.textureRegions.set(assetId, {
|
|
18879
|
-
cropOffset: {
|
|
18880
|
-
x: leftCrop - rightCrop,
|
|
18881
|
-
y: bottomCrop - topCrop
|
|
18882
|
-
},
|
|
18883
|
-
originalSize: {
|
|
18884
|
-
width: frame.sourceSize.w,
|
|
18885
|
-
height: frame.sourceSize.h
|
|
18886
|
-
},
|
|
18887
|
-
uvOffset: {
|
|
18888
|
-
x: frame.frame.x / cpuTextureAtlas.width,
|
|
18889
|
-
y: frame.frame.y / cpuTextureAtlas.height
|
|
18890
|
-
},
|
|
18891
|
-
uvScale: {
|
|
18892
|
-
width: frame.sourceSize.w / cpuTextureAtlas.width,
|
|
18893
|
-
height: frame.sourceSize.h / cpuTextureAtlas.height
|
|
18894
|
-
},
|
|
18895
|
-
uvScaleCropped: {
|
|
18896
|
-
width: frame.frame.w / cpuTextureAtlas.width,
|
|
18897
|
-
height: frame.frame.h / cpuTextureAtlas.height
|
|
18898
|
-
}
|
|
18899
|
-
});
|
|
18900
|
-
}
|
|
18901
|
-
atlases.push(cpuTextureAtlas);
|
|
18902
|
-
}
|
|
18903
|
-
this.#bundles.set(bundleId, {
|
|
18904
|
-
atlases,
|
|
18905
|
-
atlasIndices: [],
|
|
18906
|
-
isLoaded: false
|
|
18907
|
-
});
|
|
19104
|
+
await this.bundles.registerAtlasBundle(bundleId, opts);
|
|
18908
19105
|
}
|
|
18909
19106
|
extra = {
|
|
18910
19107
|
getRegisteredBundleIds: () => {
|
|
18911
|
-
return this
|
|
19108
|
+
return this.bundles.getRegisteredBundleIds();
|
|
18912
19109
|
},
|
|
18913
19110
|
getLoadedBundleIds: () => {
|
|
18914
|
-
return
|
|
19111
|
+
return this.bundles.getLoadedBundleIds();
|
|
18915
19112
|
},
|
|
18916
19113
|
setAtlasCoords: (id, coords) => {
|
|
18917
|
-
|
|
18918
|
-
if (!oldCoords)
|
|
18919
|
-
return;
|
|
18920
|
-
const indexToModify = oldCoords.findIndex((coord) => coord.atlasIndex === coords.atlasIndex);
|
|
18921
|
-
if (indexToModify === -1)
|
|
18922
|
-
return;
|
|
18923
|
-
oldCoords[indexToModify] = coords;
|
|
18924
|
-
this.#textures.set(id, oldCoords);
|
|
19114
|
+
this.bundles.setAtlasCoords(id, coords);
|
|
18925
19115
|
},
|
|
18926
19116
|
getAtlasCoords: (id) => {
|
|
18927
|
-
|
|
18928
|
-
throw new Error(`Texture ${id} not found in atlas. Have you called toodle.loadBundle with a bundle that contains this id (or toodle.loadTextures with this id as a key)?`);
|
|
18929
|
-
}
|
|
18930
|
-
return this.#textures.get(id) ?? [];
|
|
19117
|
+
return this.bundles.getAtlasCoords(id);
|
|
18931
19118
|
},
|
|
18932
19119
|
getTextureOffset: (id) => {
|
|
18933
|
-
|
|
18934
|
-
if (!texture) {
|
|
18935
|
-
throw new Error(`Texture ${id} not found in atlas. Have you called toodle.loadTextures with this id or toodle.loadBundle with a bundle that contains it?`);
|
|
18936
|
-
}
|
|
18937
|
-
return texture[0].cropOffset;
|
|
19120
|
+
return this.bundles.getTextureOffset(id);
|
|
18938
19121
|
},
|
|
18939
19122
|
getAtlasUsage: () => {
|
|
18940
19123
|
return {
|
|
@@ -18971,25 +19154,13 @@ class AssetManager {
|
|
|
18971
19154
|
}, [atlas.texture.width, atlas.texture.height, 1]);
|
|
18972
19155
|
}
|
|
18973
19156
|
for (const [id, region] of atlas.textureRegions) {
|
|
18974
|
-
|
|
18975
|
-
if (existing) {
|
|
18976
|
-
existing.push({ ...region, atlasIndex });
|
|
18977
|
-
} else
|
|
18978
|
-
this.#addTexture(id, region, atlasIndex);
|
|
19157
|
+
this.bundles.addTextureEntry(id, { ...region, atlasIndex });
|
|
18979
19158
|
}
|
|
18980
19159
|
return atlasIndex;
|
|
18981
19160
|
},
|
|
18982
19161
|
unloadAtlas: async (atlasIndex) => {
|
|
18983
19162
|
this.#availableIndices.add(atlasIndex);
|
|
18984
|
-
|
|
18985
|
-
const indexToModify = coords.findIndex((coord) => coord.atlasIndex === atlasIndex);
|
|
18986
|
-
if (indexToModify !== -1) {
|
|
18987
|
-
coords.splice(indexToModify, 1);
|
|
18988
|
-
}
|
|
18989
|
-
if (!coords.length) {
|
|
18990
|
-
this.#textures.delete(id);
|
|
18991
|
-
}
|
|
18992
|
-
}
|
|
19163
|
+
this.bundles.removeTextureEntriesForAtlas(atlasIndex);
|
|
18993
19164
|
}
|
|
18994
19165
|
};
|
|
18995
19166
|
#wrapBitmapToTexture(bitmap, name = "Unknown") {
|
|
@@ -19647,6 +19818,9 @@ __export(exports_mod7, {
|
|
|
19647
19818
|
});
|
|
19648
19819
|
// src/textures/mod.ts
|
|
19649
19820
|
var exports_mod8 = {};
|
|
19821
|
+
__export(exports_mod8, {
|
|
19822
|
+
Bundles: () => Bundles
|
|
19823
|
+
});
|
|
19650
19824
|
export {
|
|
19651
19825
|
exports_mod as Utils,
|
|
19652
19826
|
Toodle,
|
|
@@ -19658,8 +19832,9 @@ export {
|
|
|
19658
19832
|
exports_mod3 as GfxMath,
|
|
19659
19833
|
DEFAULT_LIMITS,
|
|
19660
19834
|
exports_mod2 as Colors,
|
|
19835
|
+
Bundles,
|
|
19661
19836
|
AssetManager
|
|
19662
19837
|
};
|
|
19663
19838
|
|
|
19664
|
-
//# debugId=
|
|
19839
|
+
//# debugId=9F2329B11FF4504E64756E2164756E21
|
|
19665
19840
|
//# sourceMappingURL=mod.js.map
|