@hology/core 0.0.261 → 0.0.262

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.
Files changed (34) hide show
  1. package/dist/gameplay/index.d.ts +1 -0
  2. package/dist/gameplay/index.js +1 -1
  3. package/dist/gameplay/initiate.js +1 -1
  4. package/dist/gameplay/inject.d.ts +8 -0
  5. package/dist/gameplay/inject.js +1 -1
  6. package/dist/gameplay/services/asset-loader.d.ts +3 -0
  7. package/dist/gameplay/services/asset-loader.js +1 -1
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +1 -1
  10. package/dist/rendering/graphics-runtime.d.ts +1 -1
  11. package/dist/rendering/graphics-runtime.js +1 -1
  12. package/dist/rendering/node-material-webgpu-resolver.js +1 -1
  13. package/dist/rendering.d.ts +6 -1
  14. package/dist/rendering.js +1 -1
  15. package/dist/scene/asset-resource-loader.d.ts +3 -0
  16. package/dist/scene/asset-resource-loader.js +1 -1
  17. package/dist/scene/custom-param-deserialize.js +1 -1
  18. package/dist/scene/custom-param-runtime-types.js +1 -1
  19. package/dist/scene/lattice-deformation.d.ts +28 -0
  20. package/dist/scene/lattice-deformation.js +4 -0
  21. package/dist/scene/materializer.d.ts +12 -3
  22. package/dist/scene/materializer.js +1 -1
  23. package/dist/scene/model-ref.d.ts +7 -0
  24. package/dist/scene/model-ref.js +4 -0
  25. package/dist/scene/model.d.ts +2 -1
  26. package/dist/scene/model.js +1 -1
  27. package/dist/shader/parameter.d.ts +2 -1
  28. package/dist/test/graphics-runtime.test.js +1 -1
  29. package/dist/test/lattice-deformation.test.d.ts +2 -0
  30. package/dist/test/lattice-deformation.test.js +4 -0
  31. package/dist/test/materializer-prefetch.test.js +1 -1
  32. package/docs/actor-persistence.md +87 -87
  33. package/package.json +1 -1
  34. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,4 @@
1
- import{AudioLoader as e,BufferGeometry as t,Euler as r,Group as a,LoadingManager as s,Mesh as i,Object3D as n,Texture as o,TextureLoader as l,Vector3 as c}from"three";import{MTLLoader as h,OBJLoader as u,LUTCubeLoader as m}from"three-stdlib";import{cloneMesh as d,mergeCompatibleSkinnedMeshes as f}from"../utils/mesh.js";import{pathJoin as p}from"../utils/files.js";import{Subject as g,firstValueFrom as y}from"rxjs";import{BoxCollisionShape as w,CapsuleCollisionShape as x,CollisionShapeSource as M,CylinderCollisionShape as b,SphereCollisionShape as A}from"./collision/collision-shape.js";import{importCollisionShapes as L,isCollisionMesh as S}from"./collision/collision-shape-import.js";import*as _ from"three";import{iterateMaterials as v}from"../utils/materials.js";import{applyMaterial as T,getConvertedFbxToGlbAssignedMaterialTextureFlipY as R}from"./materializer.js";import{BufferGeometryUtils as C,DRACOLoader as P,EXRLoader as F,FBXLoader as K,GLTFLoader as k,KTX2Loader as I,TGALoader as B,UltraHDRLoader as j}from"three/examples/jsm/Addons.js";import{disposeScene as D}from"../utils/three/cleanup.js";import{resolveAnimationRigBasisRotation as W,setAnimationClipRigId as U}from"../gameplay/animation/retarget.js";(()=>{const e=new Uint8Array([255,0,0,255]),t=new _.DataTexture(e,1,1,_.RGBAFormat);t.needsUpdate=!0})();const z=new P;z.setDecoderConfig({type:"js"}),z.setDecoderPath("/assets/draco/");const G=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new s,this.glbLoader=new k(this.loadingManager).setDRACOLoader(z),this.fbxLoader=new K(this.loadingManager),this.objLoader=new u(this.loadingManager),this.textureLoader=new l(this.loadingManager),this.tgaLoader=new B(this.loadingManager),this.exrLoader=new F(this.loadingManager),this.cubeLoader=new m(this.loadingManager),this.hdrLoader=new j(this.loadingManager),this.ktx2Loader=new I(this.loadingManager),this.ktx2Ready=Promise.resolve(),this._textureLoader=new _.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.initialisedKtx2=!1,this._retrievedMeshes=[],this._retrievedTextures=[],this.makeReady=new g,this.ready=y(this.makeReady),this.directFileLoading=!1,this._texturePromises=new Map,this._arrayTexturesByFileKey=new Map,this._arrayTexturePromisesByFileKey=new Map,this._arrayTextureSettingsByFileKey=new Map,this._animationPromises=new Map,this._animationCache=new Map,this.asyncMeshResults=new Map,this.asyncAudioResults=new Map,this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}setDirectFileLoading(e){this.directFileLoading=e}configureKtx2(){this.initialisedKtx2=!0;null!=getElectronArg("windowId")||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?this.ktx2Loader.setTranscoderPath("/assets/basis/"):this.ktx2Loader.setTranscoderPath(new URL("../assets/basis/",import.meta.url).href),this.ktx2Loader.setWorkerLimit(6)}initKtx2(e){this.configureKtx2(),this.ktx2Loader.detectSupport(e)}initKtx2ForWebGpu(){this.configureKtx2(),this.ktx2Ready=Promise.resolve(navigator.gpu?.requestAdapter({powerPreference:"high-performance"})??null).then(e=>{this.ktx2Loader.detectSupport({isWebGPURenderer:!0,hasFeature:t=>!0===e?.features.has(t)})})}setDataDir(e){this.basePath=p(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){const t=function(e){return E.get(e)}(e),r=getElectronArg("windowId");return null!=r||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?p(this.basePath,e)+(null!=r?`?windowId=${r}${null!=t?`&v=${t}`:""}`:""):new URL(p("..",this.basePath,e),import.meta.url).href}async getTexture(e){if(!e||!e.fileKey)return null;if("png"===e.fileFormat||e.fileFormat,this._texturePromises.has(e.id))return this._texturePromises.get(e.id);const t=this._getTexture(e).finally(()=>{this._texturePromises.delete(e.id)});return this._texturePromises.set(e.id,t),t}async _getTexture(e){if(null==e||null==e.fileKey)return null;if(await this.ready,e.fileKey.toLowerCase().endsWith(".ktx2")&&await this.ktx2Ready,this.textureCache.has(e.id)){const t=this.textureCache.get(e.id);if(null!=e.texture){const r=q(t,e);t.flipY!==r?(t.needsUpdate=!0,t.flipY=r):t.wrapS!==Y(e.texture?.wrapS)?(t.needsUpdate=!0,t.wrapS=Y(e.texture?.wrapS)):t.wrapT!==Y(e.texture?.wrapT)&&(t.wrapT=Y(e.texture?.wrapT),t.needsUpdate=!0)}const r=V(X(e));t.colorSpace!==r&&(t.colorSpace=r,t.needsUpdate=!0)}else try{const t=this._getTextureLoader(e.fileKey),r=this.directFileLoading&&t===this.textureLoader;await(r?this._textureLoader:t).loadAsync(this.getUri(e.fileKey)).then(t=>(r&&((t=new o(t)).needsUpdate=!0),t.texture3D?t=t.texture3D:(t.wrapS=Y(e.texture?.wrapS),t.wrapT=Y(e.texture?.wrapT),t.flipY=q(t,e),t.colorSpace=V(X(e))),this.textureCache.set(e.id,t),this._retrievedTextures.push(t),t))}catch(t){return console.warn("Failed to load texture "+e.name,t),null}const t=this.textureCache.get(e.id);return null!=t&&(t.userData.assetId=e.id),t}async getTextureArray(e){const t=e.texture?.textureArrayFileKey,r=e.texture?.textureArrayLayer;if(!t||null==r)return{texture:null,layerIndex:null};let a=this._arrayTexturesByFileKey.get(t);if(null==a){let e=this._arrayTexturePromisesByFileKey.get(t);null==e&&(e=this.loadTextureArray(t).finally(()=>{this._arrayTexturePromisesByFileKey.delete(t)}),this._arrayTexturePromisesByFileKey.set(t,e)),a=await e}return this.applyTextureArraySettings(t,a,e),{texture:a,layerIndex:r}}async loadTextureArray(e){const t=this._getTextureLoader(e);let r=await t.loadAsync(this.getUri(e));return r instanceof o||(r=r.texture3D),this._arrayTexturesByFileKey.set(e,r),this._retrievedTextures.push(r),r}applyTextureArraySettings(e,t,r){const a=function(e){return{wrapS:Y(e.texture?.wrapS),wrapT:Y(e.texture?.wrapT)}}(r),s=this._arrayTextureSettingsByFileKey.get(e);if(null!=s&&(n=a,(i=s).wrapS!==n.wrapS||i.wrapT!==n.wrapT))return void console.warn(`Texture array ${e} is used with incompatible texture settings. Texture arrays share wrapping; rebuild arrays so incompatible textures are grouped separately.`);var i,n;null==s&&this._arrayTextureSettingsByFileKey.set(e,a);let o=!1;t.wrapS!==a.wrapS&&(t.wrapS=a.wrapS,o=!0),t.wrapT!==a.wrapT&&(t.wrapT=a.wrapT,o=!0),!1!==t.flipY&&(t.flipY=!1,o=!0),o&&(t.needsUpdate=!0)}_getTextureLoader(e){return e?.toLowerCase().endsWith(".tga")?this.tgaLoader:e?.toLowerCase().endsWith(".ktx2")?this.ktx2Loader:e?.toLowerCase().endsWith(".exr")?this.exrLoader:e?.toLowerCase().endsWith(".cube")?this.cubeLoader:this.textureLoader}clearCache(e){this.clearCacheByAsset(e)}clearCacheByAsset(e){null!=e&&(this.clearCacheById(e.id),null!=e.fileKey&&(Array.from(this.cache.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.cache.delete(t)}),Array.from(this.asyncMeshResults.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.asyncMeshResults.delete(t)}),Array.from(this._animationCache.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationCache.delete(t)}),Array.from(this._animationPromises.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationPromises.delete(t)}),$(e.fileKey)),null!=e.materialLib&&$(e.materialLib))}clearCacheById(e){const t=Array.from(this.cache.values()).find(t=>t.scene.userData.assetId===e);t&&Array.from(this.cache.keys()).forEach(e=>{this.cache.get(e)===t&&this.cache.delete(e)}),this.textureCache.delete(e),this._texturePromises.delete(e),Array.from(this.collisionShapeCache.keys()).forEach(t=>{t.startsWith(e+"|")&&this.collisionShapeCache.delete(t)})}async getMesh(e,t){if(await this.ready,null==e)return console.error("No asset was provided"),{scene:new a,animations:[]};if(!G.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new a,animations:[]};const r=e.fileKey+(!0===t?.mergeGeomtries?"1":"0");if(!this.cache.has(r))try{this.asyncMeshResults.has(r)||this.asyncMeshResults.set(r,this.loadMesh(e).finally(()=>this.asyncMeshResults.delete(r))),this.cache.set(r,await this.asyncMeshResults.get(r))}catch(e){return this.onError(e),{scene:new a,animations:[]}}const s=this.cache.get(r),n=s.scene,o=s.animations;if(!1===t?.clone)return{scene:n,animations:o};const l=this.computeCollisionShapes(e,n),c=(e.mesh?.secondaryMotion?.regions.length??0)>0;!0!==t?.mergeGeomtries||c||this.optimizeDrawGroups(n);const h=d(n);h.traverse(e=>{e instanceof i&&e.material instanceof Array&&(e.material=e.material.slice())});const u=new AssetMeshInstance;u.add(h),u.collisionShapes=l,u.animations=o,u.userData.assetId=e.id,u.userData.secondaryMotion=e.mesh?.secondaryMotion,function(e){const t=e.children.length>0?e.children:[e];for(let e=0;e<t.length;e++)r(t[e],"",e);function r(e,t,a){const s=e instanceof i?"Mesh":"Group",n=`${t}/${e.name?.trim()?.length>0?e.name:s}[${a}]`;e.userData.secondaryMotionMeshPath=n;for(let t=0;t<e.children.length;t++)r(e.children[t],n,t)}}(u);const m=e.mesh?.animationRigId??e.anim?.rigId;if(u.userData.animationRigId=m,h.userData.animationRigId=m,null!=m&&null!=this.animationRigProvider){const e=await this.animationRigProvider(m);u.userData.animationRig=e,h.userData.animationRig=e,null!=e&&!1!==t?.applyRigBasis&&u.quaternion.copy(W(e))}const f=e.receiveShadow??!1,p=e.castShadow??!1;if(h.traverse(e=>{e.castShadow=p,e.receiveShadow=f}),!0===t?.rescale&&"number"==typeof e.mesh?.rescale&&u.scale.setScalar(e.mesh?.rescale),!0===t?.applyMaterials){const r=t?.materialResolver??this.materialProvider;if(null!=r)for(const t of e.materialAssignments??[])await T(u,t,r,void 0,{textureFlipY:R(e)});else console.warn(`applyMaterials was set to true for ${e.name} but no material resolver was provided.`)}return{scene:u,animations:o}}async getAudio(e){await this.ready;const t=e.fileKey;if(this.asyncAudioResults.has(t))return await this.asyncAudioResults.get(t);const r=this.audioLoader.loadAsync(this.getUri(e.fileKey)).finally(()=>{setTimeout(()=>{this.asyncAudioResults.delete(t)},1e3)});return this.asyncAudioResults.set(t,r),r}async getAnimationClip(e){if(null==e||null==e.fileKey||null==e.anim?.clip)return console.warn("Asset or animation clip name is not defined",e),null;const t=e.anim.clip,r=e.fileKey+"|"+t;if(this._animationCache.has(r))return this._animationCache.get(r);if(this._animationPromises.has(r))return this._animationPromises.get(r);const a=(async()=>{try{const a=await this.getMesh(e),s=a.animations.find(e=>e.name===t);return null!=s&&(U(s,e.anim?.rigId),this._animationCache.set(r,s)),s}catch(e){return this.onError(e),null}finally{setTimeout(()=>this._animationPromises.delete(r),1e3)}})();return this._animationPromises.set(r,a),a}computeCollisionShapes(e,t){if(!0!==e.collisionDetection)return[];const r=e.id+"|"+(e.mesh?.collisions?.shapeType??"")+"|"+(e.mesh?.rescale??1)+"|"+JSON.stringify(e.mesh?.colliders??[]);if(!this.collisionShapeCache.has(r)){const a=e.mesh?.colliders??[],s=a.length>0?createAuthoredCollisionShapes(a,e.mesh?.rescale):L(t,e);this.collisionShapeCache.set(r,s)}return this.collisionShapeCache.get(r)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then(r=>(r.scene.traverse(r=>{if(r instanceof i&&r.geometry instanceof t){const t=removeInvalidFaces(r.geometry);t>0&&console.warn(`Removed ${t} invalid face${1===t?"":"s"} from ${e.name}/${r.name||"unnamed mesh"}`)}r instanceof i&&r.material&&function(e){let t=e.material;if(null==t)return;Array.isArray(t)?e.material=t.map(Q):e.material=Q(t)}(r),S(r)?r.visible=!1:r instanceof i&&r.geometry instanceof t&&(r.geometry.hasAttribute("normal")||r.geometry.computeVertexNormals())}),this._retrievedMeshes.push(r.scene),r.scene=function(e,t){let r=!1;if(t.traverseVisible(e=>{H.test(e.name)&&(r=!0)}),!r)return t;const a=[],s=[t];for(;s.length>0;){const e=s.shift(),t=e.name.match(H);if(null!=t){const r=parseInt(t[1]);if(0!==r){console.warn(`Skipping LOD level ${r} for now as LOD is not fully supported`),a.push(e);continue}}s.push(...e.children)}for(const e of a)e.removeFromParent();return t}(0,r.scene),function(e){const t=Z;Z.length=0,e.traverse(e=>{(e instanceof _.Camera||e instanceof _.Light)&&t.push(e)}),t.forEach(e=>e.removeFromParent())}(r.scene),r.scene.userData.assetId=e.id,r))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid),e.updateWorldMatrix(!0,!0);const r=[];e.traverse(e=>{e instanceof i&&!(e instanceof _.SkinnedMesh)&&e.geometry instanceof t&&Array.isArray(e.material)&&!S(e)&&r.push({mesh:e,geometry:e.geometry,materialArray:e.material,parent:e.parent})});for(const{mesh:t,geometry:a,materialArray:s,parent:n}of r){t.removeFromParent();for(let r=0;r<s.length;r++){const o=s[r],l=a.groups.filter(e=>e.materialIndex===r);if(0===l.length)continue;const c=this.extractGeometryGroups(a,l);c.groups.length>1&&C.mergeGroups(c);const h=new i(c,o);h.copy(t,!1),h.geometry=c,h.material=o,n?n.add(h):e.add(h)}a.dispose()}f(e,S);let a=!0,s=0,n=0;if(e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!S(e)){s++;const t=Object.keys(e.geometry.attributes).length;t!==n&&0!==n&&(a=!1),n=t}else(e instanceof _.SkinnedMesh||e instanceof _.Bone)&&(a=!1)}),s>1&&a){const r=new Map;e.traverse(a=>{if(a instanceof i&&a.geometry instanceof t&&!S(a)){if(Array.isArray(a.material))return;a.updateWorldMatrix(!0,!0);const t=a.material?.uuid||"default";r.has(t)||r.set(t,{material:a.material,geometries:[],objects:[]});const s=r.get(t),i=e.matrixWorld.clone().invert().multiply(a.matrixWorld);s.geometries.push(a.geometry.clone().applyMatrix4(i)),s.objects.push(a)}});for(const e of r.values())for(const t of e.objects)t.removeFromParent();for(const t of r.values()){let r,a=t.geometries;if(a.some(e=>null!=e.index)&&(a=a.map(e=>{if(null!=e.index)return e;const t=e.getAttribute("position");if(null==t)return e;const r=t.count>65535?new Uint32Array(t.count):new Uint16Array(t.count);for(let e=0;e<r.length;e++)r[e]=e;return e.setIndex(new _.BufferAttribute(r,1)),e})),r=1===t.geometries.length?a[0]:O(a)?C.mergeGeometries(a,!0):null,null!=r)r.groups.length>1&&C.mergeGroups(r),e.add(new i(r,t.material));else for(const r of a)e.add(new i(r,t.material))}}e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!S(e)){const t=e.geometry;!Array.isArray(e.material)&&t.groups.length>1&&C.mergeGroups(t)}})}extractGeometryGroups(e,r){const a=e.index;if(!a){const a=new t;let s=0;for(const e of r)s+=e.count;if(0===s)return a;for(const t in e.attributes){const i=e.attributes[t],n=i.itemSize,o=i.array,l=new(0,o.constructor)(s*n);let c=0;for(const e of r){const t=e.start*n,r=e.count*n;for(let e=0;e<r;e++)l[c+e]=o[t+e];c+=r}const h=new _.BufferAttribute(l,n,i.normalized);a.setAttribute(t,h)}return a.groups=[{start:0,count:s,materialIndex:0}],a}const s=[];for(const e of r)for(let t=0;t<e.count;t++){const r=a.getX(e.start+t);s.push(r)}if(0===s.length)return new t;const i=new Map,n=[];let o=0;for(const e of s)i.has(e)||(i.set(e,o),o++),n.push(i.get(e));if(0===n.length||0===i.size)return new t;const l=new t;for(const t in e.attributes){const r=e.attributes[t],a=r.itemSize,s=r.array,n=new(0,s.constructor)(i.size*a);for(const[e,t]of i)for(let r=0;r<a;r++)n[t*a+r]=s[e*a+r];const o=new _.BufferAttribute(n,a,r.normalized);l.setAttribute(t,o)}const c=new((n.length>0?Math.max(...n):0)>65535?Uint32Array:Uint16Array)(n.length);for(let e=0;e<n.length;e++)c[e]=n[e];return l.setIndex(new _.BufferAttribute(c,1)),l.groups=[{start:0,count:n.length,materialIndex:0}],l}async loadByAsset(e){this.fbxLoader;const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then(t=>{const r=!0===e.originalFileKey?.toLowerCase().endsWith(".fbx")&&1===t.scene.children.length?t.scene.children[0]:t.scene;return r!==t.scene&&t.scene.remove(r),{scene:r,animations:t.animations}});case"fbx":if(this.directFileLoading){const e=await fetch(t);if(!e.ok)throw new Error(`Failed to load FBX ${t}: ${e.status}`);const r=await e.arrayBuffer(),a=this.fbxLoader.parse(r,_.LoaderUtils.extractUrlBase(t));return{scene:a,animations:a.animations}}return this.fbxLoader.loadAsync(t).then(e=>({scene:e,animations:e.animations}));case"obj":if(null!=e.materialLib){const t=new h;t.materialOptions={normalizeRGB:!1};const r=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(r)}return this.objLoader.loadAsync(t).then(e=>(N(e),e)).then(e=>({scene:e,animations:e.animations}))}}disposeAll(){this.cache.clear(),this._retrievedMeshes.forEach(e=>D(e)),this._retrievedTextures.forEach(e=>e.dispose()),this._retrievedMeshes.length=0,this._retrievedTextures.length=0}}const E=new Map;function $(e){E.set(e,(E.get(e)??0)+1)}function O(e){if(e.length<2)return!0;const t=e[0],r=Object.keys(t.attributes).sort(),a=Object.keys(t.morphAttributes).sort();return e.slice(1).every(e=>{if(null==e.index!=(null==t.index))return!1;if(e.morphTargetsRelative!==t.morphTargetsRelative)return!1;const s=Object.keys(e.attributes).sort(),i=Object.keys(e.morphAttributes).sort();if(s.join("|")!==r.join("|"))return!1;if(i.join("|")!==a.join("|"))return!1;for(const a of r){const r=t.getAttribute(a),s=e.getAttribute(a);if(r.itemSize!==s.itemSize||r.normalized!==s.normalized||r.array.constructor!==s.array.constructor)return!1}for(const r of a){const a=t.morphAttributes[r],s=e.morphAttributes[r];if(a.length!==s.length)return!1;for(let e=0;e<a.length;e++)if(a[e].itemSize!==s[e].itemSize||a[e].normalized!==s[e].normalized||a[e].array.constructor!==s[e].array.constructor)return!1}return!0})}function N(e){if(e instanceof i)for(const t of v(e.material))t instanceof _.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(N)}export class AssetMeshInstance extends n{}export function createAuthoredCollisionShapes(e,t=1){const a=null!=t&&0!==t?1/t:1;return e.map(e=>{let t;switch(e.type){case"box":t=new w((new c).fromArray(e.size).multiplyScalar(a));break;case"sphere":t=new A(e.radius*a);break;case"capsule":t=new x(e.length*a,e.radius*a);break;case"cylinder":t=new b(e.radius*a,e.radius*a,e.height*a,16,new r)}return t.source=M.custom,t.offset.fromArray(e.position??[0,0,0]).multiplyScalar(a),t.rotation.fromArray(e.rotation??[0,0,0,"XYZ"]),t})}export function getElectronArg(e){const t=`--${e}=`,r=window.process?.argv.find(e=>e.startsWith(t));return r?.substring(t.length)}function Y(e){switch(e){case"clamp":return _.ClampToEdgeWrapping;case"repeat":return _.RepeatWrapping;case"mirror":return _.MirroredRepeatWrapping}return _.RepeatWrapping}function q(e,t){const r=e;return!0!==r.isCompressedTexture&&!0!==r.isCompressedArrayTexture&&(t.texture?.flipY??!0)}function X(e){return e.texture?.colorSpace??function(e){if("exr"===e.fileFormat||e.fileKey?.toLowerCase().endsWith(".exr"))return"linear";const t=`${e.name} ${e.fileKey??""}`.toLowerCase();if(J.some(e=>t.includes(e)))return"linear";return"srgb"}(e)}function V(e){return"linear"===e?_.LinearSRGBColorSpace:_.SRGBColorSpace}const J=["_normal","_nrm","_nor","_norm","_roughness","_rough","_metalness","_metallic","_metal","_ao","_ambient","_occlusion","_mask","_height","_disp","_displacement","_bump","_opacity"];new _.Matrix4;const Z=[];const H=/_LOD(\d+)/;export function removeInvalidFaces(e){const t=e.getAttribute("position");if(null==t||t.itemSize<3)return 0;const r=e.index,a=r?.count??t.count,s=Math.floor(a/3),i=[],n=new Uint32Array(s+1),o=new c,l=new c,h=new c;let u=0;for(let e=0;e<s;e++){const a=3*e,s=r?.getX(a)??a,c=r?.getX(a+1)??a+1,m=r?.getX(a+2)??a+2;let d=Number.isInteger(s)&&Number.isInteger(c)&&Number.isInteger(m)&&s>=0&&c>=0&&m>=0&&s<t.count&&c<t.count&&m<t.count;if(d){o.fromBufferAttribute(t,s),l.fromBufferAttribute(t,c).sub(o),h.fromBufferAttribute(t,m).sub(o);const e=Math.max(l.lengthSq(),h.lengthSq(),l.distanceToSquared(h)),r=l.cross(h).lengthSq();d=Number.isFinite(e)&&Number.isFinite(r)&&e>0&&r>Number.EPSILON*e*e}d?i.push(s,c,m):u++,n[e+1]=i.length}if(0===u)return 0;if(e.setIndex(i),e.groups.length>0){const t=e.groups.slice();e.clearGroups();for(const r of t){const t=Math.max(0,Math.ceil(r.start/3)),a=Math.min(s,Math.floor((r.start+r.count)/3));if(a<=t)continue;const i=n[t],o=n[a]-i;o>0&&e.addGroup(i,o,r.materialIndex)}}const m=Math.max(0,Math.ceil(e.drawRange.start/3)),d=Number.isFinite(e.drawRange.count)?Math.min(s,Math.floor((e.drawRange.start+e.drawRange.count)/3)):s,f=Math.min(m,s),p=Math.min(s,Math.max(f,d)),g=n[f];return e.setDrawRange(g,n[p]-g),u}function Q(e){let t=e instanceof _.MeshPhysicalMaterial&&0===e.sheen&&0===e.anisotropy;if("MeshLambertMaterial"===e.type||"MeshPhongMaterial"===e.type||t){let t={};(e instanceof _.MeshLambertMaterial||e instanceof _.MeshPhongMaterial||e instanceof _.MeshPhysicalMaterial)&&(t.color=e.color,t.map=e.map,t.bumpMap=e.bumpMap,t.bumpScale=e.bumpScale,t.lightMap=e.lightMap,t.lightMapIntensity=e.lightMapIntensity,t.aoMap=e.aoMap,t.aoMapIntensity=e.aoMapIntensity,t.emissiveMap=e.emissiveMap,t.alphaMap=e.alphaMap,t.envMap=e.envMap,t.envMapRotation=e.envMapRotation,t.wireframe=e.wireframe,t.wireframeLinewidth=e.wireframeLinewidth,t.fog=e.fog,t.opacity=e.opacity,t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.alphaTest=e.alphaTest,t.displacementMap=e.displacementMap,t.displacementScale=e.displacementScale,t.displacementBias=e.displacementBias);const r=new _.MeshStandardMaterial(t);return r.userData={...e.userData??{}},r.name=e.name,r}return e}/*
1
+ import{AudioLoader as e,BufferGeometry as t,Euler as r,Group as a,LoadingManager as s,Mesh as i,Object3D as n,Texture as o,TextureLoader as l,Vector3 as c}from"three";import{MTLLoader as h,OBJLoader as u,LUTCubeLoader as m}from"three-stdlib";import{cloneMesh as d,mergeCompatibleSkinnedMeshes as p}from"../utils/mesh.js";import{pathJoin as f}from"../utils/files.js";import{Subject as g,firstValueFrom as y}from"rxjs";import{BoxCollisionShape as w,CapsuleCollisionShape as x,CollisionShapeSource as M,CylinderCollisionShape as b,SphereCollisionShape as A}from"./collision/collision-shape.js";import{importCollisionShapes as L,isCollisionMesh as S}from"./collision/collision-shape-import.js";import*as _ from"three";import{iterateMaterials as v}from"../utils/materials.js";import{applyMaterial as T,getConvertedFbxToGlbAssignedMaterialTextureFlipY as R}from"./materializer.js";import{BufferGeometryUtils as C,DRACOLoader as B,EXRLoader as P,FBXLoader as I,GLTFLoader as k,KTX2Loader as F,TGALoader as K,UltraHDRLoader as D}from"three/examples/jsm/Addons.js";import{disposeScene as j}from"../utils/three/cleanup.js";import{resolveAnimationRigBasisRotation as W,setAnimationClipRigId as U}from"../gameplay/animation/retarget.js";(()=>{const e=new Uint8Array([255,0,0,255]),t=new _.DataTexture(e,1,1,_.RGBAFormat);t.needsUpdate=!0})();const z=new B;z.setDecoderConfig({type:"js"}),z.setDecoderPath("/assets/draco/");const G=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new s,this.glbLoader=new k(this.loadingManager).setDRACOLoader(z),this.fbxLoader=new I(this.loadingManager),this.objLoader=new u(this.loadingManager),this.textureLoader=new l(this.loadingManager),this.tgaLoader=new K(this.loadingManager),this.exrLoader=new P(this.loadingManager),this.cubeLoader=new m(this.loadingManager),this.hdrLoader=new D(this.loadingManager),this.ktx2Loader=new F(this.loadingManager),this.ktx2Ready=Promise.resolve(),this._textureLoader=new _.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.initialisedKtx2=!1,this._retrievedMeshes=[],this._retrievedTextures=[],this.makeReady=new g,this.ready=y(this.makeReady),this.directFileLoading=!1,this._texturePromises=new Map,this._arrayTexturesByFileKey=new Map,this._arrayTexturePromisesByFileKey=new Map,this._arrayTextureSettingsByFileKey=new Map,this._animationPromises=new Map,this._animationCache=new Map,this.asyncMeshResults=new Map,this.asyncAudioResults=new Map,this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}setDirectFileLoading(e){this.directFileLoading=e}setImageBitmapDecoder(e){this.imageBitmapDecoder=e}decodeImageBitmap(e){return this.imageBitmapDecoder?.(e)}configureKtx2(){this.initialisedKtx2=!0;null!=getElectronArg("windowId")||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?this.ktx2Loader.setTranscoderPath("/assets/basis/"):this.ktx2Loader.setTranscoderPath(new URL("../assets/basis/",import.meta.url).href),this.ktx2Loader.setWorkerLimit(6)}initKtx2(e){this.configureKtx2(),this.ktx2Loader.detectSupport(e)}initKtx2ForWebGpu(){this.configureKtx2(),this.ktx2Ready=Promise.resolve(navigator.gpu?.requestAdapter({powerPreference:"high-performance"})??null).then(e=>{this.ktx2Loader.detectSupport({isWebGPURenderer:!0,hasFeature:t=>!0===e?.features.has(t)})})}setDataDir(e){this.basePath=f(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){if(e.startsWith("asset://"))return e;const t=function(e){return $.get(e)}(e),r=getElectronArg("windowId");return null!=r||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?f(this.basePath,e)+(null!=r?`?windowId=${r}${null!=t?`&v=${t}`:""}`:""):new URL(f("..",this.basePath,e),import.meta.url).href}async getTexture(e){if(!e||!e.fileKey)return null;if("png"===e.fileFormat||e.fileFormat,this._texturePromises.has(e.id))return this._texturePromises.get(e.id);const t=this._getTexture(e).finally(()=>{this._texturePromises.delete(e.id)});return this._texturePromises.set(e.id,t),t}async _getTexture(e){if(null==e||null==e.fileKey)return null;if(await this.ready,e.fileKey.toLowerCase().endsWith(".ktx2")&&await this.ktx2Ready,this.textureCache.has(e.id)){const t=this.textureCache.get(e.id);if(null!=e.texture){const r=q(t,e);t.flipY!==r?(t.needsUpdate=!0,t.flipY=r):t.wrapS!==Y(e.texture?.wrapS)?(t.needsUpdate=!0,t.wrapS=Y(e.texture?.wrapS)):t.wrapT!==Y(e.texture?.wrapT)&&(t.wrapT=Y(e.texture?.wrapT),t.needsUpdate=!0)}const r=V(X(e));t.colorSpace!==r&&(t.colorSpace=r,t.needsUpdate=!0)}else try{const t=this._getTextureLoader(e.fileKey),r=null!=this.imageBitmapDecoder&&/\.(png|jpe?g)$/i.test(e.fileKey),a=r||this.directFileLoading&&t===this.textureLoader,s=this.getUri(e.fileKey),i=r?this.imageBitmapDecoder(s).catch(t=>(console.warn(`Worker image decode failed for ${e.name}; falling back to ImageBitmapLoader`,t),this._textureLoader.loadAsync(s))):(a?this._textureLoader:t).loadAsync(s);await i.then(t=>(a&&((t=new o(t)).needsUpdate=!0),t.texture3D?t=t.texture3D:(t.wrapS=Y(e.texture?.wrapS),t.wrapT=Y(e.texture?.wrapT),t.flipY=q(t,e),t.colorSpace=V(X(e))),this.textureCache.set(e.id,t),this._retrievedTextures.push(t),t))}catch(t){return console.warn("Failed to load texture "+e.name,t),null}const t=this.textureCache.get(e.id);return null!=t&&(t.userData.assetId=e.id),t}async getTextureArray(e){const t=e.texture?.textureArrayFileKey,r=e.texture?.textureArrayLayer;if(!t||null==r)return{texture:null,layerIndex:null};let a=this._arrayTexturesByFileKey.get(t);if(null==a){let e=this._arrayTexturePromisesByFileKey.get(t);null==e&&(e=this.loadTextureArray(t).finally(()=>{this._arrayTexturePromisesByFileKey.delete(t)}),this._arrayTexturePromisesByFileKey.set(t,e)),a=await e}return this.applyTextureArraySettings(t,a,e),{texture:a,layerIndex:r}}async loadTextureArray(e){const t=this._getTextureLoader(e);let r=await t.loadAsync(this.getUri(e));return r instanceof o||(r=r.texture3D),this._arrayTexturesByFileKey.set(e,r),this._retrievedTextures.push(r),r}applyTextureArraySettings(e,t,r){const a=function(e){return{wrapS:Y(e.texture?.wrapS),wrapT:Y(e.texture?.wrapT)}}(r),s=this._arrayTextureSettingsByFileKey.get(e);if(null!=s&&(n=a,(i=s).wrapS!==n.wrapS||i.wrapT!==n.wrapT))return void console.warn(`Texture array ${e} is used with incompatible texture settings. Texture arrays share wrapping; rebuild arrays so incompatible textures are grouped separately.`);var i,n;null==s&&this._arrayTextureSettingsByFileKey.set(e,a);let o=!1;t.wrapS!==a.wrapS&&(t.wrapS=a.wrapS,o=!0),t.wrapT!==a.wrapT&&(t.wrapT=a.wrapT,o=!0),!1!==t.flipY&&(t.flipY=!1,o=!0),o&&(t.needsUpdate=!0)}_getTextureLoader(e){return e?.toLowerCase().endsWith(".tga")?this.tgaLoader:e?.toLowerCase().endsWith(".ktx2")?this.ktx2Loader:e?.toLowerCase().endsWith(".exr")?this.exrLoader:e?.toLowerCase().endsWith(".cube")?this.cubeLoader:this.textureLoader}clearCache(e){this.clearCacheByAsset(e)}clearCacheByAsset(e){null!=e&&(this.clearCacheById(e.id),null!=e.fileKey&&(Array.from(this.cache.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.cache.delete(t)}),Array.from(this.asyncMeshResults.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.asyncMeshResults.delete(t)}),Array.from(this._animationCache.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationCache.delete(t)}),Array.from(this._animationPromises.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationPromises.delete(t)}),E(e.fileKey)),null!=e.materialLib&&E(e.materialLib))}clearCacheById(e){const t=Array.from(this.cache.values()).find(t=>t.scene.userData.assetId===e);t&&Array.from(this.cache.keys()).forEach(e=>{this.cache.get(e)===t&&this.cache.delete(e)}),this.textureCache.delete(e),this._texturePromises.delete(e),Array.from(this.collisionShapeCache.keys()).forEach(t=>{t.startsWith(e+"|")&&this.collisionShapeCache.delete(t)})}async getMesh(e,t){if(await this.ready,null==e)return console.error("No asset was provided"),{scene:new a,animations:[]};if(!G.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new a,animations:[]};const r=e.fileKey+(!0===t?.mergeGeomtries?"1":"0");if(!this.cache.has(r))try{this.asyncMeshResults.has(r)||this.asyncMeshResults.set(r,this.loadMesh(e).finally(()=>this.asyncMeshResults.delete(r))),this.cache.set(r,await this.asyncMeshResults.get(r))}catch(e){return this.onError(e),{scene:new a,animations:[]}}const s=this.cache.get(r),n=s.scene,o=s.animations;if(!1===t?.clone)return{scene:n,animations:o};const l=this.computeCollisionShapes(e,n),c=(e.mesh?.secondaryMotion?.regions.length??0)>0;!0!==t?.mergeGeomtries||c||this.optimizeDrawGroups(n);const h=d(n);h.traverse(e=>{e instanceof i&&e.material instanceof Array&&(e.material=e.material.slice())});const u=new AssetMeshInstance;u.add(h),u.collisionShapes=l,u.animations=o,u.userData.assetId=e.id,u.userData.secondaryMotion=e.mesh?.secondaryMotion,function(e){const t=e.children.length>0?e.children:[e];for(let e=0;e<t.length;e++)r(t[e],"",e);function r(e,t,a){const s=e instanceof i?"Mesh":"Group",n=`${t}/${e.name?.trim()?.length>0?e.name:s}[${a}]`;e.userData.secondaryMotionMeshPath=n;for(let t=0;t<e.children.length;t++)r(e.children[t],n,t)}}(u);const m=e.mesh?.animationRigId??e.anim?.rigId;if(u.userData.animationRigId=m,h.userData.animationRigId=m,null!=m&&null!=this.animationRigProvider){const e=await this.animationRigProvider(m);u.userData.animationRig=e,h.userData.animationRig=e,null!=e&&!1!==t?.applyRigBasis&&u.quaternion.copy(W(e))}const p=e.receiveShadow??!1,f=e.castShadow??!1;if(h.traverse(e=>{e.castShadow=f,e.receiveShadow=p}),!0===t?.rescale&&"number"==typeof e.mesh?.rescale&&u.scale.setScalar(e.mesh?.rescale),!0===t?.applyMaterials){const r=t?.materialResolver??this.materialProvider;if(null!=r)for(const t of e.materialAssignments??[])await T(u,t,r,void 0,{textureFlipY:R(e)});else console.warn(`applyMaterials was set to true for ${e.name} but no material resolver was provided.`)}return{scene:u,animations:o}}async getAudio(e){await this.ready;const t=e.fileKey;if(this.asyncAudioResults.has(t))return await this.asyncAudioResults.get(t);const r=this.audioLoader.loadAsync(this.getUri(e.fileKey)).finally(()=>{setTimeout(()=>{this.asyncAudioResults.delete(t)},1e3)});return this.asyncAudioResults.set(t,r),r}async getAnimationClip(e){if(null==e||null==e.fileKey||null==e.anim?.clip)return console.warn("Asset or animation clip name is not defined",e),null;const t=e.anim.clip,r=e.fileKey+"|"+t;if(this._animationCache.has(r))return this._animationCache.get(r);if(this._animationPromises.has(r))return this._animationPromises.get(r);const a=(async()=>{try{const a=await this.getMesh(e),s=a.animations.find(e=>e.name===t);return null!=s&&(U(s,e.anim?.rigId),this._animationCache.set(r,s)),s}catch(e){return this.onError(e),null}finally{setTimeout(()=>this._animationPromises.delete(r),1e3)}})();return this._animationPromises.set(r,a),a}computeCollisionShapes(e,t){if(!0!==e.collisionDetection)return[];const r=e.id+"|"+(e.mesh?.collisions?.shapeType??"")+"|"+(e.mesh?.rescale??1)+"|"+JSON.stringify(e.mesh?.colliders??[]);if(!this.collisionShapeCache.has(r)){const a=e.mesh?.colliders??[],s=a.length>0?createAuthoredCollisionShapes(a,e.mesh?.rescale):L(t,e);this.collisionShapeCache.set(r,s)}return this.collisionShapeCache.get(r)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then(r=>(r.scene.traverse(r=>{if(r instanceof i&&r.geometry instanceof t){const t=removeInvalidFaces(r.geometry);t>0&&console.warn(`Removed ${t} invalid face${1===t?"":"s"} from ${e.name}/${r.name||"unnamed mesh"}`)}r instanceof i&&r.material&&function(e){let t=e.material;if(null==t)return;Array.isArray(t)?e.material=t.map(Q):e.material=Q(t)}(r),S(r)?r.visible=!1:r instanceof i&&r.geometry instanceof t&&(r.geometry.hasAttribute("normal")||r.geometry.computeVertexNormals())}),this._retrievedMeshes.push(r.scene),r.scene=function(e,t){let r=!1;if(t.traverseVisible(e=>{H.test(e.name)&&(r=!0)}),!r)return t;const a=[],s=[t];for(;s.length>0;){const e=s.shift(),t=e.name.match(H);if(null!=t){const r=parseInt(t[1]);if(0!==r){console.warn(`Skipping LOD level ${r} for now as LOD is not fully supported`),a.push(e);continue}}s.push(...e.children)}for(const e of a)e.removeFromParent();return t}(0,r.scene),function(e){const t=Z;Z.length=0,e.traverse(e=>{(e instanceof _.Camera||e instanceof _.Light)&&t.push(e)}),t.forEach(e=>e.removeFromParent())}(r.scene),r.scene.userData.assetId=e.id,r))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid),e.updateWorldMatrix(!0,!0);const r=[];e.traverse(e=>{e instanceof i&&!(e instanceof _.SkinnedMesh)&&e.geometry instanceof t&&Array.isArray(e.material)&&!S(e)&&r.push({mesh:e,geometry:e.geometry,materialArray:e.material,parent:e.parent})});for(const{mesh:t,geometry:a,materialArray:s,parent:n}of r){t.removeFromParent();for(let r=0;r<s.length;r++){const o=s[r],l=a.groups.filter(e=>e.materialIndex===r);if(0===l.length)continue;const c=this.extractGeometryGroups(a,l);c.groups.length>1&&C.mergeGroups(c);const h=new i(c,o);h.copy(t,!1),h.geometry=c,h.material=o,n?n.add(h):e.add(h)}a.dispose()}p(e,S);let a=!0,s=0,n=0;if(e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!S(e)){s++;const t=Object.keys(e.geometry.attributes).length;t!==n&&0!==n&&(a=!1),n=t}else(e instanceof _.SkinnedMesh||e instanceof _.Bone)&&(a=!1)}),s>1&&a){const r=new Map;e.traverse(a=>{if(a instanceof i&&a.geometry instanceof t&&!S(a)){if(Array.isArray(a.material))return;a.updateWorldMatrix(!0,!0);const t=a.material?.uuid||"default";r.has(t)||r.set(t,{material:a.material,geometries:[],objects:[]});const s=r.get(t),i=e.matrixWorld.clone().invert().multiply(a.matrixWorld);s.geometries.push(a.geometry.clone().applyMatrix4(i)),s.objects.push(a)}});for(const e of r.values())for(const t of e.objects)t.removeFromParent();for(const t of r.values()){let r,a=t.geometries;if(a.some(e=>null!=e.index)&&(a=a.map(e=>{if(null!=e.index)return e;const t=e.getAttribute("position");if(null==t)return e;const r=t.count>65535?new Uint32Array(t.count):new Uint16Array(t.count);for(let e=0;e<r.length;e++)r[e]=e;return e.setIndex(new _.BufferAttribute(r,1)),e})),r=1===t.geometries.length?a[0]:O(a)?C.mergeGeometries(a,!0):null,null!=r)r.groups.length>1&&C.mergeGroups(r),e.add(new i(r,t.material));else for(const r of a)e.add(new i(r,t.material))}}e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!S(e)){const t=e.geometry;!Array.isArray(e.material)&&t.groups.length>1&&C.mergeGroups(t)}})}extractGeometryGroups(e,r){const a=e.index;if(!a){const a=new t;let s=0;for(const e of r)s+=e.count;if(0===s)return a;for(const t in e.attributes){const i=e.attributes[t],n=i.itemSize,o=i.array,l=new(0,o.constructor)(s*n);let c=0;for(const e of r){const t=e.start*n,r=e.count*n;for(let e=0;e<r;e++)l[c+e]=o[t+e];c+=r}const h=new _.BufferAttribute(l,n,i.normalized);a.setAttribute(t,h)}return a.groups=[{start:0,count:s,materialIndex:0}],a}const s=[];for(const e of r)for(let t=0;t<e.count;t++){const r=a.getX(e.start+t);s.push(r)}if(0===s.length)return new t;const i=new Map,n=[];let o=0;for(const e of s)i.has(e)||(i.set(e,o),o++),n.push(i.get(e));if(0===n.length||0===i.size)return new t;const l=new t;for(const t in e.attributes){const r=e.attributes[t],a=r.itemSize,s=r.array,n=new(0,s.constructor)(i.size*a);for(const[e,t]of i)for(let r=0;r<a;r++)n[t*a+r]=s[e*a+r];const o=new _.BufferAttribute(n,a,r.normalized);l.setAttribute(t,o)}const c=new((n.length>0?Math.max(...n):0)>65535?Uint32Array:Uint16Array)(n.length);for(let e=0;e<n.length;e++)c[e]=n[e];return l.setIndex(new _.BufferAttribute(c,1)),l.groups=[{start:0,count:n.length,materialIndex:0}],l}async loadByAsset(e){this.fbxLoader;const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then(t=>{const r=!0===e.originalFileKey?.toLowerCase().endsWith(".fbx")&&1===t.scene.children.length?t.scene.children[0]:t.scene;return r!==t.scene&&t.scene.remove(r),{scene:r,animations:t.animations}});case"fbx":if(this.directFileLoading){const e=await fetch(t);if(!e.ok)throw new Error(`Failed to load FBX ${t}: ${e.status}`);const r=await e.arrayBuffer(),a=this.fbxLoader.parse(r,_.LoaderUtils.extractUrlBase(t));return{scene:a,animations:a.animations}}return this.fbxLoader.loadAsync(t).then(e=>({scene:e,animations:e.animations}));case"obj":if(null!=e.materialLib){const t=new h;t.materialOptions={normalizeRGB:!1};const r=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(r)}return this.objLoader.loadAsync(t).then(e=>(N(e),e)).then(e=>({scene:e,animations:e.animations}))}}disposeAll(){this.cache.clear(),this._retrievedMeshes.forEach(e=>j(e)),this._retrievedTextures.forEach(e=>e.dispose()),this._retrievedMeshes.length=0,this._retrievedTextures.length=0}}const $=new Map;function E(e){$.set(e,($.get(e)??0)+1)}function O(e){if(e.length<2)return!0;const t=e[0],r=Object.keys(t.attributes).sort(),a=Object.keys(t.morphAttributes).sort();return e.slice(1).every(e=>{if(null==e.index!=(null==t.index))return!1;if(e.morphTargetsRelative!==t.morphTargetsRelative)return!1;const s=Object.keys(e.attributes).sort(),i=Object.keys(e.morphAttributes).sort();if(s.join("|")!==r.join("|"))return!1;if(i.join("|")!==a.join("|"))return!1;for(const a of r){const r=t.getAttribute(a),s=e.getAttribute(a);if(r.itemSize!==s.itemSize||r.normalized!==s.normalized||r.array.constructor!==s.array.constructor)return!1}for(const r of a){const a=t.morphAttributes[r],s=e.morphAttributes[r];if(a.length!==s.length)return!1;for(let e=0;e<a.length;e++)if(a[e].itemSize!==s[e].itemSize||a[e].normalized!==s[e].normalized||a[e].array.constructor!==s[e].array.constructor)return!1}return!0})}function N(e){if(e instanceof i)for(const t of v(e.material))t instanceof _.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(N)}export class AssetMeshInstance extends n{}export function createAuthoredCollisionShapes(e,t=1){const a=null!=t&&0!==t?1/t:1;return e.map(e=>{let t;switch(e.type){case"box":t=new w((new c).fromArray(e.size).multiplyScalar(a));break;case"sphere":t=new A(e.radius*a);break;case"capsule":t=new x(e.length*a,e.radius*a);break;case"cylinder":t=new b(e.radius*a,e.radius*a,e.height*a,16,new r)}return t.source=M.custom,t.offset.fromArray(e.position??[0,0,0]).multiplyScalar(a),t.rotation.fromArray(e.rotation??[0,0,0,"XYZ"]),t})}export function getElectronArg(e){const t=`--${e}=`,r=window.process?.argv.find(e=>e.startsWith(t));return r?.substring(t.length)}function Y(e){switch(e){case"clamp":return _.ClampToEdgeWrapping;case"repeat":return _.RepeatWrapping;case"mirror":return _.MirroredRepeatWrapping}return _.RepeatWrapping}function q(e,t){const r=e;return!0!==r.isCompressedTexture&&!0!==r.isCompressedArrayTexture&&(t.texture?.flipY??!0)}function X(e){return e.texture?.colorSpace??function(e){if("exr"===e.fileFormat||e.fileKey?.toLowerCase().endsWith(".exr"))return"linear";const t=`${e.name} ${e.fileKey??""}`.toLowerCase();if(J.some(e=>t.includes(e)))return"linear";return"srgb"}(e)}function V(e){return"linear"===e?_.LinearSRGBColorSpace:_.SRGBColorSpace}const J=["_normal","_nrm","_nor","_norm","_roughness","_rough","_metalness","_metallic","_metal","_ao","_ambient","_occlusion","_mask","_height","_disp","_displacement","_bump","_opacity"];new _.Matrix4;const Z=[];const H=/_LOD(\d+)/;export function removeInvalidFaces(e){const t=e.getAttribute("position");if(null==t||t.itemSize<3)return 0;const r=e.index,a=r?.count??t.count,s=Math.floor(a/3),i=[],n=new Uint32Array(s+1),o=new c,l=new c,h=new c;let u=0;for(let e=0;e<s;e++){const a=3*e,s=r?.getX(a)??a,c=r?.getX(a+1)??a+1,m=r?.getX(a+2)??a+2;let d=Number.isInteger(s)&&Number.isInteger(c)&&Number.isInteger(m)&&s>=0&&c>=0&&m>=0&&s<t.count&&c<t.count&&m<t.count;if(d){o.fromBufferAttribute(t,s),l.fromBufferAttribute(t,c).sub(o),h.fromBufferAttribute(t,m).sub(o);const e=Math.max(l.lengthSq(),h.lengthSq(),l.distanceToSquared(h)),r=l.cross(h).lengthSq();d=Number.isFinite(e)&&Number.isFinite(r)&&e>0&&r>Number.EPSILON*e*e}d?i.push(s,c,m):u++,n[e+1]=i.length}if(0===u)return 0;if(e.setIndex(i),e.groups.length>0){const t=e.groups.slice();e.clearGroups();for(const r of t){const t=Math.max(0,Math.ceil(r.start/3)),a=Math.min(s,Math.floor((r.start+r.count)/3));if(a<=t)continue;const i=n[t],o=n[a]-i;o>0&&e.addGroup(i,o,r.materialIndex)}}const m=Math.max(0,Math.ceil(e.drawRange.start/3)),d=Number.isFinite(e.drawRange.count)?Math.min(s,Math.floor((e.drawRange.start+e.drawRange.count)/3)):s,p=Math.min(m,s),f=Math.min(s,Math.max(p,d)),g=n[p];return e.setDrawRange(g,n[f]-g),u}function Q(e){let t=e instanceof _.MeshPhysicalMaterial&&0===e.sheen&&0===e.anisotropy;if("MeshLambertMaterial"===e.type||"MeshPhongMaterial"===e.type||t){let t={};(e instanceof _.MeshLambertMaterial||e instanceof _.MeshPhongMaterial||e instanceof _.MeshPhysicalMaterial)&&(t.color=e.color,t.map=e.map,t.bumpMap=e.bumpMap,t.bumpScale=e.bumpScale,t.lightMap=e.lightMap,t.lightMapIntensity=e.lightMapIntensity,t.aoMap=e.aoMap,t.aoMapIntensity=e.aoMapIntensity,t.emissiveMap=e.emissiveMap,t.alphaMap=e.alphaMap,t.envMap=e.envMap,t.envMapRotation=e.envMapRotation,t.wireframe=e.wireframe,t.wireframeLinewidth=e.wireframeLinewidth,t.fog=e.fog,t.opacity=e.opacity,t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.alphaTest=e.alphaTest,t.displacementMap=e.displacementMap,t.displacementScale=e.displacementScale,t.displacementBias=e.displacementBias);const r=new _.MeshStandardMaterial(t);return r.userData={...e.userData??{}},r.name=e.name,r}return e}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{Color as e,Euler as a,Vector2 as r,Vector3 as u,Vector4 as t}from"three";import{getParameterDefinitionType as l,isParameterDefinitionAbstract as n}from"../shader/parameter.js";import{Curve2 as s}from"../utils/curve.js";import{isSequenceData as c,Sequence as o}from"../effects/sequence/sequence-data.js";import{SerializedParamType as v}from"./model.js";export function customParamValueNeedsAsyncResolution(e){if(null==e||null==e.value||""===e.value)return!1;if(i(e))return e.value.some(a=>customParamValueNeedsAsyncResolution(f(e,a)));switch(e.type){case v.Texture:case v.Sampler2DNode:case v.Object3D:case v.Material:case v.AudioBuffer:case v.VisualEffect:case v.Prefab:case v.PrefabActor:case v.DataAsset:case v.AnimationClip:return!0;case v.Sequence:return!c(e.value);case v.SequenceData:return!1;case v.Struct:return Object.values(y(e.value)).some(e=>customParamValueNeedsAsyncResolution(e));default:return!1}}export function deserializeCustomParamValueSync(l,n={}){if(null==l||null==l.value||""===l.value)return l?.value??null;switch(l.type){case v.Array:return i(l)&&Array.isArray(l.value)?l.value.map(e=>deserializeCustomParamValueSync(f(l,e),n)):[];case v.Number:case v.FloatNode:return"string"==typeof l.value?parseFloat(l.value):l.value;case v.Boolean:case v.BooleanNode:case v.String:return l.value;case v.Vector2:case v.Vec2Node:return"object"==typeof l.value?Array.isArray(l.value)?(new r).fromArray(l.value):new r(l.value.x,l.value.y):null;case v.Vector3:case v.Vec3Node:return"object"==typeof l.value?Array.isArray(l.value)?(new u).fromArray(l.value):new u(l.value.x,l.value.y,l.value.z):null;case v.Vector4:case v.Vec4Node:return"object"==typeof l.value?Array.isArray(l.value)?(new t).fromArray(l.value):new t(l.value.x,l.value.y,l.value.z,l.value.w):null;case v.Color:case v.RgbNode:return new e(l.value);case v.Euler:return Array.isArray(l.value)?(new a).fromArray(l.value):l.value;case v.BaseActor:return n.actor?.(l.value)??l.value;case v.Sequence:return c(l.value)?new o(l.value):l.value;case v.SequenceData:return c(l.value)?l.value:null;case v.Curve:return s.decode(l.value);case v.Struct:return function(e,a){const r=A(e.value),u=m(r?.struct??e.struct);for(const[t,l]of Object.entries(r?.value??y(e.value)))u[t]=deserializeCustomParamValueSync(l,a);return u}(l,n);default:return l.value}}export async function deserializeCustomParamValue(e,a={}){if(null==e||null==e.value||""===e.value)return e?.value??null;if(!customParamValueNeedsAsyncResolution(e))return deserializeCustomParamValueSync(e,a);switch(e.type){case v.Array:return i(e)&&Array.isArray(e.value)?Promise.all(e.value.map(r=>deserializeCustomParamValue(f(e,r),a))):[];case v.Texture:return a.texture?.(e.value)??null;case v.Sampler2DNode:return a.sampler2DNode?.(e.value)??null;case v.Object3D:return a.object3D?.(e.value)??null;case v.Material:return a.material?.(e.value)??null;case v.AudioBuffer:return a.audioBuffer?.(e.value)??null;case v.VisualEffect:return a.visualEffect?.(e.value)??null;case v.Prefab:return a.prefab?.(e.value)??null;case v.PrefabActor:return a.prefabActor?.(e.value)??null;case v.DataAsset:return a.dataAsset?.(e.value)??null;case v.Sequence:return c(e.value)?new o(e.value):a.sequence?.(e.value)??null;case v.SequenceData:return c(e.value)?e.value:null;case v.AnimationClip:return a.animationClip?.(e.value)??null;case v.Struct:return async function(e,a){const r=A(e.value),u=m(r?.struct??e.struct);for(const[t,l]of Object.entries(r?.value??y(e.value)))u[t]=await deserializeCustomParamValue(l,a);return u}(e,a);default:return deserializeCustomParamValueSync(e,a)}}function i(e){return e.type===v.Array}function f(e,a){const r=A(a);return{type:e.element,...null!=r?.struct||null!=e.elementStruct?{struct:r?.struct??e.elementStruct}:{},value:r?.value??a}}function m(e){const a=null!=e?l(e):void 0;if(null==a||n(e))return{};try{return new a}catch{return{}}}function y(e){const a=A(e);return null!=a?a.value:p(e)?e:null!=e&&"object"==typeof e&&p(e.params)?e.params:{}}function A(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)&&"string"==typeof e.struct&&p(e.value)?e:null}function p(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)&&Object.values(e).every(e=>null!=e&&"object"==typeof e&&"type"in e)}/*
1
+ import{Color as e,Euler as a,Vector2 as r,Vector3 as u,Vector4 as t}from"three";import{getParameterDefinitionType as l,isParameterDefinitionAbstract as n}from"../shader/parameter.js";import{Curve2 as s}from"../utils/curve.js";import{isSequenceData as c,Sequence as o}from"../effects/sequence/sequence-data.js";import{SerializedParamType as v}from"./model.js";import{ModelRef as i}from"./model-ref.js";export function customParamValueNeedsAsyncResolution(e){if(null==e||null==e.value||""===e.value)return!1;if(f(e))return e.value.some(a=>customParamValueNeedsAsyncResolution(m(e,a)));switch(e.type){case v.Texture:case v.Sampler2DNode:case v.Object3D:case v.Material:case v.AudioBuffer:case v.VisualEffect:case v.Prefab:case v.PrefabActor:case v.DataAsset:case v.AnimationClip:return!0;case v.Sequence:return!c(e.value);case v.SequenceData:return!1;case v.Struct:return Object.values(p(e.value)).some(e=>customParamValueNeedsAsyncResolution(e));default:return!1}}export function deserializeCustomParamValueSync(l,n={}){if(null==l||null==l.value||""===l.value)return l?.value??null;switch(l.type){case v.Array:return f(l)&&Array.isArray(l.value)?l.value.map(e=>deserializeCustomParamValueSync(m(l,e),n)):[];case v.Number:case v.FloatNode:return"string"==typeof l.value?parseFloat(l.value):l.value;case v.Boolean:case v.BooleanNode:case v.String:return l.value;case v.Vector2:case v.Vec2Node:return"object"==typeof l.value?Array.isArray(l.value)?(new r).fromArray(l.value):new r(l.value.x,l.value.y):null;case v.Vector3:case v.Vec3Node:return"object"==typeof l.value?Array.isArray(l.value)?(new u).fromArray(l.value):new u(l.value.x,l.value.y,l.value.z):null;case v.Vector4:case v.Vec4Node:return"object"==typeof l.value?Array.isArray(l.value)?(new t).fromArray(l.value):new t(l.value.x,l.value.y,l.value.z,l.value.w):null;case v.Color:case v.RgbNode:return new e(l.value);case v.Euler:return Array.isArray(l.value)?(new a).fromArray(l.value):l.value;case v.BaseActor:return n.actor?.(l.value)??l.value;case v.ModelRef:return"string"==typeof l.value?new i(l.value):null;case v.Sequence:return c(l.value)?new o(l.value):l.value;case v.SequenceData:return c(l.value)?l.value:null;case v.Curve:return s.decode(l.value);case v.Struct:return function(e,a){const r=A(e.value),u=y(r?.struct??e.struct);for(const[t,l]of Object.entries(r?.value??p(e.value)))u[t]=deserializeCustomParamValueSync(l,a);return u}(l,n);default:return l.value}}export async function deserializeCustomParamValue(e,a={}){if(null==e||null==e.value||""===e.value)return e?.value??null;if(!customParamValueNeedsAsyncResolution(e))return deserializeCustomParamValueSync(e,a);switch(e.type){case v.Array:return f(e)&&Array.isArray(e.value)?Promise.all(e.value.map(r=>deserializeCustomParamValue(m(e,r),a))):[];case v.Texture:return a.texture?.(e.value)??null;case v.Sampler2DNode:return a.sampler2DNode?.(e.value)??null;case v.Object3D:return a.object3D?.(e.value)??null;case v.Material:return a.material?.(e.value)??null;case v.AudioBuffer:return a.audioBuffer?.(e.value)??null;case v.VisualEffect:return a.visualEffect?.(e.value)??null;case v.Prefab:return a.prefab?.(e.value)??null;case v.PrefabActor:return a.prefabActor?.(e.value)??null;case v.DataAsset:return a.dataAsset?.(e.value)??null;case v.Sequence:return c(e.value)?new o(e.value):a.sequence?.(e.value)??null;case v.SequenceData:return c(e.value)?e.value:null;case v.AnimationClip:return a.animationClip?.(e.value)??null;case v.Struct:return async function(e,a){const r=A(e.value),u=y(r?.struct??e.struct);for(const[t,l]of Object.entries(r?.value??p(e.value)))u[t]=await deserializeCustomParamValue(l,a);return u}(e,a);default:return deserializeCustomParamValueSync(e,a)}}function f(e){return e.type===v.Array}function m(e,a){const r=A(a);return{type:e.element,...null!=r?.struct||null!=e.elementStruct?{struct:r?.struct??e.elementStruct}:{},value:r?.value??a}}function y(e){const a=null!=e?l(e):void 0;if(null==a||n(e))return{};try{return new a}catch{return{}}}function p(e){const a=A(e);return null!=a?a.value:d(e)?e:null!=e&&"object"==typeof e&&d(e.params)?e.params:{}}function A(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)&&"string"==typeof e.struct&&d(e.value)?e:null}function d(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)&&Object.values(e).every(e=>null!=e&&"object"==typeof e&&"type"in e)}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{Color as e,Euler as r,Material as t,Object3D as n,Texture as u,Vector2 as o,Vector3 as a,Vector4 as c,AnimationClip as l}from"three";import{BooleanNode as i,FloatNode as s,RgbNode as f,Sampler2DNode as y,Texture2dLookupNode as p,Vec2Node as m,Vec3Node as d,Vec4Node as b}from"three-shader-graph";import{getParameterDefinitionId as A,getParameterDefinitionType as g,isParameterDefinitionStructAssignableTo as S}from"../shader/parameter.js";import{Curve2 as N}from"../utils/curve.js";import{isSequenceData as V}from"../effects/sequence/sequence-data.js";import{SerializedParamType as v}from"./model.js";export const applyRuntimeParamTypeInference=!0;export function convertConfiguredParamsToRuntimeTypes(e,r={}){const t={},n=[],u=Object.entries(e),o=r.applyRuntimeParamTypeInference??true;if(0===u.length||!o)return o?{params:t,skipped:n}:{params:e,skipped:n};const a=getRuntimeParameterTypeHints(e,r);for(const[e,r]of u){const u=a.get(e),o=P(r,u);if(null==o)continue;if(!1===o.override){t[e]=o;continue}const c=null!=u?convertConfiguredParamValueToRuntimeType(o,u):o;null!=c?t[e]=c:n.push({key:e,sourceType:o.type,targetType:u.type})}return{params:t,skipped:n}}function P(e,r){return function(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)&&"number"==typeof e.type&&"value"in e}(e)?e:r?.type===v.SequenceData&&V(e)?{type:v.SequenceData,value:e}:null}export function getRuntimeParameterTypeHints(e,r={}){const t=new Map,n=Object.keys(e).filter(r=>!1!==e[r]?.override);if(0===n.length)return t;const u=new Set(n),o=r.parameterTarget??function(e){if(null==e)return null;try{return new e}catch{return null}}(r.parameterType),a=function(e,r){if(null!=r.propertyParams)return r.propertyParams;if(null==r.extractPropertyParameters)return[];if(null!=r.parameterType)return R(r.parameterType,r.extractPropertyParameters);if(null!=e)return R(e.constructor,r.extractPropertyParameters);return[]}(o,r);for(const e of a){if(!u.has(e.name))continue;const n=w(e,r.toSerializedParamType);null!=n&&t.set(e.name,n);const a=inferRuntimeSerializedParamTypeHint(j(o,e.name))??inferRuntimeSerializedParamTypeHint(e.options.defaultValue);null!=a&&t.set(e.name,x(a,n))}if(null!=o)for(const e of n){const r=inferRuntimeSerializedParamTypeHint(j(o,e));if(null!=r){const n=t.get(e);t.set(e,x(r,n))}}return t}const T=new WeakMap,h=new WeakMap,C=Symbol("noCachedSerializedParamType");function R(e,r){let t=T.get(r);null==t&&(t=new WeakMap,T.set(r,t));const n=t.get(e);if(null!=n)return n;const u=function(e,r){try{return r(e)}catch{return[]}}(e,r);return t.set(e,u),u}function j(e,r){return null!=e?e[r]:void 0}function w(e,r){const t=function(e,r){if(null==e||null==r)return;const t=function(e,r){const t=h.get(r);if(null==t||!t.has(e))return C;const n=t.get(e);return null===n?void 0:n}(e,r);if(t!==C)return t;try{const t=r(e);return D(e,r,t),t}catch{return void D(e,r,void 0)}}(e.type,r),n=t===v.Struct?A(e.type):void 0;return!0===e.options.array?{type:v.Array,...null!=t?{element:t}:{},...null!=n?{elementStruct:n}:{}}:null!=t?{type:t,...null!=n?{struct:n}:{}}:void 0}function D(e,r,t){let n=h.get(r);null==n&&(n=new WeakMap,h.set(r,n)),n.set(e,t??null)}function x(e,r){return e.type!==v.Array?e:{type:v.Array,element:e.element??r?.element,elementStruct:e.elementStruct??r?.elementStruct}}export function inferRuntimeSerializedParamTypeHint(g){if(null==g)return;if(Array.isArray(g)){const e=g.map(e=>inferRuntimeSerializedParamTypeHint(e)).find(e=>null!=e);return{type:v.Array,...null!=e&&e.type!==v.Array?{element:e.type}:{},...null!=e?.struct?{elementStruct:e.struct}:{}}}switch(typeof g){case"number":return{type:v.Number};case"boolean":return{type:v.Boolean};case"string":return{type:v.String}}const S=function(e){const r=e;if(e instanceof s||"function"==typeof r?.isFloat||!0===r?.isFloat)return v.FloatNode;if(e instanceof i||"function"==typeof r?.isBool||!0===r?.isBool)return v.BooleanNode;if(e instanceof f||"function"==typeof r?.isRgb||!0===r?.isRgb)return v.RgbNode;if(e instanceof m||"function"==typeof r?.isVec2||!0===r?.isVec2)return v.Vec2Node;if(e instanceof d||"function"==typeof r?.isVec3||!0===r?.isVec3)return v.Vec3Node;if(e instanceof b||"function"==typeof r?.isVec4||!0===r?.isVec4)return v.Vec4Node;if(e instanceof y||e instanceof p||"function"==typeof r?.isSampler2D||!0===r?.isSampler2D)return v.Sampler2DNode;return}(g);if(null!=S)return{type:S};if(g instanceof o)return{type:v.Vector2};if(g instanceof a)return{type:v.Vector3};if(g instanceof c)return{type:v.Vector4};if(g instanceof e)return{type:v.Color};if(g instanceof r)return{type:v.Euler};if(g instanceof u)return{type:v.Texture};if(g instanceof t)return{type:v.Material};if(g instanceof n)return{type:v.Object3D};if("undefined"!=typeof AudioBuffer&&g instanceof AudioBuffer)return{type:v.AudioBuffer};if(X(g,"VisualEffect"))return{type:v.VisualEffect};if(X(g,"PrefabOf"))return{type:v.PrefabActor};if(X(g,"Prefab"))return{type:v.Prefab};if(X(g,"DataAssetRef"))return{type:v.DataAsset};if(g instanceof N)return{type:v.Curve};if(X(g,"ColorLayer"))return{type:v.ColorLayer};if(X(g,"MaskLayer"))return{type:v.MaskLayer};if(g instanceof l)return{type:v.AnimationClip};if(X(g,"Sequence"))return{type:v.Sequence};if(V(g))return{type:v.SequenceData};const P=A(g.constructor);return null!=P?{type:v.Struct,struct:P}:void 0}export function convertConfiguredParamValueToRuntimeType(e,r){if(null==e||null==r)return e;if(e.type===v.Array||r.type===v.Array)return function(e,r){if(r.type===v.Array){const t=B(e),n=r.element??(t?e.element:e.type);if(null==n)return t?e:null;const u=t?e.element:e.type,o=(t?Array.isArray(e.value)?e.value:[]:[e.value]).map(e=>M(e,u,n));return o.some(e=>e===q)?null:{...e,type:v.Array,element:n,...F(e,r),value:o}}if(!B(e))return null;const t=Array.isArray(e.value)?e.value[0]:void 0;if(null==t)return null;const n=M(t,e.element,r.type);if(n===q)return null;return{...e,type:r.type,...k(e,r),value:n}}(e,r);const t=M(e.value,e.type,r.type);return t===q?null:{...e,type:r.type,...k(e,r),value:t}}function B(e){return e.type===v.Array}function k(e,r){if(r.type!==v.Struct&&e.type!==v.Struct)return{};const t=function(e,r){if(null==r)return e;if(null==e)return r;if(e===r||S(e,r))return e;const t=g(e),n=g(r);if(null==t||null==n)return e;return r}(e.type===v.Struct?e.struct:void 0,r.struct);return null!=t?{struct:t}:{}}function F(e,r){if(r.type!==v.Array)return{};const t=B(e)?e.elementStruct:void 0,n=r.elementStruct??t;return null!=n?{elementStruct:n}:{}}const q=Symbol("skippedParamValue");function M(e,r,t){if(function(e,r){if(e===r)return!0;const t=L(e);return null!=t&&t===L(r)}(r,t)&&function(e,r){switch(r){case v.Number:return"number"==typeof e||"string"==typeof e&&Number.isFinite(parseFloat(e));case v.FloatNode:return"number"==typeof e||"string"==typeof e&&Number.isFinite(parseFloat(e))||function(e){if(null==e||"object"!=typeof e||Array.isArray(e))return!1;const r=e;return"particle"===r.time&&"string"==typeof r.easing&&null!=H(r.a)&&null!=H(r.b)}(e);case v.Boolean:case v.BooleanNode:return"boolean"==typeof e;case v.Vector2:case v.Vec2Node:return z(e,2);case v.Vector3:case v.Vec3Node:return z(e,3);case v.Vector4:case v.Vec4Node:return z(e,4);case v.Euler:return Array.isArray(e)&&e.length>=3&&null!=O(e,3);case v.Color:case v.RgbNode:return null!=I(e);case v.String:return"string"==typeof e;case v.Scene:return null!=e&&"object"==typeof e&&"string"==typeof e.id;case v.Array:return Array.isArray(e);case v.Texture:case v.Sampler2DNode:case v.BaseActor:case v.Object3D:case v.Material:case v.AudioBuffer:case v.VisualEffect:case v.Prefab:case v.PrefabActor:case v.DataAsset:case v.AnimationClip:case v.Sequence:return null==e||"string"==typeof e||"object"==typeof e;case v.SequenceData:return null==e||V(e);case v.Struct:return null!=e&&"object"==typeof e&&!Array.isArray(e);case v.Curve:case v.ColorLayer:case v.MaskLayer:return null!=e}return!0}(e,t))return e;switch(t){case v.Number:case v.FloatNode:{const r=H(e);return null!=r?r:q}case v.Boolean:case v.BooleanNode:{const r=function(e){if("boolean"==typeof e)return e;if("number"==typeof e)return 0!==e;if("string"==typeof e){const r=e.trim().toLowerCase();if(["true","1","yes","on"].includes(r))return!0;if(["false","0","no","off"].includes(r))return!1}return null}(e);return null!=r?r:q}case v.Vector2:case v.Vec2Node:return E(e,2,r)??q;case v.Vector3:case v.Vec3Node:return E(e,3,r)??q;case v.Vector4:case v.Vec4Node:return E(e,4,r)??q;case v.Color:case v.RgbNode:return function(e,r){if(r===v.Color||r===v.RgbNode)return"string"==typeof e||"number"==typeof e?e:W(e);return W(e)}(e,r)??q;case v.Euler:return function(e,r){if(Array.isArray(e)){const r=O(e,3);if(null==r)return null;const t="string"==typeof e[3]?e[3]:"XYZ";return[r[0],r[1],r[2],t]}const t=E(e,3,r);return null!=t?[t[0],t[1],t[2],"XYZ"]:null}(e,r)??q;case v.String:return"string"==typeof e?e:String(e);case v.Scene:return"string"==typeof e?{id:e,name:e}:null!=e&&"object"==typeof e&&"string"==typeof e.id?e:q;case v.Texture:case v.Sampler2DNode:case v.BaseActor:case v.Object3D:case v.Material:case v.AudioBuffer:case v.VisualEffect:case v.Curve:case v.ColorLayer:case v.MaskLayer:case v.Prefab:case v.PrefabActor:case v.DataAsset:case v.AnimationClip:case v.Sequence:case v.SequenceData:case v.Struct:return t===v.SequenceData&&V(e)?e:q}return q}function z(e,r){if(Array.isArray(e))return e.length>=r&&null!=O(e,r);if(null!=e&&"object"==typeof e){const t=e;return["x","y","z","w"].slice(0,r).every(e=>null!=H(t[e]))}return!1}function L(e){switch(e){case v.Number:case v.FloatNode:return"number";case v.Boolean:case v.BooleanNode:return"boolean";case v.Vector2:case v.Vec2Node:return"vector2";case v.Vector3:case v.Vec3Node:return"vector3";case v.Vector4:case v.Vec4Node:return"vector4";case v.Color:case v.RgbNode:return"color";case v.Texture:case v.Sampler2DNode:return"texture";case v.Prefab:case v.PrefabActor:return"prefab";case v.DataAsset:return"dataAsset";case v.Struct:return"struct"}}function H(e){if("number"==typeof e)return Number.isFinite(e)?e:null;if("string"==typeof e){const r=parseFloat(e);return Number.isFinite(r)?r:null}if("boolean"==typeof e)return e?1:0;if(Array.isArray(e))return H(e[0]);if(null!=e&&"object"==typeof e){const r=e;return H(r.x??r.r??r.value)}return null}function E(e,r,t){if(t===v.Color||t===v.RgbNode){const t=I(e);if(null!=t)return O(t.toArray(),r,4===r?1:0)}if(Array.isArray(e))return O(e,r);if("number"==typeof e||"string"==typeof e||"boolean"==typeof e){const t=H(e);return null!=t?new Array(r).fill(t):null}if(null!=e&&"object"==typeof e){const t=e,n=["x","y","z","w"].slice(0,r).map(e=>t[e]);if(n.some(e=>null!=e))return O(n,r);const u=["r","g","b","a"].slice(0,r).map(e=>t[e]);if(u.some(e=>null!=e))return O(u,r,4===r?1:0)}return null}function O(e,r,t=0){const n=[];for(let u=0;u<r;u++){const r=H(e[u]??t);if(null==r)return null;n.push(r)}return n}function W(e){const r=I(e);return null!=r?"#"+r.getHexString():null}function I(r){try{if(r instanceof e)return r.clone();if("string"==typeof r)return function(e){return/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(e.trim())||/^(rgb|hsl)a?\(/i.test(e.trim())}(r)?new e(r):null;if("number"==typeof r)return Number.isInteger(r)&&r>=0?new e(r):null;if(Array.isArray(r)){const t=O(r,3);return null!=t?(new e).fromArray(t):null}if(null!=r&&"object"==typeof r){const t=r;if(null!=t.r||null!=t.g||null!=t.b){const r=O([t.r,t.g,t.b],3);return null!=r?(new e).fromArray(r):null}if(null!=t.x||null!=t.y||null!=t.z){const r=O([t.x,t.y,t.z],3);return null!=r?(new e).fromArray(r):null}}}catch{return null}return null}function X(e,r){return null!=e&&"object"==typeof e&&e.constructor?.name===r}/*
1
+ import{Color as e,Euler as r,Material as t,Object3D as n,Texture as u,Vector2 as o,Vector3 as a,Vector4 as c,AnimationClip as i}from"three";import{BooleanNode as l,FloatNode as s,RgbNode as f,Sampler2DNode as y,Texture2dLookupNode as p,Vec2Node as m,Vec3Node as d,Vec4Node as b}from"three-shader-graph";import{getParameterDefinitionId as A,getParameterDefinitionType as g,isParameterDefinitionStructAssignableTo as S}from"../shader/parameter.js";import{Curve2 as N}from"../utils/curve.js";import{isSequenceData as V}from"../effects/sequence/sequence-data.js";import{SerializedParamType as v}from"./model.js";import{ModelRef as P}from"./model-ref.js";export const applyRuntimeParamTypeInference=!0;export function convertConfiguredParamsToRuntimeTypes(e,r={}){const t={},n=[],u=Object.entries(e),o=r.applyRuntimeParamTypeInference??true;if(0===u.length||!o)return o?{params:t,skipped:n}:{params:e,skipped:n};const a=getRuntimeParameterTypeHints(e,r);for(const[e,r]of u){const u=a.get(e),o=T(r,u);if(null==o)continue;if(!1===o.override){t[e]=o;continue}const c=null!=u?convertConfiguredParamValueToRuntimeType(o,u):o;null!=c?t[e]=c:n.push({key:e,sourceType:o.type,targetType:u.type})}return{params:t,skipped:n}}function T(e,r){return function(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)&&"number"==typeof e.type&&"value"in e}(e)?e:r?.type===v.SequenceData&&V(e)?{type:v.SequenceData,value:e}:null}export function getRuntimeParameterTypeHints(e,r={}){const t=new Map,n=Object.keys(e).filter(r=>!1!==e[r]?.override);if(0===n.length)return t;const u=new Set(n),o=r.parameterTarget??function(e){if(null==e)return null;try{return new e}catch{return null}}(r.parameterType),a=function(e,r){if(null!=r.propertyParams)return r.propertyParams;if(null==r.extractPropertyParameters)return[];if(null!=r.parameterType)return C(r.parameterType,r.extractPropertyParameters);if(null!=e)return C(e.constructor,r.extractPropertyParameters);return[]}(o,r);for(const e of a){if(!u.has(e.name))continue;const n=D(e,r.toSerializedParamType);null!=n&&t.set(e.name,n);const a=inferRuntimeSerializedParamTypeHint(w(o,e.name))??inferRuntimeSerializedParamTypeHint(e.options.defaultValue);null!=a&&t.set(e.name,B(a,n))}if(null!=o)for(const e of n){const r=inferRuntimeSerializedParamTypeHint(w(o,e));if(null!=r){const n=t.get(e);t.set(e,B(r,n))}}return t}const R=new WeakMap,h=new WeakMap,j=Symbol("noCachedSerializedParamType");function C(e,r){let t=R.get(r);null==t&&(t=new WeakMap,R.set(r,t));const n=t.get(e);if(null!=n)return n;const u=function(e,r){try{return r(e)}catch{return[]}}(e,r);return t.set(e,u),u}function w(e,r){return null!=e?e[r]:void 0}function D(e,r){const t=function(e,r){if(null==e||null==r)return;const t=function(e,r){const t=h.get(r);if(null==t||!t.has(e))return j;const n=t.get(e);return null===n?void 0:n}(e,r);if(t!==j)return t;try{const t=r(e);return x(e,r,t),t}catch{return void x(e,r,void 0)}}(e.type,r),n=t===v.Struct?A(e.type):void 0;return!0===e.options.array?{type:v.Array,...null!=t?{element:t}:{},...null!=n?{elementStruct:n}:{}}:null!=t?{type:t,...null!=n?{struct:n}:{}}:void 0}function x(e,r,t){let n=h.get(r);null==n&&(n=new WeakMap,h.set(r,n)),n.set(e,t??null)}function B(e,r){return e.type!==v.Array?e:{type:v.Array,element:e.element??r?.element,elementStruct:e.elementStruct??r?.elementStruct}}export function inferRuntimeSerializedParamTypeHint(g){if(null==g)return;if(Array.isArray(g)){const e=g.map(e=>inferRuntimeSerializedParamTypeHint(e)).find(e=>null!=e);return{type:v.Array,...null!=e&&e.type!==v.Array?{element:e.type}:{},...null!=e?.struct?{elementStruct:e.struct}:{}}}switch(typeof g){case"number":return{type:v.Number};case"boolean":return{type:v.Boolean};case"string":return{type:v.String}}const S=function(e){const r=e;if(e instanceof s||"function"==typeof r?.isFloat||!0===r?.isFloat)return v.FloatNode;if(e instanceof l||"function"==typeof r?.isBool||!0===r?.isBool)return v.BooleanNode;if(e instanceof f||"function"==typeof r?.isRgb||!0===r?.isRgb)return v.RgbNode;if(e instanceof m||"function"==typeof r?.isVec2||!0===r?.isVec2)return v.Vec2Node;if(e instanceof d||"function"==typeof r?.isVec3||!0===r?.isVec3)return v.Vec3Node;if(e instanceof b||"function"==typeof r?.isVec4||!0===r?.isVec4)return v.Vec4Node;if(e instanceof y||e instanceof p||"function"==typeof r?.isSampler2D||!0===r?.isSampler2D)return v.Sampler2DNode;return}(g);if(null!=S)return{type:S};if(g instanceof o)return{type:v.Vector2};if(g instanceof a)return{type:v.Vector3};if(g instanceof c)return{type:v.Vector4};if(g instanceof e)return{type:v.Color};if(g instanceof r)return{type:v.Euler};if(g instanceof u)return{type:v.Texture};if(g instanceof t)return{type:v.Material};if(g instanceof n)return{type:v.Object3D};if(g instanceof P)return{type:v.ModelRef};if("undefined"!=typeof AudioBuffer&&g instanceof AudioBuffer)return{type:v.AudioBuffer};if(Y(g,"VisualEffect"))return{type:v.VisualEffect};if(Y(g,"PrefabOf"))return{type:v.PrefabActor};if(Y(g,"Prefab"))return{type:v.Prefab};if(Y(g,"DataAssetRef"))return{type:v.DataAsset};if(g instanceof N)return{type:v.Curve};if(Y(g,"ColorLayer"))return{type:v.ColorLayer};if(Y(g,"MaskLayer"))return{type:v.MaskLayer};if(g instanceof i)return{type:v.AnimationClip};if(Y(g,"Sequence"))return{type:v.Sequence};if(V(g))return{type:v.SequenceData};const T=A(g.constructor);return null!=T?{type:v.Struct,struct:T}:void 0}export function convertConfiguredParamValueToRuntimeType(e,r){if(null==e||null==r)return e;if(e.type===v.Array||r.type===v.Array)return function(e,r){if(r.type===v.Array){const t=M(e),n=r.element??(t?e.element:e.type);if(null==n)return t?e:null;const u=t?e.element:e.type,o=(t?Array.isArray(e.value)?e.value:[]:[e.value]).map(e=>z(e,u,n));return o.some(e=>e===q)?null:{...e,type:v.Array,element:n,...F(e,r),value:o}}if(!M(e))return null;const t=Array.isArray(e.value)?e.value[0]:void 0;if(null==t)return null;const n=z(t,e.element,r.type);if(n===q)return null;return{...e,type:r.type,...k(e,r),value:n}}(e,r);const t=z(e.value,e.type,r.type);return t===q?null:{...e,type:r.type,...k(e,r),value:t}}function M(e){return e.type===v.Array}function k(e,r){if(r.type!==v.Struct&&e.type!==v.Struct)return{};const t=function(e,r){if(null==r)return e;if(null==e)return r;if(e===r||S(e,r))return e;const t=g(e),n=g(r);if(null==t||null==n)return e;return r}(e.type===v.Struct?e.struct:void 0,r.struct);return null!=t?{struct:t}:{}}function F(e,r){if(r.type!==v.Array)return{};const t=M(e)?e.elementStruct:void 0,n=r.elementStruct??t;return null!=n?{elementStruct:n}:{}}const q=Symbol("skippedParamValue");function z(e,r,t){if(function(e,r){if(e===r)return!0;const t=H(e);return null!=t&&t===H(r)}(r,t)&&function(e,r){switch(r){case v.Number:return"number"==typeof e||"string"==typeof e&&Number.isFinite(parseFloat(e));case v.FloatNode:return"number"==typeof e||"string"==typeof e&&Number.isFinite(parseFloat(e))||function(e){if(null==e||"object"!=typeof e||Array.isArray(e))return!1;const r=e;return"particle"===r.time&&"string"==typeof r.easing&&null!=E(r.a)&&null!=E(r.b)}(e);case v.Boolean:case v.BooleanNode:return"boolean"==typeof e;case v.Vector2:case v.Vec2Node:return L(e,2);case v.Vector3:case v.Vec3Node:return L(e,3);case v.Vector4:case v.Vec4Node:return L(e,4);case v.Euler:return Array.isArray(e)&&e.length>=3&&null!=W(e,3);case v.Color:case v.RgbNode:return null!=X(e);case v.String:return"string"==typeof e;case v.Scene:return null!=e&&"object"==typeof e&&"string"==typeof e.id;case v.ModelRef:return"string"==typeof e;case v.Array:return Array.isArray(e);case v.Texture:case v.Sampler2DNode:case v.BaseActor:case v.Object3D:case v.Material:case v.AudioBuffer:case v.VisualEffect:case v.Prefab:case v.PrefabActor:case v.DataAsset:case v.AnimationClip:case v.Sequence:return null==e||"string"==typeof e||"object"==typeof e;case v.SequenceData:return null==e||V(e);case v.Struct:return null!=e&&"object"==typeof e&&!Array.isArray(e);case v.Curve:case v.ColorLayer:case v.MaskLayer:return null!=e}return!0}(e,t))return e;switch(t){case v.Number:case v.FloatNode:{const r=E(e);return null!=r?r:q}case v.Boolean:case v.BooleanNode:{const r=function(e){if("boolean"==typeof e)return e;if("number"==typeof e)return 0!==e;if("string"==typeof e){const r=e.trim().toLowerCase();if(["true","1","yes","on"].includes(r))return!0;if(["false","0","no","off"].includes(r))return!1}return null}(e);return null!=r?r:q}case v.Vector2:case v.Vec2Node:return O(e,2,r)??q;case v.Vector3:case v.Vec3Node:return O(e,3,r)??q;case v.Vector4:case v.Vec4Node:return O(e,4,r)??q;case v.Color:case v.RgbNode:return function(e,r){if(r===v.Color||r===v.RgbNode)return"string"==typeof e||"number"==typeof e?e:I(e);return I(e)}(e,r)??q;case v.Euler:return function(e,r){if(Array.isArray(e)){const r=W(e,3);if(null==r)return null;const t="string"==typeof e[3]?e[3]:"XYZ";return[r[0],r[1],r[2],t]}const t=O(e,3,r);return null!=t?[t[0],t[1],t[2],"XYZ"]:null}(e,r)??q;case v.String:return"string"==typeof e?e:String(e);case v.Scene:return"string"==typeof e?{id:e,name:e}:null!=e&&"object"==typeof e&&"string"==typeof e.id?e:q;case v.ModelRef:return"string"==typeof e?e:q;case v.Texture:case v.Sampler2DNode:case v.BaseActor:case v.Object3D:case v.Material:case v.AudioBuffer:case v.VisualEffect:case v.Curve:case v.ColorLayer:case v.MaskLayer:case v.Prefab:case v.PrefabActor:case v.DataAsset:case v.AnimationClip:case v.Sequence:case v.SequenceData:case v.Struct:return t===v.SequenceData&&V(e)?e:q}return q}function L(e,r){if(Array.isArray(e))return e.length>=r&&null!=W(e,r);if(null!=e&&"object"==typeof e){const t=e;return["x","y","z","w"].slice(0,r).every(e=>null!=E(t[e]))}return!1}function H(e){switch(e){case v.Number:case v.FloatNode:return"number";case v.Boolean:case v.BooleanNode:return"boolean";case v.Vector2:case v.Vec2Node:return"vector2";case v.Vector3:case v.Vec3Node:return"vector3";case v.Vector4:case v.Vec4Node:return"vector4";case v.Color:case v.RgbNode:return"color";case v.Texture:case v.Sampler2DNode:return"texture";case v.Prefab:case v.PrefabActor:return"prefab";case v.DataAsset:return"dataAsset";case v.Struct:return"struct"}}function E(e){if("number"==typeof e)return Number.isFinite(e)?e:null;if("string"==typeof e){const r=parseFloat(e);return Number.isFinite(r)?r:null}if("boolean"==typeof e)return e?1:0;if(Array.isArray(e))return E(e[0]);if(null!=e&&"object"==typeof e){const r=e;return E(r.x??r.r??r.value)}return null}function O(e,r,t){if(t===v.Color||t===v.RgbNode){const t=X(e);if(null!=t)return W(t.toArray(),r,4===r?1:0)}if(Array.isArray(e))return W(e,r);if("number"==typeof e||"string"==typeof e||"boolean"==typeof e){const t=E(e);return null!=t?new Array(r).fill(t):null}if(null!=e&&"object"==typeof e){const t=e,n=["x","y","z","w"].slice(0,r).map(e=>t[e]);if(n.some(e=>null!=e))return W(n,r);const u=["r","g","b","a"].slice(0,r).map(e=>t[e]);if(u.some(e=>null!=e))return W(u,r,4===r?1:0)}return null}function W(e,r,t=0){const n=[];for(let u=0;u<r;u++){const r=E(e[u]??t);if(null==r)return null;n.push(r)}return n}function I(e){const r=X(e);return null!=r?"#"+r.getHexString():null}function X(r){try{if(r instanceof e)return r.clone();if("string"==typeof r)return function(e){return/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(e.trim())||/^(rgb|hsl)a?\(/i.test(e.trim())}(r)?new e(r):null;if("number"==typeof r)return Number.isInteger(r)&&r>=0?new e(r):null;if(Array.isArray(r)){const t=W(r,3);return null!=t?(new e).fromArray(t):null}if(null!=r&&"object"==typeof r){const t=r;if(null!=t.r||null!=t.g||null!=t.b){const r=W([t.r,t.g,t.b],3);return null!=r?(new e).fromArray(r):null}if(null!=t.x||null!=t.y||null!=t.z){const r=W([t.x,t.y,t.z],3);return null!=r?(new e).fromArray(r):null}}}catch{return null}return null}function Y(e,r){return null!=e&&"object"==typeof e&&e.constructor?.name===r}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,28 @@
1
+ import { BufferGeometry, Matrix4, Object3D, Vector3 } from 'three';
2
+ /** Offsets are in asset-root space, ordered x fastest, then y, then z. */
3
+ export interface LatticeDeformation {
4
+ enabled?: boolean;
5
+ segments: [number, number, number];
6
+ min: [number, number, number];
7
+ max: [number, number, number];
8
+ offsets: [number, number, number][];
9
+ }
10
+ export declare function isValidLattice(data: LatticeDeformation): boolean;
11
+ export declare function latticePoint(data: LatticeDeformation, index: number, target: Vector3): Vector3;
12
+ export declare function createLatticeDeformation(root: Object3D, segments?: [number, number, number]): LatticeDeformation;
13
+ /** Piecewise trilinear FFD. Eight control points per vertex, independent of cage resolution. */
14
+ export declare function deformLatticeGeometry(source: BufferGeometry, matrix: Matrix4, data: LatticeDeformation): BufferGeometry;
15
+ /** Internal identity for independently baked copies of the same static skin pose. */
16
+ export declare function setLatticeGeometrySourceIdentity(geometry: BufferGeometry, identity: string): void;
17
+ /** Owns only generated buffers. Live copies share buffers; a small idle cache supports undo. */
18
+ export declare class LatticeGeometryCache {
19
+ private disposed;
20
+ private readonly roots;
21
+ private readonly entries;
22
+ private readonly bindings;
23
+ apply(root: Object3D, data?: LatticeDeformation, variant?: string): void;
24
+ release(root: Object3D): void;
25
+ private prune;
26
+ dispose(): void;
27
+ }
28
+ //# sourceMappingURL=lattice-deformation.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{isCollisionMesh as e}from"./collision/collision-shape-import.js";import{Box3 as t,Matrix3 as r,Matrix4 as s,Mesh as i,Vector3 as n}from"three";export function isValidLattice(e){return Array.isArray(e?.segments)&&3===e.segments.length&&e.segments.every(e=>Number.isInteger(e)&&e>=1&&e<=8)&&(null==e.enabled||"boolean"==typeof e.enabled)&&Array.isArray(e.min)&&3===e.min.length&&Array.isArray(e.max)&&3===e.max.length&&e.min.every((t,r)=>Number.isFinite(t)&&Number.isFinite(e.max[r])&&e.max[r]>t)&&Array.isArray(e.offsets)&&e.offsets.length===e.segments.reduce((e,t)=>e*(t+1),1)&&e.offsets.every(e=>Array.isArray(e)&&3===e.length&&e.every(Number.isFinite))}export function latticePoint(e,t,r){const[s,i,n]=e.segments,o=t%(s+1),a=Math.floor(t/(s+1))%(i+1),m=Math.floor(t/((s+1)*(i+1)));return r.set(e.min[0]+(e.max[0]-e.min[0])*o/s+e.offsets[t][0],e.min[1]+(e.max[1]-e.min[1])*a/i+e.offsets[t][1],e.min[2]+(e.max[2]-e.min[2])*m/n+e.offsets[t][2])}function o(t,r){const s=n=>{if(!n.userData.isEditorVisualization&&(n===t||null==n.userData.src&&null==n.userData._src)){n instanceof i&&!e(n)&&r(n);for(const e of n.children)s(e)}};s(t)}function a(e,t){const r=new s;for(let s=t;s&&s!==e;s=s.parent)s.updateMatrix(),r.premultiply(s.matrix);return r}export function createLatticeDeformation(e,r=[2,2,2]){if(!Array.isArray(r)||3!==r.length||!r.every(e=>Number.isInteger(e)&&e>=1&&e<=8))throw new Error("Lattice segments must be integers from 1 to 8.");const s=new t,i=new n;if(o(e,t=>{const r=t.geometry.getAttribute("position"),n=a(e,t);if(r)for(let e=0;e<r.count;e++)s.expandByPoint(i.fromBufferAttribute(r,e).applyMatrix4(n))}),s.isEmpty())throw new Error("The model has no vertices to deform.");for(const e of["x","y","z"])s.max[e]-s.min[e]<1e-5&&(s.min[e]-=.005,s.max[e]+=.005);const m={enabled:!0,segments:[...r],min:s.min.toArray(),max:s.max.toArray(),offsets:Array.from({length:r.reduce((e,t)=>e*(t+1),1)},()=>[0,0,0])};if(!isValidLattice(m))throw new Error("Lattice segments must be integers from 1 to 8.");return m}export function deformLatticeGeometry(e,t,s){if(!isValidLattice(s))throw new Error("Invalid lattice deformation.");const i=e.clone(),o=i.getAttribute("position");if(!o)return i;const a=i.getAttribute("normal"),m=i.getAttribute("tangent"),f=t.clone().invert(),l=(new r).getNormalMatrix(t),u=(new r).getNormalMatrix(f),c=(new r).setFromMatrix4(t),d=(new r).setFromMatrix4(f),y=new n,p=new n,h=new n,x=new n,g=new r,b=new r,[M,w,A]=s.segments,v=M/(s.max[0]-s.min[0]),z=w/(s.max[1]-s.min[1]),L=A/(s.max[2]-s.min[2]);for(let e=0;e<o.count;e++){y.fromBufferAttribute(o,e).applyMatrix4(t);const r=Math.max(0,Math.min(M,(y.x-s.min[0])*v)),i=Math.max(0,Math.min(w,(y.y-s.min[1])*z)),n=Math.max(0,Math.min(A,(y.z-s.min[2])*L)),k=Math.min(M-1,Math.floor(r)),N=Math.min(w-1,Math.floor(i)),B=Math.min(A-1,Math.floor(n)),S=r-k,V=i-N,E=n-B,F=y.x>=s.min[0]&&y.x<=s.max[0]?v:0,W=y.y>=s.min[1]&&y.y<=s.max[1]?z:0,j=y.z>=s.min[2]&&y.z<=s.max[2]?L:0;p.set(0,0,0),g.identity();const D=g.elements;for(let e=0;e<2;e++)for(let t=0;t<2;t++)for(let r=0;r<2;r++){const i=s.offsets[k+r+(M+1)*(N+t+(w+1)*(B+e))],n=r?S:1-S,o=t?V:1-V,a=e?E:1-E,m=n*o*a,f=(r?F:-F)*o*a,l=n*(t?W:-W)*a,u=n*o*(e?j:-j);p.x+=i[0]*m,p.y+=i[1]*m,p.z+=i[2]*m;for(let e=0;e<3;e++)D[e]+=i[e]*f,D[3+e]+=i[e]*l,D[6+e]+=i[e]*u}y.add(p).applyMatrix4(f),o.setXYZ(e,y.x,y.y,y.z),a&&(b.copy(g).invert().transpose(),h.fromBufferAttribute(a,e).applyMatrix3(l).applyMatrix3(b).applyMatrix3(u).normalize(),a.setXYZ(e,h.x,h.y,h.z)),m&&(x.fromBufferAttribute(m,e).applyMatrix3(c).applyMatrix3(g).applyMatrix3(d),a&&x.addScaledVector(h,-x.dot(h)),x.normalize(),m.setXYZ(e,x.x,x.y,x.z),m.itemSize>3&&g.determinant()<0&&m.setW(e,-m.getW(e)))}return o.needsUpdate=!0,a?a.needsUpdate=!0:i.computeVertexNormals(),m&&(m.needsUpdate=!0),i.computeBoundingBox(),i.computeBoundingSphere(),"boundsTree"in i&&(i.boundsTree=null),i}const m=new WeakMap;export function setLatticeGeometrySourceIdentity(e,t){m.set(e,t)}function f(e){const t=new Set;for(const r of[...Object.values(e.attributes),...Object.values(e.morphAttributes).flat(),e.index]){if(!r)continue;const e="data"in r?r.data.array:r.array;t.add(e.buffer)}let r=0;for(const e of t)r+=e.byteLength;return r}export class LatticeGeometryCache{constructor(){this.disposed=!1,this.roots=new WeakSet,this.entries=new Map,this.bindings=new WeakMap}apply(e,t,r=""){if(this.disposed)return;const s=isValidLattice(t)&&!1!==t.enabled&&t.offsets.some(e=>0!==e[0]||0!==e[1]||0!==e[2]);if(!s&&!this.roots.has(e))return;s?this.roots.add(e):this.roots.delete(e);const i=s?JSON.stringify([t.segments,t.min,t.max,t.offsets]):"";o(e,n=>{let o=this.bindings.get(n);if(!o&&!s)return;o||(o={source:n.geometry},this.bindings.set(n,o));const l=s?a(e,n):null,u=s?`${m.get(o.source)??o.source.uuid}:${l.elements.join(",")}:${i}:${r}`:void 0;if(o.key!==u)if(o.key&&this.entries.get(o.key).users--,o.key=u,u){let e=this.entries.get(u);if(!e){const r=deformLatticeGeometry(o.source,l,t);e={geometry:r,users:0,bytes:f(r)},this.entries.set(u,e)}e.users++,n.geometry=e.geometry}else n.geometry=o.source}),this.prune()}release(e){this.disposed||(this.roots.delete(e),e.traverse(e=>{if(!(e instanceof i))return;const t=this.bindings.get(e);t?.key&&this.entries.get(t.key).users--,this.bindings.delete(e)}),this.prune())}prune(){let e=0,t=0;for(const r of this.entries.values())r.users||(e++,t+=r.bytes);for(const[r,s]of this.entries)!s.users&&(e>8||t>67108864)&&(s.geometry.dispose(),this.entries.delete(r),e--,t-=s.bytes)}dispose(){if(!this.disposed){this.disposed=!0;for(const e of this.entries.values())e.geometry.dispose();this.entries.clear()}}}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -1,3 +1,5 @@
1
+ import { type LatticeDeformation } from './lattice-deformation.js';
2
+ export { createLatticeDeformation, latticePoint, isValidLattice, deformLatticeGeometry, LatticeGeometryCache, type LatticeDeformation } from './lattice-deformation.js';
1
3
  import { Subject } from "rxjs";
2
4
  import * as THREE from "three";
3
5
  import { Euler, Material, Object3D, Scene, Vector3 } from "three";
@@ -125,9 +127,9 @@ export type SceneObject = {
125
127
  * Grass settings. Only relevant for object type landscape
126
128
  */
127
129
  grass?: GrassSettings;
128
- /**
129
- * Surface scatter settings. Only relevant for object type asset_mesh in v1.
130
- */
130
+ /** Object-local cage for static mesh assets. Does not deform authored collision shapes. */
131
+ latticeDeformation?: LatticeDeformation;
132
+ /** Surface scatter settings. Only relevant for object type asset_mesh in v1. */
131
133
  surfaceScatter?: SurfaceScatterSettings;
132
134
  /**
133
135
  * Artist-painted scatter settings. Only relevant for object type scatter.
@@ -416,6 +418,7 @@ export declare class SceneMaterializer {
416
418
  * when needed to support larger worlds.
417
419
  */
418
420
  private initTextures;
421
+ private texturePrefetch?;
419
422
  private prefetchAssets;
420
423
  private collectAssetMeshIds;
421
424
  private collectObjectAssetMeshIds;
@@ -479,6 +482,9 @@ export declare class SceneMaterializer {
479
482
  private attachEditorComponents;
480
483
  private addVfxChildActors;
481
484
  private applyActorComponentParams;
485
+ private readonly latticeGeometries;
486
+ /** Editor preview only; persistence and history remain the editor's responsibility. */
487
+ previewLatticeDeformation(object: Object3D, data?: LatticeDeformation): void;
482
488
  private canObjectBeInstanced;
483
489
  private _canBeInstancedCache;
484
490
  private experimentalStaticDrawSetDisposer?;
@@ -608,6 +614,8 @@ export declare class SceneMaterializer {
608
614
  private geometryCache;
609
615
  private collisionShapeCache;
610
616
  private createMeshByShape;
617
+ private readonly modelImageBitmaps;
618
+ private decodeModelImage;
611
619
  private createFromAsset;
612
620
  private createFromPrefab;
613
621
  /**
@@ -692,4 +700,5 @@ type MaterializeContext = {
692
700
  /** Runtime-spawned prefabs are owned directly by World instead. */
693
701
  runtimeSpawn?: boolean;
694
702
  };
703
+ export declare function freezeSkinnedMeshes(object: Object3D, cacheLatticeIdentity?: boolean): Object3D;
695
704
  //# sourceMappingURL=materializer.d.ts.map