minerender 2.1.0-alpha.7 → 2.1.0-alpha.8
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/browser/index.d.mts +5 -1
- package/dist/browser/index.d.ts +5 -1
- package/dist/browser/index.js +86 -48
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +86 -48
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +86 -48
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +4 -0
- package/dist/node/index.d.ts +4 -0
- package/dist/node/index.js +88 -49
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +88 -49
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.mjs
CHANGED
|
@@ -758,29 +758,41 @@ var ImageLoader = class _ImageLoader {
|
|
|
758
758
|
static async loadAsync(src) {
|
|
759
759
|
return new Promise((resolve, reject) => {
|
|
760
760
|
const image = this._createImage();
|
|
761
|
-
image.src = src;
|
|
762
761
|
image.onload = () => resolve(image);
|
|
763
|
-
image.onerror = (err) => reject(err);
|
|
762
|
+
image.onerror = (err) => reject(err instanceof Error ? err : new Error("Failed to decode image"));
|
|
763
|
+
image.src = src;
|
|
764
764
|
});
|
|
765
765
|
}
|
|
766
766
|
static loadElement(src, onload, onerr) {
|
|
767
767
|
const image = this._createImage();
|
|
768
|
-
image.src = src;
|
|
769
768
|
if (onload)
|
|
770
769
|
image.onload = onload;
|
|
771
770
|
if (onerr)
|
|
772
771
|
image.onerror = onerr;
|
|
772
|
+
image.src = src;
|
|
773
773
|
return image;
|
|
774
774
|
}
|
|
775
775
|
static async loadData(src) {
|
|
776
776
|
console.debug(p2, "loadData", src);
|
|
777
|
-
|
|
777
|
+
const image = await this.loadCanvasData(src);
|
|
778
|
+
return image.data.getImageData(0, 0, image.width, image.height);
|
|
778
779
|
}
|
|
779
780
|
static async loadCanvasData(src) {
|
|
780
|
-
|
|
781
|
+
const keyStr = serializeImageKey({ src });
|
|
782
|
+
const info = this.getInfo(src);
|
|
783
|
+
const cached = Caching.rawImageCache.getIfPresent(keyStr);
|
|
784
|
+
try {
|
|
785
|
+
return await this.infoToCanvasData(await info);
|
|
786
|
+
} catch (err) {
|
|
787
|
+
if (cached && Caching.rawImageCache.getIfPresent(keyStr) === cached) {
|
|
788
|
+
Caching.rawImageCache.invalidate(keyStr);
|
|
789
|
+
}
|
|
790
|
+
throw err;
|
|
791
|
+
}
|
|
781
792
|
}
|
|
782
793
|
static async infoToCanvasData(info) {
|
|
783
|
-
const
|
|
794
|
+
const type = info.type === "jpg" ? "jpeg" : info.type ?? "png";
|
|
795
|
+
const image = await _ImageLoader.loadAsync(`data:image/${type};base64,${info.data.toString("base64")}`);
|
|
784
796
|
const canvas = createCanvas(info.width, info.height);
|
|
785
797
|
const context = canvas.getContext("2d");
|
|
786
798
|
context.drawImage(image, 0, 0);
|
|
@@ -791,11 +803,8 @@ var ImageLoader = class _ImageLoader {
|
|
|
791
803
|
};
|
|
792
804
|
}
|
|
793
805
|
static async infoToData(info) {
|
|
794
|
-
const image = await
|
|
795
|
-
|
|
796
|
-
const context = canvas.getContext("2d");
|
|
797
|
-
context.drawImage(image, 0, 0);
|
|
798
|
-
return context.getImageData(0, 0, canvas.width, canvas.height);
|
|
806
|
+
const image = await this.infoToCanvasData(info);
|
|
807
|
+
return image.data.getImageData(0, 0, image.width, image.height);
|
|
799
808
|
}
|
|
800
809
|
static async getData(src) {
|
|
801
810
|
const keyStr = serializeImageKey({ src });
|
|
@@ -810,13 +819,16 @@ var ImageLoader = class _ImageLoader {
|
|
|
810
819
|
});
|
|
811
820
|
}
|
|
812
821
|
static async processResponse(response) {
|
|
813
|
-
const src = response.config
|
|
822
|
+
const src = response.config?.url;
|
|
814
823
|
const data = Buffer2.from(response.data);
|
|
815
824
|
const { width, height, type } = Env.provider.imageSize(data);
|
|
825
|
+
if (!width || !height) {
|
|
826
|
+
throw new Error("Invalid or unsupported image dimensions");
|
|
827
|
+
}
|
|
816
828
|
return {
|
|
817
829
|
src,
|
|
818
|
-
width
|
|
819
|
-
height
|
|
830
|
+
width,
|
|
831
|
+
height,
|
|
820
832
|
type,
|
|
821
833
|
data
|
|
822
834
|
};
|
|
@@ -833,15 +845,7 @@ var ImageLoader = class _ImageLoader {
|
|
|
833
845
|
return Requests.genericRequest({
|
|
834
846
|
url: src,
|
|
835
847
|
responseType: "arraybuffer"
|
|
836
|
-
}).then(this.processResponse)
|
|
837
|
-
return {
|
|
838
|
-
src,
|
|
839
|
-
width: 0,
|
|
840
|
-
height: 0,
|
|
841
|
-
type: void 0,
|
|
842
|
-
data: Buffer2.from([0])
|
|
843
|
-
};
|
|
844
|
-
});
|
|
848
|
+
}).then(this.processResponse);
|
|
845
849
|
}
|
|
846
850
|
static async getInfo(src) {
|
|
847
851
|
const keyStr = serializeImageKey({ src });
|
|
@@ -863,16 +867,22 @@ var ImageLoader = class _ImageLoader {
|
|
|
863
867
|
|
|
864
868
|
// src/texture/TextureLoader.ts
|
|
865
869
|
var TextureLoader = class {
|
|
870
|
+
/** Reports whether image loading failed, so cached textures can be retried. */
|
|
871
|
+
static hasFailed(texture) {
|
|
872
|
+
return this.failedTextures.has(texture);
|
|
873
|
+
}
|
|
866
874
|
static createTexture() {
|
|
867
875
|
return new Texture();
|
|
868
876
|
}
|
|
869
877
|
static loadInBackground(src, format = RGBAFormat, rotation = 0) {
|
|
870
878
|
const texture = this.createTexture();
|
|
871
879
|
texture.colorSpace = THREE.SRGBColorSpace;
|
|
872
|
-
const image = ImageLoader.loadElement(src)
|
|
873
|
-
image.onload = function() {
|
|
880
|
+
const image = ImageLoader.loadElement(src, () => {
|
|
874
881
|
texture.needsUpdate = true;
|
|
875
|
-
}
|
|
882
|
+
}, (error) => {
|
|
883
|
+
this.failedTextures.add(texture);
|
|
884
|
+
console.warn("Failed to load texture", src, error);
|
|
885
|
+
});
|
|
876
886
|
texture.image = image;
|
|
877
887
|
texture.format = format;
|
|
878
888
|
texture.rotation = rotation;
|
|
@@ -882,14 +892,18 @@ var TextureLoader = class {
|
|
|
882
892
|
const texture = new Texture();
|
|
883
893
|
texture.colorSpace = THREE.SRGBColorSpace;
|
|
884
894
|
ImageLoader.getData(src).then((image) => {
|
|
885
|
-
texture.needsUpdate = true;
|
|
886
895
|
texture.image = image;
|
|
896
|
+
texture.needsUpdate = true;
|
|
897
|
+
}).catch((error) => {
|
|
898
|
+
this.failedTextures.add(texture);
|
|
899
|
+
console.warn("Failed to load texture", src, error);
|
|
887
900
|
});
|
|
888
901
|
texture.format = format;
|
|
889
902
|
texture.rotation = rotation;
|
|
890
903
|
return Textures.initTextureProps(texture);
|
|
891
904
|
}
|
|
892
905
|
};
|
|
906
|
+
TextureLoader.failedTextures = /* @__PURE__ */ new WeakSet();
|
|
893
907
|
|
|
894
908
|
// src/texture/Textures.ts
|
|
895
909
|
import * as THREE2 from "three";
|
|
@@ -913,6 +927,10 @@ var Textures = class _Textures {
|
|
|
913
927
|
}
|
|
914
928
|
static getImage(key) {
|
|
915
929
|
const keyStr = serializeTextureKey(key);
|
|
930
|
+
const cached = Caching.textureCache.peek(keyStr);
|
|
931
|
+
if (cached && TextureLoader.hasFailed(cached)) {
|
|
932
|
+
Caching.textureCache.invalidate(keyStr);
|
|
933
|
+
}
|
|
916
934
|
return Caching.textureCache.get(keyStr, (k) => {
|
|
917
935
|
return _Textures.createImage(key);
|
|
918
936
|
});
|
|
@@ -1057,6 +1075,10 @@ var _Materials = class _Materials {
|
|
|
1057
1075
|
}
|
|
1058
1076
|
static getImage(key) {
|
|
1059
1077
|
const keyStr = serializeMaterialKey(key);
|
|
1078
|
+
const map = Caching.materialCache.peek(keyStr)?.map;
|
|
1079
|
+
if (map && TextureLoader.hasFailed(map)) {
|
|
1080
|
+
Caching.materialCache.invalidate(keyStr);
|
|
1081
|
+
}
|
|
1060
1082
|
return Caching.materialCache.get(keyStr, (k) => {
|
|
1061
1083
|
return _Materials.createImage(key);
|
|
1062
1084
|
});
|
|
@@ -1714,11 +1736,21 @@ var ModelTextures = class {
|
|
|
1714
1736
|
return this._persistentMetaCache ?? (this._persistentMetaCache = PersistentCache.open("minerender-texturemeta"));
|
|
1715
1737
|
}
|
|
1716
1738
|
static async get(key) {
|
|
1717
|
-
const
|
|
1718
|
-
|
|
1719
|
-
|
|
1739
|
+
const keyStr = key.serialize();
|
|
1740
|
+
const pending = this.preload(key);
|
|
1741
|
+
const cached = Caching.textureAssetCache.getIfPresent(keyStr);
|
|
1742
|
+
try {
|
|
1743
|
+
const asset = await pending;
|
|
1744
|
+
if (asset) {
|
|
1745
|
+
return await ImageLoader.infoToCanvasData(asset);
|
|
1746
|
+
}
|
|
1747
|
+
return void 0;
|
|
1748
|
+
} catch (err) {
|
|
1749
|
+
if (cached && Caching.textureAssetCache.getIfPresent(keyStr) === cached) {
|
|
1750
|
+
Caching.textureAssetCache.invalidate(keyStr);
|
|
1751
|
+
}
|
|
1752
|
+
throw err;
|
|
1720
1753
|
}
|
|
1721
|
-
return void 0;
|
|
1722
1754
|
}
|
|
1723
1755
|
static async preload(key) {
|
|
1724
1756
|
const keyStr = key.serialize();
|
|
@@ -2909,8 +2941,8 @@ var EntityObject = class extends SceneObject {
|
|
|
2909
2941
|
dispose() {
|
|
2910
2942
|
super.dispose();
|
|
2911
2943
|
}
|
|
2912
|
-
|
|
2913
|
-
|
|
2944
|
+
get textureKey() {
|
|
2945
|
+
return new AssetKey(
|
|
2914
2946
|
this.entity.key?.namespace ?? DEFAULT_NAMESPACE,
|
|
2915
2947
|
this.entity.key.path,
|
|
2916
2948
|
//TODO: texture may differ from entity name; most of them are in subdirectories for multiple variants etc.
|
|
@@ -2918,7 +2950,10 @@ var EntityObject = class extends SceneObject {
|
|
|
2918
2950
|
"entity",
|
|
2919
2951
|
"assets",
|
|
2920
2952
|
".png"
|
|
2921
|
-
)
|
|
2953
|
+
);
|
|
2954
|
+
}
|
|
2955
|
+
async loadTextures() {
|
|
2956
|
+
this.imageData = await ModelTextures.get(this.textureKey);
|
|
2922
2957
|
}
|
|
2923
2958
|
//TODO: abstract this, since extracted model data can be used for entities, blocks, players
|
|
2924
2959
|
createMeshes(force = false) {
|
|
@@ -2951,20 +2986,23 @@ var EntityObject = class extends SceneObject {
|
|
|
2951
2986
|
this.meshesCreated = true;
|
|
2952
2987
|
}
|
|
2953
2988
|
async applyTextures() {
|
|
2954
|
-
const
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2989
|
+
const assetKeyStr = this.textureKey.serialize();
|
|
2990
|
+
const keyStr = `entity:${assetKeyStr}`;
|
|
2991
|
+
let mat = Caching.materialCache.getIfPresent(keyStr);
|
|
2992
|
+
if (!mat) {
|
|
2993
|
+
const pending = this.loadTextures();
|
|
2994
|
+
const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
|
|
2995
|
+
await pending;
|
|
2996
|
+
if (!this.imageData) return;
|
|
2997
|
+
const canvas = this.imageData.data.canvas;
|
|
2998
|
+
const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
|
|
2999
|
+
mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
|
|
3000
|
+
this.imageData = void 0;
|
|
3001
|
+
}
|
|
3002
|
+
this.iterateAllMeshes((mesh) => {
|
|
3003
|
+
mesh.material = mat;
|
|
3004
|
+
});
|
|
3005
|
+
this.notifyDirty();
|
|
2968
3006
|
}
|
|
2969
3007
|
};
|
|
2970
3008
|
EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, {});
|