@bloopjs/toodle 0.0.101 → 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 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, format = "rgba8unorm") {
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.#textures.has(id)) {
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.#textures.get(id)[0].uvScaleCropped === undefined;
18971
+ return this.bundles.getAtlasCoords(id)[0].uvScaleCropped === undefined;
18701
18972
  }
18702
18973
  get textures() {
18703
- return this.#textures;
18974
+ return this.bundles.textures;
18704
18975
  }
18705
18976
  get textureIds() {
18706
- return Array.from(this.#textures.keys());
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.#textures.set(id, [coords]);
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
- const bundle = this.#bundles.get(bundleId);
18751
- if (!bundle) {
19021
+ if (!this.bundles.hasBundle(bundleId)) {
18752
19022
  throw new Error(`Bundle ${bundleId} not found`);
18753
19023
  }
18754
- if (bundle.isLoaded) {
19024
+ if (this.bundles.isBundleLoaded(bundleId)) {
18755
19025
  console.warn(`Bundle ${bundleId} is already loaded.`);
18756
19026
  return;
18757
19027
  }
18758
- for (const atlas of bundle.atlases) {
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
- bundle.atlasIndices.push(atlasIndex);
19032
+ atlasIndices.push(atlasIndex);
18761
19033
  }
18762
- bundle.isLoaded = true;
19034
+ this.bundles.setBundleLoaded(bundleId, atlasIndices);
18763
19035
  }
18764
19036
  async unloadBundle(bundleId) {
18765
- const bundle = this.#bundles.get(bundleId);
18766
- if (!bundle) {
19037
+ if (!this.bundles.hasBundle(bundleId)) {
18767
19038
  throw new Error(`Bundle ${bundleId} not found`);
18768
19039
  }
18769
- if (!bundle.isLoaded) {
19040
+ if (!this.bundles.isBundleLoaded(bundleId)) {
18770
19041
  console.warn(`Bundle ${bundleId} is not loaded.`);
18771
19042
  return;
18772
19043
  }
18773
- await Promise.all(bundle.atlasIndices.map((atlasIndex) => this.extra.unloadAtlas(atlasIndex)));
18774
- bundle.isLoaded = false;
18775
- bundle.atlasIndices = [];
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
- const coords = this.#textures.get(node.textureId);
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.#bundles.set(bundleId, {
18839
- atlases,
18840
- atlasIndices: [],
18841
- isLoaded: false
18842
- });
19101
+ this.bundles.registerDynamicBundle(bundleId, atlases);
18843
19102
  }
18844
19103
  async#registerBundleFromAtlases(bundleId, opts) {
18845
- const atlases = [];
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.#bundles ? Array.from(this.#bundles.keys()) : [];
19108
+ return this.bundles.getRegisteredBundleIds();
18912
19109
  },
18913
19110
  getLoadedBundleIds: () => {
18914
- return Array.from(this.#bundles.entries()).filter(([, value]) => value.isLoaded).map(([key]) => key);
19111
+ return this.bundles.getLoadedBundleIds();
18915
19112
  },
18916
19113
  setAtlasCoords: (id, coords) => {
18917
- const oldCoords = this.#textures.get(id);
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
- if (!this.#textures.has(id)) {
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
- const texture = this.#textures.get(id);
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
- const existing = this.#textures.get(id);
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
- for (const [id, coords] of this.#textures.entries()) {
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=E4D2A9C0603A997464756E2164756E21
19839
+ //# debugId=9F2329B11FF4504E64756E2164756E21
19665
19840
  //# sourceMappingURL=mod.js.map