minerender 2.1.0-beta.6 → 2.1.0-beta.7
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/esm/Materials.mjs +3 -1
- package/dist/browser/esm/Materials.mjs.map +1 -1
- package/dist/browser/esm/Ticker.mjs +3 -1
- package/dist/browser/esm/Ticker.mjs.map +1 -1
- package/dist/browser/esm/UVMapper.mjs +9 -9
- package/dist/browser/esm/UVMapper.mjs.map +1 -1
- package/dist/browser/esm/assets/AssetDefaults.mjs +8 -0
- package/dist/browser/esm/assets/AssetDefaults.mjs.map +1 -0
- package/dist/browser/esm/assets/AssetKey.mjs +1 -1
- package/dist/browser/esm/assets/AssetKey.mjs.map +1 -1
- package/dist/browser/esm/assets/AssetLoader.mjs +5 -5
- package/dist/browser/esm/assets/AssetLoader.mjs.map +1 -1
- package/dist/browser/esm/assets/Assets.mjs +1 -5
- package/dist/browser/esm/assets/Assets.mjs.map +1 -1
- package/dist/browser/esm/assets/BlockEntities.mjs +3 -1
- package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
- package/dist/browser/esm/assets/BlockStates.mjs +1 -1
- package/dist/browser/esm/assets/BlockStates.mjs.map +1 -1
- package/dist/browser/esm/assets/Entities.mjs +1 -1
- package/dist/browser/esm/assets/Entities.mjs.map +1 -1
- package/dist/browser/esm/assets/Models.mjs +1 -1
- package/dist/browser/esm/assets/Models.mjs.map +1 -1
- package/dist/browser/esm/assets/_fonts/Unihex.mjs +5 -3
- package/dist/browser/esm/assets/_fonts/Unihex.mjs.map +1 -1
- package/dist/browser/esm/assets/index.mjs +1 -0
- package/dist/browser/esm/assets/index.mjs.map +1 -1
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs +7 -8
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs.map +1 -1
- package/dist/browser/esm/env/browser/BrowserCache.mjs +3 -3
- package/dist/browser/esm/env/browser/BrowserCache.mjs.map +1 -1
- package/dist/browser/esm/image/ImageLoader.mjs +3 -3
- package/dist/browser/esm/image/ImageLoader.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +64 -11
- package/dist/browser/esm/inspector/SceneInspector.mjs +3 -3
- package/dist/browser/esm/inspector/SceneInspector.mjs.map +1 -1
- package/dist/browser/esm/instance/InstanceManager.mjs +4 -4
- package/dist/browser/esm/instance/InstanceManager.mjs.map +1 -1
- package/dist/browser/esm/model/block/scene/BlockObject.mjs +3 -1
- package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
- package/dist/browser/esm/model/multiblock/StructureParser.mjs +7 -4
- package/dist/browser/esm/model/multiblock/StructureParser.mjs.map +1 -1
- package/dist/browser/esm/model/scene/ModelObject.mjs +4 -4
- package/dist/browser/esm/model/scene/ModelObject.mjs.map +1 -1
- package/dist/browser/esm/nbt/NBTHelper.mjs +5 -2
- package/dist/browser/esm/nbt/NBTHelper.mjs.map +1 -1
- package/dist/browser/esm/renderer/Renderer.mjs +4 -2
- package/dist/browser/esm/renderer/Renderer.mjs.map +1 -1
- package/dist/browser/esm/renderer/SceneObject.mjs +0 -6
- package/dist/browser/esm/renderer/SceneObject.mjs.map +1 -1
- package/dist/browser/esm/request/Requests.mjs +3 -3
- package/dist/browser/esm/request/Requests.mjs.map +1 -1
- package/dist/browser/esm/skin/Skins.mjs +6 -4
- package/dist/browser/esm/skin/Skins.mjs.map +1 -1
- package/dist/browser/esm/texture/TextureLoader.mjs +4 -2
- package/dist/browser/esm/texture/TextureLoader.mjs.map +1 -1
- package/dist/browser/esm/util/log.mjs +75 -0
- package/dist/browser/esm/util/log.mjs.map +1 -1
- package/dist/browser/esm/util/performance.mjs.map +1 -1
- package/dist/browser/esm/world/Chunk.mjs +8 -5
- package/dist/browser/esm/world/Chunk.mjs.map +1 -1
- package/dist/browser/esm/world/MineRenderWorld.mjs +96 -54
- package/dist/browser/esm/world/MineRenderWorld.mjs.map +1 -1
- package/dist/browser/esm/world/WorldStreamer.mjs +21 -20
- package/dist/browser/esm/world/WorldStreamer.mjs.map +1 -1
- package/dist/browser/esm/world/_culling/BlockCulling.mjs +1 -1
- package/dist/browser/esm/world/_culling/BlockCulling.mjs.map +1 -1
- package/dist/browser/esm/world/_entities/WorldEntities.mjs +3 -1
- package/dist/browser/esm/world/_entities/WorldEntities.mjs.map +1 -1
- package/dist/browser/index.d.ts +64 -11
- package/dist/browser/index.js +3071 -2956
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +6095 -5975
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +64 -11
- package/dist/node/index.d.ts +64 -11
- package/dist/node/index.js +3095 -2978
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +3087 -2971
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -4,6 +4,8 @@ import { Color, CustomBlending, DoubleSide, OneFactor, OneMinusSrcAlphaFactor, R
|
|
|
4
4
|
import { Textures } from "./texture/Textures.mjs";
|
|
5
5
|
import { TextureLoader } from "./texture/TextureLoader.mjs";
|
|
6
6
|
import { Caching } from "./cache/Caching.mjs";
|
|
7
|
+
import { logger } from "./util/log.mjs";
|
|
8
|
+
var log = logger("Materials");
|
|
7
9
|
var Materials = class _Materials {
|
|
8
10
|
/** Shared checkerboard material, created on first access. */
|
|
9
11
|
static get MISSING_TEXTURE() {
|
|
@@ -274,7 +276,7 @@ var Materials = class _Materials {
|
|
|
274
276
|
Object.assign(material.defaultAttributeValues, { shade: [1], uvBounds: [0, 0, 1, 1] });
|
|
275
277
|
return material;
|
|
276
278
|
} catch (e) {
|
|
277
|
-
|
|
279
|
+
log.warn(e);
|
|
278
280
|
}
|
|
279
281
|
return this.createBasicCanvasMaterial(canvas, transparent, shade);
|
|
280
282
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/Materials.ts"],"sourcesContent":["import { MaterialKey, serializeMaterialKey } from \"./cache/CacheKey\";\nimport { Color, ColorRepresentation, CustomBlending, DoubleSide, OneFactor, OneMinusSrcAlphaFactor, RepeatWrapping, FrontSide, Material, MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial, MeshStandardMaterial, ShaderChunk, ShaderMaterial } from \"three\";\nimport { Textures } from \"./texture/Textures\";\nimport { TextureLoader } from \"./texture/TextureLoader\";\nimport { Caching } from \"./cache/Caching\";\nimport { AssetKey } from \"./assets/AssetKey\";\nimport type { EntityRenderMode } from \"./entity/EntityModel\";\n\n/** Creates Minecraft model, entity, and GUI materials, with shared caches for image materials. */\nexport class Materials {\n\n /** Shared checkerboard material, created on first access. */\n public static get MISSING_TEXTURE(): Material {\n return Caching.materialCache.get(\"builtin:missing-texture\", () => new MeshBasicMaterial({\n map: Textures.getMissing(),\n alphaTest: 0.5\n }))!;\n }\n\n public static createImage(key: MaterialKey): Material {\n //TODO: type from key\n const transparent = key.transparent || false;\n return new MeshBasicMaterial({\n map: Textures.getImage(key.texture),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5\n });\n //TODO: params\n }\n\n\n public static createBasicCanvasMaterial(canvas: HTMLCanvasElement, transparent: boolean = false, shade: boolean = false): Material {\n if (shade) {\n return new MeshStandardMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n\n })\n }\n return new MeshBasicMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n\n })\n }\n\n /** Whether vanilla's render type for the mode culls back faces. */\n public static entityModeCulls(mode: EntityRenderMode = \"cutout\"): boolean {\n return mode === \"cutout_cull\" || mode === \"solid\" || mode === \"eyes\" || mode === \"water_mask\";\n }\n\n /** UV offset per tick of entity age for the scrolling modes, as vanilla's texture matrix applies it. */\n public static entityModeScroll(mode: EntityRenderMode = \"cutout\"): [number, number] | undefined {\n if (mode === \"energy_swirl\") return [0.01, 0.01];\n if (mode === \"breeze_wind\") return [0.02, 0];\n return undefined;\n }\n\n /**\n * Entity material for one of vanilla's render types. Entities are unlit here, so the lit and full-bright modes\n * differ only in blending and depth state. Culling is not a material property: {@link entityModeCulls} decides\n * whether the geometry gets inward faces.\n */\n public static createEntityCanvasMaterial(canvas: HTMLCanvasElement, mode: EntityRenderMode = \"cutout\", tint?: ColorRepresentation): MeshBasicMaterial {\n const material = Materials.createBasicCanvasMaterial(canvas) as MeshBasicMaterial;\n switch (mode) {\n case \"cutout\":\n case \"cutout_cull\":\n break;\n case \"cutout_z_offset\":\n material.polygonOffset = true;\n material.polygonOffsetFactor = -1;\n material.polygonOffsetUnits = -10;\n break;\n case \"solid\":\n material.alphaTest = 0;\n break;\n case \"translucent\":\n case \"breeze_wind\":\n material.transparent = true;\n material.alphaTest = 0.1;\n break;\n case \"translucent_emissive\":\n material.transparent = true;\n material.alphaTest = 0.1;\n material.depthWrite = false;\n break;\n case \"eyes\":\n case \"no_outline\":\n material.transparent = true;\n material.alphaTest = 0;\n material.depthWrite = false;\n break;\n case \"energy_swirl\":\n material.transparent = true;\n material.alphaTest = 0.1;\n material.blending = CustomBlending;\n material.blendSrc = OneFactor;\n material.blendDst = OneFactor;\n // The canvas is premultiplied: a glow pixel needs alpha, or browsers and image exports drop it wherever\n // nothing opaque is behind it. Its brightness serves as coverage, so the glow stays visible outside the body.\n material.blendSrcAlpha = OneFactor;\n material.blendDstAlpha = OneMinusSrcAlphaFactor;\n material.onBeforeCompile = shader => {\n shader.fragmentShader = shader.fragmentShader.replace(\"#include <dithering_fragment>\",\n \"gl_FragColor.a = max(gl_FragColor.r, max(gl_FragColor.g, gl_FragColor.b));\\n#include <dithering_fragment>\");\n };\n material.customProgramCacheKey = () => \"energy_swirl\";\n // Vanilla submits the swirl with half-grey vertex colour.\n material.color.set(0x808080);\n break;\n case \"water_mask\":\n material.alphaTest = 0;\n material.colorWrite = false;\n break;\n }\n if (Materials.entityModeScroll(mode)) {\n material.map!.wrapS = material.map!.wrapT = RepeatWrapping;\n }\n if (tint !== undefined) material.color.multiply(new Color(tint));\n return material;\n }\n\n /** Creates an unlit, transparent GUI material without depth writes or tone mapping. */\n public static createGuiCanvasMaterial(canvas: HTMLCanvasElement): MeshBasicMaterial {\n const material = new MeshBasicMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: true,\n depthWrite: false,\n side: DoubleSide,\n toneMapped: false\n });\n material.onBeforeCompile = shader => {\n // Keep MSAA edge pixels inside the layer's cropped texture region.\n for (const [stage, direction] of [[\"vertex\", \"out\"], [\"fragment\", \"in\"]] as const) {\n const chunk = `uv_pars_${stage}` as const;\n shader[`${stage}Shader`] = shader[`${stage}Shader`].replace(`#include <${chunk}>`,\n ShaderChunk[chunk].replace(\"varying vec2 vMapUv;\", `\n #if __VERSION__ >= 300\n centroid ${direction} vec2 vMapUv;\n #else\n varying vec2 vMapUv;\n #endif\n `));\n }\n };\n return material;\n }\n\n public static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent: boolean = false, shade:boolean=false, boundUvs: boolean = false):Material {\n //TODO\n // this might help https://github.com/JannisX11/blockbench/blob/1701f764641376414d29100c4f6c7cd74997fad8/js/preview/canvas.js#L62\n\n\n // Based on https://github.com/JannisX11/blockbench/blob/cc73aa8a9c0494fd9fe1cee4d062d060af4db06d/js/texturing/textures.js#L59\n // + support for instanced meshes\n const vertShader =`\n uniform bool SHADE;\n attribute float shade;\n \n // Keep MSAA edge pixels from sampling outside the face's atlas region.\n #if __VERSION__ >= 300\n centroid out vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n #ifdef BOUND_UVS\n attribute vec4 uvBounds;\n flat out vec4 vUvBounds;\n #endif\n varying vec3 vTint;\n varying float light;\n varying float lift;\n\n float AMBIENT = 0.5;\n float XFAC = -0.15;\n float ZFAC = 0.05;\n\n void main()\n {\n\n if (SHADE && shade > 0.5) {\n\n #ifdef USE_INSTANCING\n vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );\n #else\n vec3 N = vec3( modelMatrix * vec4(normal, 0.0) );\n #endif\n\n float yLight = (1.0+N.y) * 0.5;\n light = yLight * (1.0-AMBIENT) + N.x*N.x * XFAC + N.z*N.z * ZFAC + AMBIENT;\n\n } else {\n\n light = 1.0;\n\n } \n\n if (color.b > 1.1) {\n lift = 0.1;\n } else {\n lift = 0.0;\n }\n \n vUv = uv;\n #ifdef BOUND_UVS\n vUvBounds = uvBounds;\n #endif\n vTint = color;\n \n vec4 mvPosition = vec4(position, 1.0);\n #ifdef USE_INSTANCING\n mvPosition = instanceMatrix * mvPosition;\n #endif\n mvPosition = modelViewMatrix * mvPosition;\n gl_Position = projectionMatrix * mvPosition;\n \n }\n `\n const fragShader = `\n #ifdef GL_ES\n precision highp float;\n #endif\n\n uniform sampler2D map;\n\n uniform bool SHADE;\n uniform bool EMISSIVE;\n uniform float BRIGHTNESS;\n\n #if __VERSION__ >= 300\n centroid in vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n #ifdef BOUND_UVS\n flat in vec4 vUvBounds;\n #endif\n varying vec3 vTint;\n varying float light;\n varying float lift;\n\n void main(void)\n {\n #ifdef BOUND_UVS\n // Keep edge samples inside their texture even without centroid interpolation.\n vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);\n #else\n vec2 mapUv = vUv;\n #endif\n vec4 color = texture2D(map, mapUv);\n color.rgb *= vTint;\n \n if (color.a < 0.01) discard;\n\n if (EMISSIVE == false) {\n\n gl_FragColor = vec4(lift + color.rgb * light * BRIGHTNESS, color.a);\n\n } else {\n\n float light2 = (light * BRIGHTNESS) + (1.0 - light * BRIGHTNESS) * (1.0 - color.a);\n gl_FragColor = vec4(lift + color.rgb * light2, 1.0);\n\n }\n\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n }\n `\n //TODO: this does add the MC-like shading, but breaks when stuff is instanced (can't updated position)\n // https://medium.com/@pailhead011/instancing-with-three-js-part-2-3be34ae83c57 might help with that\n\n try {\n const material = new ShaderMaterial({\n defines: boundUvs ? { BOUND_UVS: true } : {},\n uniforms: {\n SHADE: { value: true },\n BRIGHTNESS: { value: 1 },\n EMISSIVE:{value:false},\n base: { value: new Color(0xc1c1c1)/*TODO*/ },\n map: {value:Textures.createCanvasTexture(canvas)}\n },\n vertexShader: vertShader,\n fragmentShader: fragShader,\n vertexColors: true,\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n });\n Object.assign(material.defaultAttributeValues, { shade: [1], uvBounds: [0, 0, 1, 1] });\n return material;\n } catch (e) {\n console.warn(e)\n }\n\n // fallback\n return this.createBasicCanvasMaterial(canvas, transparent, shade);\n }\n\n /** Returns a shared image material. Use {@link createImage} for a separate material instance. */\n public static getImage(key: MaterialKey): Material {\n const keyStr = serializeMaterialKey(key);\n const map = (Caching.materialCache.peek(keyStr) as MeshBasicMaterial | undefined)?.map;\n if (map && TextureLoader.hasFailed(map)) {\n Caching.materialCache.invalidate(keyStr);\n }\n return Caching.materialCache.get(keyStr, k => {\n return Materials.createImage(key);\n })!;\n }\n\n public static needsUpdate(mat: Material) {\n mat.needsUpdate = true;\n\n if (mat.type === 'ShaderMaterial') {\n let mat1=mat as ShaderMaterial;\n if (\"map\" in mat1.uniforms) {\n mat1.uniforms.map.value.needsUpdate = true;\n }\n }\n if (mat.type === 'MeshBasicMaterial' || mat.type === 'MeshStandardMaterial') {\n let mat1 = mat as (MeshBasicMaterial | MeshStandardMaterial);\n if (mat1.map) {\n mat1.map.needsUpdate = true;\n }\n }\n }\n\n}\n"],"mappings":";AAAA,SAAsB,4BAA4B;AAClD,SAAS,OAA4B,gBAAgB,YAAY,WAAW,wBAAwB,gBAAgB,WAAqB,mBAA2D,sBAAsB,aAAa,sBAAsB;AAC7P,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAC9B,SAAS,eAAe;AAKjB,IAAM,YAAN,MAAM,WAAU;AAAA;AAAA,EAGnB,WAAkB,kBAA4B;AAC1C,WAAO,QAAQ,cAAc,IAAI,2BAA2B,MAAM,IAAI,kBAAkB;AAAA,MACpF,KAAK,SAAS,WAAW;AAAA,MACzB,WAAW;AAAA,IACf,CAAC,CAAC;AAAA,EACN;AAAA,EAEA,OAAc,YAAY,KAA4B;AAElD,UAAM,cAAc,IAAI,eAAe;AACvC,WAAO,IAAI,kBAAkB;AAAA,MACzB,KAAK,SAAS,SAAS,IAAI,OAAO;AAAA,MAClC;AAAA,MACA,MAAM,cAAc,aAAa;AAAA,MACjC,WAAW;AAAA,IACf,CAAC;AAAA,EAEL;AAAA,EAGA,OAAc,0BAA0B,QAA2B,cAAuB,OAAO,QAAiB,OAAiB;AAC/H,QAAI,OAAO;AACP,aAAO,IAAI,qBAAqB;AAAA,QAC5B,KAAK,SAAS,oBAAoB,MAAM;AAAA,QACxC;AAAA,QACA,MAAM,cAAc,aAAa;AAAA,QACjC,WAAW;AAAA,MAEf,CAAC;AAAA,IACL;AACA,WAAO,IAAI,kBAAkB;AAAA,MACzB,KAAK,SAAS,oBAAoB,MAAM;AAAA,MACxC;AAAA,MACA,MAAM,cAAc,aAAa;AAAA,MACjC,WAAW;AAAA,IAEf,CAAC;AAAA,EACL;AAAA;AAAA,EAGA,OAAc,gBAAgB,OAAyB,UAAmB;AACtE,WAAO,SAAS,iBAAiB,SAAS,WAAW,SAAS,UAAU,SAAS;AAAA,EACrF;AAAA;AAAA,EAGA,OAAc,iBAAiB,OAAyB,UAAwC;AAC5F,QAAI,SAAS,eAAgB,QAAO,CAAC,MAAM,IAAI;AAC/C,QAAI,SAAS,cAAe,QAAO,CAAC,MAAM,CAAC;AAC3C,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,2BAA2B,QAA2B,OAAyB,UAAU,MAA+C;AAClJ,UAAM,WAAW,WAAU,0BAA0B,MAAM;AAC3D,YAAQ,MAAM;AAAA,MACV,KAAK;AAAA,MACL,KAAK;AACD;AAAA,MACJ,KAAK;AACD,iBAAS,gBAAgB;AACzB,iBAAS,sBAAsB;AAC/B,iBAAS,qBAAqB;AAC9B;AAAA,MACJ,KAAK;AACD,iBAAS,YAAY;AACrB;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AACD,iBAAS,cAAc;AACvB,iBAAS,YAAY;AACrB;AAAA,MACJ,KAAK;AACD,iBAAS,cAAc;AACvB,iBAAS,YAAY;AACrB,iBAAS,aAAa;AACtB;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AACD,iBAAS,cAAc;AACvB,iBAAS,YAAY;AACrB,iBAAS,aAAa;AACtB;AAAA,MACJ,KAAK;AACD,iBAAS,cAAc;AACvB,iBAAS,YAAY;AACrB,iBAAS,WAAW;AACpB,iBAAS,WAAW;AACpB,iBAAS,WAAW;AAGpB,iBAAS,gBAAgB;AACzB,iBAAS,gBAAgB;AACzB,iBAAS,kBAAkB,YAAU;AACjC,iBAAO,iBAAiB,OAAO,eAAe;AAAA,YAAQ;AAAA,YAClD;AAAA,UAA2G;AAAA,QACnH;AACA,iBAAS,wBAAwB,MAAM;AAEvC,iBAAS,MAAM,IAAI,OAAQ;AAC3B;AAAA,MACJ,KAAK;AACD,iBAAS,YAAY;AACrB,iBAAS,aAAa;AACtB;AAAA,IACR;AACA,QAAI,WAAU,iBAAiB,IAAI,GAAG;AAClC,eAAS,IAAK,QAAQ,SAAS,IAAK,QAAQ;AAAA,IAChD;AACA,QAAI,SAAS,OAAW,UAAS,MAAM,SAAS,IAAI,MAAM,IAAI,CAAC;AAC/D,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,OAAc,wBAAwB,QAA8C;AAChF,UAAM,WAAW,IAAI,kBAAkB;AAAA,MACnC,KAAK,SAAS,oBAAoB,MAAM;AAAA,MACxC,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,MAAM;AAAA,MACN,YAAY;AAAA,IAChB,CAAC;AACD,aAAS,kBAAkB,YAAU;AAEjC,iBAAW,CAAC,OAAO,SAAS,KAAK,CAAC,CAAC,UAAU,KAAK,GAAG,CAAC,YAAY,IAAI,CAAC,GAAY;AAC/E,cAAM,QAAQ,WAAW,KAAK;AAC9B,eAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AAAA,UAAQ,aAAa,KAAK;AAAA,UAC1E,YAAY,KAAK,EAAE,QAAQ,wBAAwB;AAAA;AAAA,mCAEpC,SAAS;AAAA;AAAA;AAAA;AAAA,qBAIvB;AAAA,QAAC;AAAA,MACV;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA,EAEA,OAAc,2BAA2B,QAA2B,cAAuB,OAAO,QAAc,OAAO,WAAoB,OAAgB;AAOvJ,UAAM,aAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA+DlB,UAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsDnB,QAAI;AACA,YAAM,WAAW,IAAI,eAAe;AAAA,QAChC,SAAS,WAAW,EAAE,WAAW,KAAK,IAAI,CAAC;AAAA,QAC3C,UAAU;AAAA,UACN,OAAO,EAAE,OAAO,KAAK;AAAA,UACrB,YAAY,EAAE,OAAO,EAAE;AAAA,UACvB,UAAS,EAAC,OAAM,MAAK;AAAA,UACrB,MAAM;AAAA,YAAE,OAAO,IAAI,MAAM,QAAQ;AAAA;AAAA,UAAU;AAAA,UAC3C,KAAK,EAAC,OAAM,SAAS,oBAAoB,MAAM,EAAC;AAAA,QACpD;AAAA,QACA,cAAc;AAAA,QACd,gBAAgB;AAAA,QAChB,cAAc;AAAA,QACd;AAAA,QACA,MAAM,cAAc,aAAa;AAAA,QACjC,WAAW;AAAA,MACf,CAAC;AACD,aAAO,OAAO,SAAS,wBAAwB,EAAE,OAAO,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC;AACrF,aAAO;AAAA,IACX,SAAS,GAAG;AACR,cAAQ,KAAK,CAAC;AAAA,IAClB;AAGA,WAAO,KAAK,0BAA0B,QAAQ,aAAa,KAAK;AAAA,EACpE;AAAA;AAAA,EAGA,OAAc,SAAS,KAA4B;AAC/C,UAAM,SAAS,qBAAqB,GAAG;AACvC,UAAM,MAAO,QAAQ,cAAc,KAAK,MAAM,GAAqC;AACnF,QAAI,OAAO,cAAc,UAAU,GAAG,GAAG;AACrC,cAAQ,cAAc,WAAW,MAAM;AAAA,IAC3C;AACA,WAAO,QAAQ,cAAc,IAAI,QAAQ,OAAK;AAC1C,aAAO,WAAU,YAAY,GAAG;AAAA,IACpC,CAAC;AAAA,EACL;AAAA,EAEA,OAAc,YAAY,KAAe;AACrC,QAAI,cAAc;AAElB,QAAI,IAAI,SAAS,kBAAkB;AAC/B,UAAI,OAAK;AACT,UAAI,SAAS,KAAK,UAAU;AACxB,aAAK,SAAS,IAAI,MAAM,cAAc;AAAA,MAC1C;AAAA,IACJ;AACA,QAAI,IAAI,SAAS,uBAAuB,IAAI,SAAS,wBAAwB;AACzE,UAAI,OAAO;AACX,UAAI,KAAK,KAAK;AACV,aAAK,IAAI,cAAc;AAAA,MAC3B;AAAA,IACJ;AAAA,EACJ;AAEJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/Materials.ts"],"sourcesContent":["import { MaterialKey, serializeMaterialKey } from \"./cache/CacheKey\";\nimport { Color, ColorRepresentation, CustomBlending, DoubleSide, OneFactor, OneMinusSrcAlphaFactor, RepeatWrapping, FrontSide, Material, MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial, MeshStandardMaterial, ShaderChunk, ShaderMaterial } from \"three\";\nimport { Textures } from \"./texture/Textures\";\nimport { TextureLoader } from \"./texture/TextureLoader\";\nimport { Caching } from \"./cache/Caching\";\nimport { AssetKey } from \"./assets/AssetKey\";\nimport type { EntityRenderMode } from \"./entity/EntityModel\";\nimport { logger } from \"./util/log\";\n\nconst log = logger(\"Materials\");\n\n/** Creates Minecraft model, entity, and GUI materials, with shared caches for image materials. */\nexport class Materials {\n\n /** Shared checkerboard material, created on first access. */\n public static get MISSING_TEXTURE(): Material {\n return Caching.materialCache.get(\"builtin:missing-texture\", () => new MeshBasicMaterial({\n map: Textures.getMissing(),\n alphaTest: 0.5\n }))!;\n }\n\n public static createImage(key: MaterialKey): Material {\n //TODO: type from key\n const transparent = key.transparent || false;\n return new MeshBasicMaterial({\n map: Textures.getImage(key.texture),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5\n });\n //TODO: params\n }\n\n\n public static createBasicCanvasMaterial(canvas: HTMLCanvasElement, transparent: boolean = false, shade: boolean = false): Material {\n if (shade) {\n return new MeshStandardMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n\n })\n }\n return new MeshBasicMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n\n })\n }\n\n /** Whether vanilla's render type for the mode culls back faces. */\n public static entityModeCulls(mode: EntityRenderMode = \"cutout\"): boolean {\n return mode === \"cutout_cull\" || mode === \"solid\" || mode === \"eyes\" || mode === \"water_mask\";\n }\n\n /** UV offset per tick of entity age for the scrolling modes, as vanilla's texture matrix applies it. */\n public static entityModeScroll(mode: EntityRenderMode = \"cutout\"): [number, number] | undefined {\n if (mode === \"energy_swirl\") return [0.01, 0.01];\n if (mode === \"breeze_wind\") return [0.02, 0];\n return undefined;\n }\n\n /**\n * Entity material for one of vanilla's render types. Entities are unlit here, so the lit and full-bright modes\n * differ only in blending and depth state. Culling is not a material property: {@link entityModeCulls} decides\n * whether the geometry gets inward faces.\n */\n public static createEntityCanvasMaterial(canvas: HTMLCanvasElement, mode: EntityRenderMode = \"cutout\", tint?: ColorRepresentation): MeshBasicMaterial {\n const material = Materials.createBasicCanvasMaterial(canvas) as MeshBasicMaterial;\n switch (mode) {\n case \"cutout\":\n case \"cutout_cull\":\n break;\n case \"cutout_z_offset\":\n material.polygonOffset = true;\n material.polygonOffsetFactor = -1;\n material.polygonOffsetUnits = -10;\n break;\n case \"solid\":\n material.alphaTest = 0;\n break;\n case \"translucent\":\n case \"breeze_wind\":\n material.transparent = true;\n material.alphaTest = 0.1;\n break;\n case \"translucent_emissive\":\n material.transparent = true;\n material.alphaTest = 0.1;\n material.depthWrite = false;\n break;\n case \"eyes\":\n case \"no_outline\":\n material.transparent = true;\n material.alphaTest = 0;\n material.depthWrite = false;\n break;\n case \"energy_swirl\":\n material.transparent = true;\n material.alphaTest = 0.1;\n material.blending = CustomBlending;\n material.blendSrc = OneFactor;\n material.blendDst = OneFactor;\n // The canvas is premultiplied: a glow pixel needs alpha, or browsers and image exports drop it wherever\n // nothing opaque is behind it. Its brightness serves as coverage, so the glow stays visible outside the body.\n material.blendSrcAlpha = OneFactor;\n material.blendDstAlpha = OneMinusSrcAlphaFactor;\n material.onBeforeCompile = shader => {\n shader.fragmentShader = shader.fragmentShader.replace(\"#include <dithering_fragment>\",\n \"gl_FragColor.a = max(gl_FragColor.r, max(gl_FragColor.g, gl_FragColor.b));\\n#include <dithering_fragment>\");\n };\n material.customProgramCacheKey = () => \"energy_swirl\";\n // Vanilla submits the swirl with half-grey vertex colour.\n material.color.set(0x808080);\n break;\n case \"water_mask\":\n material.alphaTest = 0;\n material.colorWrite = false;\n break;\n }\n if (Materials.entityModeScroll(mode)) {\n material.map!.wrapS = material.map!.wrapT = RepeatWrapping;\n }\n if (tint !== undefined) material.color.multiply(new Color(tint));\n return material;\n }\n\n /** Creates an unlit, transparent GUI material without depth writes or tone mapping. */\n public static createGuiCanvasMaterial(canvas: HTMLCanvasElement): MeshBasicMaterial {\n const material = new MeshBasicMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: true,\n depthWrite: false,\n side: DoubleSide,\n toneMapped: false\n });\n material.onBeforeCompile = shader => {\n // Keep MSAA edge pixels inside the layer's cropped texture region.\n for (const [stage, direction] of [[\"vertex\", \"out\"], [\"fragment\", \"in\"]] as const) {\n const chunk = `uv_pars_${stage}` as const;\n shader[`${stage}Shader`] = shader[`${stage}Shader`].replace(`#include <${chunk}>`,\n ShaderChunk[chunk].replace(\"varying vec2 vMapUv;\", `\n #if __VERSION__ >= 300\n centroid ${direction} vec2 vMapUv;\n #else\n varying vec2 vMapUv;\n #endif\n `));\n }\n };\n return material;\n }\n\n public static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent: boolean = false, shade:boolean=false, boundUvs: boolean = false):Material {\n //TODO\n // this might help https://github.com/JannisX11/blockbench/blob/1701f764641376414d29100c4f6c7cd74997fad8/js/preview/canvas.js#L62\n\n\n // Based on https://github.com/JannisX11/blockbench/blob/cc73aa8a9c0494fd9fe1cee4d062d060af4db06d/js/texturing/textures.js#L59\n // + support for instanced meshes\n const vertShader =`\n uniform bool SHADE;\n attribute float shade;\n \n // Keep MSAA edge pixels from sampling outside the face's atlas region.\n #if __VERSION__ >= 300\n centroid out vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n #ifdef BOUND_UVS\n attribute vec4 uvBounds;\n flat out vec4 vUvBounds;\n #endif\n varying vec3 vTint;\n varying float light;\n varying float lift;\n\n float AMBIENT = 0.5;\n float XFAC = -0.15;\n float ZFAC = 0.05;\n\n void main()\n {\n\n if (SHADE && shade > 0.5) {\n\n #ifdef USE_INSTANCING\n vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );\n #else\n vec3 N = vec3( modelMatrix * vec4(normal, 0.0) );\n #endif\n\n float yLight = (1.0+N.y) * 0.5;\n light = yLight * (1.0-AMBIENT) + N.x*N.x * XFAC + N.z*N.z * ZFAC + AMBIENT;\n\n } else {\n\n light = 1.0;\n\n } \n\n if (color.b > 1.1) {\n lift = 0.1;\n } else {\n lift = 0.0;\n }\n \n vUv = uv;\n #ifdef BOUND_UVS\n vUvBounds = uvBounds;\n #endif\n vTint = color;\n \n vec4 mvPosition = vec4(position, 1.0);\n #ifdef USE_INSTANCING\n mvPosition = instanceMatrix * mvPosition;\n #endif\n mvPosition = modelViewMatrix * mvPosition;\n gl_Position = projectionMatrix * mvPosition;\n \n }\n `\n const fragShader = `\n #ifdef GL_ES\n precision highp float;\n #endif\n\n uniform sampler2D map;\n\n uniform bool SHADE;\n uniform bool EMISSIVE;\n uniform float BRIGHTNESS;\n\n #if __VERSION__ >= 300\n centroid in vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n #ifdef BOUND_UVS\n flat in vec4 vUvBounds;\n #endif\n varying vec3 vTint;\n varying float light;\n varying float lift;\n\n void main(void)\n {\n #ifdef BOUND_UVS\n // Keep edge samples inside their texture even without centroid interpolation.\n vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);\n #else\n vec2 mapUv = vUv;\n #endif\n vec4 color = texture2D(map, mapUv);\n color.rgb *= vTint;\n \n if (color.a < 0.01) discard;\n\n if (EMISSIVE == false) {\n\n gl_FragColor = vec4(lift + color.rgb * light * BRIGHTNESS, color.a);\n\n } else {\n\n float light2 = (light * BRIGHTNESS) + (1.0 - light * BRIGHTNESS) * (1.0 - color.a);\n gl_FragColor = vec4(lift + color.rgb * light2, 1.0);\n\n }\n\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n }\n `\n //TODO: this does add the MC-like shading, but breaks when stuff is instanced (can't updated position)\n // https://medium.com/@pailhead011/instancing-with-three-js-part-2-3be34ae83c57 might help with that\n\n try {\n const material = new ShaderMaterial({\n defines: boundUvs ? { BOUND_UVS: true } : {},\n uniforms: {\n SHADE: { value: true },\n BRIGHTNESS: { value: 1 },\n EMISSIVE:{value:false},\n base: { value: new Color(0xc1c1c1)/*TODO*/ },\n map: {value:Textures.createCanvasTexture(canvas)}\n },\n vertexShader: vertShader,\n fragmentShader: fragShader,\n vertexColors: true,\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n });\n Object.assign(material.defaultAttributeValues, { shade: [1], uvBounds: [0, 0, 1, 1] });\n return material;\n } catch (e) {\n log.warn(e)\n }\n\n // fallback\n return this.createBasicCanvasMaterial(canvas, transparent, shade);\n }\n\n /** Returns a shared image material. Use {@link createImage} for a separate material instance. */\n public static getImage(key: MaterialKey): Material {\n const keyStr = serializeMaterialKey(key);\n const map = (Caching.materialCache.peek(keyStr) as MeshBasicMaterial | undefined)?.map;\n if (map && TextureLoader.hasFailed(map)) {\n Caching.materialCache.invalidate(keyStr);\n }\n return Caching.materialCache.get(keyStr, k => {\n return Materials.createImage(key);\n })!;\n }\n\n public static needsUpdate(mat: Material) {\n mat.needsUpdate = true;\n\n if (mat.type === 'ShaderMaterial') {\n let mat1=mat as ShaderMaterial;\n if (\"map\" in mat1.uniforms) {\n mat1.uniforms.map.value.needsUpdate = true;\n }\n }\n if (mat.type === 'MeshBasicMaterial' || mat.type === 'MeshStandardMaterial') {\n let mat1 = mat as (MeshBasicMaterial | MeshStandardMaterial);\n if (mat1.map) {\n mat1.map.needsUpdate = true;\n }\n }\n }\n\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// src/Ticker.ts
|
|
2
|
+
import { logger } from "./util/log.mjs";
|
|
3
|
+
var log = logger("Ticker");
|
|
2
4
|
var _Ticker = class _Ticker {
|
|
3
5
|
static schedule(fn, ms) {
|
|
4
6
|
const handle = setInterval(fn, ms);
|
|
@@ -16,7 +18,7 @@ var _Ticker = class _Ticker {
|
|
|
16
18
|
try {
|
|
17
19
|
t();
|
|
18
20
|
} catch (e) {
|
|
19
|
-
|
|
21
|
+
log.warn(e);
|
|
20
22
|
}
|
|
21
23
|
});
|
|
22
24
|
_Ticker.oneSecondTicks++;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/Ticker.ts"],"sourcesContent":["/** A synchronous callback registered with {@link Ticker.add}. */\nexport interface TickerFunction {\n (): void;\n}\n\ntype IntervalHandle = ReturnType<typeof setInterval>;\n\n/**\n * Shared 20-per-second tick loop, used for things like animated texture frames.\n *\n * The timers are started lazily by {@link Ticker.add} and unref'd where the platform supports it -\n * importing MineRender must never on its own keep a Node process alive.\n */\nexport class Ticker {\n\n public static readonly TPS = 20;\n\n private static counter: number = 0;\n private static readonly _tickers: Map<number, TickerFunction> = new Map<number, TickerFunction>();\n\n private static interval: IntervalHandle | undefined;\n private static oneSecondTicksTracker: IntervalHandle | undefined;\n private static fiveSecondTicksTracker: IntervalHandle | undefined;\n\n private static oneSecondTps = 0;\n private static oneSecondTicks = 0;\n\n private static fiveSecondTps = 0;\n private static fiveSecondTicks = 0;\n\n private static schedule(fn: () => void, ms: number): IntervalHandle {\n const handle = setInterval(fn, ms);\n // Node's Timeout keeps the event loop alive unless unref'd; browsers return a plain number\n const unref = (handle as { unref?: () => void }).unref;\n if (typeof unref === \"function\") {\n unref.call(handle);\n }\n return handle;\n }\n\n /** Starts or resumes the shared tick loop. Repeated calls have no effect. */\n public static start(): void {\n if (this.interval) return;\n\n this.interval = this.schedule(() => {\n Ticker._tickers.forEach(t => {\n try {\n t();\n } catch (e) {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/Ticker.ts"],"sourcesContent":["import { logger } from \"./util/log\";\n\nconst log = logger(\"Ticker\");\n\n/** A synchronous callback registered with {@link Ticker.add}. */\nexport interface TickerFunction {\n (): void;\n}\n\ntype IntervalHandle = ReturnType<typeof setInterval>;\n\n/**\n * Shared 20-per-second tick loop, used for things like animated texture frames.\n *\n * The timers are started lazily by {@link Ticker.add} and unref'd where the platform supports it -\n * importing MineRender must never on its own keep a Node process alive.\n */\nexport class Ticker {\n\n public static readonly TPS = 20;\n\n private static counter: number = 0;\n private static readonly _tickers: Map<number, TickerFunction> = new Map<number, TickerFunction>();\n\n private static interval: IntervalHandle | undefined;\n private static oneSecondTicksTracker: IntervalHandle | undefined;\n private static fiveSecondTicksTracker: IntervalHandle | undefined;\n\n private static oneSecondTps = 0;\n private static oneSecondTicks = 0;\n\n private static fiveSecondTps = 0;\n private static fiveSecondTicks = 0;\n\n private static schedule(fn: () => void, ms: number): IntervalHandle {\n const handle = setInterval(fn, ms);\n // Node's Timeout keeps the event loop alive unless unref'd; browsers return a plain number\n const unref = (handle as { unref?: () => void }).unref;\n if (typeof unref === \"function\") {\n unref.call(handle);\n }\n return handle;\n }\n\n /** Starts or resumes the shared tick loop. Repeated calls have no effect. */\n public static start(): void {\n if (this.interval) return;\n\n this.interval = this.schedule(() => {\n Ticker._tickers.forEach(t => {\n try {\n t();\n } catch (e) {\n log.warn(e);\n }\n });\n Ticker.oneSecondTicks++;\n Ticker.fiveSecondTicks++;\n }, 1000 / this.TPS);\n\n this.oneSecondTicksTracker = this.schedule(() => {\n Ticker.oneSecondTps = Ticker.oneSecondTicks;\n Ticker.oneSecondTicks = 0;\n }, 1000);\n\n this.fiveSecondTicksTracker = this.schedule(() => {\n Ticker.fiveSecondTps = Ticker.fiveSecondTicks / 5;\n Ticker.fiveSecondTicks = 0;\n }, 1000 * 5);\n }\n\n /** Pauses the loop while retaining callbacks for a later {@link start}. */\n public static stop(): void {\n if (this.interval) clearInterval(this.interval);\n if (this.oneSecondTicksTracker) clearInterval(this.oneSecondTicksTracker);\n if (this.fiveSecondTicksTracker) clearInterval(this.fiveSecondTicksTracker);\n this.interval = undefined;\n this.oneSecondTicksTracker = undefined;\n this.fiveSecondTicksTracker = undefined;\n }\n\n /** Registers a callback, starts the loop if needed, and returns an ID for {@link remove}. */\n public static add(tick: TickerFunction): number {\n this.start();\n const c = this.counter++;\n this._tickers.set(c, tick);\n return c;\n }\n\n /** Removes a callback by ID and stops the timers when no callbacks remain. */\n public static remove(c?: number) {\n // note: plain `if (c)` used to drop id 0, i.e. the very first registered ticker\n if (typeof c === \"number\") this._tickers.delete(c);\n if (!this._tickers.size) this.stop();\n }\n\n public static get tickers(): Map<number, TickerFunction> {\n return this._tickers;\n }\n\n public static get tpsOneSecond() {\n return this.oneSecondTps;\n }\n\n public static get tpsFiveSeconds() {\n return this.fiveSecondTps;\n }\n\n /** Stops the loop and removes all registered callbacks. */\n public static dispose() {\n this.stop();\n this._tickers.clear();\n }\n\n}\n"],"mappings":";AAAA,SAAS,cAAc;AAEvB,IAAM,MAAM,OAAO,QAAQ;AAepB,IAAM,UAAN,MAAM,QAAO;AAAA,EAiBhB,OAAe,SAAS,IAAgB,IAA4B;AAChE,UAAM,SAAS,YAAY,IAAI,EAAE;AAEjC,UAAM,QAAS,OAAkC;AACjD,QAAI,OAAO,UAAU,YAAY;AAC7B,YAAM,KAAK,MAAM;AAAA,IACrB;AACA,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,OAAc,QAAc;AACxB,QAAI,KAAK,SAAU;AAEnB,SAAK,WAAW,KAAK,SAAS,MAAM;AAChC,cAAO,SAAS,QAAQ,OAAK;AACzB,YAAI;AACA,YAAE;AAAA,QACN,SAAS,GAAG;AACR,cAAI,KAAK,CAAC;AAAA,QACd;AAAA,MACJ,CAAC;AACD,cAAO;AACP,cAAO;AAAA,IACX,GAAG,MAAO,KAAK,GAAG;AAElB,SAAK,wBAAwB,KAAK,SAAS,MAAM;AAC7C,cAAO,eAAe,QAAO;AAC7B,cAAO,iBAAiB;AAAA,IAC5B,GAAG,GAAI;AAEP,SAAK,yBAAyB,KAAK,SAAS,MAAM;AAC9C,cAAO,gBAAgB,QAAO,kBAAkB;AAChD,cAAO,kBAAkB;AAAA,IAC7B,GAAG,MAAO,CAAC;AAAA,EACf;AAAA;AAAA,EAGA,OAAc,OAAa;AACvB,QAAI,KAAK,SAAU,eAAc,KAAK,QAAQ;AAC9C,QAAI,KAAK,sBAAuB,eAAc,KAAK,qBAAqB;AACxE,QAAI,KAAK,uBAAwB,eAAc,KAAK,sBAAsB;AAC1E,SAAK,WAAW;AAChB,SAAK,wBAAwB;AAC7B,SAAK,yBAAyB;AAAA,EAClC;AAAA;AAAA,EAGA,OAAc,IAAI,MAA8B;AAC5C,SAAK,MAAM;AACX,UAAM,IAAI,KAAK;AACf,SAAK,SAAS,IAAI,GAAG,IAAI;AACzB,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,OAAc,OAAO,GAAY;AAE7B,QAAI,OAAO,MAAM,SAAU,MAAK,SAAS,OAAO,CAAC;AACjD,QAAI,CAAC,KAAK,SAAS,KAAM,MAAK,KAAK;AAAA,EACvC;AAAA,EAEA,WAAkB,UAAuC;AACrD,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,WAAkB,eAAe;AAC7B,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,WAAkB,iBAAiB;AAC/B,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAGA,OAAc,UAAU;AACpB,SAAK,KAAK;AACV,SAAK,SAAS,MAAM;AAAA,EACxB;AAEJ;AAjGa,QAEc,MAAM;AAFpB,QAIM,UAAkB;AAJxB,QAKe,WAAwC,oBAAI,IAA4B;AALvF,QAWM,eAAe;AAXrB,QAYM,iBAAiB;AAZvB,QAcM,gBAAgB;AAdtB,QAeM,kBAAkB;AAf9B,IAAM,SAAN;","names":[]}
|
|
@@ -9,9 +9,9 @@ import { Caching } from "./cache/Caching.mjs";
|
|
|
9
9
|
import { Textures } from "./texture/Textures.mjs";
|
|
10
10
|
import { AssetKey } from "./assets/AssetKey.mjs";
|
|
11
11
|
import { ModelGenerator } from "./model/ModelGenerator.mjs";
|
|
12
|
-
import {
|
|
12
|
+
import { logger } from "./util/log.mjs";
|
|
13
13
|
import { DEFAULT_UV, makeUv, makeUvCoords, setFaceUvInArray, setCubeFaceUvInArray, addCubeFaceUvToArray, facesToUvArray } from "./util/_internal/cubeUv.mjs";
|
|
14
|
-
var
|
|
14
|
+
var log = logger("UVMapper");
|
|
15
15
|
var X = 0;
|
|
16
16
|
var Y = 1;
|
|
17
17
|
var Z = 2;
|
|
@@ -244,7 +244,7 @@ var UVMapper = class {
|
|
|
244
244
|
model.elements = originalModel.elements.map((element) => ({ ...element }));
|
|
245
245
|
}
|
|
246
246
|
const isItemModel = !("elements" in model);
|
|
247
|
-
|
|
247
|
+
log.debug("Creating Atlas for", model.key);
|
|
248
248
|
if (model.textures) {
|
|
249
249
|
const promises = [];
|
|
250
250
|
const uniqueTextureNames = [];
|
|
@@ -258,7 +258,7 @@ var UVMapper = class {
|
|
|
258
258
|
const assetKey = AssetKey.parse("textures", textureValue, model.key);
|
|
259
259
|
promises.push(ModelTextures.get(assetKey).then((asset) => {
|
|
260
260
|
if (!asset) {
|
|
261
|
-
|
|
261
|
+
log.warn("Missing texture", assetKey);
|
|
262
262
|
return;
|
|
263
263
|
}
|
|
264
264
|
textureMap[textureKey] = new WrappedImage(asset);
|
|
@@ -270,7 +270,7 @@ var UVMapper = class {
|
|
|
270
270
|
}
|
|
271
271
|
await Promise.all(promises);
|
|
272
272
|
const textureCount = uniqueTextureNames.length;
|
|
273
|
-
|
|
273
|
+
log.debug("Creating Atlas for", textureCount, "textures");
|
|
274
274
|
this.fillMissingTextureKeys(model.textures, textureMap);
|
|
275
275
|
this.fillMissingTextureKeys(model.textures, metaMap);
|
|
276
276
|
const sizes = {};
|
|
@@ -301,7 +301,7 @@ var UVMapper = class {
|
|
|
301
301
|
this.fillMissingTextureKeys(model.textures, sizes);
|
|
302
302
|
const s = Math.ceil(Math.sqrt(textureCount + 1));
|
|
303
303
|
const size = Math.ceil(s * maxWidth);
|
|
304
|
-
|
|
304
|
+
log.debug("Atlas size:", size);
|
|
305
305
|
const squaredSize = size * size;
|
|
306
306
|
const image = new CanvasImage(size, size);
|
|
307
307
|
const missing = Textures.getMissing().image;
|
|
@@ -380,7 +380,7 @@ var UVMapper = class {
|
|
|
380
380
|
}
|
|
381
381
|
this.fillMissingTextureKeys(model.textures, positions);
|
|
382
382
|
if (isItemModel) {
|
|
383
|
-
|
|
383
|
+
log.debug("Generating item model for", model);
|
|
384
384
|
model.elements = [];
|
|
385
385
|
for (let layerName of ModelGenerator.ITEM_LAYERS) {
|
|
386
386
|
const textureImage = textureMap[layerName];
|
|
@@ -396,7 +396,7 @@ var UVMapper = class {
|
|
|
396
396
|
), layerName));
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
|
-
|
|
399
|
+
log.debug("Item model elements", model.elements);
|
|
400
400
|
}
|
|
401
401
|
if (!model.elements) {
|
|
402
402
|
}
|
|
@@ -453,7 +453,7 @@ var UVMapper = class {
|
|
|
453
453
|
hasTranslucency
|
|
454
454
|
);
|
|
455
455
|
} else {
|
|
456
|
-
|
|
456
|
+
log.warn("Model does not have any textures", model);
|
|
457
457
|
}
|
|
458
458
|
return void 0;
|
|
459
459
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/UVMapper.ts"],"sourcesContent":["import { BoxGeometry, BufferAttribute, Euler, Float32BufferAttribute, Vector2, Vector3, Vector4 } from \"three\";\nimport { DoubleArray, Model, QuadArray, TextureAsset } from \"./model/Model\";\nimport { ModelElement, ModelFaces } from \"./model/ModelElement\";\nimport { CUBE_FACES, CubeFace } from \"./CubeFace\";\nimport { ModelTextures } from \"./assets/ModelTextures\";\nimport { Assets } from \"./assets/Assets\";\nimport { Maybe, toRadians } from \"./util/util\";\nimport { WrappedImage } from \"./WrappedImage\";\nimport { CanvasImage } from \"./canvas/CanvasImage\";\nimport { TextureAtlas } from \"./texture/TextureAtlas\";\nimport { Caching } from \"./cache/Caching\";\nimport { Textures } from \"./texture/Textures\";\nimport { AnimatorFunction } from \"./AnimatorFunction\";\nimport { MinecraftTextureMeta } from \"./MinecraftTextureMeta\";\nimport { AssetKey } from \"./assets/AssetKey\";\nimport { ModelGenerator } from \"./model/ModelGenerator\";\nimport { prefix } from \"./util/log\";\nimport { DEFAULT_UV, makeUv, makeUvCoords, setFaceUvInArray, setCubeFaceUvInArray, addCubeFaceUvToArray, facesToUvArray } from \"./util/_internal/cubeUv\";\n\nconst p = prefix(\"UVMapper\");\n\nexport { DEFAULT_UV };\nconst X = 0;\nconst Y = 1;\nconst Z = 2;\n\n// Each face's right/down axes in Minecraft's top-origin UV coordinates.\nconst FACE_UV_AXES: Record<CubeFace, [Vector3, Vector3]> = {\n east: [new Vector3(0, 0, -1), new Vector3(0, -1, 0)],\n west: [new Vector3(0, 0, 1), new Vector3(0, -1, 0)],\n up: [new Vector3(1, 0, 0), new Vector3(0, 0, 1)],\n down: [new Vector3(1, 0, 0), new Vector3(0, 0, -1)],\n south: [new Vector3(1, 0, 0), new Vector3(0, -1, 0)],\n north: [new Vector3(-1, 0, 0), new Vector3(0, -1, 0)]\n};\n\n/*\n * - Minecraft Block UVs are from the top-left to bottom-right\n * - three.js UVs are from the bottom-left to top-right\n * - canvas coordinates are from the top-left to bottom-right\n */\n\n// noinspection PointlessArithmeticExpressionJS\n/** Maps Minecraft face coordinates to Three.js UVs and builds per-model texture atlases. */\nexport class UVMapper {\n\n protected static makeUv(uvCoord: number, originalTextureSize: number, actualTextureSize: number): number {\n return makeUv(uvCoord, originalTextureSize, actualTextureSize);\n }\n\n protected static makeUvCoords([originalTextureWidth, originalTextureHeight]: DoubleArray, [actualTextureWidth, actualTextureHeight]: DoubleArray, [x1, y1, x2, y2]: QuadArray): QuadArray {\n return makeUvCoords([originalTextureWidth, originalTextureHeight], [actualTextureWidth, actualTextureHeight], [x1, y1, x2, y2]);\n }\n\n\n public static rotateSingleUv([u, v]: DoubleArray, [px, py]: DoubleArray, radians: number): DoubleArray {\n const sin = Math.sin(radians);\n const cos = Math.cos(radians);\n\n u -= px;\n v -= py;\n\n const uc = u;\n const vc = v;\n\n u = cos * uc - sin * vc;\n v = cos * vc + sin * uc;\n\n u += px;\n v += py;\n\n // return [parseFloat(u.toFixed(8)), parseFloat(v.toFixed(8))];\n return [u, v];\n }\n\n public static addCubeFaceUvToArray(array: number[], faceIndex: number, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, originalCoords: QuadArray) {\n return addCubeFaceUvToArray(array, faceIndex, originalTextureSize, actualTextureSize, originalCoords);\n }\n\n public static setCubeFaceUvInArray(array: number[], faceIndex: number, [u1, v1, u2, v2]: QuadArray) {\n return setCubeFaceUvInArray(array, faceIndex, [u1, v1, u2, v2]);\n }\n\n public static setFaceUvInArrayV(array: number[], faceIndex: number, uvs: QuadArray<Vector2>) {\n array[((faceIndex + 0) * 2) + 0] = uvs[0].x;\n array[((faceIndex + 0) * 2) + 1] = uvs[0].y;\n\n array[((faceIndex + 1) * 2) + 0] = uvs[1].x;\n array[((faceIndex + 1) * 2) + 1] = uvs[1].y;\n\n array[((faceIndex + 2) * 2) + 0] = uvs[2].x;\n array[((faceIndex + 2) * 2) + 1] = uvs[2].y;\n\n array[((faceIndex + 3) * 2) + 0] = uvs[3].x;\n array[((faceIndex + 3) * 2) + 1] = uvs[3].y;\n }\n\n public static setFaceUvInArray(array: number[], faceIndex: number, uvs: QuadArray<DoubleArray>) {\n return setFaceUvInArray(array, faceIndex, uvs);\n }\n\n public static setCubeFaceUvAttribute(attributes: BufferAttribute, faceIndex: number, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, originalCoords: QuadArray): void {\n const uv = this.makeUvCoords(originalTextureSize, actualTextureSize, originalCoords);\n this.setCubeFaceUvInAttribute(attributes, faceIndex, uv);\n }\n\n public static setCubeFaceUvInAttribute(attributes: BufferAttribute, faceIndex: number, [u1, v1, u2, v2]: QuadArray) {\n attributes.setXY(faceIndex + 0, u1, v1);\n attributes.setXY(faceIndex + 1, u2, v1);\n attributes.setXY(faceIndex + 2, u1, v2);\n attributes.setXY(faceIndex + 3, u2, v2);\n }\n\n public static setCubeUvs(geometry: BoxGeometry, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, faces: ModelFaces): void {\n const attributes = geometry.getAttribute(\"uv\") as BufferAttribute;\n for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {\n let faceName = CUBE_FACES[faceIndex];\n let face = faces[faceName];\n if (!face) continue;\n if (!face.uv) {\n face.uv = DEFAULT_UV;\n }\n\n this.setCubeFaceUvAttribute(attributes, faceIndex * 4, originalTextureSize, actualTextureSize, face.uv);\n }\n }\n\n public static facesToUvArray(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): number[] {\n return facesToUvArray(faces, originalTextureSize, actualTextureSize);\n }\n\n public static facesToUv(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): Float32BufferAttribute {\n return new Float32BufferAttribute(this.facesToUvArray(faces, originalTextureSize, actualTextureSize), 2);\n }\n\n /** Bounds texture sampling to texel centres without changing cropped face UVs. */\n public static setAtlasUvBounds(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas): void {\n const uv = geometry.getAttribute(\"uv\");\n const bounds = new Float32Array(uv.count * 4);\n for (const [faceIndex, faceName] of CUBE_FACES.entries()) {\n const texture = faces[faceName]?.texture?.substring(1);\n const position = texture && atlas.positions[texture];\n const size = texture && atlas.sizes[texture];\n let minU = Infinity, minV = Infinity, maxU = -Infinity, maxV = -Infinity;\n if (position && size) {\n minU = position[0] / atlas.image.width;\n maxU = (position[0] + size[0]) / atlas.image.width;\n minV = 1 - (position[1] + size[1]) / atlas.image.height;\n maxV = 1 - position[1] / atlas.image.height;\n } else {\n for (let corner = 0; corner < 4; corner++) {\n const index = faceIndex * 4 + corner;\n minU = Math.min(minU, uv.getX(index));\n minV = Math.min(minV, uv.getY(index));\n maxU = Math.max(maxU, uv.getX(index));\n maxV = Math.max(maxV, uv.getY(index));\n }\n }\n const insetU = Math.min(0.5 / atlas.image.width, (maxU - minU) / 2);\n const insetV = Math.min(0.5 / atlas.image.height, (maxV - minV) / 2);\n for (let corner = 0; corner < 4; corner++) {\n bounds.set([minU + insetU, minV + insetV, maxU - insetU, maxV - insetV], (faceIndex * 4 + corner) * 4);\n }\n }\n geometry.setAttribute(\"uvBounds\", new Float32BufferAttribute(bounds, 4));\n }\n\n public static lockUvs(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas, rotation: Euler): void {\n const uv = geometry.getAttribute(\"uv\") as BufferAttribute;\n for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {\n const faceName = CUBE_FACES[faceIndex];\n const texture = faces[faceName]?.texture?.substring(1);\n const position = texture && atlas.positions[texture];\n const size = texture && atlas.sizes[texture];\n if (!position || !size) continue;\n\n const [sourceU, sourceV] = FACE_UV_AXES[faceName];\n const uAxis = sourceU.clone().applyEuler(rotation);\n const vAxis = sourceV.clone().applyEuler(rotation);\n const normal = vAxis.clone().cross(uAxis);\n const targetFace = CUBE_FACES.find(name => {\n const [u, v] = FACE_UV_AXES[name];\n return v.clone().cross(u).dot(normal) > 0.5;\n })!;\n const [targetU, targetV] = FACE_UV_AXES[targetFace];\n const uu = Math.round(targetU.dot(uAxis));\n const uvCross = Math.round(targetU.dot(vAxis));\n const vu = Math.round(targetV.dot(uAxis));\n const vv = Math.round(targetV.dot(vAxis));\n\n // Rotate about the full texture center, not the cropped face or atlas center.\n for (let corner = 0; corner < 4; corner++) {\n const index = faceIndex * 4 + corner;\n const u = (uv.getX(index) * atlas.image.width - position[0]) / size[0] - 0.5;\n const v = ((1 - uv.getY(index)) * atlas.image.height - position[1]) / size[1] - 0.5;\n const lockedU = uu * u + uvCross * v + 0.5;\n const lockedV = vu * u + vv * v + 0.5;\n uv.setXY(index,\n (position[0] + lockedU * size[0]) / atlas.image.width,\n 1 - (position[1] + lockedV * size[1]) / atlas.image.height);\n }\n }\n uv.needsUpdate = true;\n }\n\n /** Returns the shared atlas for a keyed, merged model, creating it on first use. */\n public static async getAtlas(model: Model): Promise<Maybe<TextureAtlas>> {\n const keyStr = model.key!.serialize();\n return Caching.modelTextureAtlasCache.get(keyStr, k => {\n return this.createAtlas(model);\n })\n }\n\n public static fillMissingTextureKeys<T>(textures: ModelTextures, target: { [k: string]: T }): { [k: string]: T } {\n for (const key in textures) {\n // Follow references such as \"#all\" -> \"#texture\" to the variable that names a texture.\n let name = key;\n const seen = new Set<string>();\n while (textures[name]?.startsWith(\"#\") && !seen.has(name)) {\n seen.add(name);\n name = textures[name].substr(1);\n }\n if (name !== key) target[key] = target[name];\n }\n return target;\n }\n\n // https://yeleha.co/3qlboGS\n protected static getFallbackUv(element: ModelElement, faceName: CubeFace): QuadArray {\n switch (faceName) {\n case CubeFace.DOWN:\n return [element.from[X], 16 - element.to[Z], element.to[X], 16 - element.from[Z]];\n case CubeFace.UP:\n return [element.from[X], element.from[Z], element.to[X], element.to[Z]];\n case CubeFace.NORTH:\n default:\n return [16 - element.to[X], 16 - element.to[Y], 16 - element.from[X], 16 - element.from[Y]];\n case CubeFace.SOUTH:\n return [element.from[X], 16 - element.to[Y], element.to[X], 16 - element.from[Y]];\n case CubeFace.WEST:\n return [element.from[Z], 16 - element.to[Y], element.to[Z], 16 - element.from[Y]];\n case CubeFace.EAST:\n return [16 - element.to[Z], 16 - element.to[Y], 16 - element.from[Z], 16 - element.from[Y]];\n }\n }\n\n protected static expandAndRotateMcUvs([u1, v1, u2, v2]: QuadArray, rotation: number = 0, actualWidth: number, actualHeight: number): QuadArray<Vector2> {\n // Resize coordinates to actual texture size\n const scaleU = actualWidth / 16;\n const scaleV = actualHeight / 16;\n u1 *= scaleU;\n v1 *= scaleV;\n u2 *= scaleU;\n v2 *= scaleV;\n\n let tl: Vector2 = new Vector2(u1, v1);// top left\n let tr: Vector2 = new Vector2(u2, v1);// top right\n let bl: Vector2 = new Vector2(u1, v2);// bottom left\n let br: Vector2 = new Vector2(u2, v2);// bottom right\n\n switch (rotation) {\n case 0:\n case 360:\n default:\n break;\n case 90:\n tl = new Vector2(u1, v2);\n tr = new Vector2(u1, v1);\n bl = new Vector2(u2, v2);\n br = new Vector2(u2, v1);\n break;\n case 180:\n tl = new Vector2(u2, v2);\n tr = new Vector2(u1, v2);\n bl = new Vector2(u2, v1);\n br = new Vector2(u1, v1);\n break;\n case 270:\n tl = new Vector2(u2, v1);\n tr = new Vector2(u2, v2);\n bl = new Vector2(u1, v1);\n br = new Vector2(u1, v2);\n break;\n }\n\n return [tl, tr, bl, br];\n }\n\n /**\n * Combines model textures and animation metadata into an atlas.\n * Mapped UVs are stored on copies of the model's elements, available through the returned atlas.\n * Returns `undefined` for models without a texture map.\n */\n public static async createAtlas(originalModel: Model): Promise<Maybe<TextureAtlas>> {\n const textureMap: { [key: string]: Maybe<WrappedImage>; } = {};\n const metaMap: { [key: string]: Maybe<MinecraftTextureMeta>; } = {};\n const model = {...originalModel};\n // Merged models share element objects with their cached parents (cube, cube_all, ...), so the\n // baked UVs below must go onto this atlas's own copies, not onto objects other atlases read.\n if (originalModel.elements) {\n model.elements = originalModel.elements.map(element => ({ ...element }));\n }\n const isItemModel = !(\"elements\" in model);\n\n console.debug(p, \"Creating Atlas for\", model.key);\n\n if (model.textures) {\n const promises: Promise<void>[] = [];\n const uniqueTextureNames: string[] = []; // TODO: make these actually unique\n const textureReferences: { [k: string]: string; } = {};\n for (let textureKey in model.textures) {\n let textureValue = model.textures[textureKey];\n if (textureValue.startsWith(\"#\")) {\n textureReferences[textureKey] = textureValue.substr(1);\n } else {\n uniqueTextureNames.push(textureKey);\n const assetKey = AssetKey.parse(\"textures\", textureValue, model.key);\n promises.push(ModelTextures.get(assetKey).then(asset => {\n if (!asset) {\n console.warn(p, \"Missing texture\", assetKey)\n return;\n }\n textureMap[textureKey] = new WrappedImage(asset);\n }));\n promises.push(ModelTextures.getMeta(assetKey).then(meta => {\n metaMap[textureKey] = meta;\n }))\n }\n }\n await Promise.all(promises);\n const textureCount = uniqueTextureNames.length;\n console.debug(p, \"Creating Atlas for\", textureCount, \"textures\");\n // console.log(model.textures)\n\n this.fillMissingTextureKeys(model.textures, textureMap);\n this.fillMissingTextureKeys(model.textures, metaMap);\n\n const sizes: { [texture: string]: DoubleArray; } = {};\n const frames: { [texture: string]: { index: number; time: number }[] } = {};\n\n // Find largest texture dimensions\n let maxWidth = 0;\n for (let textureKey of uniqueTextureNames) {\n let texture = textureMap[textureKey];\n if (!texture) continue;\n const animation = metaMap[textureKey]?.animation;\n let width = texture.width, height = texture.height;\n if (animation) {\n const square = Math.min(width, height);\n width = animation.width ?? (animation.height === undefined ? square : width);\n height = animation.height ?? (animation.width === undefined ? square : height);\n if (!Number.isInteger(width) || !Number.isInteger(height) || width <= 0 || height <= 0\n || texture.width % width || texture.height % height) {\n throw new RangeError(`Invalid animation frame dimensions for ${textureKey}`);\n }\n const count = (texture.width / width) * (texture.height / height);\n const time = animation.frametime ?? 1;\n frames[textureKey] = (animation.frames ?? Array.from({ length: count }, (_, index) => index))\n .map(frame => typeof frame === \"number\" ? { index: frame, time } : { index: frame.index, time: frame.time ?? time });\n if (!frames[textureKey].length || frames[textureKey].some(frame => !Number.isInteger(frame.index)\n || frame.index < 0 || frame.index >= count || !Number.isInteger(frame.time) || frame.time < 1)) {\n throw new RangeError(`Invalid animation frames for ${textureKey}`);\n }\n }\n sizes[textureKey] = [width, height];\n maxWidth = Math.max(maxWidth, width, height);\n }\n this.fillMissingTextureKeys(model.textures, sizes);\n\n // console.log(\"sizes\", sizes);\n\n const s = (Math.ceil(Math.sqrt(textureCount + 1))); // +1 for transparency\n const size = Math.ceil(s * maxWidth)\n console.debug(p, \"Atlas size:\", size);\n // console.log(\"size: \" + size);\n const squaredSize = size * size;\n\n const image = new CanvasImage(size, size);\n const missing = Textures.getMissing().image;\n const missingPixels = image.context.createImageData(missing.width, missing.height);\n missingPixels.data.set(missing.data!);\n image.putData(missingPixels, 0, 0);\n // The top-left atlas cell keeps absent model faces transparent.\n image.context.clearRect(0, 0, maxWidth, maxWidth);\n\n const positions: { [texture: string]: DoubleArray; } = {};\n\n let hasTransparency = false;\n let hasTranslucency = false;\n\n let hasAnimation = false;\n const animatorFunctions: { [texture: string]: AnimatorFunction; } = {};\n\n // Draw all textures onto a single image\n let tx = 1; // start one over to leave room for the transparent space\n let ty = 0;\n for (let textureIndex = 0; textureIndex < uniqueTextureNames.length; textureIndex++) {\n let textureKey = uniqueTextureNames[textureIndex];\n let texture = textureMap[textureKey];\n let x = tx * maxWidth;\n let y = ty * maxWidth;\n if (texture) {\n positions[textureKey] = [x, y];\n const [width, height] = sizes[textureKey];\n const sequence = frames[textureKey];\n const getFrameData = (index: number) => {\n const columns = texture!.width / width;\n return texture!.getSectionData((index % columns) * width,\n Math.floor(index / columns) * height, width, height);\n };\n const firstFrame = getFrameData(sequence?.[0].index ?? 0);\n image.putData(firstFrame, x, y);\n\n if (texture.hasTransparency) {\n hasTransparency = true;\n }\n if (texture.hasTranslucency) {\n hasTranslucency = true;\n }\n\n if (sequence && sequence.some(frame => frame.index !== sequence[0].index)) {\n hasAnimation = true;\n let t = 0;\n let f = 0;\n const interpolated = metaMap[textureKey]?.animation?.interpolate\n ? image.context.createImageData(width, height) : undefined;\n let currentFrame = firstFrame;\n let nextFrame = interpolated ? getFrameData(sequence[1].index) : firstFrame;\n\n animatorFunctions[textureKey] = () => {\n if (++t >= sequence[f].time) {\n t = 0;\n const previous = sequence[f].index;\n f = (f + 1) % sequence.length;\n if (interpolated) {\n currentFrame = nextFrame;\n nextFrame = getFrameData(sequence[(f + 1) % sequence.length].index);\n }\n if (sequence[f].index === previous) return false;\n image.putData(interpolated ? currentFrame : getFrameData(sequence[f].index), x, y);\n return true;\n }\n if (!interpolated || sequence[f].index === sequence[(f + 1) % sequence.length].index) return false;\n // Vanilla encodes the atlas shader's interpolation progress in thousandths.\n const progress = Math.floor(Math.fround(Math.fround(t / sequence[f].time) * 1000)) / 1000;\n for (let i = 0; i < interpolated.data.length; i++) {\n interpolated.data[i] = currentFrame.data[i] + (nextFrame.data[i] - currentFrame.data[i]) * progress;\n }\n image.putData(interpolated, x, y);\n return true;\n };\n }\n }\n tx++;\n if (tx >= s) {\n tx = 0;\n ty++;\n }\n }\n this.fillMissingTextureKeys(model.textures, positions);\n\n // console.log(\"positions\", positions);\n\n if (isItemModel) {\n console.debug(p, \"Generating item model for\", model);\n model.elements = [];\n for (let layerName of ModelGenerator.ITEM_LAYERS) {\n const textureImage = textureMap[layerName];\n if (textureImage) {\n // Outline the frame that was drawn into the atlas, not the whole animation strip.\n const [width, height] = sizes[layerName];\n const frame = frames[layerName]?.[0].index ?? 0;\n const columns = textureImage.width / width;\n model.elements.push(...ModelGenerator.generateItemModel(textureImage.getSectionData(\n (frame % columns) * width, Math.floor(frame / columns) * height, width, height), layerName))\n }\n }\n console.debug(p, \"Item model elements\", model.elements)\n }\n\n if (!model.elements) {\n //TODO: default elements\n }\n\n // Adjust UV positions\n if (model.elements) {\n for (let elementIndex = 0; elementIndex < model.elements.length; elementIndex++) {\n let element = model.elements[elementIndex];\n let uv: number[] = [];\n // Set default uvs to missing texture\n for (let i = 0; i < CUBE_FACES.length; i++) {\n this.setCubeFaceUvInArray(uv, i * 4, [0, 0, 8 / size, 8 / size])\n }\n for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {\n let faceName = CUBE_FACES[faceIndex];\n // console.log(faceName)\n let face = element.faces[faceName];\n if (!face) {\n // set uv transparent\n this.setCubeFaceUvInArray(uv, faceIndex * 4, [0, 1, 8 / size, (size - 8) / size])\n continue;\n }\n // Keep the missing-texture UVs when no texture is referenced.\n if (!face.texture) continue;\n if (!face.uv) {\n face.uv = this.getFallbackUv(element, faceName);\n }\n\n const faceTexture = face.texture.substr(1); // remove #\n const texPosition = positions[faceTexture] || [0, 0];\n const texSize = sizes[faceTexture] || [16, 16];\n\n let texPosV = new Vector2(texPosition[0], texPosition[1]);\n\n const [tl, tr, bl, br] = this.expandAndRotateMcUvs(face.uv, face.rotation, texSize[0], texSize[1]);\n\n // move to atlas position\n tl.add(texPosV);\n tr.add(texPosV);\n bl.add(texPosV);\n br.add(texPosV);\n\n // divide to 0-1\n tl.divideScalar(size);\n tr.divideScalar(size);\n bl.divideScalar(size);\n br.divideScalar(size);\n\n // flip y coordinates\n tl.y = 1 - tl.y;\n tr.y = 1 - tr.y;\n bl.y = 1 - bl.y;\n br.y = 1 - br.y;\n\n let uvs: QuadArray<Vector2> = [tl, tr, bl, br];\n // console.log(\"uvs\", uvs);\n this.setFaceUvInArrayV(uv, faceIndex * 4, uvs);\n }\n\n element.mappedUv = uv;\n }\n } else {\n //TODO: item model\n }\n\n return new TextureAtlas(\n model,\n image,\n sizes,\n positions,\n hasAnimation,\n animatorFunctions,\n hasTransparency,\n hasTranslucency\n );\n } else {\n console.warn(p, \"Model does not have any textures\", model);\n }\n return undefined;\n }\n\n}\n\n// Based on net.minecraft.client.renderer.block.model.BlockFaceUV\n/** Stores a Minecraft face's UV rectangle and its rotation in degrees. */\nexport class MinecraftFaceUV {\n\n constructor(readonly uv: QuadArray = [0, 0, 16, 16], readonly rotation: number = 0) {\n }\n\n getU(index: number): number {\n const shiftedIndex = this.getShiftedIndex(index);\n return this.uv[shiftedIndex !== 0 && index !== 1 ? 2 : 0];\n }\n\n getV(index: number): number {\n const shiftedIndex = this.getShiftedIndex(index);\n return this.uv[shiftedIndex !== 0 && index !== 3 ? 3 : 1];\n }\n\n protected getShiftedIndex(index: number): number {\n return (index + this.rotation / 90) % 40;\n }\n\n protected getReverseIndex(index: number): number {\n return (index + 4 - this.rotation / 90) % 4;\n }\n\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/UVMapper.ts"],"sourcesContent":["import { BoxGeometry, BufferAttribute, Euler, Float32BufferAttribute, Vector2, Vector3, Vector4 } from \"three\";\nimport { DoubleArray, Model, QuadArray, TextureAsset } from \"./model/Model\";\nimport { ModelElement, ModelFaces } from \"./model/ModelElement\";\nimport { CUBE_FACES, CubeFace } from \"./CubeFace\";\nimport { ModelTextures } from \"./assets/ModelTextures\";\nimport { Assets } from \"./assets/Assets\";\nimport { Maybe, toRadians } from \"./util/util\";\nimport { WrappedImage } from \"./WrappedImage\";\nimport { CanvasImage } from \"./canvas/CanvasImage\";\nimport { TextureAtlas } from \"./texture/TextureAtlas\";\nimport { Caching } from \"./cache/Caching\";\nimport { Textures } from \"./texture/Textures\";\nimport { AnimatorFunction } from \"./AnimatorFunction\";\nimport { MinecraftTextureMeta } from \"./MinecraftTextureMeta\";\nimport { AssetKey } from \"./assets/AssetKey\";\nimport { ModelGenerator } from \"./model/ModelGenerator\";\nimport { logger } from \"./util/log\";\nimport { DEFAULT_UV, makeUv, makeUvCoords, setFaceUvInArray, setCubeFaceUvInArray, addCubeFaceUvToArray, facesToUvArray } from \"./util/_internal/cubeUv\";\n\nconst log = logger(\"UVMapper\");\n\nexport { DEFAULT_UV };\nconst X = 0;\nconst Y = 1;\nconst Z = 2;\n\n// Each face's right/down axes in Minecraft's top-origin UV coordinates.\nconst FACE_UV_AXES: Record<CubeFace, [Vector3, Vector3]> = {\n east: [new Vector3(0, 0, -1), new Vector3(0, -1, 0)],\n west: [new Vector3(0, 0, 1), new Vector3(0, -1, 0)],\n up: [new Vector3(1, 0, 0), new Vector3(0, 0, 1)],\n down: [new Vector3(1, 0, 0), new Vector3(0, 0, -1)],\n south: [new Vector3(1, 0, 0), new Vector3(0, -1, 0)],\n north: [new Vector3(-1, 0, 0), new Vector3(0, -1, 0)]\n};\n\n/*\n * - Minecraft Block UVs are from the top-left to bottom-right\n * - three.js UVs are from the bottom-left to top-right\n * - canvas coordinates are from the top-left to bottom-right\n */\n\n// noinspection PointlessArithmeticExpressionJS\n/** Maps Minecraft face coordinates to Three.js UVs and builds per-model texture atlases. */\nexport class UVMapper {\n\n protected static makeUv(uvCoord: number, originalTextureSize: number, actualTextureSize: number): number {\n return makeUv(uvCoord, originalTextureSize, actualTextureSize);\n }\n\n protected static makeUvCoords([originalTextureWidth, originalTextureHeight]: DoubleArray, [actualTextureWidth, actualTextureHeight]: DoubleArray, [x1, y1, x2, y2]: QuadArray): QuadArray {\n return makeUvCoords([originalTextureWidth, originalTextureHeight], [actualTextureWidth, actualTextureHeight], [x1, y1, x2, y2]);\n }\n\n\n public static rotateSingleUv([u, v]: DoubleArray, [px, py]: DoubleArray, radians: number): DoubleArray {\n const sin = Math.sin(radians);\n const cos = Math.cos(radians);\n\n u -= px;\n v -= py;\n\n const uc = u;\n const vc = v;\n\n u = cos * uc - sin * vc;\n v = cos * vc + sin * uc;\n\n u += px;\n v += py;\n\n // return [parseFloat(u.toFixed(8)), parseFloat(v.toFixed(8))];\n return [u, v];\n }\n\n public static addCubeFaceUvToArray(array: number[], faceIndex: number, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, originalCoords: QuadArray) {\n return addCubeFaceUvToArray(array, faceIndex, originalTextureSize, actualTextureSize, originalCoords);\n }\n\n public static setCubeFaceUvInArray(array: number[], faceIndex: number, [u1, v1, u2, v2]: QuadArray) {\n return setCubeFaceUvInArray(array, faceIndex, [u1, v1, u2, v2]);\n }\n\n public static setFaceUvInArrayV(array: number[], faceIndex: number, uvs: QuadArray<Vector2>) {\n array[((faceIndex + 0) * 2) + 0] = uvs[0].x;\n array[((faceIndex + 0) * 2) + 1] = uvs[0].y;\n\n array[((faceIndex + 1) * 2) + 0] = uvs[1].x;\n array[((faceIndex + 1) * 2) + 1] = uvs[1].y;\n\n array[((faceIndex + 2) * 2) + 0] = uvs[2].x;\n array[((faceIndex + 2) * 2) + 1] = uvs[2].y;\n\n array[((faceIndex + 3) * 2) + 0] = uvs[3].x;\n array[((faceIndex + 3) * 2) + 1] = uvs[3].y;\n }\n\n public static setFaceUvInArray(array: number[], faceIndex: number, uvs: QuadArray<DoubleArray>) {\n return setFaceUvInArray(array, faceIndex, uvs);\n }\n\n public static setCubeFaceUvAttribute(attributes: BufferAttribute, faceIndex: number, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, originalCoords: QuadArray): void {\n const uv = this.makeUvCoords(originalTextureSize, actualTextureSize, originalCoords);\n this.setCubeFaceUvInAttribute(attributes, faceIndex, uv);\n }\n\n public static setCubeFaceUvInAttribute(attributes: BufferAttribute, faceIndex: number, [u1, v1, u2, v2]: QuadArray) {\n attributes.setXY(faceIndex + 0, u1, v1);\n attributes.setXY(faceIndex + 1, u2, v1);\n attributes.setXY(faceIndex + 2, u1, v2);\n attributes.setXY(faceIndex + 3, u2, v2);\n }\n\n public static setCubeUvs(geometry: BoxGeometry, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, faces: ModelFaces): void {\n const attributes = geometry.getAttribute(\"uv\") as BufferAttribute;\n for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {\n let faceName = CUBE_FACES[faceIndex];\n let face = faces[faceName];\n if (!face) continue;\n if (!face.uv) {\n face.uv = DEFAULT_UV;\n }\n\n this.setCubeFaceUvAttribute(attributes, faceIndex * 4, originalTextureSize, actualTextureSize, face.uv);\n }\n }\n\n public static facesToUvArray(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): number[] {\n return facesToUvArray(faces, originalTextureSize, actualTextureSize);\n }\n\n public static facesToUv(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): Float32BufferAttribute {\n return new Float32BufferAttribute(this.facesToUvArray(faces, originalTextureSize, actualTextureSize), 2);\n }\n\n /** Bounds texture sampling to texel centres without changing cropped face UVs. */\n public static setAtlasUvBounds(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas): void {\n const uv = geometry.getAttribute(\"uv\");\n const bounds = new Float32Array(uv.count * 4);\n for (const [faceIndex, faceName] of CUBE_FACES.entries()) {\n const texture = faces[faceName]?.texture?.substring(1);\n const position = texture && atlas.positions[texture];\n const size = texture && atlas.sizes[texture];\n let minU = Infinity, minV = Infinity, maxU = -Infinity, maxV = -Infinity;\n if (position && size) {\n minU = position[0] / atlas.image.width;\n maxU = (position[0] + size[0]) / atlas.image.width;\n minV = 1 - (position[1] + size[1]) / atlas.image.height;\n maxV = 1 - position[1] / atlas.image.height;\n } else {\n for (let corner = 0; corner < 4; corner++) {\n const index = faceIndex * 4 + corner;\n minU = Math.min(minU, uv.getX(index));\n minV = Math.min(minV, uv.getY(index));\n maxU = Math.max(maxU, uv.getX(index));\n maxV = Math.max(maxV, uv.getY(index));\n }\n }\n const insetU = Math.min(0.5 / atlas.image.width, (maxU - minU) / 2);\n const insetV = Math.min(0.5 / atlas.image.height, (maxV - minV) / 2);\n for (let corner = 0; corner < 4; corner++) {\n bounds.set([minU + insetU, minV + insetV, maxU - insetU, maxV - insetV], (faceIndex * 4 + corner) * 4);\n }\n }\n geometry.setAttribute(\"uvBounds\", new Float32BufferAttribute(bounds, 4));\n }\n\n public static lockUvs(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas, rotation: Euler): void {\n const uv = geometry.getAttribute(\"uv\") as BufferAttribute;\n for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {\n const faceName = CUBE_FACES[faceIndex];\n const texture = faces[faceName]?.texture?.substring(1);\n const position = texture && atlas.positions[texture];\n const size = texture && atlas.sizes[texture];\n if (!position || !size) continue;\n\n const [sourceU, sourceV] = FACE_UV_AXES[faceName];\n const uAxis = sourceU.clone().applyEuler(rotation);\n const vAxis = sourceV.clone().applyEuler(rotation);\n const normal = vAxis.clone().cross(uAxis);\n const targetFace = CUBE_FACES.find(name => {\n const [u, v] = FACE_UV_AXES[name];\n return v.clone().cross(u).dot(normal) > 0.5;\n })!;\n const [targetU, targetV] = FACE_UV_AXES[targetFace];\n const uu = Math.round(targetU.dot(uAxis));\n const uvCross = Math.round(targetU.dot(vAxis));\n const vu = Math.round(targetV.dot(uAxis));\n const vv = Math.round(targetV.dot(vAxis));\n\n // Rotate about the full texture center, not the cropped face or atlas center.\n for (let corner = 0; corner < 4; corner++) {\n const index = faceIndex * 4 + corner;\n const u = (uv.getX(index) * atlas.image.width - position[0]) / size[0] - 0.5;\n const v = ((1 - uv.getY(index)) * atlas.image.height - position[1]) / size[1] - 0.5;\n const lockedU = uu * u + uvCross * v + 0.5;\n const lockedV = vu * u + vv * v + 0.5;\n uv.setXY(index,\n (position[0] + lockedU * size[0]) / atlas.image.width,\n 1 - (position[1] + lockedV * size[1]) / atlas.image.height);\n }\n }\n uv.needsUpdate = true;\n }\n\n /** Returns the shared atlas for a keyed, merged model, creating it on first use. */\n public static async getAtlas(model: Model): Promise<Maybe<TextureAtlas>> {\n const keyStr = model.key!.serialize();\n return Caching.modelTextureAtlasCache.get(keyStr, k => {\n return this.createAtlas(model);\n })\n }\n\n public static fillMissingTextureKeys<T>(textures: ModelTextures, target: { [k: string]: T }): { [k: string]: T } {\n for (const key in textures) {\n // Follow references such as \"#all\" -> \"#texture\" to the variable that names a texture.\n let name = key;\n const seen = new Set<string>();\n while (textures[name]?.startsWith(\"#\") && !seen.has(name)) {\n seen.add(name);\n name = textures[name].substr(1);\n }\n if (name !== key) target[key] = target[name];\n }\n return target;\n }\n\n // https://yeleha.co/3qlboGS\n protected static getFallbackUv(element: ModelElement, faceName: CubeFace): QuadArray {\n switch (faceName) {\n case CubeFace.DOWN:\n return [element.from[X], 16 - element.to[Z], element.to[X], 16 - element.from[Z]];\n case CubeFace.UP:\n return [element.from[X], element.from[Z], element.to[X], element.to[Z]];\n case CubeFace.NORTH:\n default:\n return [16 - element.to[X], 16 - element.to[Y], 16 - element.from[X], 16 - element.from[Y]];\n case CubeFace.SOUTH:\n return [element.from[X], 16 - element.to[Y], element.to[X], 16 - element.from[Y]];\n case CubeFace.WEST:\n return [element.from[Z], 16 - element.to[Y], element.to[Z], 16 - element.from[Y]];\n case CubeFace.EAST:\n return [16 - element.to[Z], 16 - element.to[Y], 16 - element.from[Z], 16 - element.from[Y]];\n }\n }\n\n protected static expandAndRotateMcUvs([u1, v1, u2, v2]: QuadArray, rotation: number = 0, actualWidth: number, actualHeight: number): QuadArray<Vector2> {\n // Resize coordinates to actual texture size\n const scaleU = actualWidth / 16;\n const scaleV = actualHeight / 16;\n u1 *= scaleU;\n v1 *= scaleV;\n u2 *= scaleU;\n v2 *= scaleV;\n\n let tl: Vector2 = new Vector2(u1, v1);// top left\n let tr: Vector2 = new Vector2(u2, v1);// top right\n let bl: Vector2 = new Vector2(u1, v2);// bottom left\n let br: Vector2 = new Vector2(u2, v2);// bottom right\n\n switch (rotation) {\n case 0:\n case 360:\n default:\n break;\n case 90:\n tl = new Vector2(u1, v2);\n tr = new Vector2(u1, v1);\n bl = new Vector2(u2, v2);\n br = new Vector2(u2, v1);\n break;\n case 180:\n tl = new Vector2(u2, v2);\n tr = new Vector2(u1, v2);\n bl = new Vector2(u2, v1);\n br = new Vector2(u1, v1);\n break;\n case 270:\n tl = new Vector2(u2, v1);\n tr = new Vector2(u2, v2);\n bl = new Vector2(u1, v1);\n br = new Vector2(u1, v2);\n break;\n }\n\n return [tl, tr, bl, br];\n }\n\n /**\n * Combines model textures and animation metadata into an atlas.\n * Mapped UVs are stored on copies of the model's elements, available through the returned atlas.\n * Returns `undefined` for models without a texture map.\n */\n public static async createAtlas(originalModel: Model): Promise<Maybe<TextureAtlas>> {\n const textureMap: { [key: string]: Maybe<WrappedImage>; } = {};\n const metaMap: { [key: string]: Maybe<MinecraftTextureMeta>; } = {};\n const model = {...originalModel};\n // Merged models share element objects with their cached parents (cube, cube_all, ...), so the\n // baked UVs below must go onto this atlas's own copies, not onto objects other atlases read.\n if (originalModel.elements) {\n model.elements = originalModel.elements.map(element => ({ ...element }));\n }\n const isItemModel = !(\"elements\" in model);\n\n log.debug(\"Creating Atlas for\", model.key);\n\n if (model.textures) {\n const promises: Promise<void>[] = [];\n const uniqueTextureNames: string[] = []; // TODO: make these actually unique\n const textureReferences: { [k: string]: string; } = {};\n for (let textureKey in model.textures) {\n let textureValue = model.textures[textureKey];\n if (textureValue.startsWith(\"#\")) {\n textureReferences[textureKey] = textureValue.substr(1);\n } else {\n uniqueTextureNames.push(textureKey);\n const assetKey = AssetKey.parse(\"textures\", textureValue, model.key);\n promises.push(ModelTextures.get(assetKey).then(asset => {\n if (!asset) {\n log.warn(\"Missing texture\", assetKey)\n return;\n }\n textureMap[textureKey] = new WrappedImage(asset);\n }));\n promises.push(ModelTextures.getMeta(assetKey).then(meta => {\n metaMap[textureKey] = meta;\n }))\n }\n }\n await Promise.all(promises);\n const textureCount = uniqueTextureNames.length;\n log.debug(\"Creating Atlas for\", textureCount, \"textures\");\n\n this.fillMissingTextureKeys(model.textures, textureMap);\n this.fillMissingTextureKeys(model.textures, metaMap);\n\n const sizes: { [texture: string]: DoubleArray; } = {};\n const frames: { [texture: string]: { index: number; time: number }[] } = {};\n\n // Find largest texture dimensions\n let maxWidth = 0;\n for (let textureKey of uniqueTextureNames) {\n let texture = textureMap[textureKey];\n if (!texture) continue;\n const animation = metaMap[textureKey]?.animation;\n let width = texture.width, height = texture.height;\n if (animation) {\n const square = Math.min(width, height);\n width = animation.width ?? (animation.height === undefined ? square : width);\n height = animation.height ?? (animation.width === undefined ? square : height);\n if (!Number.isInteger(width) || !Number.isInteger(height) || width <= 0 || height <= 0\n || texture.width % width || texture.height % height) {\n throw new RangeError(`Invalid animation frame dimensions for ${textureKey}`);\n }\n const count = (texture.width / width) * (texture.height / height);\n const time = animation.frametime ?? 1;\n frames[textureKey] = (animation.frames ?? Array.from({ length: count }, (_, index) => index))\n .map(frame => typeof frame === \"number\" ? { index: frame, time } : { index: frame.index, time: frame.time ?? time });\n if (!frames[textureKey].length || frames[textureKey].some(frame => !Number.isInteger(frame.index)\n || frame.index < 0 || frame.index >= count || !Number.isInteger(frame.time) || frame.time < 1)) {\n throw new RangeError(`Invalid animation frames for ${textureKey}`);\n }\n }\n sizes[textureKey] = [width, height];\n maxWidth = Math.max(maxWidth, width, height);\n }\n this.fillMissingTextureKeys(model.textures, sizes);\n\n\n const s = (Math.ceil(Math.sqrt(textureCount + 1))); // +1 for transparency\n const size = Math.ceil(s * maxWidth)\n log.debug(\"Atlas size:\", size);\n const squaredSize = size * size;\n\n const image = new CanvasImage(size, size);\n const missing = Textures.getMissing().image;\n const missingPixels = image.context.createImageData(missing.width, missing.height);\n missingPixels.data.set(missing.data!);\n image.putData(missingPixels, 0, 0);\n // The top-left atlas cell keeps absent model faces transparent.\n image.context.clearRect(0, 0, maxWidth, maxWidth);\n\n const positions: { [texture: string]: DoubleArray; } = {};\n\n let hasTransparency = false;\n let hasTranslucency = false;\n\n let hasAnimation = false;\n const animatorFunctions: { [texture: string]: AnimatorFunction; } = {};\n\n // Draw all textures onto a single image\n let tx = 1; // start one over to leave room for the transparent space\n let ty = 0;\n for (let textureIndex = 0; textureIndex < uniqueTextureNames.length; textureIndex++) {\n let textureKey = uniqueTextureNames[textureIndex];\n let texture = textureMap[textureKey];\n let x = tx * maxWidth;\n let y = ty * maxWidth;\n if (texture) {\n positions[textureKey] = [x, y];\n const [width, height] = sizes[textureKey];\n const sequence = frames[textureKey];\n const getFrameData = (index: number) => {\n const columns = texture!.width / width;\n return texture!.getSectionData((index % columns) * width,\n Math.floor(index / columns) * height, width, height);\n };\n const firstFrame = getFrameData(sequence?.[0].index ?? 0);\n image.putData(firstFrame, x, y);\n\n if (texture.hasTransparency) {\n hasTransparency = true;\n }\n if (texture.hasTranslucency) {\n hasTranslucency = true;\n }\n\n if (sequence && sequence.some(frame => frame.index !== sequence[0].index)) {\n hasAnimation = true;\n let t = 0;\n let f = 0;\n const interpolated = metaMap[textureKey]?.animation?.interpolate\n ? image.context.createImageData(width, height) : undefined;\n let currentFrame = firstFrame;\n let nextFrame = interpolated ? getFrameData(sequence[1].index) : firstFrame;\n\n animatorFunctions[textureKey] = () => {\n if (++t >= sequence[f].time) {\n t = 0;\n const previous = sequence[f].index;\n f = (f + 1) % sequence.length;\n if (interpolated) {\n currentFrame = nextFrame;\n nextFrame = getFrameData(sequence[(f + 1) % sequence.length].index);\n }\n if (sequence[f].index === previous) return false;\n image.putData(interpolated ? currentFrame : getFrameData(sequence[f].index), x, y);\n return true;\n }\n if (!interpolated || sequence[f].index === sequence[(f + 1) % sequence.length].index) return false;\n // Vanilla encodes the atlas shader's interpolation progress in thousandths.\n const progress = Math.floor(Math.fround(Math.fround(t / sequence[f].time) * 1000)) / 1000;\n for (let i = 0; i < interpolated.data.length; i++) {\n interpolated.data[i] = currentFrame.data[i] + (nextFrame.data[i] - currentFrame.data[i]) * progress;\n }\n image.putData(interpolated, x, y);\n return true;\n };\n }\n }\n tx++;\n if (tx >= s) {\n tx = 0;\n ty++;\n }\n }\n this.fillMissingTextureKeys(model.textures, positions);\n\n\n if (isItemModel) {\n log.debug(\"Generating item model for\", model);\n model.elements = [];\n for (let layerName of ModelGenerator.ITEM_LAYERS) {\n const textureImage = textureMap[layerName];\n if (textureImage) {\n // Outline the frame that was drawn into the atlas, not the whole animation strip.\n const [width, height] = sizes[layerName];\n const frame = frames[layerName]?.[0].index ?? 0;\n const columns = textureImage.width / width;\n model.elements.push(...ModelGenerator.generateItemModel(textureImage.getSectionData(\n (frame % columns) * width, Math.floor(frame / columns) * height, width, height), layerName))\n }\n }\n log.debug(\"Item model elements\", model.elements)\n }\n\n if (!model.elements) {\n //TODO: default elements\n }\n\n // Adjust UV positions\n if (model.elements) {\n for (let elementIndex = 0; elementIndex < model.elements.length; elementIndex++) {\n let element = model.elements[elementIndex];\n let uv: number[] = [];\n // Set default uvs to missing texture\n for (let i = 0; i < CUBE_FACES.length; i++) {\n this.setCubeFaceUvInArray(uv, i * 4, [0, 0, 8 / size, 8 / size])\n }\n for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {\n let faceName = CUBE_FACES[faceIndex];\n let face = element.faces[faceName];\n if (!face) {\n // set uv transparent\n this.setCubeFaceUvInArray(uv, faceIndex * 4, [0, 1, 8 / size, (size - 8) / size])\n continue;\n }\n // Keep the missing-texture UVs when no texture is referenced.\n if (!face.texture) continue;\n if (!face.uv) {\n face.uv = this.getFallbackUv(element, faceName);\n }\n\n const faceTexture = face.texture.substr(1); // remove #\n const texPosition = positions[faceTexture] || [0, 0];\n const texSize = sizes[faceTexture] || [16, 16];\n\n let texPosV = new Vector2(texPosition[0], texPosition[1]);\n\n const [tl, tr, bl, br] = this.expandAndRotateMcUvs(face.uv, face.rotation, texSize[0], texSize[1]);\n\n // move to atlas position\n tl.add(texPosV);\n tr.add(texPosV);\n bl.add(texPosV);\n br.add(texPosV);\n\n // divide to 0-1\n tl.divideScalar(size);\n tr.divideScalar(size);\n bl.divideScalar(size);\n br.divideScalar(size);\n\n // flip y coordinates\n tl.y = 1 - tl.y;\n tr.y = 1 - tr.y;\n bl.y = 1 - bl.y;\n br.y = 1 - br.y;\n\n let uvs: QuadArray<Vector2> = [tl, tr, bl, br];\n this.setFaceUvInArrayV(uv, faceIndex * 4, uvs);\n }\n\n element.mappedUv = uv;\n }\n } else {\n //TODO: item model\n }\n\n return new TextureAtlas(\n model,\n image,\n sizes,\n positions,\n hasAnimation,\n animatorFunctions,\n hasTransparency,\n hasTranslucency\n );\n } else {\n log.warn(\"Model does not have any textures\", model);\n }\n return undefined;\n }\n\n}\n\n// Based on net.minecraft.client.renderer.block.model.BlockFaceUV\n/** Stores a Minecraft face's UV rectangle and its rotation in degrees. */\nexport class MinecraftFaceUV {\n\n constructor(readonly uv: QuadArray = [0, 0, 16, 16], readonly rotation: number = 0) {\n }\n\n getU(index: number): number {\n const shiftedIndex = this.getShiftedIndex(index);\n return this.uv[shiftedIndex !== 0 && index !== 1 ? 2 : 0];\n }\n\n getV(index: number): number {\n const shiftedIndex = this.getShiftedIndex(index);\n return this.uv[shiftedIndex !== 0 && index !== 3 ? 3 : 1];\n }\n\n protected getShiftedIndex(index: number): number {\n return (index + this.rotation / 90) % 40;\n }\n\n protected getReverseIndex(index: number): number {\n return (index + 4 - this.rotation / 90) % 4;\n }\n\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/assets/AssetDefaults.ts"],"sourcesContent":["// Kept free of imports: AssetLoader reads DEFAULT_ROOT in a static initializer, and Assets.ts sits in an import\n// cycle with AssetLoader, so code-split bundles could run that initializer before the constant was assigned.\nexport const DEFAULT_ROOT = \"https://assets.mcasset.cloud/1.21.11\";\nexport const DEFAULT_NAMESPACE = \"minecraft\";\n"],"mappings":";AAEO,IAAM,eAAe;AACrB,IAAM,oBAAoB;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/assets/AssetKey.ts"],"sourcesContent":["import { Serializable } from \"../Serializable\";\nimport { DEFAULT_NAMESPACE } from \"./
|
|
1
|
+
{"version":3,"sources":["../../../../src/assets/AssetKey.ts"],"sourcesContent":["import { Serializable } from \"../Serializable\";\nimport { DEFAULT_NAMESPACE } from \"./AssetDefaults\";\nimport { AssetLoader } from \"./AssetLoader\";\n\nexport type AssetType = \"models\" | \"textures\" | \"blockstates\" | string;\n\n/** A Minecraft namespace and path, such as `minecraft` and `zombie`. */\nexport class BasicAssetKey implements Serializable {\n\n readonly namespace: string;\n readonly path: string;\n\n constructor(key: BasicAssetKey);\n constructor(namespace: string, path: string);\n constructor(namespaceOrKey: string | BasicAssetKey, path?: string) {\n if (path) {\n this.namespace = namespaceOrKey as string;\n this.path = path;\n } else {\n this.namespace = (namespaceOrKey as BasicAssetKey).namespace;\n this.path = (namespaceOrKey as BasicAssetKey).path\n }\n }\n\n toNamespacedString() {\n return this.namespace + \":\" + this.path;\n }\n\n toString() {\n return this.toNamespacedString();\n }\n\n serialize(): string {\n return this.toString();\n }\n}\n\n// TODO: rewrite this to be less dumb\n/** Locates an asset by namespace, directory, extension, and optional asset root. */\nexport class AssetKey extends BasicAssetKey {\n\n public readonly isAssetKey: true = true;\n\n /**\n * Creates a key from separate path components. Use {@link parse} for a combined reference.\n *\n * @param assetType - Asset directory, such as `models`, `textures`, or `blockstates`.\n * @param type - Subdirectory, such as `block` or `item`.\n * @param rootType - Top-level directory, usually `assets` or `data`.\n * @param root - Base URL override for hosted asset sources.\n */\n constructor(\n readonly namespace: string, readonly path: string,\n public assetType?: AssetType,\n public type?: string,\n public rootType: \"assets\" | \"data\" | string = \"assets\",\n public extension: \".json\" | \".png\" | string = \".json\",\n public root?: string,\n ) {\n super(namespace, path);\n }\n\n\n /**\n * Parses an asset reference such as `minecraft:block/stone`.\n * A missing namespace defaults to the origin's namespace or `minecraft`.\n *\n * @param assetType - Asset category, such as `models` or `textures`.\n * @param str - Path with an optional namespace and file extension.\n * @param origin - Supplies the asset root, default namespace, and non-texture extension.\n * @returns A key with the matching extension removed from its path. Textures use `.png`;\n * other assets use the origin's extension or `.json`.\n */\n public static parse(assetType: AssetType, str: string, origin?: AssetKey): AssetKey {\n let namespace = origin?.namespace || DEFAULT_NAMESPACE;\n if (str.includes(\":\")) {\n let split = str.split(\"\\:\");\n namespace = split[0];\n str = split[1];\n }\n\n let split = str.split(\"\\/\");\n let type: string | undefined = undefined;\n if (split.length > 1) {\n type = split[0];\n split.shift();\n }\n let path = split.join(\"/\");\n\n const extension = assetType === \"textures\" ? \".png\" :\n origin?.extension ?? \".json\";\n if (extension && path.endsWith(extension)) {\n path = path.slice(0, -extension.length);\n }\n\n return new AssetKey(namespace, path, assetType, type, \"assets\", extension, origin?.root);\n }\n\n toString(): string {\n let a = [\n this.root ?? AssetLoader.ROOT,\n this.rootType ?? \"__rootType__\",\n this.assetType ?? \"__assetType__\",\n this.type ?? \"__type__\",\n this.namespace,\n this.path\n ];\n return a.join(\"/\");\n }\n\n /** Joins the type subdirectory and path without adding a namespace or file extension. */\n getFullPath() {\n let p: string[] = [];\n if (this.type) {\n p.push(this.type);\n }\n p.push(this.path);\n return p.join(\"/\");\n }\n\n toNamespacedString() {\n return this.namespace + \":\" + this.getFullPath();\n }\n\n /** Returns a cache identifier that includes the explicit root or {@link AssetLoader.ROOT}. */\n serialize(): string {\n return this.toString();\n }\n}\n\nexport function isResourceLocation(value: unknown): value is string {\n return typeof value === \"string\" && /^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(value);\n}\n\nexport function isBasicAssetKey(obj: any): obj is BasicAssetKey {\n return obj !== null && typeof obj === \"object\"\n && typeof obj.namespace === \"string\" && typeof obj.path === \"string\";\n}\n\nexport function isAssetKey(obj: any): obj is AssetKey {\n return isBasicAssetKey(obj) && (<AssetKey>obj).isAssetKey === true;\n}\n"],"mappings":";AACA,SAAS,yBAAyB;AAClC,SAAS,mBAAmB;AAKrB,IAAM,gBAAN,MAA4C;AAAA,EAO/C,YAAY,gBAAwC,MAAe;AAC/D,QAAI,MAAM;AACN,WAAK,YAAY;AACjB,WAAK,OAAO;AAAA,IAChB,OAAO;AACH,WAAK,YAAa,eAAiC;AACnD,WAAK,OAAQ,eAAiC;AAAA,IAClD;AAAA,EACJ;AAAA,EAEA,qBAAqB;AACjB,WAAO,KAAK,YAAY,MAAM,KAAK;AAAA,EACvC;AAAA,EAEA,WAAW;AACP,WAAO,KAAK,mBAAmB;AAAA,EACnC;AAAA,EAEA,YAAoB;AAChB,WAAO,KAAK,SAAS;AAAA,EACzB;AACJ;AAIO,IAAM,WAAN,MAAM,kBAAiB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYxC,YACa,WAA4B,MAC9B,WACA,MACA,WAAuC,UACvC,YAAuC,SACvC,MACT;AACE,UAAM,WAAW,IAAI;AAPZ;AAA4B;AAC9B;AACA;AACA;AACA;AACA;AAhBX,SAAgB,aAAmB;AAAA,EAmBnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,OAAc,MAAM,WAAsB,KAAa,QAA6B;AAChF,QAAI,YAAY,QAAQ,aAAa;AACrC,QAAI,IAAI,SAAS,GAAG,GAAG;AACnB,UAAIA,SAAQ,IAAI,MAAM,GAAI;AAC1B,kBAAYA,OAAM,CAAC;AACnB,YAAMA,OAAM,CAAC;AAAA,IACjB;AAEA,QAAI,QAAQ,IAAI,MAAM,GAAI;AAC1B,QAAI,OAA2B;AAC/B,QAAI,MAAM,SAAS,GAAG;AAClB,aAAO,MAAM,CAAC;AACd,YAAM,MAAM;AAAA,IAChB;AACA,QAAI,OAAO,MAAM,KAAK,GAAG;AAEzB,UAAM,YAAY,cAAc,aAAa,SACzC,QAAQ,aAAa;AACzB,QAAI,aAAa,KAAK,SAAS,SAAS,GAAG;AACvC,aAAO,KAAK,MAAM,GAAG,CAAC,UAAU,MAAM;AAAA,IAC1C;AAEA,WAAO,IAAI,UAAS,WAAW,MAAM,WAAW,MAAM,UAAU,WAAW,QAAQ,IAAI;AAAA,EAC3F;AAAA,EAEA,WAAmB;AACf,QAAI,IAAI;AAAA,MACJ,KAAK,QAAQ,YAAY;AAAA,MACzB,KAAK,YAAY;AAAA,MACjB,KAAK,aAAa;AAAA,MAClB,KAAK,QAAQ;AAAA,MACb,KAAK;AAAA,MACL,KAAK;AAAA,IACT;AACA,WAAO,EAAE,KAAK,GAAG;AAAA,EACrB;AAAA;AAAA,EAGA,cAAc;AACV,QAAI,IAAc,CAAC;AACnB,QAAI,KAAK,MAAM;AACX,QAAE,KAAK,KAAK,IAAI;AAAA,IACpB;AACA,MAAE,KAAK,KAAK,IAAI;AAChB,WAAO,EAAE,KAAK,GAAG;AAAA,EACrB;AAAA,EAEA,qBAAqB;AACjB,WAAO,KAAK,YAAY,MAAM,KAAK,YAAY;AAAA,EACnD;AAAA;AAAA,EAGA,YAAoB;AAChB,WAAO,KAAK,SAAS;AAAA,EACzB;AACJ;AAEO,SAAS,mBAAmB,OAAiC;AAChE,SAAO,OAAO,UAAU,YAAY,oCAAoC,KAAK,KAAK;AACtF;AAEO,SAAS,gBAAgB,KAAgC;AAC5D,SAAO,QAAQ,QAAQ,OAAO,QAAQ,YAC/B,OAAO,IAAI,cAAc,YAAY,OAAO,IAAI,SAAS;AACpE;AAEO,SAAS,WAAW,KAA2B;AAClD,SAAO,gBAAgB,GAAG,KAAgB,IAAK,eAAe;AAClE;","names":["split"]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// src/assets/AssetLoader.ts
|
|
2
|
-
import { DEFAULT_ROOT } from "./
|
|
2
|
+
import { DEFAULT_ROOT } from "./AssetDefaults.mjs";
|
|
3
3
|
import { AssetKey } from "./AssetKey.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { logger } from "../util/log.mjs";
|
|
5
5
|
import { HostedAssetSource } from "./source/index.mjs";
|
|
6
6
|
import { Caching } from "../cache/Caching.mjs";
|
|
7
|
-
var
|
|
7
|
+
var log = logger("AssetLoader");
|
|
8
8
|
var AssetLoader = class {
|
|
9
9
|
static get _SOURCES() {
|
|
10
10
|
return this.sources ?? (this.sources = [{ key: "mcassets", source: new HostedAssetSource(this.ROOT, { retryDefaults: false }) }]);
|
|
@@ -59,11 +59,11 @@ ${key}` : key;
|
|
|
59
59
|
if (override) {
|
|
60
60
|
const existing = this.removeSource(key);
|
|
61
61
|
if (existing) {
|
|
62
|
-
|
|
62
|
+
log.info("Removed existing AssetSource", key);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
this._SOURCES.unshift({ key, source });
|
|
66
|
-
|
|
66
|
+
log.info("Added AssetSource", key);
|
|
67
67
|
}
|
|
68
68
|
/** Removes and returns the first source with this name. Call {@link Caching.clear} to reload assets. */
|
|
69
69
|
static removeSource(key) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/assets/AssetLoader.ts"],"sourcesContent":["import { Model, TextureAsset } from \"../model/Model\";\nimport { Maybe } from \"../util/util\";\nimport { Requests } from \"../request/Requests\";\nimport { MinecraftAsset } from \"../MinecraftAsset\";\nimport { ImageInfo, ImageLoader } from \"../image/ImageLoader\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport { DEFAULT_NAMESPACE, DEFAULT_ROOT } from \"./
|
|
1
|
+
{"version":3,"sources":["../../../../src/assets/AssetLoader.ts"],"sourcesContent":["import { Model, TextureAsset } from \"../model/Model\";\nimport { Maybe } from \"../util/util\";\nimport { Requests } from \"../request/Requests\";\nimport { MinecraftAsset } from \"../MinecraftAsset\";\nimport { ImageInfo, ImageLoader } from \"../image/ImageLoader\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport { DEFAULT_NAMESPACE, DEFAULT_ROOT } from \"./AssetDefaults\";\nimport { ListAsset } from \"../ListAsset\";\nimport { AssetKey } from \"./AssetKey\";\nimport { NBTAsset, NBTHelper } from \"../nbt/NBTHelper\";\nimport { logger } from \"../util/log\";\nimport { AssetSource } from \"./source/AssetSource\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\nimport { HostedAssetSource } from \"./source\";\nimport { Caching } from \"../cache/Caching\";\n\nconst log = logger(\"AssetLoader\");\n\n\n/** Loads assets from a shared, ordered registry of hosted sources and resource packs. */\nexport class AssetLoader {\n\n /** Default asset base URL. Use {@link setVersion} to select a Minecraft version. */\n static ROOT: string = DEFAULT_ROOT;\n\n private static sources: AssetSourceReference[] | undefined;\n\n private static get _SOURCES(): AssetSourceReference[] {\n return this.sources ??= [{ key: \"mcassets\", source: new HostedAssetSource(this.ROOT, { retryDefaults: false }) }];\n }\n\n private static set _SOURCES(sources: AssetSourceReference[]) {\n this.sources = sources;\n }\n\n /** Used when a registered source cannot identify its content, so nothing persists past this session. */\n private static readonly SESSION_SCOPE = `session:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;\n\n public static get version(): string {\n return this.ROOT.substring(this.ROOT.lastIndexOf(\"/\") + 1);\n }\n\n /** Selects an mcasset.cloud version, updates the vanilla source, and clears in-memory caches. */\n public static setVersion(version: string): void {\n this.ROOT = `https://assets.mcasset.cloud/${version}`;\n const source = new HostedAssetSource(this.ROOT, { retryDefaults: false });\n const index = this._SOURCES.findIndex(s => s.key === \"mcassets\");\n if (index !== -1) {\n this._SOURCES[index] = { key: \"mcassets\", source };\n } else {\n this.addSource(\"mcassets\", source);\n }\n Caching.clear();\n }\n\n /**\n * Scope for persistent cache keys. Empty with only the default vanilla source, so its\n * entries stay valid across sessions; otherwise it names every added source (resource packs,\n * mirrors) so their results never masquerade as vanilla assets after a reload.\n */\n public static get persistentScope(): string {\n const parts: string[] = [];\n for (const { key, source } of this._SOURCES) {\n const id = source.cacheId;\n if (key === \"mcassets\" && id === `hosted:${this.ROOT}`) continue;\n if (id === undefined) return this.SESSION_SCOPE;\n parts.push(`${key}=${id}`);\n }\n return parts.join(\"|\");\n }\n\n /** Prefixes a persistent cache key with the current source scope. */\n public static persistentKey(key: string): string {\n const scope = this.persistentScope;\n return scope ? `${scope}\\n${key}` : key;\n }\n\n /**\n * Registers a source at the highest priority.\n * Call {@link Caching.clear} after changing sources to discard previously loaded assets.\n *\n * @param key - Name used to replace or remove this source.\n * @param override - Removes the first source with this name before adding the new one.\n */\n public static addSource(key: string, source: AssetSource, override: boolean = true) {\n if (override) {\n const existing = this.removeSource(key);\n if (existing) {\n log.info(\"Removed existing AssetSource\", key);\n }\n }\n\n this._SOURCES.unshift({key, source});\n log.info(\"Added AssetSource\", key);\n }\n\n /** Removes and returns the first source with this name. Call {@link Caching.clear} to reload assets. */\n public static removeSource(key: string): Maybe<AssetSource> {\n const index = this._SOURCES.findIndex(s => s.key === key);\n if (index != -1) {\n const spliced = this._SOURCES.splice(index, 1);\n if (spliced.length > 0) {\n return spliced[0].source;\n }\n }\n return undefined;\n }\n\n /** Loads from all sources and returns defined results in priority order. Any source failure rejects the call. */\n public static async getAll<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<T[]> {\n const sources = [...this._SOURCES];\n const results: T[] = [];\n for (const { source } of sources) {\n const asset = await source.get<T>(key, parser);\n if (asset != undefined) results.push(asset);\n if (await source.blocks(key)) break;\n }\n return results;\n }\n\n /** Returns the first defined result in source-priority order, without merging assets. */\n public static async get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<Maybe<T>> {\n const keys = [key];\n if (key.rootType === \"data\" && (key.assetType === \"structure\" || key.assetType === \"structures\")) {\n keys.push(new AssetKey(key.namespace, key.path,\n key.assetType === \"structure\" ? \"structures\" : \"structure\",\n key.type, key.rootType, key.extension, key.root));\n }\n return (await this.getFirst<T>(keys, parser))?.asset;\n }\n\n /** Tries each path within a source before considering lower-priority sources. */\n public static async getFirst<T extends MinecraftAsset>(keys: readonly AssetKey[], parser: AssetParser | string): Promise<Maybe<{ key: AssetKey; asset: T }>> {\n // Source changes affect later lookups, not the priority of an in-flight lookup.\n const sources = [...this._SOURCES];\n let remaining = [...keys];\n for (const source of sources) {\n for (const key of remaining) {\n const result = await source.source.get<T>(key, parser);\n if (result !== undefined) {\n return { key, asset: result };\n }\n }\n const blocked = await Promise.all(remaining.map(key => source.source.blocks(key)));\n remaining = remaining.filter((_, index) => !blocked[index]);\n if (!remaining.length) break;\n }\n return undefined;\n }\n\n}\n\ninterface AssetSourceReference {\n key: string;\n source: AssetSource;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
import { Models } from "./Models.mjs";
|
|
3
3
|
import { BlockStates } from "./BlockStates.mjs";
|
|
4
4
|
import { AssetKey } from "./AssetKey.mjs";
|
|
5
|
-
var DEFAULT_ROOT = "https://assets.mcasset.cloud/1.21.11";
|
|
6
|
-
var DEFAULT_NAMESPACE = "minecraft";
|
|
7
5
|
var Assets = class {
|
|
8
6
|
/**
|
|
9
7
|
* @deprecated
|
|
@@ -21,8 +19,6 @@ var Assets = class {
|
|
|
21
19
|
}
|
|
22
20
|
};
|
|
23
21
|
export {
|
|
24
|
-
Assets
|
|
25
|
-
DEFAULT_NAMESPACE,
|
|
26
|
-
DEFAULT_ROOT
|
|
22
|
+
Assets
|
|
27
23
|
};
|
|
28
24
|
//# sourceMappingURL=Assets.mjs.map
|