minerender 2.1.0-alpha.7 → 2.1.0-alpha.9

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.
@@ -23,14 +23,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
24
  mod
25
25
  ));
26
- var __decorateClass = (decorators, target, key, kind) => {
27
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
28
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
29
- if (decorator = decorators[i])
30
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
31
- if (kind && result) __defProp(target, key, result);
32
- return result;
33
- };
34
26
 
35
27
  // ../../node_modules/ts-deepmerge/dist/index.js
36
28
  var require_dist = __commonJS({
@@ -156,11 +148,14 @@ var _PersistentCache = class _PersistentCache {
156
148
  static open(name) {
157
149
  return Env.provider.openCache(name, _PersistentCache.VERSION);
158
150
  }
151
+ /** Loads a missing entry and stores only non-nullish results. */
159
152
  async getOrLoad(key, loader) {
160
153
  let v = await this.get(key);
161
154
  if (typeof v === "undefined" || v === null) {
162
155
  v = await loader(key);
163
- await this.put(key, v);
156
+ if (typeof v !== "undefined" && v !== null) {
157
+ await this.put(key, v);
158
+ }
164
159
  }
165
160
  return v;
166
161
  }
@@ -357,7 +352,10 @@ function serializeMeshKey(key) {
357
352
  // src/cache/Caching.ts
358
353
  import { Caches } from "@inventivetalent/loading-cache";
359
354
  import { Time } from "@inventivetalent/time";
360
- var Caching = class {
355
+ var _Caching = class _Caching {
356
+ static createAssetCache() {
357
+ return Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
358
+ }
361
359
  /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */
362
360
  static get all() {
363
361
  return [
@@ -374,7 +372,10 @@ var Caching = class {
374
372
  this.rawModelCache,
375
373
  this.mergedModelCache,
376
374
  this.modelTextureAtlasCache,
377
- this.blockStateCache
375
+ this.blockStateCache,
376
+ this.listAssetCache,
377
+ this.defaultBlockStatesCache,
378
+ this.entityModelsCache
378
379
  ];
379
380
  }
380
381
  static clear() {
@@ -400,20 +401,24 @@ var Caching = class {
400
401
  };
401
402
  }
402
403
  };
403
- Caching.rawImageCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(5)).buildAsync();
404
- Caching.imageDataCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(10)).buildAsync();
405
- Caching.canvasImageDataCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(10)).buildAsync();
406
- Caching.wrappedImageCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(10)).buildAsync();
407
- Caching.boxGeometryCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(20)).build();
408
- Caching.textureCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).build();
409
- Caching.materialCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).build();
410
- Caching.boxMeshCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).build();
411
- Caching.textureAssetCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
412
- Caching.textureMetaCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
413
- Caching.rawModelCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
414
- Caching.mergedModelCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
415
- Caching.modelTextureAtlasCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
416
- Caching.blockStateCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
404
+ _Caching.rawImageCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(5)).buildAsync();
405
+ _Caching.imageDataCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(10)).buildAsync();
406
+ _Caching.canvasImageDataCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(10)).buildAsync();
407
+ _Caching.wrappedImageCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(10)).buildAsync();
408
+ _Caching.boxGeometryCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(20)).build();
409
+ _Caching.textureCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).build();
410
+ _Caching.materialCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).build();
411
+ _Caching.boxMeshCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).build();
412
+ _Caching.textureAssetCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
413
+ _Caching.textureMetaCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
414
+ _Caching.rawModelCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
415
+ _Caching.mergedModelCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
416
+ _Caching.modelTextureAtlasCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
417
+ _Caching.blockStateCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
418
+ _Caching.listAssetCache = _Caching.createAssetCache();
419
+ _Caching.defaultBlockStatesCache = _Caching.createAssetCache();
420
+ _Caching.entityModelsCache = _Caching.createAssetCache();
421
+ var Caching = _Caching;
417
422
 
418
423
  // src/Geometries.ts
419
424
  var Geometries = class _Geometries {
@@ -721,29 +726,41 @@ var ImageLoader = class _ImageLoader {
721
726
  static async loadAsync(src) {
722
727
  return new Promise((resolve, reject) => {
723
728
  const image = this._createImage();
724
- image.src = src;
725
729
  image.onload = () => resolve(image);
726
- image.onerror = (err) => reject(err);
730
+ image.onerror = (err) => reject(err instanceof Error ? err : new Error("Failed to decode image"));
731
+ image.src = src;
727
732
  });
728
733
  }
729
734
  static loadElement(src, onload, onerr) {
730
735
  const image = this._createImage();
731
- image.src = src;
732
736
  if (onload)
733
737
  image.onload = onload;
734
738
  if (onerr)
735
739
  image.onerror = onerr;
740
+ image.src = src;
736
741
  return image;
737
742
  }
738
743
  static async loadData(src) {
739
744
  console.debug(p2, "loadData", src);
740
- return await this.infoToData(await this.getInfo(src));
745
+ const image = await this.loadCanvasData(src);
746
+ return image.data.getImageData(0, 0, image.width, image.height);
741
747
  }
742
748
  static async loadCanvasData(src) {
743
- return await this.infoToCanvasData(await this.getInfo(src));
749
+ const keyStr = serializeImageKey({ src });
750
+ const info = this.getInfo(src);
751
+ const cached = Caching.rawImageCache.getIfPresent(keyStr);
752
+ try {
753
+ return await this.infoToCanvasData(await info);
754
+ } catch (err) {
755
+ if (cached && Caching.rawImageCache.getIfPresent(keyStr) === cached) {
756
+ Caching.rawImageCache.invalidate(keyStr);
757
+ }
758
+ throw err;
759
+ }
744
760
  }
745
761
  static async infoToCanvasData(info) {
746
- const image = await _ImageLoader.loadAsync(info.src);
762
+ const type = info.type === "jpg" ? "jpeg" : info.type ?? "png";
763
+ const image = await _ImageLoader.loadAsync(`data:image/${type};base64,${info.data.toString("base64")}`);
747
764
  const canvas = createCanvas2(info.width, info.height);
748
765
  const context = canvas.getContext("2d");
749
766
  context.drawImage(image, 0, 0);
@@ -754,11 +771,8 @@ var ImageLoader = class _ImageLoader {
754
771
  };
755
772
  }
756
773
  static async infoToData(info) {
757
- const image = await _ImageLoader.loadAsync(info.src);
758
- const canvas = createCanvas2(info.width, info.height);
759
- const context = canvas.getContext("2d");
760
- context.drawImage(image, 0, 0);
761
- return context.getImageData(0, 0, canvas.width, canvas.height);
774
+ const image = await this.infoToCanvasData(info);
775
+ return image.data.getImageData(0, 0, image.width, image.height);
762
776
  }
763
777
  static async getData(src) {
764
778
  const keyStr = serializeImageKey({ src });
@@ -773,13 +787,17 @@ var ImageLoader = class _ImageLoader {
773
787
  });
774
788
  }
775
789
  static async processResponse(response) {
776
- const src = response.config.url;
790
+ var _a;
791
+ const src = (_a = response.config) == null ? void 0 : _a.url;
777
792
  const data = Buffer2.from(response.data);
778
793
  const { width, height, type } = Env.provider.imageSize(data);
794
+ if (!width || !height) {
795
+ throw new Error("Invalid or unsupported image dimensions");
796
+ }
779
797
  return {
780
798
  src,
781
- width: width || 0,
782
- height: height || 0,
799
+ width,
800
+ height,
783
801
  type,
784
802
  data
785
803
  };
@@ -796,15 +814,7 @@ var ImageLoader = class _ImageLoader {
796
814
  return Requests.genericRequest({
797
815
  url: src,
798
816
  responseType: "arraybuffer"
799
- }).then(this.processResponse).catch((err) => {
800
- return {
801
- src,
802
- width: 0,
803
- height: 0,
804
- type: void 0,
805
- data: Buffer2.from([0])
806
- };
807
- });
817
+ }).then(this.processResponse);
808
818
  }
809
819
  static async getInfo(src) {
810
820
  const keyStr = serializeImageKey({ src });
@@ -826,16 +836,22 @@ var ImageLoader = class _ImageLoader {
826
836
 
827
837
  // src/texture/TextureLoader.ts
828
838
  var TextureLoader = class {
839
+ /** Reports whether image loading failed, so cached textures can be retried. */
840
+ static hasFailed(texture) {
841
+ return this.failedTextures.has(texture);
842
+ }
829
843
  static createTexture() {
830
844
  return new Texture();
831
845
  }
832
846
  static loadInBackground(src, format = RGBAFormat, rotation = 0) {
833
847
  const texture = this.createTexture();
834
848
  texture.colorSpace = THREE.SRGBColorSpace;
835
- const image = ImageLoader.loadElement(src);
836
- image.onload = function() {
849
+ const image = ImageLoader.loadElement(src, () => {
837
850
  texture.needsUpdate = true;
838
- };
851
+ }, (error) => {
852
+ this.failedTextures.add(texture);
853
+ console.warn("Failed to load texture", src, error);
854
+ });
839
855
  texture.image = image;
840
856
  texture.format = format;
841
857
  texture.rotation = rotation;
@@ -845,14 +861,18 @@ var TextureLoader = class {
845
861
  const texture = new Texture();
846
862
  texture.colorSpace = THREE.SRGBColorSpace;
847
863
  ImageLoader.getData(src).then((image) => {
848
- texture.needsUpdate = true;
849
864
  texture.image = image;
865
+ texture.needsUpdate = true;
866
+ }).catch((error) => {
867
+ this.failedTextures.add(texture);
868
+ console.warn("Failed to load texture", src, error);
850
869
  });
851
870
  texture.format = format;
852
871
  texture.rotation = rotation;
853
872
  return Textures.initTextureProps(texture);
854
873
  }
855
874
  };
875
+ TextureLoader.failedTextures = /* @__PURE__ */ new WeakSet();
856
876
 
857
877
  // src/texture/Textures.ts
858
878
  import * as THREE2 from "three";
@@ -876,6 +896,10 @@ var Textures = class _Textures {
876
896
  }
877
897
  static getImage(key) {
878
898
  const keyStr = serializeTextureKey(key);
899
+ const cached = Caching.textureCache.peek(keyStr);
900
+ if (cached && TextureLoader.hasFailed(cached)) {
901
+ Caching.textureCache.invalidate(keyStr);
902
+ }
879
903
  return Caching.textureCache.get(keyStr, (k) => {
880
904
  return _Textures.createImage(key);
881
905
  });
@@ -1019,7 +1043,12 @@ var _Materials = class _Materials {
1019
1043
  return this.createBasicCanvasMaterial(canvas, transparent, shade);
1020
1044
  }
1021
1045
  static getImage(key) {
1046
+ var _a;
1022
1047
  const keyStr = serializeMaterialKey(key);
1048
+ const map = (_a = Caching.materialCache.peek(keyStr)) == null ? void 0 : _a.map;
1049
+ if (map && TextureLoader.hasFailed(map)) {
1050
+ Caching.materialCache.invalidate(keyStr);
1051
+ }
1023
1052
  return Caching.materialCache.get(keyStr, (k) => {
1024
1053
  return _Materials.createImage(key);
1025
1054
  });
@@ -1173,9 +1202,6 @@ var ModelMerger = class {
1173
1202
  }
1174
1203
  };
1175
1204
 
1176
- // src/assets/Models.ts
1177
- import { Memoize } from "typescript-memoize";
1178
-
1179
1205
  // src/assets/source/parser/AssetParsers.ts
1180
1206
  var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
1181
1207
  AssetParser2["MODEL"] = "model";
@@ -1189,14 +1215,14 @@ var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
1189
1215
  })(AssetParser || {});
1190
1216
 
1191
1217
  // src/assets/Models.ts
1192
- var _Models = class _Models {
1218
+ var Models = class _Models {
1193
1219
  // opened lazily: touching the store at import time would hit IndexedDB/disk just for loading
1194
1220
  // the library, and would require an EnvProvider before any entry has had a chance to register
1195
1221
  static get PERSISTENT_CACHE() {
1196
1222
  return this._persistentCache ??= PersistentCache.open("minerender-models");
1197
1223
  }
1198
1224
  static async getItemList() {
1199
- return AssetLoader.get(new AssetKey(
1225
+ const key = new AssetKey(
1200
1226
  DEFAULT_NAMESPACE,
1201
1227
  "_list",
1202
1228
  "models",
@@ -1204,7 +1230,10 @@ var _Models = class _Models {
1204
1230
  "assets",
1205
1231
  ".json",
1206
1232
  DEFAULT_ROOT
1207
- ), "list" /* LIST */).then((r) => (r == null ? void 0 : r.files) ?? []);
1233
+ );
1234
+ return Caching.listAssetCache.get(key.serialize(), () => {
1235
+ return AssetLoader.get(key, "list" /* LIST */);
1236
+ }).then((r) => (r == null ? void 0 : r.files) ?? []);
1208
1237
  }
1209
1238
  static async loadAndMerge(key) {
1210
1239
  const model = await this.getRaw(key);
@@ -1251,19 +1280,15 @@ var _Models = class _Models {
1251
1280
  return this.PERSISTENT_CACHE.clear();
1252
1281
  }
1253
1282
  };
1254
- __decorateClass([
1255
- Memoize()
1256
- ], _Models, "getItemList", 1);
1257
- var Models = _Models;
1258
1283
 
1259
1284
  // src/assets/BlockStates.ts
1260
- import { Memoize as Memoize2 } from "typescript-memoize";
1261
1285
  var BlockStates = class {
1262
1286
  static get PERSISTENT_CACHE() {
1263
1287
  return this._persistentCache ??= PersistentCache.open("minerender-blockstates");
1264
1288
  }
1289
+ // BlockState names are hardcoded
1265
1290
  static async getList() {
1266
- return AssetLoader.get(new AssetKey(
1291
+ const key = new AssetKey(
1267
1292
  DEFAULT_NAMESPACE,
1268
1293
  "_list",
1269
1294
  "blockstates",
@@ -1271,11 +1296,16 @@ var BlockStates = class {
1271
1296
  "assets",
1272
1297
  ".json",
1273
1298
  DEFAULT_ROOT
1274
- ), "list" /* LIST */).then((r) => (r == null ? void 0 : r.files) ?? []);
1299
+ );
1300
+ return Caching.listAssetCache.get(key.serialize(), () => {
1301
+ return AssetLoader.get(key, "list" /* LIST */);
1302
+ }).then((r) => (r == null ? void 0 : r.files) ?? []);
1275
1303
  }
1276
1304
  static async getDefaultStates() {
1277
1305
  const key = AssetKey.parse("blockstates", "minerender:defaultBlockStates");
1278
- return AssetLoader.get(key, "json" /* JSON */);
1306
+ return Caching.defaultBlockStatesCache.get(key.serialize(), () => {
1307
+ return AssetLoader.get(key, "json" /* JSON */);
1308
+ });
1279
1309
  }
1280
1310
  static async getDefaultState(key) {
1281
1311
  const defaultStates = await this.getDefaultStates();
@@ -1314,12 +1344,6 @@ var BlockStates = class {
1314
1344
  await this.PERSISTENT_CACHE.clear();
1315
1345
  }
1316
1346
  };
1317
- __decorateClass([
1318
- Memoize2()
1319
- ], BlockStates, "getList", 1);
1320
- __decorateClass([
1321
- Memoize2()
1322
- ], BlockStates, "getDefaultStates", 1);
1323
1347
  var DefaultBlockStates = class {
1324
1348
  };
1325
1349
 
@@ -1677,11 +1701,21 @@ var ModelTextures = class {
1677
1701
  return this._persistentMetaCache ??= PersistentCache.open("minerender-texturemeta");
1678
1702
  }
1679
1703
  static async get(key) {
1680
- const asset = await this.preload(key);
1681
- if (asset) {
1682
- return ImageLoader.infoToCanvasData(asset);
1704
+ const keyStr = key.serialize();
1705
+ const pending = this.preload(key);
1706
+ const cached = Caching.textureAssetCache.getIfPresent(keyStr);
1707
+ try {
1708
+ const asset = await pending;
1709
+ if (asset) {
1710
+ return await ImageLoader.infoToCanvasData(asset);
1711
+ }
1712
+ return void 0;
1713
+ } catch (err) {
1714
+ if (cached && Caching.textureAssetCache.getIfPresent(keyStr) === cached) {
1715
+ Caching.textureAssetCache.invalidate(keyStr);
1716
+ }
1717
+ throw err;
1683
1718
  }
1684
- return void 0;
1685
1719
  }
1686
1720
  static async preload(key) {
1687
1721
  const keyStr = key.serialize();
@@ -2361,17 +2395,20 @@ function shutdown() {
2361
2395
  }
2362
2396
 
2363
2397
  // src/assets/Entities.ts
2364
- import { Memoize as Memoize3 } from "typescript-memoize";
2365
2398
  var Entities = class {
2366
2399
  static async getBlockEntityModels() {
2367
2400
  const key = AssetKey.parse("models", "minerender:blockEntityModels");
2368
2401
  console.log(key);
2369
- return AssetLoader.get(key, "json" /* JSON */);
2402
+ return Caching.entityModelsCache.get(key.serialize(), () => {
2403
+ return AssetLoader.get(key, "json" /* JSON */);
2404
+ });
2370
2405
  }
2371
2406
  static async getEntityModels() {
2372
2407
  const key = AssetKey.parse("models", "minerender:entityModels");
2373
2408
  console.log(key);
2374
- return AssetLoader.get(key, "json" /* JSON */);
2409
+ return Caching.entityModelsCache.get(key.serialize(), () => {
2410
+ return AssetLoader.get(key, "json" /* JSON */);
2411
+ });
2375
2412
  }
2376
2413
  // BlockEntity names are hardcoded
2377
2414
  static async getBlockList() {
@@ -2417,12 +2454,6 @@ var Entities = class {
2417
2454
  };
2418
2455
  }
2419
2456
  };
2420
- __decorateClass([
2421
- Memoize3()
2422
- ], Entities, "getBlockEntityModels", 1);
2423
- __decorateClass([
2424
- Memoize3()
2425
- ], Entities, "getEntityModels", 1);
2426
2457
  var EntityModels = class {
2427
2458
  };
2428
2459
  var BlockEntityModels = class {
@@ -2875,9 +2906,9 @@ var EntityObject = class extends SceneObject {
2875
2906
  dispose() {
2876
2907
  super.dispose();
2877
2908
  }
2878
- async loadTextures() {
2909
+ get textureKey() {
2879
2910
  var _a;
2880
- this.imageData = await ModelTextures.get(new AssetKey(
2911
+ return new AssetKey(
2881
2912
  ((_a = this.entity.key) == null ? void 0 : _a.namespace) ?? DEFAULT_NAMESPACE,
2882
2913
  this.entity.key.path,
2883
2914
  //TODO: texture may differ from entity name; most of them are in subdirectories for multiple variants etc.
@@ -2885,7 +2916,10 @@ var EntityObject = class extends SceneObject {
2885
2916
  "entity",
2886
2917
  "assets",
2887
2918
  ".png"
2888
- ));
2919
+ );
2920
+ }
2921
+ async loadTextures() {
2922
+ this.imageData = await ModelTextures.get(this.textureKey);
2889
2923
  }
2890
2924
  //TODO: abstract this, since extracted model data can be used for entities, blocks, players
2891
2925
  createMeshes(force = false) {
@@ -2918,21 +2952,23 @@ var EntityObject = class extends SceneObject {
2918
2952
  this.meshesCreated = true;
2919
2953
  }
2920
2954
  async applyTextures() {
2921
- var _a;
2922
- const textureAsset = await ModelTextures.preload(new AssetKey(
2923
- ((_a = this.entity.key) == null ? void 0 : _a.namespace) ?? DEFAULT_NAMESPACE,
2924
- this.entity.key.path,
2925
- "textures",
2926
- "entity",
2927
- "assets",
2928
- ".png"
2929
- ));
2930
- if (textureAsset) {
2931
- let mat = Materials.getImage({ texture: { src: textureAsset.src } });
2932
- this.iterateAllMeshes((mesh) => {
2933
- mesh.material = mat;
2934
- });
2935
- }
2955
+ const assetKeyStr = this.textureKey.serialize();
2956
+ const keyStr = `entity:${assetKeyStr}`;
2957
+ let mat = Caching.materialCache.getIfPresent(keyStr);
2958
+ if (!mat) {
2959
+ const pending = this.loadTextures();
2960
+ const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
2961
+ await pending;
2962
+ if (!this.imageData) return;
2963
+ const canvas = this.imageData.data.canvas;
2964
+ const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
2965
+ mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
2966
+ this.imageData = void 0;
2967
+ }
2968
+ this.iterateAllMeshes((mesh) => {
2969
+ mesh.material = mat;
2970
+ });
2971
+ this.notifyDirty();
2936
2972
  }
2937
2973
  };
2938
2974
  EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, {});