@hology/core 0.0.179 → 0.0.181

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.
@@ -1,4 +1,4 @@
1
- import{AudioLoader as e,BufferGeometry as t,Group as s,LoadingManager as r,Mesh as i,Object3D as a,TextureLoader as n}from"three";import{GLTFLoader as o,MTLLoader as h,OBJLoader as l,DRACOLoader as c,LUTCubeLoader as u}from"three-stdlib";import{FBXLoader as d}from"three-stdlib";import{cloneMesh as m}from"../utils/mesh.js";import{pathJoin as f}from"../utils/files.js";import{Subject as p,firstValueFrom as g}from"rxjs";import{importCollisionShapes as w,isCollisionMesh as y}from"./collision/collision-shape-import.js";import*as x from"three";import{iterateMaterials as M}from"../utils/materials.js";import{BufferGeometryUtils as L,EXRLoader as b,KTX2Loader as A,TGALoader as v,UltraHDRLoader as S}from"three/examples/jsm/Addons.js";import{disposeScene as R}from"../utils/three/cleanup.js";const C=new c;C.setDecoderConfig({type:"js"}),C.setDecoderPath("/assets/draco/");const T=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new r,this.glbLoader=new o(this.loadingManager).setDRACOLoader(C),this.fbxLoader=new d(this.loadingManager),this.objLoader=new l(this.loadingManager),this.textureLoader=new n(this.loadingManager),this.tgaLoader=new v(this.loadingManager),this.exrLoader=new b(this.loadingManager),this.cubeLoader=new u(this.loadingManager),this.hdrLoader=new S(this.loadingManager),this.ktx2Loader=new A(this.loadingManager),this._textureLoader=new x.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.initialisedKtx2=!1,this._retrievedMeshes=[],this._retrievedTextures=[],this.makeReady=new p,this.ready=g(this.makeReady),this._texturePromises=new Map,this.asyncMeshResults=new Map,this.asyncAudioResults=new Map,this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}initKtx2(e){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.detectSupport(e)}setDataDir(e){this.basePath=f(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){const t=getElectronArg("windowId");return null!=t||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?f(this.basePath,e)+(null!=t?`?windowId=${t}`:""):new URL(f("..",this.basePath,e),import.meta.url).href}async getTexture(e){if(!e||!e.fileKey)return null;if(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,this.textureCache.has(e.id)){const t=this.textureCache.get(e.id);t.dispose(),null!=e.texture&&(t.flipY!==e.texture?.flipY?(t.needsUpdate=!0,t.flipY=e.texture?.flipY??!0):t.wrapS!==j(e.texture?.wrapS)?(t.needsUpdate=!0,t.wrapS=j(e.texture?.wrapS)):t.wrapT!==j(e.texture?.wrapT)&&(t.wrapT=j(e.texture?.wrapT),t.needsUpdate=!0))}else try{await this._getTextureLoader(e.fileKey).loadAsync(this.getUri(e.fileKey)).then(t=>(t.texture3D?t=t.texture3D:(t.wrapS=j(e.texture?.wrapS),t.wrapT=j(e.texture?.wrapT),t.flipY=e.texture?.flipY??!0),this.textureCache.set(e.id,t),this._retrievedTextures.push(t),t))}catch(t){return console.warn("Failed to load texture "+e.name,t),null}return this.textureCache.get(e.id)}_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){"mesh"===e.type&&Array.from(this.cache.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.cache.delete(t)})}async getMesh(e,t){if(await this.ready,null==e)return console.error("No asset was provided"),{scene:new s,animations:[]};if(!T.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new s,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 s,animations:[]}}const a=this.cache.get(r).scene,n=this.computeCollisionShapes(e,a);!0===t?.mergeGeomtries&&this.optimizeDrawGroups(a);const o=m(a),h=this.cache.get(r).animations;o.traverse(e=>{e instanceof i&&e.material instanceof Array&&(e.material=e.material.slice())});const l=new AssetMeshInstance;l.add(o),l.collisionShapes=n,l.animations=h;const c=e.receiveShadow??!0,u=e.castShadow??!1;return o.traverse(e=>{e.castShadow=u,e.receiveShadow=c}),{scene:l,animations:h}}async getAudio(e){await this.ready;const t=e.fileKey;if(this.asyncAudioResults.has(t))return await this.asyncAudioResults.get(t);const s=this.audioLoader.loadAsync(this.getUri(e.fileKey)).finally(()=>{setTimeout(()=>{this.asyncAudioResults.delete(t)},1e3)});return this.asyncAudioResults.set(t,s),s}computeCollisionShapes(e,t){const s=e.id+e.mesh?.collisions?.shapeType;return this.collisionShapeCache.has(s)||this.collisionShapeCache.set(s,w(t,e)),this.collisionShapeCache.get(s)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then(e=>(e.scene.traverse(e=>{e instanceof i&&e.material,y(e)?e.visible=!1:e instanceof i&&e.geometry instanceof t&&(e.geometry.hasAttribute("normal")||e.geometry.computeVertexNormals())}),this._retrievedMeshes.push(e.scene),e.scene=function(e,t){let s=!1;if(t.traverseVisible(e=>{k.test(e.name)&&(s=!0)}),!s)return t;const r=new x.LOD,i=[t];for(;i.length>0;){const e=i.shift(),t=e.name.match(k);if(null!=t){const s=parseInt(t[1]);0===s?r.addLevel(e,0):console.warn(`Skipping LOD level ${s} for now as LOD is not fully supported`)}else i.push(...e.children)}return r}(0,e.scene),e))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid);let s=!0,r=0,a=0;if(e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!y(e)){r++;const t=Object.keys(e.geometry.attributes).length;t!==a&&0!==a&&(s=!1),a=t}else(e instanceof x.SkinnedMesh||e instanceof x.Bone)&&(s=!1)}),r>1&&s){const s=new Map;e.updateWorldMatrix(!0,!0),e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!y(e)){if(Array.isArray(e.material))return;e.updateWorldMatrix(!0,!0);const t=e.material?.uuid||"default";s.has(t)||s.set(t,{material:e.material,geometries:[],objects:[]});const r=s.get(t);r.geometries.push(e.geometry.clone().applyMatrix4(e.matrixWorld)),r.objects.push(e)}});for(const e of s.values())for(const t of e.objects)t.removeFromParent();for(const t of s.values()){let s;s=1===t.geometries.length?t.geometries[0]:L.mergeGeometries(t.geometries,!0),s.groups.length>1&&L.mergeGroups(s),e.add(new i(s,t.material))}}const n=[];e.traverse(e=>{e instanceof i&&e.geometry instanceof t&&Array.isArray(e.material)&&!y(e)&&n.push({mesh:e,geometry:e.geometry,materialArray:e.material,parent:e.parent})});for(const{mesh:t,geometry:s,materialArray:r,parent:a}of n){t.removeFromParent();for(let t=0;t<r.length;t++){const n=r[t],o=s.groups.filter(e=>e.materialIndex===t);if(0===o.length)continue;const h=this.extractGeometryGroups(s,o);h.groups.length>1&&L.mergeGroups(h);const l=new i(h,n);a?a.add(l):e.add(l)}s.dispose()}e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!y(e)){const t=e.geometry;!Array.isArray(e.material)&&t.groups.length>1&&L.mergeGroups(t)}})}extractGeometryGroups(e,s){const r=e.index;if(!r){const r=new t;let i=0;for(const e of s)i+=e.count;if(0===i)return r;for(const t in e.attributes){const a=e.attributes[t],n=a.itemSize,o=a.array,h=new(0,o.constructor)(i*n);let l=0;for(const e of s){const t=e.start*n,s=e.count*n;for(let e=0;e<s;e++)h[l+e]=o[t+e];l+=s}const c=new x.BufferAttribute(h,n,a.normalized);r.setAttribute(t,c)}return r.groups=[{start:0,count:i,materialIndex:0}],r}const i=[];for(const e of s)for(let t=0;t<e.count;t++){const s=r.getX(e.start+t);i.push(s)}if(0===i.length)return new t;const a=new Map,n=[];let o=0;for(const e of i)a.has(e)||(a.set(e,o),o++),n.push(a.get(e));if(0===n.length||0===a.size)return new t;const h=new t;for(const t in e.attributes){const s=e.attributes[t],r=s.itemSize,i=s.array,n=new(0,i.constructor)(a.size*r);for(const[e,t]of a)for(let s=0;s<r;s++)n[t*r+s]=i[e*r+s];const o=new x.BufferAttribute(n,r,s.normalized);h.setAttribute(t,o)}const l=new((n.length>0?Math.max(...n):0)>65535?Uint32Array:Uint16Array)(n.length);for(let e=0;e<n.length;e++)l[e]=n[e];return h.setIndex(new x.BufferAttribute(l,1)),h.groups=[{start:0,count:n.length,materialIndex:0}],h}async loadByAsset(e){this.fbxLoader;const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then(e=>({scene:e.scene,animations:e.animations}));case"fbx":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 s=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(s)}return this.objLoader.loadAsync(t).then(e=>(_(e),e)).then(e=>({scene:e,animations:e.animations}))}}disposeAll(){this.cache.clear(),this._retrievedMeshes.forEach(e=>R(e)),this._retrievedTextures.forEach(e=>e.dispose()),this._retrievedMeshes.length=0,this._retrievedTextures.length=0}}function _(e){if(e instanceof i)for(const t of M(e.material))t instanceof x.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(_)}export class AssetMeshInstance extends a{}export function getElectronArg(e){const t=`--${e}=`,s=window.process?.argv.find(e=>e.startsWith(t));return s?.substring(t.length)}function j(e){switch(e){case"clamp":return x.ClampToEdgeWrapping;case"repeat":return x.RepeatWrapping;case"mirror":return x.MirroredRepeatWrapping}return x.RepeatWrapping}new x.Matrix4;const k=/_LOD(\d+)$/;/*
1
+ import{AudioLoader as e,BufferGeometry as t,Group as s,LoadingManager as r,Mesh as i,Object3D as a,TextureLoader as n}from"three";import{GLTFLoader as o,MTLLoader as h,OBJLoader as l,DRACOLoader as c,LUTCubeLoader as u}from"three-stdlib";import{FBXLoader as d}from"three-stdlib";import{cloneMesh as m}from"../utils/mesh.js";import{pathJoin as f}from"../utils/files.js";import{Subject as p,firstValueFrom as g}from"rxjs";import{importCollisionShapes as w,isCollisionMesh as y}from"./collision/collision-shape-import.js";import*as x from"three";import{iterateMaterials as M}from"../utils/materials.js";import{BufferGeometryUtils as L,EXRLoader as b,KTX2Loader as A,TGALoader as v,UltraHDRLoader as _}from"three/examples/jsm/Addons.js";import{disposeScene as C}from"../utils/three/cleanup.js";const S=new c;S.setDecoderConfig({type:"js"}),S.setDecoderPath("/assets/draco/");const R=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new r,this.glbLoader=new o(this.loadingManager).setDRACOLoader(S),this.fbxLoader=new d(this.loadingManager),this.objLoader=new l(this.loadingManager),this.textureLoader=new n(this.loadingManager),this.tgaLoader=new v(this.loadingManager),this.exrLoader=new b(this.loadingManager),this.cubeLoader=new u(this.loadingManager),this.hdrLoader=new _(this.loadingManager),this.ktx2Loader=new A(this.loadingManager),this._textureLoader=new x.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.initialisedKtx2=!1,this._retrievedMeshes=[],this._retrievedTextures=[],this.makeReady=new p,this.ready=g(this.makeReady),this._texturePromises=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}initKtx2(e){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.detectSupport(e)}setDataDir(e){this.basePath=f(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){const t=getElectronArg("windowId");return null!=t||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?f(this.basePath,e)+(null!=t?`?windowId=${t}`:""):new URL(f("..",this.basePath,e),import.meta.url).href}async getTexture(e){if(!e||!e.fileKey)return null;if(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,this.textureCache.has(e.id)){const t=this.textureCache.get(e.id);t.dispose(),null!=e.texture&&(t.flipY!==e.texture?.flipY?(t.needsUpdate=!0,t.flipY=e.texture?.flipY??!0):t.wrapS!==P(e.texture?.wrapS)?(t.needsUpdate=!0,t.wrapS=P(e.texture?.wrapS)):t.wrapT!==P(e.texture?.wrapT)&&(t.wrapT=P(e.texture?.wrapT),t.needsUpdate=!0))}else try{await this._getTextureLoader(e.fileKey).loadAsync(this.getUri(e.fileKey)).then(t=>(t.texture3D?t=t.texture3D:(t.wrapS=P(e.texture?.wrapS),t.wrapT=P(e.texture?.wrapT),t.flipY=e.texture?.flipY??!0),this.textureCache.set(e.id,t),this._retrievedTextures.push(t),t))}catch(t){return console.warn("Failed to load texture "+e.name,t),null}return this.textureCache.get(e.id)}_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){"mesh"===e.type&&Array.from(this.cache.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.cache.delete(t)})}async getMesh(e,t){if(await this.ready,null==e)return console.error("No asset was provided"),{scene:new s,animations:[]};if(!R.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new s,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 s,animations:[]}}const a=this.cache.get(r).scene,n=this.computeCollisionShapes(e,a);!0===t?.mergeGeomtries&&this.optimizeDrawGroups(a);const o=m(a),h=this.cache.get(r).animations;o.traverse(e=>{e instanceof i&&e.material instanceof Array&&(e.material=e.material.slice())});const l=new AssetMeshInstance;l.add(o),l.collisionShapes=n,l.animations=h;const c=e.receiveShadow??!0,u=e.castShadow??!1;return o.traverse(e=>{e.castShadow=u,e.receiveShadow=c}),{scene:l,animations:h}}async getAudio(e){await this.ready;const t=e.fileKey;if(this.asyncAudioResults.has(t))return await this.asyncAudioResults.get(t);const s=this.audioLoader.loadAsync(this.getUri(e.fileKey)).finally(()=>{setTimeout(()=>{this.asyncAudioResults.delete(t)},1e3)});return this.asyncAudioResults.set(t,s),s}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,s=e.fileKey+"|"+t;if(this._animationCache.has(s))return this._animationCache.get(s);if(this._animationPromises.has(s))return this._animationPromises.get(s);const r=(async()=>{try{const r=await this.getMesh(e),i=r.animations.find(e=>e.name===t);return null!=i&&this._animationCache.set(s,i),i}catch(e){return this.onError(e),null}finally{setTimeout(()=>this._animationPromises.delete(s),1e3)}})();return this._animationPromises.set(s,r),r}computeCollisionShapes(e,t){const s=e.id+e.mesh?.collisions?.shapeType;return this.collisionShapeCache.has(s)||this.collisionShapeCache.set(s,w(t,e)),this.collisionShapeCache.get(s)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then(e=>(e.scene.traverse(e=>{e instanceof i&&e.material,y(e)?e.visible=!1:e instanceof i&&e.geometry instanceof t&&(e.geometry.hasAttribute("normal")||e.geometry.computeVertexNormals())}),this._retrievedMeshes.push(e.scene),e.scene=function(e,t){let s=!1;if(t.traverseVisible(e=>{j.test(e.name)&&(s=!0)}),!s)return t;const r=new x.LOD,i=[t];for(;i.length>0;){const e=i.shift(),t=e.name.match(j);if(null!=t){const s=parseInt(t[1]);0===s?r.addLevel(e,0):console.warn(`Skipping LOD level ${s} for now as LOD is not fully supported`)}else i.push(...e.children)}return r}(0,e.scene),e))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid);let s=!0,r=0,a=0;if(e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!y(e)){r++;const t=Object.keys(e.geometry.attributes).length;t!==a&&0!==a&&(s=!1),a=t}else(e instanceof x.SkinnedMesh||e instanceof x.Bone)&&(s=!1)}),r>1&&s){const s=new Map;e.updateWorldMatrix(!0,!0),e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!y(e)){if(Array.isArray(e.material))return;e.updateWorldMatrix(!0,!0);const t=e.material?.uuid||"default";s.has(t)||s.set(t,{material:e.material,geometries:[],objects:[]});const r=s.get(t);r.geometries.push(e.geometry.clone().applyMatrix4(e.matrixWorld)),r.objects.push(e)}});for(const e of s.values())for(const t of e.objects)t.removeFromParent();for(const t of s.values()){let s;s=1===t.geometries.length?t.geometries[0]:L.mergeGeometries(t.geometries,!0),s.groups.length>1&&L.mergeGroups(s),e.add(new i(s,t.material))}}const n=[];e.traverse(e=>{e instanceof i&&e.geometry instanceof t&&Array.isArray(e.material)&&!y(e)&&n.push({mesh:e,geometry:e.geometry,materialArray:e.material,parent:e.parent})});for(const{mesh:t,geometry:s,materialArray:r,parent:a}of n){t.removeFromParent();for(let t=0;t<r.length;t++){const n=r[t],o=s.groups.filter(e=>e.materialIndex===t);if(0===o.length)continue;const h=this.extractGeometryGroups(s,o);h.groups.length>1&&L.mergeGroups(h);const l=new i(h,n);a?a.add(l):e.add(l)}s.dispose()}e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!y(e)){const t=e.geometry;!Array.isArray(e.material)&&t.groups.length>1&&L.mergeGroups(t)}})}extractGeometryGroups(e,s){const r=e.index;if(!r){const r=new t;let i=0;for(const e of s)i+=e.count;if(0===i)return r;for(const t in e.attributes){const a=e.attributes[t],n=a.itemSize,o=a.array,h=new(0,o.constructor)(i*n);let l=0;for(const e of s){const t=e.start*n,s=e.count*n;for(let e=0;e<s;e++)h[l+e]=o[t+e];l+=s}const c=new x.BufferAttribute(h,n,a.normalized);r.setAttribute(t,c)}return r.groups=[{start:0,count:i,materialIndex:0}],r}const i=[];for(const e of s)for(let t=0;t<e.count;t++){const s=r.getX(e.start+t);i.push(s)}if(0===i.length)return new t;const a=new Map,n=[];let o=0;for(const e of i)a.has(e)||(a.set(e,o),o++),n.push(a.get(e));if(0===n.length||0===a.size)return new t;const h=new t;for(const t in e.attributes){const s=e.attributes[t],r=s.itemSize,i=s.array,n=new(0,i.constructor)(a.size*r);for(const[e,t]of a)for(let s=0;s<r;s++)n[t*r+s]=i[e*r+s];const o=new x.BufferAttribute(n,r,s.normalized);h.setAttribute(t,o)}const l=new((n.length>0?Math.max(...n):0)>65535?Uint32Array:Uint16Array)(n.length);for(let e=0;e<n.length;e++)l[e]=n[e];return h.setIndex(new x.BufferAttribute(l,1)),h.groups=[{start:0,count:n.length,materialIndex:0}],h}async loadByAsset(e){this.fbxLoader;const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then(e=>({scene:e.scene,animations:e.animations}));case"fbx":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 s=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(s)}return this.objLoader.loadAsync(t).then(e=>(T(e),e)).then(e=>({scene:e,animations:e.animations}))}}disposeAll(){this.cache.clear(),this._retrievedMeshes.forEach(e=>C(e)),this._retrievedTextures.forEach(e=>e.dispose()),this._retrievedMeshes.length=0,this._retrievedTextures.length=0}}function T(e){if(e instanceof i)for(const t of M(e.material))t instanceof x.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(T)}export class AssetMeshInstance extends a{}export function getElectronArg(e){const t=`--${e}=`,s=window.process?.argv.find(e=>e.startsWith(t));return s?.substring(t.length)}function P(e){switch(e){case"clamp":return x.ClampToEdgeWrapping;case"repeat":return x.RepeatWrapping;case"mirror":return x.MirroredRepeatWrapping}return x.RepeatWrapping}new x.Matrix4;const j=/_LOD(\d+)$/;/*
2
2
  * Copyright (©) 2025 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,10 +1,10 @@
1
1
  import { Subject } from "rxjs";
2
2
  import { Asset, AssetId } from './model.js';
3
- export interface AssetsProvider {
3
+ export declare abstract class AssetsProvider {
4
4
  onCreate: Subject<Asset>;
5
5
  onDelete: Subject<Asset>;
6
6
  onUpdate: Subject<Asset>;
7
- getAsset(assetId: AssetId): Promise<Asset>;
8
- getAssets(): Promise<Asset[]>;
7
+ abstract getAsset(assetId: AssetId): Promise<Asset>;
8
+ abstract getAssets(): Promise<Asset[]>;
9
9
  }
10
10
  //# sourceMappingURL=assets-provider.d.ts.map
@@ -1,4 +1,4 @@
1
- export{};/*
1
+ export class AssetsProvider{}/*
2
2
  * Copyright (©) 2025 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -12,7 +12,7 @@ import { Type } from '../utils/type.js';
12
12
  import { AssetResourceLoader } from './asset-resource-loader.js';
13
13
  import { AssetsProvider } from './assets-provider.js';
14
14
  import { LandscapeInitOptions } from './landscape/landscape.js';
15
- import { Asset, AssetId, CustomParamValue, DetailTier, MaterialAssignment, SerializedParamType, ShapeType } from './model.js';
15
+ import { Asset, AssetId, CustomParamValue, DetailTier, MaterialAssignment, SerializedParamType, ShapeType, PrefabInstanceSettings } from './model.js';
16
16
  export type SceneObjectId = string;
17
17
  export type SceneObjectType = "asset_mesh" | "light" | "shape_mesh" | "spline" | "landscape" | "particles" | "global_fog" | "global_light" | "actor" | "group" | "prefab" | "vfx" | "sky" | "world_env";
18
18
  export type LightType = "point" | "spot" | "directional" | "ambient";
@@ -105,6 +105,11 @@ export type SceneObject = {
105
105
  * Actor settings. Only relevant for object type actor
106
106
  */
107
107
  actor?: ActorSettings;
108
+ /**
109
+ * Per-instance prefab metadata. When the object is of type 'prefab' this
110
+ * field may hold per-instance overrides for the prefab's exposed actor.
111
+ */
112
+ prefab?: PrefabInstanceSettings;
108
113
  type: SceneObjectType;
109
114
  /** Whether the object should cast shadows. Only for shape_mesh and asset_mesh */
110
115
  castShadow?: boolean;
@@ -277,6 +282,7 @@ export declare class SceneMaterializer {
277
282
  readonly components: GameComponent[];
278
283
  private readonly landscapeManagers;
279
284
  materializedActors: Map<string, BaseActor>;
285
+ idToSceneObject: Map<string, SceneObject>;
280
286
  inEditor: boolean;
281
287
  updated$: Subject<{
282
288
  object: Object3D;
@@ -388,6 +394,12 @@ export declare class SceneMaterializer {
388
394
  * When resolving actor references, we have to prefix the current chain with the source id
389
395
  */
390
396
  private prefabInstanceChain;
397
+ /**
398
+ * Map from prefab instance id -> nested materialized actor id for the exposed actor.
399
+ * Used to resolve prefab instance references to the actual actor instance created
400
+ * when the prefab was materialized.
401
+ */
402
+ private prefabInstanceExposedActorMap;
391
403
  private getNestedActorId;
392
404
  private createFromVfx;
393
405
  private createFromShape;
@@ -402,11 +414,13 @@ export declare class SceneMaterializer {
402
414
  *
403
415
  * @param asset
404
416
  * @param instanceId A unique ID added to the stack of prefab ids
417
+ * @param delayInit If true, the actors created will not be initialized until initActorsPostInit is called. This is necessary to ensure that all actors are created before any are initialized to allow inter-actor references to work.
405
418
  * @returns
406
419
  */
407
- createFromPrefabAsset(asset: Asset, context: MaterializeContext, parent?: Object3D, source?: SceneObject): Promise<{
420
+ createFromPrefabAsset(asset: Asset, context: MaterializeContext, parent?: Object3D, source?: SceneObject, delayInit?: boolean): Promise<{
408
421
  object: Object3D;
409
422
  actors: BaseActor[];
423
+ mainActor: BaseActor | null;
410
424
  }>;
411
425
  private createParticleSystem;
412
426
  private createLight;
@@ -418,12 +432,17 @@ export declare function materialFromAsset(asset: Asset, renderingView: Rendering
418
432
  export declare function _materialFromAsset(key: string, asset: Asset, renderingView: RenderingView, assetsService: AssetsProvider, assetManagerService: AssetResourceLoader, shaders: ShaderImpl[], useCache?: boolean): Promise<Material>;
419
433
  export declare function prepareClassParameters(paramsSource: {
420
434
  [key: string]: CustomParamValue;
421
- }, type: ShaderType | ActorType, assetsService: AssetsProvider, assetManagerService: AssetResourceLoader, actors?: Map<SceneObjectId, BaseActor>, renderingView?: RenderingView, shaders?: ShaderImpl[], actorProvider?: ActorProvider): Promise<{
435
+ }, type: ShaderType | ActorType, assetsService: AssetsProvider, assetManagerService: AssetResourceLoader, actors?: Map<SceneObjectId, BaseActor>, renderingView?: RenderingView, shaders?: ShaderImpl[], actorProvider?: ActorProvider,
436
+ /**
437
+ * Optional resolver that maps a prefab instance id -> nested materialized
438
+ * actor id for that instance's exposed actor.
439
+ */
440
+ prefabResolver?: (prefabInstanceId: string) => string | null): Promise<{
422
441
  [key: string]: unknown;
423
442
  }>;
424
443
  export declare function prepareShapeParameters(paramsSource: {
425
444
  [key: string]: CustomParamValue;
426
- }): Promise<{
445
+ }, assetProvider?: AssetsProvider, assetManagerService?: AssetResourceLoader): Promise<{
427
446
  [key: string]: unknown;
428
447
  }>;
429
448
  export declare function toSerializedParamType(type: Type<any>): SerializedParamType;
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{ConvexPolyhedronCollisionShape as a}from"@hology/core";import{Subject as s}from"rxjs";import*as r from"three";import{BoxGeometry as i,Color as n,Euler as o,Fog as l,FogExp2 as c,Group as h,Material as p,Matrix4 as m,Mesh as d,MeshLambertMaterial as u,MeshPhongMaterial as f,MeshStandardMaterial as g,Object3D as y,PointLight as w,Quaternion as M,Scene as v,Texture as b,Vector2 as A,Vector3 as S,Vector4 as x}from"three";import{batchingUniformFloat as I,batchingUniformVec2 as j,batchingUniformVec3 as D,batchingUniformVec4 as P,bool as C,BooleanExpression as E,BooleanNode as T,colorToNormal as V,float as O,FloatNode as k,ifDefApply as z,mix as F,NodeShaderMaterial as B,rgb as N,rgba as _,RgbNode as U,select as $,standardMaterial as W,Texture2dLookupNode as L,textureSampler2d as R,textureSampler2dArray as G,varyingAttributes as H,varyingTransformed as J,vec2 as q,Vec2Node as X,vec3 as Y,Vec3Node as Z,vec4 as K,Vec4Node as Q}from"three-shader-graph";import{Service as ee}from"typedi";import{VfxActor as te}from"../effects/vfx/vfx-actor.js";import{VisualEffect as ae}from"../effects/vfx/vfx-param.js";import{Prefab as se}from"./objects/prefab.js";import{BaseActor as re}from"../gameplay/actors/actor.js";import ie from"../gameplay/actors/builtin/index.js";import{PhysicsBodyType as ne,ThreeBlendingMode as oe,withInjectionContext as le}from"../gameplay/index.js";import{RenderingView as ce}from"../rendering.js";import{curveSampler as he,oneMinus as pe,particleUniforms as me,Sampler2DNode as de}from"../shader-nodes/index.js";import{LambertShader as ue}from"../shader/builtin/lambert-shader.js";import{LandscapeCompositeShader as fe}from"../shader/builtin/landscape-composite-shader";import{LandscapeShader as ge}from"../shader/builtin/landscape-shader.js";import{StandardShader as ye}from"../shader/builtin/standard-shader.js";import{UnlitShader as we}from"../shader/builtin/unlit-shader.js";import{extractShaderParameters as Me}from"../shader/parameter.js";import{ArrayMap as ve,DefaultMap as be,groupBy as Ae}from"../utils/collections.js";import{iterateMaterials as Se}from"../utils/materials.js";import{filterChildrenShallow as xe,filterSceneShallow as Ie,findFirstVisibleMesh as je,findFirstVisibleObject as De,traverseAsync as Pe}from"../utils/three/traverse.js";import{AssetMeshInstance as Ce,AssetResourceLoader as Ee}from"./asset-resource-loader.js";import{isCollisionMesh as Te}from"./collision/collision-shape-import.js";import{BoxCollisionShape as Ve,PhysicalShapeMesh as Oe}from"./collision/collision-shape.js";import{LandscapeManager as ke}from"./landscape/landscape-manager.js";import{initLandscape as ze}from"./landscape/landscape.js";import{SectionGrid as Fe,smoothNormalsCrossMeshes as Be}from"./landscape/utils.js";import{createGrassFoliageMaterial as Ne}from"./materials/grass-foliage.js";import{createGrassMaterial as _e}from"./materials/grass.js";import{getMaterialAttribute as Ue}from"./materials/utils/material-painting.js";import{createWaterMaterial as $e}from"./materials/water.js";import{SerializedParamType as We}from"./model.js";import{ShapeLibrary as Le,ShapeLibraryKeys as Re}from"./objects/shapes.js";import{ambientLightName as Ge,createSky as He,defaultSkyMaterial as Je}from"./sky.js";import{Curve2 as qe}from"../utils/curve.js";import{DecalUnlitShader as Xe}from"../shader/builtin/decal-unlit-shader.js";import{DecalStandardShader as Ye}from"../shader/builtin/decal-standard-shader.js";import{ColorLayer as Ze,defaultValueColorLayer as Ke,defaultValueMaskLayer as Qe,MaskLayer as et}from"../shader/color-layer.js";import{LayeredShader as tt}from"../shader/builtin/layered-shader";import{isColorLayerSerialized as at}from"../shader/color-layer";import{FogVolume as st}from"../rendering/fog/fog-volume-actor.js";import{UnscaledSprite as rt}from"../utils/three/unscaled-sprite.js";import{ToonShader as it}from"../shader/builtin/toon-shader.js";import{BatchedMesh2 as nt}from"./batched-mesh-2.js";import{ParallaxStandardMaterial as ot}from"../shader/builtin/standard-shader";import{parallaxOcclusionMapping as lt}from"../shader-nodes/pom.js";import{traverseVisibleEvery as ct}from"../utils/three/traverse";const ht={},pt=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),mt=/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(navigator.userAgent.includes("iPhone")||navigator.userAgent.includes("iPad"))&&!!navigator.userAgent.match(/AppleWebKit/)&&!navigator.userAgent.match(/CriOS/);export const shapeDefaultColor="#aaaaaa";export class SceneMaterializerLoader{constructor(e,t,a){this.dataProvider=e,this.assetsService=t,this.assetManagerService=a}get(e,t){return new dt(e,this.dataProvider,this.assetsService,this.assetManagerService,t,[],[],{create:()=>null,initActor:async()=>{}})}}let dt=class{constructor(e,t,a,i,n,o,l,c,h=[]){this.scene=e,this.dataProvider=t,this.assetsService=a,this.assetManagerService=i,this.renderingView=n,this.shaders=o,this.actorTypes=l,this.actorProvider=c,this.componentTypes=h,this.objectMap=new Map,this.sceneObjectMap=new Map,this.components=[],this.landscapeManagers=[],this.materializedActors=new Map,this.inEditor=!0,this.updated$=new s,this.removed$=new s,this.error$=new s,this.editorActorParamSnapshot=new Map,this.assets=new Map,this._canBeInstancedCache=new Map,this._originalMaterials=new Map,this.pmremGeneratorResults=new WeakMap,this.prefabInstanceChain=[],this.geometryCache=new Map,this.collisionShapeCache=new Map,this.originalFog=null,t.onCreate(e=>this.update(e)),t.onUpdate(e=>this.update(e)),t.onRemove(e=>this.remove(e)),this.createAssetSubscription=a.onCreate.subscribe(e=>{this.assets.set(e.id,e)}),this.updateSubscription=a.onUpdate.subscribe(async t=>{this.assets.set(t.id,t),"material"==t.type?e.traverse(e=>{if(e instanceof r.Mesh)if(Array.isArray(e.material))for(let a=0;a<e.material.length;a++)this.refreshMaterial(e,e.material[a],t,a);else this.refreshMaterial(e,e.material,t)}):"mesh"==t.type?(this.findByAssetId(t.id).forEach(e=>{this.remove(e.userData.src),this.materializeAndInitActor(e.userData.src)}),this.landscapeManagers.forEach(e=>{const a=e.source?.grass?.layers?.some(e=>e.meshes.some(e=>e.assetId===t.id));a&&e.queueRefreshScatter(this.renderingView?.camera.position??new S,!0)})):"prefab"===t.type?this.findByAssetId(t.id).forEach(e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}):"vfx"===t.type&&this.dataProvider.getObjects().forEach(e=>{St(e,(e,a)=>{"vfx"===e.type&&e.assetId===t.id&&(this.remove(e),this.materializeAndInitActor(e))})})})}async refreshMaterial(e,t,a,s){const r=t?.userData?.assetId;if(r!==a.id){const e=this.assets.get(r);let t=!1;if(null!=e)for(const s of Object.values(e.material.shaderParams)){if(s.type===We.Material&&s.value===a.id){t=!0;break}if(s.type===We.Array&&"element"in s&&s.element===We.Material&&s.value.includes(a.id)){t=!0;break}}if(!t)return}const i=await materialFromAsset(this.assets.get(r),this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!1),n=i.userData;i.userData=t.userData,i.userData.hasBloom=n.hasBloom,i.userData.reflective=n.reflective,i.userData.outlineParameters=n.outlineParameters,null!=s?Et(e.material[s],i)||(e.material[s]=i):Et(e.material,i)||(e.material=i,e===this.sky&&this.applySkySettings(e.material))}getTopLevelActors(){return Array.from(this.materializedActors.entries()).filter(([e,t])=>!e.includes("/")).map(([,e])=>e)}get actorInstances(){return Array.from(this.materializedActors.values())}async initTextures(){const e=[];if(await Promise.all(this.dataProvider.getObjects().filter(e=>"shape_mesh"===e.type||"asset_mesh"===e.type).filter(e=>null!=e.materialAssignments).flatMap(e=>e.materialAssignments).map(async t=>{const a=this.assets.get(t.materialId);if(null!=a)for(const t of Object.values(a.material.shaderParams))if(t.type===We.Texture&&"string"==typeof t.value){const a=this.assets.get(t.value),s=await this.assetManagerService.getTexture(a);null!=s&&e.push(s)}})),0!==e.length&&this.renderingView){console.log(`Initializing ${e.length} textures`),console.time("Init textures");for(const t of e)this.renderingView.renderer.initTexture(t);console.timeEnd("Init textures")}}async prefetchAssets(){const e=Array.from(new Set(this.dataProvider.getObjects().filter(e=>null!=e.assetId&&"asset_mesh"==e.type).filter(e=>e.assetId)));await Promise.all(e.map(e=>this.assetsService.getAsset(e.assetId).then(e=>{if(null!=e)return this.assetManagerService.getMesh(e)}))),this.initTextures()}async init(){await this.preInit(),ft.clear(),gt.clear(),await this.prefetchAssets(),await Promise.all(this.dataProvider.getObjects().map(e=>this.materialize(e))),await this.initActorsPostInit()}initActorsPostInit(e=this.getTopLevelActors(),t){const a=e.map(async e=>{const a=e.object.userData.src??e.object.userData._src;if("vfx"===a.type)return Promise.resolve();const s=await this.assetsService.getAsset(a.assetId),r={...s?.actor?.params??{},...a.actor?.params??{}},i=null!=t?new Map(Array.from(this.materializedActors.entries()).filter(([e,a])=>e.startsWith(t.sceneObjectChain.join("/"))&&e.split("/").length-1===t.sceneObjectChain.length).map(([e,t])=>[e.split("/").pop(),t])):this.materializedActors;for(const t of a.actor.innerParams??[])await this.applyActorComponentParams(e,t.path.slice(),t.params,i);await this.attachEditorComponents(e,a,i);const n=await prepareClassParameters(r,e.constructor,this.assetsService,this.assetManagerService,i,this.renderingView,this.shaders,this.actorProvider);Object.assign(e,n);try{return await this.actorProvider.initActor(e)}catch(e){console.error(`Failed to initiate actor (name="${a.name}", id=${a.id})`,e)}});return Promise.all(a)}async attachEditorComponents(e,t,a){const s=t.actor?.components??[];for(const r of s){const s=this.componentTypes.find(e=>e.name===r.type);if(null==s){console.warn(`Component type '${r.type}' not found for actor ${t.id}`);continue}const i=e.attach(s.type);if(null!=r.params){const e=await prepareClassParameters(r.params,null,this.assetsService,this.assetManagerService,a,this.renderingView,this.shaders,this.actorProvider);Object.assign(i,e)}for(const e of r.innerParams??[])await this.applyActorComponentParams(i,e.path.slice(),e.params,a)}}addVfxChildActors(e,t=e){}async applyActorComponentParams(e,t,a,s){const r=t.length,i=t.shift();if(0==r){const t=await prepareClassParameters(a,null,this.assetsService,this.assetManagerService,s,this.renderingView,this.shaders,this.actorProvider);for(const[a,s]of Object.entries(t))null!=s&&(e[a]=s)}else null!=e[i]&&await this.applyActorComponentParams(e[i],t,a,s)}canObjectBeInstanced(e){return e.physics?.type!==ne.dynamic&&"sky"!==e.type&&"global_fog"!==e.type&&"world_env"!==e.type}async canAssetBeInstanced(e){let t=this._canBeInstancedCache.get(e.assetId);if(null==t){const a=await this.createFromAsset(e);if(null==a)return!1;const s=[];a.traverse(e=>{!Te(e)&&e.isMesh&&s.push(e)});const r=1==s.length&&0==s[0].children.length,i=!mt,n=s.every(e=>!Array.isArray(e.material)||1===e.material.length),o=s.some(e=>e instanceof d&&null!=e.geometry.morphAttributes&&Object.keys(e.geometry.morphAttributes).length>0),l=!0;t=s.length>0&&(r||n&&i)&&l&&!o,this._canBeInstancedCache.set(e.assetId,t)}return t}async preInit(){this.renderingView?.onLoop(()=>{null!=this.sky&&this.renderingView.camera.getWorldPosition(this.sky.position)}),this.assetsService.getAssets().then(e=>{for(const t of e)this.assets.set(t.id,t)})}shouldBeMaterialized(e){if(null!=this.detailTier&&"asset_mesh"===e.type&&null!=e.assetId){const t=this.assets.get(e.assetId);if(null!=t){const e=t.mesh?.detailTier;if(null!=e)return e<=this.detailTier}}return!0}async initWithInstancing(){await this.preInit(),await this.prefetchAssets(),ft.clear(),gt.clear();const e=[],t=new ve,a=new ve,s=new ve;let i=0,l=0,c=0;const h=new Map,p=new be(()=>new Map);for(const r of this.dataProvider.getObjects())await St(r,async(r,o,m)=>{if(!this.shouldBeMaterialized(r))return;const u="asset_mesh"==r.type&&this.canObjectBeInstanced(r)&&await this.canAssetBeInstanced(r),f="shape_mesh"===r.type&&"landscape"!==r.shape&&r.physics?.type!==ne.dynamic;if(u||f){if(o&&o.children?.length>0){const e=o.children.findIndex(e=>e.id===r.id);e>=0&&o.children.splice(e,1)}if(f){let e=r.shape+JSON.stringify(r.shapeParams??{})+r.castShadow+r.receiveShadow;const t=r.materialAssignments?.at(0)?.materialId,a=null!=t?this.assets.get(t):null;let i=null;if(null!=a&&"shader"!==a.material.type){if(e+=a.material.type+a.material.shader,null!=a.material.shaderParams){if(e+=Object.entries(a.material.shaderParams).filter(([e,t])=>"color"!=e).map(e=>JSON.stringify(e)).join(),null!=a.material.shaderParams.color){const e=a.material.shaderParams.color;e.type===We.Color&&null!=e.value&&(i=new n(e.value))}}}else e+=t;s.push(e,{object:{...r,parentTransform:m},color:i}),c++}else{const e=this.assets.get(r.assetId);let s=h.get(r.assetId);if(null==s){const e=await this.createFromAsset(r,{assignMaterials:!1});if(null==e)return;if(s=h.get(r.assetId),null==s){s={useBatchedMesh:null!=je(e)&&ct(e,e=>!(e instanceof d)||this.testCanBatch(e.material,e.geometry)),assetMesh:e},h.set(r.assetId,s)}}const n=It(r.materialAssignments,e.materialAssignments);if(s.useBatchedMesh)await Pe(s.assetMesh,async e=>{if(!(e instanceof d))return;const t=Array.isArray(e.material)?e.material[0]:e.material,s=n.find(e=>null!=t.color&&Ct(e.color,t.color)&&(null==e.name||t.name===e.name))?.materialId;let o=t;if(null!=s){const e=this.assets.get(s);o=await materialFromAsset(e,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!0)}if(null!=o){p.get(r.id).set(e.uuid,o);let t=zt(o);t+=Ot(e),a.push(t,{...r,parentTransform:m,meshUUID:e.uuid}),i++}else console.warn("Can not materialize mesh because missing material",r)});else{const e=r.assetId+JSON.stringify(r.materialAssignments??[]);t.push(e,{...r,parentTransform:m}),l++}}}else null==o&&e.push({...r,parentTransform:m})});console.log(`Scene init stats: \n Batched Assets: ${a.size} groups containing in total ${i} objects.\n Instanced Assets: ${t.size} groups containing in total ${l} objects.\n Shapes: ${s.size} batch groups containing in total ${c} objects. \n ${e.length} objects can not be batched. \n `);for(const e of h.values())this.prepareCollisionShapesForInstanced(e.assetMesh);console.time("materialize batches");for(const e of a.values()){if(0==e.length)continue;let t;const a=h.get(e[0].assetId).assetMesh;t=this.createBatchedMesh(e,p,h);const s=this.assets.get(e[0].assetId);t.castShadow=e[0].castShadow??s.castShadow??!0,t.receiveShadow=e[0].receiveShadow??s.receiveShadow??!0;const r=new Ce;r.add(t),r.userData.src=e[0],a instanceof Ce&&(r.collisionShapes=a.collisionShapes),r.castShadow=!1,r.receiveShadow=!1,this.scene.add(r)}for(const e of t.values()){if(0==e.length)continue;let t;const a=h.get(e[0].assetId).assetMesh;t=await this.createInstancedMesh(e,a);const s=this.assets.get(e[0].assetId);t.castShadow=e[0].castShadow??s.castShadow??!0,t.receiveShadow=e[0].receiveShadow??s.receiveShadow??!0;const r=new Ce;r.add(t),r.userData.src=e[0],a instanceof Ce&&(r.collisionShapes=a.collisionShapes),this.prepareCollisionShapesForInstanced(r),r.castShadow=!1,r.receiveShadow=!1,this.scene.add(r)}console.timeEnd("materialize batches");for(const e of s.values()){if(0==e.length)continue;const t=e[0].object,a=await this.createFromShape(t),s=De(a,e=>!Te(e)&&null!=e.geometry),i=s.material.clone();null!=e[0].color&&null!=i.color&&(i.color=new n(16777215));const l=s.geometry;let c,h;!(mt||i instanceof B||null==l.index)?(c=new r.BatchedMesh(e.length,l.getAttribute("position").count,l.index.count,i),c.perObjectFrustumCulled=!0,h=c.addGeometry(l)):c=new r.InstancedMesh(l,i,e.length),c.castShadow=a.castShadow??!0,c.receiveShadow=s.receiveShadow??!0;for(let t=0;t<e.length;t++){const a=e[t],s=(new r.Matrix4).compose((new S).fromArray(a.object.position),(new M).setFromEuler((new o).fromArray(a.object.rotation)),(new S).fromArray(a.object.scale)),i=(new m).copy(a.object.parentTransform).multiply(s);let n;n=c instanceof r.BatchedMesh?c.addInstance(h):t,c.setMatrixAt(n,i),null!=a.color&&c.setColorAt(n,a.color)}for(let t=0;t<e.length;t++){const s=e[t],r=new Ce;r.userData.src=e[0],a instanceof Oe&&(r.collisionShapes=[a.collisionShape]),r.castShadow=!1,r.receiveShadow=!1,this.scene.add(r),r.add(c),null==c.userData.hasCollision&&(c.userData.hasCollision=[]),c.userData.hasCollision[t]=!!s.object.collisionDetection}}await Promise.all(e.map(e=>this.materialize(e))),await this.initActorsPostInit()}prepareCollisionShapesForInstanced(e){e instanceof Ce&&e.collisionShapes.forEach(e=>{e instanceof a&&e.mesh instanceof d&&(e.mesh=e.mesh.geometry)})}testCanBatch(e,t){return!mt&&t.groups.length<2&&(!Array.isArray(e)||1==e.length)&&this.testCanBatchMaterial(e)}testCanBatchMaterial(e){const t=Array.isArray(e)?e[0]:e;return null!=t&&(!(t instanceof g)||null==t.bumpMap&&null==t.lightMap&&null==t.displacementMap)}createBatchedMesh(e,t,a){const s=new ve;for(const t of e)null!=t.meshUUID?s.push(t.meshUUID??t.assetId,t):console.warn("Missing mesh uuid for batching");let i=0,o=0,l=0;const c=new Map;for(const[e,t]of s.entries()){const s=t[0].assetId,r=a.get(s);if(null==r){console.warn("Missing batching info for asset id "+s);continue}const n=De(r.assetMesh,t=>t instanceof d&&t.uuid===e);if(null==n){console.warn("Missing mesh in batched asset");continue}c.set(e,n);const h=n.geometry.getAttribute("position");null==h&&console.warn("Missing position attribute for batched mesh"),i+=n.geometry.index.count*t.length,o+=h.count*t.length,l+=t.length}const h=["color","map","roughness","roughnessMap","metalness","metalnessMap","opacity","alphaMap","aoMap","aoMapIntensity","normalMap","normalScale","emissive","emissiveIntensity","emissiveMap"];let p=new Map,m=new r.MeshStandardMaterial({color:"white"});const u=t.get(e[0].id).get(e[0].meshUUID);if(null==u)throw"missing source material";if(u instanceof g){const a=new Set,s=new Map;for(const i of e){const e=t.get(i.id).get(i.meshUUID);if(null==e)throw"missing mat";for(const t of h){let i=e[t];i instanceof r.CompressedArrayTexture&&null!=i.userData.index&&(i=i.userData.index);const n=s.get(t);void 0===n||Ut(i,n)?s.set(t,i):a.add(t)}}for(const e of a){let t;const a=u[e];if("number"==typeof a)t=I(e);else if(a instanceof x)t=P(e);else if(a instanceof S||a instanceof n)t=D(e);else if(a instanceof A)t=j(e);else if(a instanceof r.CompressedArrayTexture)t=I(e+"_i");else if(a instanceof b)continue;p.set(e,t)}let i=H.uv;u instanceof ot&&null!=u.heightMap&&(i=lt(i,R(u.heightMap),O(u.heightScale)));let o=Ft(p.get("opacity"),k)??O(u.opacity??1);if(null!=u.alphaMap){let e;if(u.alphaMap instanceof r.CompressedArrayTexture){const t=G(u.alphaMap),a=Ft(p.get("alphaMap"),k)??O(u.alphaMap.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.alphaMap).sample(i);o=o.multiply(e.r)}let l=_(Ft(p.get("color"),Z)??u.color,o);if(null!=u.map){let e;if(u.map instanceof r.CompressedArrayTexture){const t=G(u.map),a=Ft(p.get("map"),k)??O(u.map.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.map).sample(i);l=l.multiply(e)}let c=_(Ft(p.get("emissive"),Z)??u.emissive,o);if(null!=u.emissiveMap){let e;if(u.emissiveMap instanceof r.CompressedArrayTexture){const t=G(u.emissiveMap),a=Ft(p.get("emissiveMap"),k)??O(u.emissiveMap.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.emissiveMap).sample(i);c=c.multiply(e)}const d=Ft(p.get("emissiveIntensity"),k)??O(u.emissiveIntensity??1),f=Ft(p.get("normalScale"),X)??q(u.normalScale??new A(1,1));let g=J.normal;if(null!=u.normalMap){let e;if(u.normalMap instanceof r.CompressedArrayTexture){const t=G(u.normalMap),a=Ft(p.get("normalMap"),k)??O(u.normalMap.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.normalMap).sample(i);g=V(e.rgb,f.x)}let y=Ft(p.get("roughness"),k)??O(u.roughness??1);if(null!=u.roughnessMap){let e;if(u.roughnessMap instanceof r.CompressedArrayTexture){const t=G(u.roughnessMap),a=Ft(p.get("roughnessMap"),k)??O(u.roughnessMap.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.roughnessMap).sample(i);y=y.multiply(e.g)}let w=Ft(p.get("metalness"),k)??O(u.metalness??0);if(null!=u.metalnessMap){let e;if(u.metalnessMap instanceof r.CompressedArrayTexture){const t=G(u.metalnessMap),a=Ft(p.get("metalnessMap"),k)??O(u.metalnessMap.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.metalnessMap).sample(i);w=w.multiply(e.b)}let M=O(1);if(null!=u.aoMap){let e;if(u.aoMap instanceof r.CompressedArrayTexture){const t=G(u.aoMap),a=Ft(p.get("aoMap"),k)??O(u.aoMap.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.aoMap).sample(i);M=M.multiply(e.r)}const v=Ft(p.get("aoMapIntensity"),k)??O(u.aoMapIntensity??0);let C=g;!0!==u.userData.disableAO&&(C=z("DOUBLE_SIDED",C,e=>$(new E("gl_FrontFacing"),e,e.multiplyScalar(-1))));const T=new B({color:W({color:l,roughness:y,metalness:w,ambientOcclusion:M,ambientOcclusionIntensity:v,emissive:c,emissiveIntensity:d,normal:C}),normal:g,roughness:y,emissive:c.rgb,transparent:u.transparent,alphaTest:u.alphaTest,envMap:u.envMap});null!=u.envMap&&(T.uniforms.envMapIntensity={value:u.envMapIntensity},T.uniforms.envMapRotation={value:_t(u.envMapRotation,u.envMap)}),T.envMap=u.envMap,T.side=u.side,m=T}else{m=u;for(const a of e){const e=t.get(a.id).get(a.meshUUID);if(e!=m){console.error(`Different materials in group for object ${a.id} and mesh uuid ${a.meshUUID}`,{objectMaterial:e,sourceMaterial:u});break}}}const f=new nt(l,o,i,m);for(const[e,t]of p.entries()){let a=1;t instanceof Q||t instanceof Z?a=4:t instanceof X&&(a=2),f.initUniform(e,a,0)}for(const[e,i]of s.entries()){const s=i[0].assetId,o=c.get(e);if(null==o){console.error(`Missing single asset mesh for mesh uuid ${e} and asset id ${s}`);continue}if(null==o.geometry){console.error("Missing geometry on mesh mesh");continue}const l=f.addGeometry(o.geometry),h=a.get(s);if(null==h){console.warn("Missing batching info when configuring for asset id "+s);continue}const m=je(h.assetMesh)?.uuid===e,d=h.assetMesh instanceof Ce&&m?h.assetMesh.collisionShapes:void 0,u=this.configureBatchedInstancedMesh(i,f,o,l,d);for(let e=0;e<u.length;e++){const a=i[e],s=u[e],o=t.get(a.id).get(a.meshUUID);for(let e of p.keys()){let t=o[e];if(t instanceof n&&(t=new S(t.r,t.g,t.b)),t instanceof r.CompressedArrayTexture)t=t.userData.index??0,e+="_i";else if(t instanceof b||null==t)continue;f.setUniformAt(e,s,t)}}}return f}async createInstancedMesh(e,t){const a=De(t,e=>!Te(e)&&null!=e.geometry),s=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(t,It(e[0].materialAssignments,s.materialAssignments)),a.updateMatrix();const i=a.geometry.clone(),n=a.material;let o;if(o=new r.InstancedMesh(i,n,e.length),this.configureBatchedInstancedMesh(e,o,a),a.material instanceof p&&o.castShadow&&o.receiveShadow&&Array.isArray(n))for(const e of n);return o}configureBatchedInstancedMesh(e,t,a,s,i){const n=[];for(let l=0;l<e.length;l++){let c=l;t instanceof r.BatchedMesh&&(c=t.addInstance(s)),n.push(c);const h=(new r.Matrix4).compose((new S).fromArray(e[l].position),(new M).setFromEuler((new o).fromArray(e[l].rotation)),(new S).fromArray(e[l].scale)),p=(new m).copy(e[l].parentTransform).multiply(h).multiply(a.matrixWorld);t.setMatrixAt(c,p),null==t.userData.hasCollision&&(t.userData.hasCollision=[]),t.userData.hasCollision[c]=!!e[l].collisionDetection,null!=i&&(null==t.userData.collisionShapes&&(t.userData.collisionShapes=[]),t.userData.collisionShapes[c]=i)}return n}remove(e){if(console.log("Remove scene object",e),"global_fog"==e.type)return void(this.scene.fog=this.originalFog);if("world_env"===e.type)this.resetWorldEnv(),this.worldEnvObj=null;else if("actor"==e.type||"vfx"===e.type){const t=this.materializedActors.get(e.id);null!=t?(t.disposed.next(!0),t.onEndPlay()):console.warn("Failed to remove actor",e)}else"prefab"===e.type&&this.materializedActors.forEach((t,a)=>{a.startsWith(e.id)&&(t.disposed.next(!0),t.onEndPlay()),this.materializedActors.delete(a)});const t=this.sceneObjectMap.get(e.id);t?.parent.remove(t),this.sceneObjectMap.delete(e.id),this.components.filter(t=>t.object.userData.src?.id===e.id).forEach(e=>this.components.splice(this.components.indexOf(e,1))),this.landscapeManagers.filter(t=>t.source.id===e.id).forEach(e=>{e.clear(),e.stop(),this.landscapeManagers.splice(this.landscapeManagers.indexOf(e,1))}),this.removed$.next({object:t,source:e})}deleteSceneObject(e){const t=this.sceneObjectMap.get(e.id);if(this.scene.remove(t),"landscape"==e.type){const t=this.landscapeManagers.findIndex(t=>t.source.id===e.id);if(t>-1){const e=this.landscapeManagers.splice(t,1)[0];e.clear(),e.stop()}}}findByAssetId(e){return Ie(this.scene,t=>t.userData.src?.assetId==e,e=>null!=e.userData.src)}applyMaterials(e,t){return null==t?Promise.resolve([]):Promise.all(t.filter(e=>"null"!==e.materialId).map(t=>this.applyMaterial(e,t)))}async applyMaterial(e,t){await applyMaterial(e,t,e=>{const t=this.assets.get(e);if(null!=t)try{return materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders)}catch(e){console.error("Failed to apply material",e)}},this._originalMaterials)}unapplyMaterials(e){e.traverse(async e=>{if(e instanceof d)if(e.material instanceof Array)for(let t=0;t<e.material.length;t++)e.material[t]=this._originalMaterials.get(e.id+"#"+t)??e.material[t];else e.material=this._originalMaterials.get(e.id)??e.material})}updateActors(e){console.log("update actors"),this.actorTypes=e;const t=new Set(Object.values(ie));Ie(this.scene,e=>e.userData.src?.id&&"actor"===e.userData.src.type&&this.materializedActors.has(e.userData.src?.id)&&!t.has(e.userData.src.actor.type)).forEach(async e=>{this.remove(e.userData.src),await this.materializeAndInitActor(e.userData.src)})}updateComponents(e){this.componentTypes=e,Ie(this.scene,e=>e.userData.src?.id&&"actor"===e.userData.src.type&&this.materializedActors.has(e.userData.src?.id)&&(e.userData.src.actor?.components?.length??0)>0).forEach(async e=>{this.remove(e.userData.src),await this.materializeAndInitActor(e.userData.src)})}updateShaders(e){this.shaders=e;for(const[e,t]of ft.entries())t.userData.customShaderName&&ft.delete(e);this.landscapeManagers.forEach(t=>t.updateShaders(e)),Ie(this.scene,e=>!0).forEach(e=>{e.traverse(async e=>{if(e instanceof d)if(Array.isArray(e.material))for(let t=0;t<e.material.length;t++){const a=e.material[t].userData?.customShaderName;if(null!=a){const a=this.assets.get(e.material[t].userData.assetId);this.refreshMaterial(e,e.material[t],a,t)}}else{const t=e.material.userData?.customShaderName;if(null!=t){const t=this.assets.get(e.material.userData.assetId);this.refreshMaterial(e,e.material,t)}}})})}async update(e){if("sky"===e.type&&null!=this.sky&&null!=this.sky.parent)return void this.updateSky(e);if("world_env"===e.type&&null!=this.worldEnvObj)return void this.updateWorldEnv(e);const t=this.sceneObjectMap.get(e.id);if(t){let s=!1;if(t.traverseAncestors(e=>{"_hology_transform_group"===e.name&&(s=!0)}),!s){const a=this.findParent(e);null!=a&&a.uuid!=t.uuid?a.attach(t):console.error("Parent is wrong")}if("prefab"!==e.type&&"group"!==e.type){this.unapplyMaterials(t);this.inEditor&&e.hidden&&!1?t.traverse(e=>{e instanceof d&&(e.material.wireframe=!0)}):t.traverse(e=>{e instanceof d&&(e.material.wireframe=!1)})}if("asset_mesh"===e.type){const a=this.assets.get(e.assetId);It(e.materialAssignments,a.materialAssignments).forEach(e=>this.applyMaterial(t,e))}else"shape_mesh"===e.type&&this.applyMaterials(t,e.materialAssignments);if(s||(null!=e.position&&t.position.fromArray(e.position),null!=e.scale&&t.scale.fromArray(e.scale),null!=e.rotation&&t.rotation.fromArray(e.rotation)),this.applyVertexMaterials(e,t),"light"==e.type)if("point"==e.light.type){const a=t;a.color=new n(e.light.point.color),a.intensity=e.light.point.intensity,a.decay=e.light.point.decay,a.castShadow=e.light.point.castShadow,a.distance=Math.max(e.light.point.distance,0),a.userData.volumetricIntensity=e.light.point.volumetricIntensity}else if("spot"==e.light.type){const a=t;a.color=new n(e.light.spot.color),a.intensity=e.light.spot.intensity,a.decay=e.light.spot.decay,a.angle=e.light.spot.angle,a.penumbra=e.light.spot.penumbra,a.castShadow=e.light.spot.castShadow,a.distance=Math.max(e.light.spot.distance,0),a.userData.volumetricIntensity=e.light.spot.volumetricIntensity}else"directional"===e.light.type?this.applyDirectionalLight(e.light.directional,e):"ambient"===e.light.type&&this.applyDirectionalAmbientLight(t,e.light.ambient,e);else if("landscape"===e.shape){const a=this.landscapeManagers.find(t=>t.source.id===e.id).source.landscape.options.density!==e.landscape.options.density;if(this.inEditor&&a){this.remove(e);const t=await this.materializeAndInitActor(e);return void this.updated$.next({object:t,source:e})}this.applyHeightMaps(t,e.landscape.heightMaps),this.inEditor&&this.landscapeManagers.filter(t=>t.source.id===e.id).forEach(t=>{t.updateSource(e),t.queueRefreshScatter(this.renderingView.camera.position,!0,e=>!0)})}else if("global_fog"===e.type){const t=(this.scene.fog instanceof c?"density":"linear")!==e.fog.type;this.scene.fog=At(e.fog),t&&(a=this.scene).traverse(e=>{if(e instanceof d){const t=e.material;t instanceof B&&(a.fog instanceof l?(t.uniforms.fogFar.value=a.fog.far,t.uniforms.fogNear.value=a.fog.near):a.fog instanceof c&&(t.uniforms.density={value:a.fog.density}),t.needsUpdate=!0,t.uniformsNeedUpdate=!0)}}),this.fixFogColor()}else if("actor"===e.type){if(this.materializedActors.has(e.id)){const t=this.materializedActors.get(e.id);if(t instanceof st){const a=await prepareClassParameters(e.actor.params,null,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,[],this.actorProvider);return void Object.assign(t,a)}const a=this.editorActorParamSnapshot.get(e.id);null!=a&&a===JSON.stringify(e.actor)||s||(this.remove(e),await this.materializeAndInitActor(e))}}else if("shape_mesh"===e.type){const a=await this.createMeshByShape(e.shape,t.material,e.shapeParams);t instanceof Oe&&(t.geometry=a.geometry,t.collisionShape=a.collisionShape)}("asset_mesh"===e.type||"shape_mesh"===e.type&&"landscape"!==e.shape)&&ut(t,e.castShadow,e.receiveShadow),e.name&&e.name.length>0&&(t.name=e.name),this.updated$.next({object:t,source:e})}else{const t=await this.materializeAndInitActor(e);this.updated$.next({object:t,source:e})}var a;this.renderingView.renderer.shadowMap.needsUpdate=!0}async materializeAndInitActor(e,t=this.findParent(e)){const a=await this.materialize(e,t);return St(e,async e=>{if("actor"===e.type){const t=this.materializedActors.get(e.id);null!=t?await this.initActorsPostInit([t]):console.error(`Something went wrong when creating actor ${e.id}`)}}),a}findParent(e){const t=this.dataProvider.getObjects().flatMap(t=>t.id===e.id?null:xe(t,t=>t.children?.some(t=>t.id===e.id),()=>!0))[0];return null==t?this.scene:null!=t?Ie(this.scene,e=>e.userData?.src?.id===t.id,e=>null!=e.userData?.src)[0]:void 0}fixFogColor(){!0===this.renderingView.options.enableOutlines&&(this.scene.fog.color=new n(this.scene.fog.color))}findMeshWithGeometry(e){let t;return e.traverse(e=>{e instanceof d&&e.geometry&&(t=e)}),t}applyVertexMaterials(e,t){if(null==e.vertexMaterials||0===e.vertexMaterials.length)return;let a=1;for(const t of e.vertexMaterials)a=Math.max(t.w.length,a);const s=Ae(e.vertexMaterials,e=>e.m);t.traverse(e=>{if(e instanceof d){if(null==e.geometry)return;if(Tt(Ue(e,0,!1)),a>0){Tt(Ue(e,0,!1))}}});const r=new Set;for(const[e,i]of s.entries()){const s=null!=e?t.getObjectByName(e):this.findMeshWithGeometry(t);let n=!1;if(null==s||null==s.geometry)return void console.warn(`Failed to apply vertex materials on mesh with name "${e}"`);const o=Ue(s,0,!0);Tt(o);for(const e of i)o.setX(e.i,e.w[0]??0),o.setY(e.i,e.w[1]??0),o.setZ(e.i,e.w[2]??0),o.setW(e.i,e.w[3]??0),n=!0;if(a>0){const e=Ue(s,4,!0);Tt(e);for(const t of i)e.setX(t.i,t.w[4]??0),e.setY(t.i,t.w[5]??0),e.setZ(t.i,t.w[6]??0),e.setW(t.i,t.w[7]??0),e.needsUpdate=!0,n=!0}n&&r.add(e)}this.inEditor&&this.landscapeManagers.filter(t=>t.source.id===e.id).forEach(e=>e.queueRefreshScatter(this.renderingView.camera.position,!0,e=>r.has(e.name)))}async materialize(e,t,a=!1,s){if(!this.shouldBeMaterialized(e))return;let r,i;switch(e.type){case"asset_mesh":r=await this.createFromAsset(e);break;case"shape_mesh":r=await this.createFromShape(e);break;case"light":r=await this.createLight(e);break;case"particles":r=await this.createParticleSystem(e),e.collisionDetection=!1;break;case"global_fog":this.scene.fog=At(e.fog),this.fixFogColor(),r=new h;break;case"sky":this.sky=He(),this.updateSky(e),r=this.sky;break;case"world_env":this.updateWorldEnv(e),r=new h,this.worldEnvObj=r;break;case"actor":({object:r,actor:i}=await this.createFromActor(e,s));break;case"group":r=new h;break;case"prefab":r=await this.createFromPrefab(e,s,t);break;case"vfx":r=await this.createFromVfx(e,s);break;default:if(this.inEditor)throw new Error("unknown type "+e.type);console.warn(`Failed to materialize object. Unknown type '${e.type}'. This might be because the hology/core library is not compatible with the editor version.`)}if(null!=r){if(e.name&&e.name.length>0&&(r.name=e.name),this.applyTransform(e,r),a?r.userData._src=e:r.userData.src=e,null!=i&&(r.userData.actor=i),this.inEditor,this.inEditor,this.objectMap.set(r.uuid,e),this.sceneObjectMap.set(e.id,r),e.physics?.type!==ne.dynamic||null==t||this.inEditor?null==t?this.scene.add(r):null==t||"actor"!==e.type||this.inEditor?t?.add(r):(t.add(r),this.scene?.attach(r),console.log(r)):(t.add(r),r.getWorldPosition(r.position),r.getWorldQuaternion(r.quaternion),r.getWorldScale(r.scale),this.scene?.attach(r)),null!=e.children&&await Promise.all(e.children?.map(e=>this.materialize(e,r,a))),this.inEditor||null!=t||"asset_mesh"!=e.type&&"shape_mesh"!==e.type&&"prefab"!==e.type&&"group"!==e.type||"landscape"===e.shape||null!=e.physics?.type&&e.physics.type==ne.dynamic||bt(r),null!=this.renderingView)return this.renderingView.renderer.shadowMap.needsUpdate=!0,r;console.warn("RenderingView not found in materializer")}}applyTransform(e,t){null!=e.position&&t.position.fromArray(e.position),null!=e.scale&&t.scale.fromArray(e.scale),null!=e.rotation&&t.rotation.fromArray(e.rotation)}updateWorldEnv(e){this.renderingView.aoPass.enabled=e.worldEnv.ao.enabled,this.renderingView.aoPass.blendIntensity=e.worldEnv.ao.blendIntensity,this.renderingView.aoPass.updateGtaoMaterial(e.worldEnv.ao);const t=e.worldEnv.toneMapping;null!=t&&(this.renderingView.renderer.toneMapping=t.mapping??0,this.renderingView.renderer.toneMappingExposure=t.exposure??1);const a=e.worldEnv.environment;null!=a&&null!=a.textureId?this.assetManagerService.getTexture(this.assets.get(a.textureId)).then(e=>{null==this.pmremGenerator&&(this.pmremGenerator=new r.PMREMGenerator(this.renderingView.renderer),this.pmremGenerator.compileEquirectangularShader()),this.pmremGeneratorResults.has(e)||this.pmremGeneratorResults.set(e,this.pmremGenerator.fromEquirectangular(e).texture);const t=this.pmremGeneratorResults.get(e);this.renderingView.scene.environment=t,this.renderingView.scene.environmentIntensity=a.intensity??1}):this.renderingView.scene.environment=null}resetWorldEnv(){this.renderingView.aoPass.enabled=!1,this.renderingView.aoPass.blendIntensity=1,this.renderingView.aoPass.output=0,this.renderingView.renderer.toneMapping=0,this.renderingView.renderer.toneMappingExposure=1}async updateSky(e){if(null==e?.sky?.materialId)return void(this.sky.material=Je);const t=await this.assetsService.getAsset(e.sky.materialId),a=await materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!1);this.applySkySettings(a),null!=this.sky?this.sky.material=a:console.warn("No sky has been created")}applySkySettings(e){e.side=r.BackSide,(e instanceof g||e instanceof r.MeshBasicMaterial||e instanceof r.ShaderMaterial)&&(e.fog=!1),e.depthTest=!1}async createComponent(e,t,a,s){const r=new ht[a.path+"/"+a.className],i=t.id+s;r.id=i,r.object=e;for(const e of a.params)null!=e.value&&(r[e.name]=e.value);return this.components.push(r),i}async createFromActor(e,t){const a=this.actorTypes.find(t=>t.name===e.actor?.type)?.type??ie[e.actor?.type];if(null==a)return{object:null,actor:null};this.inEditor&&this.editorActorParamSnapshot.set(e.id,JSON.stringify(e.actor));const s=await this.actorProvider.create(a,(new S).fromArray(e.position),(new o).fromArray(e.rotation),!0);return this.materializedActors.set(this.getNestedActorId(e.id,t),s),{object:s?.object,actor:s}}getNestedActorId(e,t){return null!=t?t.sceneObjectChain.join("/")+"/"+e:e}async createFromVfx(e,t){const a=await this.assetsService.getAsset(e.assetId);null==a&&console.error("Could not find asset",e);const s=await this.actorProvider.create(te,(new S).fromArray(e.position),(new o).fromArray(e.rotation),!1);try{await s.fromAsset(a)}catch(e){return console.error("Failed to create VFX asset",e),null}return s.play(),this.materializedActors.set(this.getNestedActorId(e.id,t),s),null!=s&&(s.object.userData.actor=s),s?.object}async createFromShape(e){const t=this.inEditor&&e.hidden;let a;if("landscape"==e.shape)a=this.createLandscape(e),a.traverse(e=>{e instanceof d&&this._originalMaterials.set(e.id,e.material)});else{let s=new g({name:"Default",color:new n("#aaaaaa"),visible:this.inEditor||!e.hidden,wireframe:!!t});const r=await this.createMeshByShape(e.shape,s,e.shapeParams);r.castShadow=e.castShadow??!0,r.receiveShadow=e.castShadow??!1,e.collisionDetection||(r.collisionShape=null),r.physics=e.physics,a=r,this._originalMaterials.set(a.id,r.material),a.traverse(e=>{})}return t||(await Promise.all((e.materialAssignments??[]).filter(e=>null!=e.materialId).map(e=>this.applyMaterial(a,e))),this.applyVertexMaterials(e,a)),a}createLandscape(e){const t=e.landscape?.options;if(null==t)return console.error(`No landscape options exist on scene object ${e.id} ${e.name}`),new h;const a=ze(e.landscape.options);this.applyHeightMaps(a,e.landscape.heightMaps,!0);const s=new ke(e,this.renderingView,a,this.assetManagerService,this.assetsService,this.shaders,t=>{(e.materialAssignments??[]).filter(e=>null!=e.materialId).forEach(e=>this.applyMaterial(t,e))});return this.landscapeManagers.push(s),s.refreshGeometry(),a}applyHeightMaps(e,t,a=!1){const s=new Fe(e.sections);for(const e of t??[]){const t=s.find(e.x,e.y);if(!t)return;const a=t.geometry.getAttribute("position");for(const t of e.points)a.setY(t.i,t.y);a.needsUpdate=!0}const r=e.sections;r.forEach(e=>{e.geometry.computeBoundsTree(),e.geometry.computeVertexNormals()}),this.inEditor&&!a||setTimeout(()=>Be(r),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&&Re.includes(e)){const s=await prepareShapeParameters(a??{}),r=e+JSON.stringify(a);if(!this.geometryCache.has(r)){const t=Le[e].geometry(s);t.computeTangents(),this.geometryCache.set(r,t)}this.collisionShapeCache.has(r)||this.collisionShapeCache.set(r,Le[e].collision(s));return new Oe(this.geometryCache.get(r),t,this.collisionShapeCache.get(r))}if(this.inEditor)throw new Error(`Unsupported shape '${e}'`);console.warn(`Failed to create shape. Unsupported shape '${e}'. This might be because the hology/core library is not compatible with the editor version.`)}async createFromAsset(e,t){const a=await this.assetsService.getAsset(e.assetId);if(null==a)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);let{scene:s}=await this.assetManagerService.getMesh(a,{mergeGeomtries:!0});if(!1!==t?.assignMaterials)try{await Promise.all(It(e.materialAssignments,a.materialAssignments).map(e=>this.applyMaterial(s,e)))}catch(t){console.error("Failed to apply material"+t,e)}const r=e.receiveShadow??!!a.receiveShadow,i=e.castShadow??!!a.castShadow;return s.receiveShadow=r,ut(s,i,r),e.collisionDetection||(s.collisionShapes=[]),null!=e.physics&&!0!==this.inEditor&&(s.physics=e.physics),this.applyVertexMaterials(e,s),s.traverse(e=>{e instanceof d&&"computeBoundsTree"in e.geometry&&null==e.geometry.boundsTree&&e.geometry.computeBoundsTree()}),s}async createFromPrefab(e,t,a){const s=await this.assetsService.getAsset(e.assetId);if(null==s)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);null==t&&(t={sceneObjectChain:[]}),t.sceneObjectChain.push(e.id);const{object:r}=await this.createFromPrefabAsset(s,t,a,e);return t.sceneObjectChain.pop(),r}async createFromPrefabAsset(e,t,a,s){const r=new h;null!=s&&this.applyTransform(s,r),null!=a&&a.add(r),await Promise.all(e.prefab.objects.filter(e=>"global_fog"!==e.type&&"world_env"!==e.type).map(e=>this.materialize(e,r,!0,structuredClone(t))));const i=t.sceneObjectChain.join("/"),n=Array.from(this.materializedActors.entries()).filter(([e,a])=>e.startsWith(i)&&e.split("/").length-1===t.sceneObjectChain.length).map(([,e])=>e);n.forEach(e=>{}),this.initActorsPostInit(n,structuredClone(t));const o=Array.from(this.materializedActors.entries()).filter(([e,t])=>e.startsWith(i)).map(([,e])=>e);return{object:r,actors:o}}async createParticleSystem(e){await this.assetsService.getAsset(e.assetId);return new y}async createLight(e){if("point"===e.light.type){const t=new w(e.light.point.color,e.light.point.intensity,e.light.point.distance,e.light.point.decay);if(t.castShadow=e.light.point.castShadow??!0,this.inEditor){const e=(new r.TextureLoader).load("assets/light-bulb-icon.webp"),a=new r.SpriteMaterial({map:e,alphaTest:.5}),s=new rt(a);s.scale.multiplyScalar(.6),t.add(s)}return t}if("spot"===e.light.type){const t=new r.SpotLight(e.light.spot.color,e.light.spot.intensity,e.light.spot.distance,e.light.spot.angle,e.light.spot.penumbra,e.light.spot.decay);if(t.castShadow=e.light.spot.castShadow??!0,t.target=new y,t.target.position.set(0,-1,0),t.add(t.target),this.inEditor){const e=(new r.TextureLoader).load("assets/light-bulb-icon.webp"),a=new r.SpriteMaterial({map:e,alphaTest:.5}),s=new rt(a);s.scale.multiplyScalar(.6),t.add(s),t.add(new r.SpotLightHelper(t))}return t}return"directional"===e.light.type?(this.applyDirectionalLight(e.light.directional,e),new h):"ambient"===e.light.type?(this.applyDirectionalAmbientLight(null,e.light.ambient,e),new h):void 0}applyDirectionalAmbientLight(e,t,a){const s=this.scene.children.find(e=>e.name===Ge);null!=s?(s.intensity=t.intensity,s.color.set(t.color),s.groundColor.set(t.color),s.userData.src=a,s.userData.volumetricIntensity=t.volumetricIntensity):console.warn("Couldn't find ambient light")}applyDirectionalLight(e,t){for(const a of this.renderingView.csm.lights)a.intensity=e.intensity,a.color.set(e.color),a.castShadow=e.castShadow,a.userData.src=t,a.userData.volumetricIntensity=e.volumetricIntensity;this.renderingView.csm.lightDirection.fromArray(e.direction).normalize()}dispose(){this.updateSubscription.unsubscribe(),this.createAssetSubscription.unsubscribe(),this.materializedActors.forEach(e=>e.disposed.next(!0)),this.materializedActors.clear()}};dt=e([ee(),t("design:paramtypes",[v,Object,Object,Ee,ce,Array,Array,Object,Array])],dt);export{dt as SceneMaterializer};function ut(e,t,a){e.castShadow=t,e.receiveShadow=a,e.traverse(e=>{e.castShadow=t,e.receiveShadow=a})}const ft=new Map,gt=new Map,yt=new u({color:16711935}),wt=new Map;export async function materialFromAsset(e,t,a,s,r,i=!0){const n=JSON.stringify(e.material)+t?._id;return i&&ft.has(n)?ft.get(n):i&&gt.has(n)?await gt.get(n):gt.set(n,_materialFromAsset(n,e,t,a,s,r,i)).get(n)}export async function _materialFromAsset(e,t,a,s,i,o,l=!0){const c={opacity:t.material.params?.opacity??1,map:null,emissive:t.material.params?.emissive??null,metalness:t.material.params?.metalness??0,flatShading:t.material.params?.flatShading??!1,color:new n(t.material.params?.color),transparent:null!=t.material.params?.opacity&&t.material.params?.opacity<1},h={};if(null!=t.material.params?.map){const e=t.material.params.map,a=await s.getAsset(e);null!=a&&(c.map=await i.getTexture(a))}let p;switch(t.material.type){case"phong":p=new f({...c,...h});break;case"water":p=$e(c,a);break;case"grassFoliage":p=Ne({color:c.color,map:c.map},a);break;case"grass":p=_e({...c,colorTwo:new n(t.material.params.colorTwo),colorThree:new n(t.material.params.colorThree)},a);break;case"standard":case"unlit":case"toon":case"layered":case"lambert":case"shader":case"landscape":case"landscape-composite":case"decal-unlit":case"decal-standard":const e={standard:pt?ue:ye,lambert:ue,unlit:we,toon:it,layered:tt,landscape:ge,"landscape-composite":fe,"decal-unlit":Xe,"decal-standard":Ye}[t.material.type]??o.find(e=>e.name==t.material.shader)?.type;if(e){try{let r=new e;const n=await prepareClassParameters(t.material?.shaderParams??{},e,s,i,null,a,o);Object.assign(r,n),p=r.build()}catch(e){console.log("Shader runtime error: "+e),wt.has(t.material.shader)||wt.set(t.material.shader,yt.clone()),p=wt.get(t.material.shader)}p.userData.customShaderName=t.material.shader}else console.warn("Missing shader implementation with name "+t.material.shader),p=yt;break;default:throw new Error("Unsupported material type"+t.material.type)}return a?.csm.setupMaterial(p),null!=a&&ft.set(e,p),p.side=t.material.side??p.side??r.FrontSide,p.transparent=(t.material.transparent??c.transparent??!1)||p.transparent,p.alphaTest=t.material.alphaTest??p.alphaTest??0,null!=t.material.blending&&(p.blending=oe[t.material.blending]??r.NormalBlending),t.material.bloom&&(p.userData.hasBloom=!0),t.material.reflective&&(p.userData.reflective=!0),!0===t.material.outlines&&(p.userData.outlineParameters={},null!=t.material.outlineParams&&(null!=t.material.outlineParams.color&&(p.userData.outlineParameters.color=new n(t.material.outlineParams.color).toArray()),null!=t.material.outlineParams.thickness&&(p.userData.outlineParameters.thickness=t.material.outlineParams.thickness))),p.userData.assetId=t.id,gt.delete(e),p}export async function prepareClassParameters(e,t,a,s,r,i,n,o){const l={};for(const[t,c]of Object.entries(e)){const e=await vt(t,c,a,s,r,i,n,o);null!=e&&(l[t]=e)}return l}export async function prepareShapeParameters(e){const t={};for(const[a,s]of Object.entries(e)){const e=await vt(a,s,null,null,null);null!=e&&(t[a]=e)}return t}const Mt=new Map;async function vt(e,t,a,s,r,i,l,c,h=t.value,p=t.type){if(null==t||null==h||""===h)return null;switch(p){case We.Array:if(Array.isArray(h)&&"element"in t)return await Promise.all(h.map(n=>vt(e,t,a,s,r,i,l,c,n,t.element)));break;case We.Number:case We.FloatNode:let p;if("string"==typeof h?p=parseFloat(h):"number"==typeof h&&(p=h),t.type===We.FloatNode){if("object"==typeof h&&"a"in h&&"b"in h){const e=h;if(null==e.a)return null;const t="string"==typeof e.a?parseFloat(e.a):e.a;if(null==e.b)return t;const a="string"==typeof e.b?parseFloat(e.b):e.b,s=function(e){let t=Mt.get(e);return null==t&&(t=he(qe.decode(e)),Mt.set(e,t)),t}(e.easing),r=s.sample(pe(me.energy));return F(O(t),O(a),r)}return O(p)}return p;case We.Texture:let m=await s.getTexture(await a.getAsset(h));return"envmap"===e.toLowerCase()&&null!=i&&(m=i.getEnvTexture(m)),m;case We.Sampler2DNode:return R(await s.getTexture(await a.getAsset(h)));case We.Boolean:return h;case We.BooleanNode:return C(h);case We.Vector2:case We.Vec2Node:if("object"==typeof h){const e=h instanceof Array?(new A).fromArray(h):new A(h.x,h.y);return t.type===We.Vec2Node?q(e):e}return null;case We.Vector3:case We.Vec3Node:if("object"==typeof h){const e=h instanceof Array?(new S).fromArray(h):new S(h.x,h.y,h.z);return t.type===We.Vec3Node?Y(e):e}return null;case We.Color:case We.RgbNode:const d=new n(h);return t.type===We.RgbNode?N(d):d;case We.String:return h;case We.BaseActor:const u=h;return null==r&&console.warn("Class parameters can not be prepared as actors are not passed in"),r?.get(u);case We.Euler:const f=h;return(new o).fromArray(f);case We.Object3D:return(await s.getMesh(await a.getAsset(h))).scene;case We.Material:return await materialFromAsset(await a.getAsset(h),i,a,s,l);case We.AudioBuffer:return await s.getAudio(await a.getAsset(h));case We.VisualEffect:const g=await a.getAsset(h);if(null==c){console.error("Can not create instance of visual effect because missing actor provider");break}if("vfx"in g)return new ae(c,g);console.error("Using a non-vfx asset for visual effect parameter");break;case We.Prefab:{const e=await a.getAsset(h);return null==e?(console.error("Using a non-prefab asset for prefab parameter",h),null):new se(e)}case We.Curve:return qe.decode(h);case We.ColorLayer:case We.MaskLayer:if(at(h)){const e=await Ze.decode(h,async e=>await s.getTexture(await a.getAsset(e))),t=await prepareClassParameters(h.params,null,a,s);return Object.assign(e,t),e}return console.warn("Expecting color layer but got",h),null}return null}function bt(e){e.updateWorldMatrix(!0,!0),e.updateMatrix(),e.traverse(e=>{e.matrixAutoUpdate=!1,e.matrixWorldNeedsUpdate=!1});const t=e.updateMatrixWorld;e.updateMatrixWorld=function(){t.apply(e),e.updateMatrixWorld=function(){}}}function At(e){return"linear"===e.type?new l(new n(e.color),e.near??100,e.far??1e3):"density"===e.type?new c(e.color,e.density):void console.warn("Invalid fog type",e)}new g({color:4229780});async function St(e,t,a,s){null==s&&(s=(new m).identity());const i=s.clone().multiply(xt(e,new r.Matrix4));if(null!=e.children&&e.children.length>0)for(let a=e.children.length-1;a>=0;a--)await St(e.children[a],t,e,i);await t(e,a,s)}function xt(e,t){return null==e.position||null==e.rotation||null==e.scale?t.identity():t.compose((new S).fromArray(e.position),(new M).setFromEuler((new o).fromArray(e.rotation)),(new S).fromArray(e.scale))}export function toSerializedParamType(e){const t=e.constructor.prototype;return t instanceof Number||e===Number?We.Number:t instanceof k||"function"==typeof e.prototype.isFloat?We.FloatNode:t instanceof b||e===b||e.isTexture?We.Texture:t instanceof de||e===L?We.Sampler2DNode:t instanceof Boolean||e===Boolean?We.Boolean:t instanceof T?We.BooleanNode:t instanceof n||e==n?We.Color:t instanceof U||"function"==typeof e.prototype.isRgb?We.RgbNode:t instanceof A||e==A?We.Vector2:t instanceof X||"function"==typeof e.prototype.isVec2?We.Vec2Node:t instanceof S||e==S?We.Vector3:t instanceof Z||"function"==typeof e.prototype.isVec3?We.Vec3Node:t instanceof String||e===String?We.String:t instanceof re||e==re||e.prototype instanceof re||e.prototype==re?We.BaseActor:t instanceof o||e==o?We.Euler:t instanceof y||e==y?We.Object3D:t instanceof p||e==p?We.Material:t instanceof AudioBuffer||e==AudioBuffer?We.AudioBuffer:t instanceof ae||e==ae?We.VisualEffect:t instanceof se||e==se?We.Prefab:t instanceof qe||e==qe?We.Curve:t instanceof Ze||e==Ze?We.ColorLayer:t instanceof et||e==et?We.MaskLayer:void console.warn("Failed to map parameter type to serialized version",{type:e})}export function prepareCustomParams(e,t,a={}){return Object.fromEntries(e.map(e=>[e.name,{type:e.options.array?We.Array:toSerializedParamType(e.type),...e.options.array?{element:toSerializedParamType(e.type)}:{},value:t[e.name]?.value??(!0!==e.options.array?a[e.name]??customParameterDefaultValueByType.get(toSerializedParamType(e.type)):[])}]))}export function prepareCustomParamsFromType(e,t,a=null){const s=Me(e);if(0===s.length)return{};let r;null!=a?le(a,()=>{r=a.get(e)}):r=new e;const i={};for(const e of s){const t=r[e.name];if(null!=t&&!0!==e.options.array){const a=serializeCustomParameter(e.type,t);null!=a&&(i[e.name]=a)}}return prepareCustomParams(s,t,i)}export function serializeCustomParameter(e,t){function a(){console.error("Failed to serialize value",{type:e,value:t})}switch(e){case Number:case Boolean:return t;case A:return t instanceof A?t.toArray():void a();case S:return t instanceof S?t.toArray():void a();case x:return t instanceof x?t.toArray():void a();case n:return t instanceof n?"#"+t.getHexString():"string"==typeof t?t:"number"==typeof t?"#"+new n(t).getHexString():void a();case String:return t;case o:return t instanceof o?t.toArray():void a();case se:return t instanceof se?t.asset?.id??null:void a()}}function It(e,t){return function(e,t,a){const s=[],r=new Set;for(const i of[...e??[],...t??[]]){const e=a(i);r.has(e)||(r.add(e),s.push(i))}return s}((e??[]).filter(e=>jt(e.materialId)),(t??[]).filter(e=>jt(e.materialId)),e=>e.color+e.name)}function jt(e){return"null"!=e&&null!=e}export const customParameterDefaultValueByType=new Map([[We.RgbNode,"#000000"],[We.Color,"#000000"],[We.Vector4,[0,0,0,0]],[We.Vec4Node,[0,0,0,0]],[We.Vector3,[0,0,0]],[We.Vec3Node,[0,0,0]],[We.Vector2,[0,0]],[We.Vec2Node,[0,0]],[We.Euler,[0,0,0,"XYZ"]],[We.Array,[]],[We.ColorLayer,Ke],[We.MaskLayer,Qe]]);let Dt=new n,Pt=new n;function Ct(e,t){return Dt.set(e),Pt.set(t),Dt.getHexString()==Pt.getHexString()}export function applyMaterial(e,t,a,s){const i=[];return e.traverse(async e=>{if(e instanceof d||e.isMesh||e instanceof r.SkinnedMesh||e.isSkinnedMesh)for(const t of Se(e.material))t.hasOwnProperty("color")&&i.push(e)}),Promise.all(i.map(async e=>{if(e.material instanceof Array)for(let r=0;r<e.material.length;r++){const i=e.material[r];if(null==i.color||!(i.color instanceof n))continue;const o="#"+i.color.getHexString(),l=i.name;if(o===t.color&&(i.name===t.name||null==t.name)||e.userData["originalColor_"+r]===t.color&&e.userData["originalMaterialName_"+r]===t.name){const i=await a(t.materialId),n=e.material[r];null!=i&&n.id!=i.id&&(e.material[r]=i,e.userData["originalColor_"+r]=e.userData["originalColor_"+r]??o,e.userData["originalMaterialName_"+r]=e.userData["originalMaterialName_"+r]??l,null!=s&&s.set(e.id+"#"+r,n))}}else if("color"in e.material){const r="#"+e.material.color.getHexString(),i=e.material.name;if(r===t.color&&(e.material.name===t.name||null==t.name)||e.userData.originalColor===t.color&&e.userData.originalName===t.name){const n=await a(t.materialId),o=e.material;null!=n&&(e.material=n,e.userData.originalColor=e.userData.originalColor??r,e.userData.originalMaterialName=e.userData.originalMaterialName??i,null!=s&&(s.has(e.id)||s.set(e.id,o)))}}}))}function Et(e,t){if(e instanceof r.ShaderMaterial&&t instanceof r.ShaderMaterial){return e.fragmentShader+e.vertexShader==t.fragmentShader+t.vertexShader&&function(e,t){if(e instanceof r.ShaderMaterial&&t instanceof r.ShaderMaterial){for(const a in e.uniforms){if(null==t.uniforms[a])return!1;if(t.uniforms[a].value!==e.uniforms[a].value)return!1}return!0}return!1}(e,t)}return!1}function Tt(e){if(null!=e){for(let t=0;t<e.array.length;t++)e.setX(t,0);e.needsUpdate=!0}}const Vt=new WeakMap;function Ot(e){let t=Vt.get(e);return null==t&&(t=function(e){const t=je(e);if(null==t)return"";return Object.keys(t.geometry.attributes).sort().join(",")}(e),Vt.set(e,t)),t}const kt=new WeakMap;function zt(e){let t=kt.get(e);return null==t&&(t=function(e){let t=e.type;e instanceof r.MeshStandardMaterial||(t+=e.id+"");(e instanceof r.MeshBasicMaterial||e instanceof r.MeshLambertMaterial||e instanceof g||e instanceof f)&&(null!=e.map&&(t+="c"+e.map?.id),null!=e.aoMap&&(t+="o"+e.aoMap?.id),null!=e.lightMap&&(t+="l"+e.lightMap?.id),null!=e.envMap&&(t+="v"+e.envMap?.id),null!=e.alphaMap&&(t+="a"+e.alphaMap?.id));e instanceof g&&(null!=e.normalMap&&(t+="n"+e.normalMap?.id),null!=e.roughnessMap&&(t+="r"+e.roughnessMap?.id),null!=e.metalnessMap&&(t+="m"+e.metalnessMap?.id),null!=e.emissiveMap&&(t+="e"+e.emissiveMap?.id));(e instanceof u||e instanceof f)&&null!=e.specularMap&&(t+="s"+e.specularMap?.id);e instanceof r.MeshToonMaterial&&(null!=e.map&&(t+="c"+e.map?.id),null!=e.aoMap&&(t+="o"+e.aoMap?.id),null!=e.lightMap&&(t+="l"+e.lightMap?.id),null!=e.alphaMap&&(t+="a"+e.alphaMap?.id));e instanceof ot&&null!=e.heightMap&&(t+="h"+e.heightMap?.id);if(e instanceof r.ShaderMaterial){t+=e.vertexShader,t+=e.fragmentShader;for(const a in e.uniforms){const s=e.uniforms[a];s&&s.value&&s.value.isTexture&&null!=s.value.id&&(t+="t:"+a+":"+s.value.id)}}null!=e.userData.outlineParameters&&(t+=e.userData.outlineParameters.color,t+=e.userData.outlineParameters.thickness);return t+=e.side,t+=e.transparent?"t":"",t+=e.depthWrite?"dw":"",t+=e.depthTest?"dt":"",t+=e.alphaTest,t}(e),kt.set(e,t)),t}function Ft(e,t){if(null==e)return null;if(!(e instanceof t))throw new Error(`Value is not an instance of ${t.name}`);return e}const Bt=new m,Nt=new o;function _t(e,t){return Nt.copy(e),Nt.x*=-1,Nt.y*=-1,Nt.z*=-1,t.isCubeTexture&&!1===t.isRenderTargetTexture&&(Nt.y*=-1,Nt.z*=-1),(new r.Matrix3).setFromMatrix4(Bt.makeRotationFromEuler(Nt))}new x;function Ut(e,t){return e===t||null==e==(null==t)&&("number"==typeof e&&"number"==typeof t?e===t||isNaN(e)&&isNaN(t):e instanceof r.Color&&t instanceof r.Color?e.r===t.r&&e.g===t.g&&e.b===t.b:e instanceof A&&t instanceof A?e.x===t.x&&e.y===t.y:e instanceof S&&t instanceof S?e.x===t.x&&e.y===t.y&&e.z===t.z:e instanceof x&&t instanceof x&&(e.x===t.x&&e.y===t.y&&e.z===t.z&&e.w===t.w))}/*
1
+ import{__decorate as e,__metadata as t}from"tslib";import{ConvexPolyhedronCollisionShape as a}from"@hology/core";import{Subject as s}from"rxjs";import*as r from"three";import{BoxGeometry as i,Color as n,Euler as o,Fog as l,FogExp2 as c,Group as h,Material as p,Matrix4 as d,Mesh as m,MeshLambertMaterial as u,MeshPhongMaterial as f,MeshStandardMaterial as g,Object3D as y,PointLight as w,Quaternion as M,Scene as v,Texture as b,Vector2 as A,Vector3 as S,Vector4 as x}from"three";import{batchingUniformFloat as I,batchingUniformVec2 as j,batchingUniformVec3 as D,batchingUniformVec4 as P,bool as C,BooleanExpression as E,BooleanNode as T,colorToNormal as V,float as O,FloatNode as k,ifDefApply as z,mix as F,NodeShaderMaterial as B,rgb as N,rgba as _,RgbNode as U,select as $,standardMaterial as W,Texture2dLookupNode as L,textureSampler2d as R,textureSampler2dArray as G,varyingAttributes as H,varyingTransformed as J,vec2 as q,Vec2Node as X,vec3 as Y,Vec3Node as Z,vec4 as K,Vec4Node as Q}from"three-shader-graph";import{Service as ee}from"typedi";import{VfxActor as te}from"../effects/vfx/vfx-actor.js";import{VisualEffect as ae}from"../effects/vfx/vfx-param.js";import{Prefab as se,PrefabOf as re}from"./objects/prefab.js";import{BaseActor as ie}from"../gameplay/actors/actor.js";import ne from"../gameplay/actors/builtin/index.js";import{PhysicsBodyType as oe,ThreeBlendingMode as le,withInjectionContext as ce}from"../gameplay/index.js";import{RenderingView as he}from"../rendering.js";import{curveSampler as pe,oneMinus as de,particleUniforms as me,Sampler2DNode as ue}from"../shader-nodes/index.js";import{LambertShader as fe}from"../shader/builtin/lambert-shader.js";import{LandscapeCompositeShader as ge}from"../shader/builtin/landscape-composite-shader";import{LandscapeShader as ye}from"../shader/builtin/landscape-shader.js";import{StandardShader as we}from"../shader/builtin/standard-shader.js";import{UnlitShader as Me}from"../shader/builtin/unlit-shader.js";import{extractShaderParameters as ve}from"../shader/parameter.js";import{ArrayMap as be,DefaultMap as Ae,groupBy as Se}from"../utils/collections.js";import{iterateMaterials as xe}from"../utils/materials.js";import{filterChildrenShallow as Ie,filterSceneShallow as je,findFirstVisibleMesh as De,findFirstVisibleObject as Pe,traverseAsync as Ce}from"../utils/three/traverse.js";import{AssetMeshInstance as Ee,AssetResourceLoader as Te}from"./asset-resource-loader.js";import{AssetsProvider as Ve}from"./assets-provider.js";import{isCollisionMesh as Oe}from"./collision/collision-shape-import.js";import{BoxCollisionShape as ke,PhysicalShapeMesh as ze}from"./collision/collision-shape.js";import{LandscapeManager as Fe}from"./landscape/landscape-manager.js";import{initLandscape as Be}from"./landscape/landscape.js";import{SectionGrid as Ne,smoothNormalsCrossMeshes as _e}from"./landscape/utils.js";import{createGrassFoliageMaterial as Ue}from"./materials/grass-foliage.js";import{createGrassMaterial as $e}from"./materials/grass.js";import{getMaterialAttribute as We}from"./materials/utils/material-painting.js";import{createWaterMaterial as Le}from"./materials/water.js";import{SerializedParamType as Re}from"./model.js";import{ShapeLibrary as Ge,ShapeLibraryKeys as He}from"./objects/shapes.js";import{ambientLightName as Je,createSky as qe,defaultSkyMaterial as Xe}from"./sky.js";import{Curve2 as Ye}from"../utils/curve.js";import{DecalUnlitShader as Ze}from"../shader/builtin/decal-unlit-shader.js";import{DecalStandardShader as Ke}from"../shader/builtin/decal-standard-shader.js";import{ColorLayer as Qe,defaultValueColorLayer as et,defaultValueMaskLayer as tt,MaskLayer as at}from"../shader/color-layer.js";import{LayeredShader as st}from"../shader/builtin/layered-shader";import{isColorLayerSerialized as rt}from"../shader/color-layer";import{FogVolume as it}from"../rendering/fog/fog-volume-actor.js";import{UnscaledSprite as nt}from"../utils/three/unscaled-sprite.js";import{ToonShader as ot}from"../shader/builtin/toon-shader.js";import{BatchedMesh2 as lt}from"./batched-mesh-2.js";import{ParallaxStandardMaterial as ct}from"../shader/builtin/standard-shader";import{parallaxOcclusionMapping as ht}from"../shader-nodes/pom.js";import{traverseVisibleEvery as pt}from"../utils/three/traverse";const dt={},mt=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),ut=/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(navigator.userAgent.includes("iPhone")||navigator.userAgent.includes("iPad"))&&!!navigator.userAgent.match(/AppleWebKit/)&&!navigator.userAgent.match(/CriOS/);export const shapeDefaultColor="#aaaaaa";export class SceneMaterializerLoader{constructor(e,t,a){this.dataProvider=e,this.assetsService=t,this.assetManagerService=a}get(e,t){return new ft(e,this.dataProvider,this.assetsService,this.assetManagerService,t,[],[],{create:()=>null,initActor:async()=>{}})}}let ft=class{constructor(e,t,a,i,n,o,l,c,h=[]){this.scene=e,this.dataProvider=t,this.assetsService=a,this.assetManagerService=i,this.renderingView=n,this.shaders=o,this.actorTypes=l,this.actorProvider=c,this.componentTypes=h,this.objectMap=new Map,this.sceneObjectMap=new Map,this.components=[],this.landscapeManagers=[],this.materializedActors=new Map,this.idToSceneObject=new Map,this.inEditor=!0,this.updated$=new s,this.removed$=new s,this.error$=new s,this.editorActorParamSnapshot=new Map,this.assets=new Map,this._canBeInstancedCache=new Map,this._originalMaterials=new Map,this.pmremGeneratorResults=new WeakMap,this.prefabInstanceChain=[],this.prefabInstanceExposedActorMap=new Map,this.geometryCache=new Map,this.collisionShapeCache=new Map,this.originalFog=null,t.onCreate(e=>this.update(e)),t.onUpdate(e=>this.update(e)),t.onRemove(e=>this.remove(e)),this.createAssetSubscription=a.onCreate.subscribe(e=>{this.assets.set(e.id,e)}),this.updateSubscription=a.onUpdate.subscribe(async t=>{this.assets.set(t.id,t),"material"==t.type?e.traverse(e=>{if(e instanceof r.Mesh)if(Array.isArray(e.material))for(let a=0;a<e.material.length;a++)this.refreshMaterial(e,e.material[a],t,a);else this.refreshMaterial(e,e.material,t)}):"mesh"==t.type?(this.findByAssetId(t.id).forEach(e=>{this.remove(e.userData.src),this.materializeAndInitActor(e.userData.src)}),this.landscapeManagers.forEach(e=>{const a=e.source?.grass?.layers?.some(e=>e.meshes.some(e=>e.assetId===t.id));a&&e.queueRefreshScatter(this.renderingView?.camera.position??new S,!0)})):"prefab"===t.type?this.findByAssetId(t.id).forEach(e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}):"vfx"===t.type&&this.dataProvider.getObjects().forEach(e=>{It(e,(e,a)=>{"vfx"===e.type&&e.assetId===t.id&&(this.remove(e),this.materializeAndInitActor(e))})})})}async refreshMaterial(e,t,a,s){const r=t?.userData?.assetId;if(r!==a.id){const e=this.assets.get(r);let t=!1;if(null!=e)for(const s of Object.values(e.material.shaderParams)){if(s.type===Re.Material&&s.value===a.id){t=!0;break}if(s.type===Re.Array&&"element"in s&&s.element===Re.Material&&s.value.includes(a.id)){t=!0;break}}if(!t)return}const i=await materialFromAsset(this.assets.get(r),this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!1),n=i.userData;i.userData=t.userData,i.userData.hasBloom=n.hasBloom,i.userData.reflective=n.reflective,i.userData.outlineParameters=n.outlineParameters,null!=s?Vt(e.material[s],i)||(e.material[s]=i):Vt(e.material,i)||(e.material=i,e===this.sky&&this.applySkySettings(e.material))}getTopLevelActors(){return Array.from(this.materializedActors.entries()).filter(([e,t])=>!e.includes("/")).map(([,e])=>e)}get actorInstances(){return Array.from(this.materializedActors.values())}async initTextures(){const e=[];if(await Promise.all(this.dataProvider.getObjects().filter(e=>"shape_mesh"===e.type||"asset_mesh"===e.type).filter(e=>null!=e.materialAssignments).flatMap(e=>e.materialAssignments).map(async t=>{const a=this.assets.get(t.materialId);if(null!=a)for(const t of Object.values(a.material.shaderParams??{}))if(t.type===Re.Texture&&"string"==typeof t.value){const a=this.assets.get(t.value),s=await this.assetManagerService.getTexture(a);null!=s&&e.push(s)}})),0!==e.length&&this.renderingView){console.log(`Initializing ${e.length} textures`),console.time("Init textures");for(const t of e)this.renderingView.renderer.initTexture(t);console.timeEnd("Init textures")}}async prefetchAssets(){const e=Array.from(new Set(this.dataProvider.getObjects().filter(e=>null!=e.assetId&&"asset_mesh"==e.type).filter(e=>e.assetId)));await Promise.all(e.map(e=>this.assetsService.getAsset(e.assetId).then(e=>{if(null!=e)return this.assetManagerService.getMesh(e)}))),this.initTextures()}async init(){await this.preInit(),yt.clear(),wt.clear(),await this.prefetchAssets(),await Promise.all(this.dataProvider.getObjects().map(e=>this.materialize(e))),await this.initActorsPostInit()}async initActorsPostInit(e=Array.from(this.materializedActors.entries())){const t=e.map(async([e,t])=>{const a=t.object.userData.src??t.object.userData._src;if("vfx"===a.type)return Promise.resolve();const s=await this.assetsService.getAsset(a.assetId),r=e.split("/"),i=r.slice(0,-1),n=i.join("/"),o=(r[r.length-1],new Map);for(const[e,t]of this.materializedActors)if(o.set(e,t),0===n.length)e.includes("/")||o.set(e,t);else if(e.startsWith(n+"/")){const a=e.slice(n.length+1);a.includes("/")||o.set(a,t)}const l={...s?.actor?.params??{},...a.actor?.params??{}},c=[...a.actor?.innerParams??[]];for(let t=i.length-1;t>=0;t--){const a=i.slice(0,t+1).join("/"),s=this.idToSceneObject.get(a);if("prefab"===s?.type&&null!=s.prefab){const i=await this.assetsService.getAsset(s.assetId);if(null!=i){let n=!1,o=a+"/"+i.prefab?.mainActorId;for(;null!=o;){if(o===e){n=!0;break}o=this.prefabInstanceExposedActorMap.get(o)}if(n&&null!=s.prefab.params&&Object.assign(l,s.prefab.params),null!=s.prefab.innerParams)for(const e of s.prefab.innerParams){const a=r.slice(t+1);e.path.length>=a.length&&e.path.slice(0,a.length).every((e,t)=>e===a[t])&&c.push({path:e.path.slice(a.length),params:e.params})}}}}for(const e of c)await this.applyActorComponentParams(t,e.path.slice(),e.params,o);await this.attachEditorComponents(t,a,o);const h=await prepareClassParameters(l,t.constructor,this.assetsService,this.assetManagerService,o,this.renderingView,this.shaders,this.actorProvider,e=>{const t=n.length>0?n+"/"+e:e;return this.prefabInstanceExposedActorMap.get(t)??null});Object.assign(t,h);try{return await this.actorProvider.initActor(t)}catch(e){console.error(`Failed to initiate actor (name="${a.name}", id=${a.id})`,e)}});return Promise.all(t)}async attachEditorComponents(e,t,a){const s=t.actor?.components??[];for(const r of s){const s=this.componentTypes.find(e=>e.name===r.type);if(null==s){console.warn(`Component type '${r.type}' not found for actor ${t.id}`);continue}const i=e.attach(s.type);if(null!=r.params){const e=await prepareClassParameters(r.params,null,this.assetsService,this.assetManagerService,a,this.renderingView,this.shaders,this.actorProvider,e=>this.prefabInstanceExposedActorMap.get(e)??null);Object.assign(i,e)}for(const e of r.innerParams??[])await this.applyActorComponentParams(i,e.path.slice(),e.params,a)}}addVfxChildActors(e,t=e){}async applyActorComponentParams(e,t,a,s){const r=t.length,i=t.shift();if(0==r){const t=await prepareClassParameters(a,null,this.assetsService,this.assetManagerService,s,this.renderingView,this.shaders,this.actorProvider,e=>this.prefabInstanceExposedActorMap.get(e)??null);for(const[a,s]of Object.entries(t))null!=s&&(e[a]=s)}else null!=e[i]&&await this.applyActorComponentParams(e[i],t,a,s)}canObjectBeInstanced(e){return e.physics?.type!==oe.dynamic&&"sky"!==e.type&&"global_fog"!==e.type&&"world_env"!==e.type}async canAssetBeInstanced(e){let t=this._canBeInstancedCache.get(e.assetId);if(null==t){const a=await this.createFromAsset(e);if(null==a)return!1;const s=[];a.traverse(e=>{!Oe(e)&&e.isMesh&&s.push(e)});const r=1==s.length&&0==s[0].children.length,i=!ut,n=s.every(e=>!Array.isArray(e.material)||1===e.material.length),o=s.some(e=>e instanceof m&&null!=e.geometry.morphAttributes&&Object.keys(e.geometry.morphAttributes).length>0),l=!0;t=s.length>0&&(r||n&&i)&&l&&!o,this._canBeInstancedCache.set(e.assetId,t)}return t}async preInit(){this.renderingView?.onLoop(()=>{null!=this.sky&&this.renderingView.camera.getWorldPosition(this.sky.position)}),this.assetsService.getAssets().then(e=>{for(const t of e)this.assets.set(t.id,t)})}shouldBeMaterialized(e){if(null!=this.detailTier&&"asset_mesh"===e.type&&null!=e.assetId){const t=this.assets.get(e.assetId);if(null!=t){const e=t.mesh?.detailTier;if(null!=e)return e<=this.detailTier}}return!0}async initWithInstancing(){await this.preInit(),await this.prefetchAssets(),yt.clear(),wt.clear();const e=[],t=new be,a=new be,s=new be;let i=0,l=0,c=0;const h=new Map,p=new Ae(()=>new Map);for(const r of this.dataProvider.getObjects())await It(r,async(r,o,d)=>{if(!this.shouldBeMaterialized(r))return;const u="asset_mesh"==r.type&&this.canObjectBeInstanced(r)&&await this.canAssetBeInstanced(r),f="shape_mesh"===r.type&&"landscape"!==r.shape&&r.physics?.type!==oe.dynamic;if(u||f){if(o&&o.children?.length>0){const e=o.children.findIndex(e=>e.id===r.id);e>=0&&o.children.splice(e,1)}if(f){let e=r.shape+JSON.stringify(r.shapeParams??{})+r.castShadow+r.receiveShadow;const t=r.materialAssignments?.at(0)?.materialId,a=null!=t?this.assets.get(t):null;let i=null;if(null!=a&&"shader"!==a.material.type){if(e+=a.material.type+a.material.shader,null!=a.material.shaderParams){if(e+=Object.entries(a.material.shaderParams).filter(([e,t])=>"color"!=e).map(e=>JSON.stringify(e)).join(),null!=a.material.shaderParams.color){const e=a.material.shaderParams.color;e.type===Re.Color&&null!=e.value&&(i=new n(e.value))}}}else e+=t;s.push(e,{object:{...r,parentTransform:d},color:i}),c++}else{const e=this.assets.get(r.assetId);let s=h.get(r.assetId);if(null==s){const e=await this.createFromAsset(r,{assignMaterials:!1});if(null==e)return;if(s=h.get(r.assetId),null==s){s={useBatchedMesh:null!=De(e)&&pt(e,e=>!(e instanceof m)||this.testCanBatch(e.material,e.geometry)),assetMesh:e},h.set(r.assetId,s)}}const n=Dt(r.materialAssignments,e.materialAssignments);if(s.useBatchedMesh)await Ce(s.assetMesh,async e=>{if(!(e instanceof m))return;const t=Array.isArray(e.material)?e.material[0]:e.material,s=n.find(e=>null!=t.color&&Tt(e.color,t.color)&&(null==e.name||t.name===e.name))?.materialId;let o=t;if(null!=s){const e=this.assets.get(s);o=await materialFromAsset(e,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!0)}if(null!=o){p.get(r.id).set(e.uuid,o);let t=Bt(o);t+=zt(e),a.push(t,{...r,parentTransform:d,meshUUID:e.uuid}),i++}else console.warn("Can not materialize mesh because missing material",r)});else{const e=r.assetId+JSON.stringify(r.materialAssignments??[]);t.push(e,{...r,parentTransform:d}),l++}}}else null==o&&e.push({...r,parentTransform:d})});console.log(`Scene init stats: \n Batched Assets: ${a.size} groups containing in total ${i} objects.\n Instanced Assets: ${t.size} groups containing in total ${l} objects.\n Shapes: ${s.size} batch groups containing in total ${c} objects. \n ${e.length} objects can not be batched. \n `);for(const e of h.values())this.prepareCollisionShapesForInstanced(e.assetMesh);console.time("materialize batches");for(const e of a.values()){if(0==e.length)continue;let t;const a=h.get(e[0].assetId).assetMesh;t=this.createBatchedMesh(e,p,h);const s=this.assets.get(e[0].assetId);t.castShadow=e[0].castShadow??s.castShadow??!0,t.receiveShadow=e[0].receiveShadow??s.receiveShadow??!0;const r=new Ee;r.add(t),r.userData.src=e[0],a instanceof Ee&&(r.collisionShapes=a.collisionShapes),r.castShadow=!1,r.receiveShadow=!1,this.scene.add(r)}for(const e of t.values()){if(0==e.length)continue;let t;const a=h.get(e[0].assetId).assetMesh;t=await this.createInstancedMesh(e,a);const s=this.assets.get(e[0].assetId);t.castShadow=e[0].castShadow??s.castShadow??!0,t.receiveShadow=e[0].receiveShadow??s.receiveShadow??!0;const r=new Ee;r.add(t),r.userData.src=e[0],a instanceof Ee&&(r.collisionShapes=a.collisionShapes),this.prepareCollisionShapesForInstanced(r),r.castShadow=!1,r.receiveShadow=!1,this.scene.add(r)}console.timeEnd("materialize batches");for(const e of s.values()){if(0==e.length)continue;const t=e[0].object,a=await this.createFromShape(t),s=Pe(a,e=>!Oe(e)&&null!=e.geometry),i=s.material.clone();null!=e[0].color&&null!=i.color&&(i.color=new n(16777215));const l=s.geometry;let c,h;!(ut||i instanceof B||null==l.index)?(c=new r.BatchedMesh(e.length,l.getAttribute("position").count,l.index.count,i),c.perObjectFrustumCulled=!0,h=c.addGeometry(l)):c=new r.InstancedMesh(l,i,e.length),c.castShadow=a.castShadow??!0,c.receiveShadow=s.receiveShadow??!0;for(let t=0;t<e.length;t++){const a=e[t],s=(new r.Matrix4).compose((new S).fromArray(a.object.position),(new M).setFromEuler((new o).fromArray(a.object.rotation)),(new S).fromArray(a.object.scale)),i=(new d).copy(a.object.parentTransform).multiply(s);let n;n=c instanceof r.BatchedMesh?c.addInstance(h):t,c.setMatrixAt(n,i),null!=a.color&&c.setColorAt(n,a.color)}for(let t=0;t<e.length;t++){const s=e[t],r=new Ee;r.userData.src=e[0],a instanceof ze&&(r.collisionShapes=[a.collisionShape]),r.castShadow=!1,r.receiveShadow=!1,this.scene.add(r),r.add(c),null==c.userData.hasCollision&&(c.userData.hasCollision=[]),c.userData.hasCollision[t]=!!s.object.collisionDetection}}await Promise.all(e.map(e=>this.materialize(e))),await this.initActorsPostInit()}prepareCollisionShapesForInstanced(e){e instanceof Ee&&e.collisionShapes.forEach(e=>{e instanceof a&&e.mesh instanceof m&&(e.mesh=e.mesh.geometry)})}testCanBatch(e,t){return!ut&&t.groups.length<2&&(!Array.isArray(e)||1==e.length)&&this.testCanBatchMaterial(e)}testCanBatchMaterial(e){const t=Array.isArray(e)?e[0]:e;return null!=t&&(!(t instanceof g)||null==t.bumpMap&&null==t.lightMap&&null==t.displacementMap)}createBatchedMesh(e,t,a){const s=new be;for(const t of e)null!=t.meshUUID?s.push(t.meshUUID??t.assetId,t):console.warn("Missing mesh uuid for batching");let i=0,o=0,l=0;const c=new Map;for(const[e,t]of s.entries()){const s=t[0].assetId,r=a.get(s);if(null==r){console.warn("Missing batching info for asset id "+s);continue}const n=Pe(r.assetMesh,t=>t instanceof m&&t.uuid===e);if(null==n){console.warn("Missing mesh in batched asset");continue}c.set(e,n);const h=n.geometry.getAttribute("position");null==h&&console.warn("Missing position attribute for batched mesh"),i+=n.geometry.index.count*t.length,o+=h.count*t.length,l+=t.length}const h=["color","map","roughness","roughnessMap","metalness","metalnessMap","opacity","alphaMap","aoMap","aoMapIntensity","normalMap","normalScale","emissive","emissiveIntensity","emissiveMap"];let p=new Map,d=new r.MeshStandardMaterial({color:"white"});const u=t.get(e[0].id).get(e[0].meshUUID);if(null==u)throw"missing source material";if(u instanceof g){const a=new Set,s=new Map;for(const i of e){const e=t.get(i.id).get(i.meshUUID);if(null==e)throw"missing mat";for(const t of h){let i=e[t];i instanceof r.CompressedArrayTexture&&null!=i.userData.index&&(i=i.userData.index);const n=s.get(t);void 0===n||Wt(i,n)?s.set(t,i):a.add(t)}}for(const e of a){let t;const a=u[e];if("number"==typeof a)t=I(e);else if(a instanceof x)t=P(e);else if(a instanceof S||a instanceof n)t=D(e);else if(a instanceof A)t=j(e);else if(a instanceof r.CompressedArrayTexture)t=I(e+"_i");else if(a instanceof b)continue;p.set(e,t)}let i=H.uv;u instanceof ct&&null!=u.heightMap&&(i=ht(i,R(u.heightMap),O(u.heightScale)));let o=Nt(p.get("opacity"),k)??O(u.opacity??1);if(null!=u.alphaMap){let e;if(u.alphaMap instanceof r.CompressedArrayTexture){const t=G(u.alphaMap),a=Nt(p.get("alphaMap"),k)??O(u.alphaMap.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.alphaMap).sample(i);o=o.multiply(e.r)}let l=_(Nt(p.get("color"),Z)??u.color,o);if(null!=u.map){let e;if(u.map instanceof r.CompressedArrayTexture){const t=G(u.map),a=Nt(p.get("map"),k)??O(u.map.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.map).sample(i);l=l.multiply(e)}let c=_(Nt(p.get("emissive"),Z)??u.emissive,o);if(null!=u.emissiveMap){let e;if(u.emissiveMap instanceof r.CompressedArrayTexture){const t=G(u.emissiveMap),a=Nt(p.get("emissiveMap"),k)??O(u.emissiveMap.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.emissiveMap).sample(i);c=c.multiply(e)}const m=Nt(p.get("emissiveIntensity"),k)??O(u.emissiveIntensity??1),f=Nt(p.get("normalScale"),X)??q(u.normalScale??new A(1,1));let g=J.normal;if(null!=u.normalMap){let e;if(u.normalMap instanceof r.CompressedArrayTexture){const t=G(u.normalMap),a=Nt(p.get("normalMap"),k)??O(u.normalMap.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.normalMap).sample(i);g=V(e.rgb,f.x)}let y=Nt(p.get("roughness"),k)??O(u.roughness??1);if(null!=u.roughnessMap){let e;if(u.roughnessMap instanceof r.CompressedArrayTexture){const t=G(u.roughnessMap),a=Nt(p.get("roughnessMap"),k)??O(u.roughnessMap.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.roughnessMap).sample(i);y=y.multiply(e.g)}let w=Nt(p.get("metalness"),k)??O(u.metalness??0);if(null!=u.metalnessMap){let e;if(u.metalnessMap instanceof r.CompressedArrayTexture){const t=G(u.metalnessMap),a=Nt(p.get("metalnessMap"),k)??O(u.metalnessMap.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.metalnessMap).sample(i);w=w.multiply(e.b)}let M=O(1);if(null!=u.aoMap){let e;if(u.aoMap instanceof r.CompressedArrayTexture){const t=G(u.aoMap),a=Nt(p.get("aoMap"),k)??O(u.aoMap.userData.index??0);e=t.sample(Y(i.x,i.y,a))}else e=R(u.aoMap).sample(i);M=M.multiply(e.r)}const v=Nt(p.get("aoMapIntensity"),k)??O(u.aoMapIntensity??0);let C=g;!0!==u.userData.disableAO&&(C=z("DOUBLE_SIDED",C,e=>$(new E("gl_FrontFacing"),e,e.multiplyScalar(-1))));const T=new B({color:W({color:l,roughness:y,metalness:w,ambientOcclusion:M,ambientOcclusionIntensity:v,emissive:c,emissiveIntensity:m,normal:C}),normal:g,roughness:y,emissive:c.rgb,transparent:u.transparent,alphaTest:u.alphaTest,envMap:u.envMap});null!=u.envMap&&(T.uniforms.envMapIntensity={value:u.envMapIntensity},T.uniforms.envMapRotation={value:$t(u.envMapRotation,u.envMap)}),T.envMap=u.envMap,T.side=u.side,d=T}else{d=u;for(const a of e){const e=t.get(a.id).get(a.meshUUID);if(e!=d){console.error(`Different materials in group for object ${a.id} and mesh uuid ${a.meshUUID}`,{objectMaterial:e,sourceMaterial:u});break}}}const f=new lt(l,o,i,d);for(const[e,t]of p.entries()){let a=1;t instanceof Q||t instanceof Z?a=4:t instanceof X&&(a=2),f.initUniform(e,a,0)}for(const[e,i]of s.entries()){const s=i[0].assetId,o=c.get(e);if(null==o){console.error(`Missing single asset mesh for mesh uuid ${e} and asset id ${s}`);continue}if(null==o.geometry){console.error("Missing geometry on mesh mesh");continue}const l=f.addGeometry(o.geometry),h=a.get(s);if(null==h){console.warn("Missing batching info when configuring for asset id "+s);continue}const d=De(h.assetMesh)?.uuid===e,m=h.assetMesh instanceof Ee&&d?h.assetMesh.collisionShapes:void 0,u=this.configureBatchedInstancedMesh(i,f,o,l,m);for(let e=0;e<u.length;e++){const a=i[e],s=u[e],o=t.get(a.id).get(a.meshUUID);for(let e of p.keys()){let t=o[e];if(t instanceof n&&(t=new S(t.r,t.g,t.b)),t instanceof r.CompressedArrayTexture)t=t.userData.index??0,e+="_i";else if(t instanceof b||null==t)continue;f.setUniformAt(e,s,t)}}}return f}async createInstancedMesh(e,t){const a=Pe(t,e=>!Oe(e)&&null!=e.geometry),s=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(t,Dt(e[0].materialAssignments,s.materialAssignments)),a.updateMatrix();const i=a.geometry.clone(),n=a.material;let o;if(o=new r.InstancedMesh(i,n,e.length),this.configureBatchedInstancedMesh(e,o,a),a.material instanceof p&&o.castShadow&&o.receiveShadow&&Array.isArray(n))for(const e of n);return o}configureBatchedInstancedMesh(e,t,a,s,i){const n=[];for(let l=0;l<e.length;l++){let c=l;t instanceof r.BatchedMesh&&(c=t.addInstance(s)),n.push(c);const h=(new r.Matrix4).compose((new S).fromArray(e[l].position),(new M).setFromEuler((new o).fromArray(e[l].rotation)),(new S).fromArray(e[l].scale)),p=(new d).copy(e[l].parentTransform).multiply(h).multiply(a.matrixWorld);t.setMatrixAt(c,p),null==t.userData.hasCollision&&(t.userData.hasCollision=[]),t.userData.hasCollision[c]=!!e[l].collisionDetection,null!=i&&(null==t.userData.collisionShapes&&(t.userData.collisionShapes=[]),t.userData.collisionShapes[c]=i)}return n}remove(e){if(console.log("Remove scene object",e),"global_fog"==e.type)return void(this.scene.fog=this.originalFog);if("world_env"===e.type)this.resetWorldEnv(),this.worldEnvObj=null;else if("actor"==e.type||"vfx"===e.type){const t=this.materializedActors.get(e.id);null!=t?(t.disposed.next(!0),t.onEndPlay()):console.warn("Failed to remove actor",e)}else"prefab"===e.type&&this.materializedActors.forEach((t,a)=>{a.startsWith(e.id)&&(t.disposed.next(!0),t.onEndPlay()),this.materializedActors.delete(a)});const t=this.sceneObjectMap.get(e.id);t?.parent.remove(t),this.sceneObjectMap.delete(e.id),this.components.filter(t=>t.object.userData.src?.id===e.id).forEach(e=>this.components.splice(this.components.indexOf(e,1))),this.landscapeManagers.filter(t=>t.source.id===e.id).forEach(e=>{e.clear(),e.stop(),this.landscapeManagers.splice(this.landscapeManagers.indexOf(e,1))}),this.removed$.next({object:t,source:e})}deleteSceneObject(e){const t=this.sceneObjectMap.get(e.id);if(this.scene.remove(t),"landscape"==e.type){const t=this.landscapeManagers.findIndex(t=>t.source.id===e.id);if(t>-1){const e=this.landscapeManagers.splice(t,1)[0];e.clear(),e.stop()}}}findByAssetId(e){return je(this.scene,t=>t.userData.src?.assetId==e,e=>null!=e.userData.src)}applyMaterials(e,t){return null==t?Promise.resolve([]):Promise.all(t.filter(e=>"null"!==e.materialId).map(t=>this.applyMaterial(e,t)))}async applyMaterial(e,t){await applyMaterial(e,t,e=>{const t=this.assets.get(e);if(null!=t)try{return materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders)}catch(e){console.error("Failed to apply material",e)}},this._originalMaterials)}unapplyMaterials(e){e.traverse(async e=>{if(e instanceof m)if(e.material instanceof Array)for(let t=0;t<e.material.length;t++)e.material[t]=this._originalMaterials.get(e.id+"#"+t)??e.material[t];else e.material=this._originalMaterials.get(e.id)??e.material})}updateActors(e){console.log("update actors"),this.actorTypes=e;const t=new Set(Object.values(ne));je(this.scene,e=>e.userData.src?.id&&"actor"===e.userData.src.type&&this.materializedActors.has(e.userData.src?.id)&&!t.has(e.userData.src.actor.type)).forEach(async e=>{this.remove(e.userData.src),await this.materializeAndInitActor(e.userData.src)})}updateComponents(e){this.componentTypes=e,je(this.scene,e=>e.userData.src?.id&&"actor"===e.userData.src.type&&this.materializedActors.has(e.userData.src?.id)&&(e.userData.src.actor?.components?.length??0)>0).forEach(async e=>{this.remove(e.userData.src),await this.materializeAndInitActor(e.userData.src)})}updateShaders(e){this.shaders=e;for(const[e,t]of yt.entries())t.userData.customShaderName&&yt.delete(e);this.landscapeManagers.forEach(t=>t.updateShaders(e)),je(this.scene,e=>!0).forEach(e=>{e.traverse(async e=>{if(e instanceof m)if(Array.isArray(e.material))for(let t=0;t<e.material.length;t++){const a=e.material[t].userData?.customShaderName;if(null!=a){const a=this.assets.get(e.material[t].userData.assetId);this.refreshMaterial(e,e.material[t],a,t)}}else{const t=e.material.userData?.customShaderName;if(null!=t){const t=this.assets.get(e.material.userData.assetId);this.refreshMaterial(e,e.material,t)}}})})}async update(e){if("sky"===e.type&&null!=this.sky&&null!=this.sky.parent)return void this.updateSky(e);if("world_env"===e.type&&null!=this.worldEnvObj)return void this.updateWorldEnv(e);const t=this.sceneObjectMap.get(e.id);if(t){let s=!1;if(t.traverseAncestors(e=>{"_hology_transform_group"===e.name&&(s=!0)}),!s){const a=this.findParent(e);null!=a&&a.uuid!=t.uuid?a.attach(t):console.error("Parent is wrong")}if("prefab"!==e.type&&"group"!==e.type){this.unapplyMaterials(t);this.inEditor&&e.hidden&&!1?t.traverse(e=>{e instanceof m&&(e.material.wireframe=!0)}):t.traverse(e=>{e instanceof m&&(e.material.wireframe=!1)})}if("asset_mesh"===e.type){const a=this.assets.get(e.assetId);Dt(e.materialAssignments,a.materialAssignments).forEach(e=>this.applyMaterial(t,e))}else"shape_mesh"===e.type&&this.applyMaterials(t,e.materialAssignments);if(s||(null!=e.position&&t.position.fromArray(e.position),null!=e.scale&&t.scale.fromArray(e.scale),null!=e.rotation&&t.rotation.fromArray(e.rotation)),this.applyVertexMaterials(e,t),"light"==e.type)if("point"==e.light.type){const a=t;a.color=new n(e.light.point.color),a.intensity=e.light.point.intensity,a.decay=e.light.point.decay,a.castShadow=e.light.point.castShadow,a.distance=Math.max(e.light.point.distance,0),a.userData.volumetricIntensity=e.light.point.volumetricIntensity}else if("spot"==e.light.type){const a=t;a.color=new n(e.light.spot.color),a.intensity=e.light.spot.intensity,a.decay=e.light.spot.decay,a.angle=e.light.spot.angle,a.penumbra=e.light.spot.penumbra,a.castShadow=e.light.spot.castShadow,a.distance=Math.max(e.light.spot.distance,0),a.userData.volumetricIntensity=e.light.spot.volumetricIntensity}else"directional"===e.light.type?this.applyDirectionalLight(e.light.directional,e):"ambient"===e.light.type&&this.applyDirectionalAmbientLight(t,e.light.ambient,e);else if("landscape"===e.shape){const a=this.landscapeManagers.find(t=>t.source.id===e.id).source.landscape.options.density!==e.landscape.options.density;if(this.inEditor&&a){this.remove(e);const t=await this.materializeAndInitActor(e);return void this.updated$.next({object:t,source:e})}this.applyHeightMaps(t,e.landscape.heightMaps),this.inEditor&&this.landscapeManagers.filter(t=>t.source.id===e.id).forEach(t=>{t.updateSource(e),t.queueRefreshScatter(this.renderingView.camera.position,!0,e=>!0)})}else if("global_fog"===e.type){const t=(this.scene.fog instanceof c?"density":"linear")!==e.fog.type;this.scene.fog=xt(e.fog),t&&(a=this.scene).traverse(e=>{if(e instanceof m){const t=e.material;t instanceof B&&(a.fog instanceof l?(t.uniforms.fogFar.value=a.fog.far,t.uniforms.fogNear.value=a.fog.near):a.fog instanceof c&&(t.uniforms.density={value:a.fog.density}),t.needsUpdate=!0,t.uniformsNeedUpdate=!0)}}),this.fixFogColor()}else if("actor"===e.type){if(this.materializedActors.has(e.id)){const t=this.materializedActors.get(e.id);if(t instanceof it){const a=await prepareClassParameters(e.actor.params,null,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,[],this.actorProvider,e=>this.prefabInstanceExposedActorMap.get(e)??null);return void Object.assign(t,a)}const a=this.editorActorParamSnapshot.get(e.id);null!=a&&a===JSON.stringify(e.actor)||s||(this.remove(e),await this.materializeAndInitActor(e))}}else if("shape_mesh"===e.type){const a=await this.createMeshByShape(e.shape,t.material,e.shapeParams);t instanceof ze&&(t.geometry=a.geometry,t.collisionShape=a.collisionShape)}("asset_mesh"===e.type||"shape_mesh"===e.type&&"landscape"!==e.shape)&&gt(t,e.castShadow,e.receiveShadow),e.name&&e.name.length>0&&(t.name=e.name),this.updated$.next({object:t,source:e})}else{const t=await this.materializeAndInitActor(e);this.updated$.next({object:t,source:e})}var a;this.renderingView.renderer.shadowMap.needsUpdate=!0}async materializeAndInitActor(e,t=this.findParent(e)){const a=await this.materialize(e,t),s=Array.from(this.materializedActors.entries()).filter(([t])=>t===e.id||t.startsWith(e.id+"/"));return await this.initActorsPostInit(s),a}findParent(e){const t=this.dataProvider.getObjects().flatMap(t=>t.id===e.id?null:Ie(t,t=>t.children?.some(t=>t.id===e.id),()=>!0))[0];return null==t?this.scene:null!=t?je(this.scene,e=>e.userData?.src?.id===t.id,e=>null!=e.userData?.src)[0]:void 0}fixFogColor(){!0===this.renderingView.options.enableOutlines&&(this.scene.fog.color=new n(this.scene.fog.color))}findMeshWithGeometry(e){let t;return e.traverse(e=>{e instanceof m&&e.geometry&&(t=e)}),t}applyVertexMaterials(e,t){if(null==e.vertexMaterials||0===e.vertexMaterials.length)return;let a=1;for(const t of e.vertexMaterials)a=Math.max(t.w.length,a);const s=Se(e.vertexMaterials,e=>e.m);t.traverse(e=>{if(e instanceof m){if(null==e.geometry)return;if(Ot(We(e,0,!1)),a>0){Ot(We(e,0,!1))}}});const r=new Set;for(const[e,i]of s.entries()){const s=null!=e?t.getObjectByName(e):this.findMeshWithGeometry(t);let n=!1;if(null==s||null==s.geometry)return void console.warn(`Failed to apply vertex materials on mesh with name "${e}"`);const o=We(s,0,!0);Ot(o);for(const e of i)o.setX(e.i,e.w[0]??0),o.setY(e.i,e.w[1]??0),o.setZ(e.i,e.w[2]??0),o.setW(e.i,e.w[3]??0),n=!0;if(a>0){const e=We(s,4,!0);Ot(e);for(const t of i)e.setX(t.i,t.w[4]??0),e.setY(t.i,t.w[5]??0),e.setZ(t.i,t.w[6]??0),e.setW(t.i,t.w[7]??0),e.needsUpdate=!0,n=!0}n&&r.add(e)}this.inEditor&&this.landscapeManagers.filter(t=>t.source.id===e.id).forEach(e=>e.queueRefreshScatter(this.renderingView.camera.position,!0,e=>r.has(e.name)))}async materialize(e,t,a=!1,s){const r=this.getNestedActorId(e.id,s);if(this.idToSceneObject.set(r,e),!this.shouldBeMaterialized(e))return;let i,n;switch(e.type){case"asset_mesh":i=await this.createFromAsset(e);break;case"shape_mesh":i=await this.createFromShape(e);break;case"light":i=await this.createLight(e);break;case"particles":i=await this.createParticleSystem(e),e.collisionDetection=!1;break;case"global_fog":this.scene.fog=xt(e.fog),this.fixFogColor(),i=new h;break;case"sky":this.sky=qe(),this.updateSky(e),i=this.sky;break;case"world_env":this.updateWorldEnv(e),i=new h,this.worldEnvObj=i;break;case"actor":({object:i,actor:n}=await this.createFromActor(e,s));break;case"group":i=new h;break;case"prefab":i=await this.createFromPrefab(e,s,t);break;case"vfx":i=await this.createFromVfx(e,s);break;default:if(this.inEditor)throw new Error("unknown type "+e.type);console.warn(`Failed to materialize object. Unknown type '${e.type}'. This might be because the hology/core library is not compatible with the editor version.`)}if(null!=i){if(e.name&&e.name.length>0&&(i.name=e.name),this.applyTransform(e,i),a?i.userData._src=e:i.userData.src=e,null!=n&&(i.userData.actor=n),this.inEditor,this.inEditor,this.objectMap.set(i.uuid,e),this.sceneObjectMap.set(e.id,i),e.physics?.type!==oe.dynamic||null==t||this.inEditor?null==t?this.scene.add(i):null==t||"actor"!==e.type||this.inEditor?t?.add(i):(t.add(i),this.scene?.attach(i),console.log(i)):(t.add(i),i.getWorldPosition(i.position),i.getWorldQuaternion(i.quaternion),i.getWorldScale(i.scale),this.scene?.attach(i)),null!=e.children&&await Promise.all(e.children?.map(e=>this.materialize(e,i,a))),this.inEditor||null!=t||"asset_mesh"!=e.type&&"shape_mesh"!==e.type&&"prefab"!==e.type&&"group"!==e.type||"landscape"===e.shape||null!=e.physics?.type&&e.physics.type==oe.dynamic||St(i),null!=this.renderingView)return this.renderingView.renderer.shadowMap.needsUpdate=!0,i;console.warn("RenderingView not found in materializer")}}applyTransform(e,t){null!=e.position&&t.position.fromArray(e.position),null!=e.scale&&t.scale.fromArray(e.scale),null!=e.rotation&&t.rotation.fromArray(e.rotation)}updateWorldEnv(e){this.renderingView.aoPass.enabled=e.worldEnv.ao.enabled,this.renderingView.aoPass.blendIntensity=e.worldEnv.ao.blendIntensity,this.renderingView.aoPass.updateGtaoMaterial(e.worldEnv.ao);const t=e.worldEnv.toneMapping;null!=t&&(this.renderingView.renderer.toneMapping=t.mapping??0,this.renderingView.renderer.toneMappingExposure=t.exposure??1);const a=e.worldEnv.environment;null!=a&&null!=a.textureId?this.assetManagerService.getTexture(this.assets.get(a.textureId)).then(e=>{null==this.pmremGenerator&&(this.pmremGenerator=new r.PMREMGenerator(this.renderingView.renderer),this.pmremGenerator.compileEquirectangularShader()),this.pmremGeneratorResults.has(e)||this.pmremGeneratorResults.set(e,this.pmremGenerator.fromEquirectangular(e).texture);const t=this.pmremGeneratorResults.get(e);this.renderingView.scene.environment=t,this.renderingView.scene.environmentIntensity=a.intensity??1}):this.renderingView.scene.environment=null}resetWorldEnv(){this.renderingView.aoPass.enabled=!1,this.renderingView.aoPass.blendIntensity=1,this.renderingView.aoPass.output=0,this.renderingView.renderer.toneMapping=0,this.renderingView.renderer.toneMappingExposure=1}async updateSky(e){if(null==e?.sky?.materialId)return void(this.sky.material=Xe);const t=await this.assetsService.getAsset(e.sky.materialId),a=await materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!1);this.applySkySettings(a),null!=this.sky?this.sky.material=a:console.warn("No sky has been created")}applySkySettings(e){e.side=r.BackSide,(e instanceof g||e instanceof r.MeshBasicMaterial||e instanceof r.ShaderMaterial)&&(e.fog=!1),e.depthTest=!1}async createComponent(e,t,a,s){const r=new dt[a.path+"/"+a.className],i=t.id+s;r.id=i,r.object=e;for(const e of a.params)null!=e.value&&(r[e.name]=e.value);return this.components.push(r),i}async createFromActor(e,t){const a=this.actorTypes.find(t=>t.name===e.actor?.type)?.type??ne[e.actor?.type];if(null==a)return{object:null,actor:null};this.inEditor&&this.editorActorParamSnapshot.set(e.id,JSON.stringify(e.actor));const s=await this.actorProvider.create(a,(new S).fromArray(e.position),(new o).fromArray(e.rotation),!0);return this.materializedActors.set(this.getNestedActorId(e.id,t),s),{object:s?.object,actor:s}}getNestedActorId(e,t){return null!=t?t.sceneObjectChain.join("/")+"/"+e:e}async createFromVfx(e,t){const a=await this.assetsService.getAsset(e.assetId);null==a&&console.error("Could not find asset",e);const s=await this.actorProvider.create(te,(new S).fromArray(e.position),(new o).fromArray(e.rotation),!1);try{await s.fromAsset(a)}catch(e){return console.error("Failed to create VFX asset",e),null}return s.play(),this.materializedActors.set(this.getNestedActorId(e.id,t),s),null!=s&&(s.object.userData.actor=s),s?.object}async createFromShape(e){const t=this.inEditor&&e.hidden;let a;if("landscape"==e.shape)a=this.createLandscape(e),a.traverse(e=>{e instanceof m&&this._originalMaterials.set(e.id,e.material)});else{let s=new g({name:"Default",color:new n("#aaaaaa"),visible:this.inEditor||!e.hidden,wireframe:!!t});const r=await this.createMeshByShape(e.shape,s,e.shapeParams);r.castShadow=e.castShadow??!0,r.receiveShadow=e.castShadow??!1,e.collisionDetection||(r.collisionShape=null),r.physics=e.physics,a=r,this._originalMaterials.set(a.id,r.material),a.traverse(e=>{})}return t||(await Promise.all((e.materialAssignments??[]).filter(e=>null!=e.materialId).map(e=>this.applyMaterial(a,e))),this.applyVertexMaterials(e,a)),a}createLandscape(e){const t=e.landscape?.options;if(null==t)return console.error(`No landscape options exist on scene object ${e.id} ${e.name}`),new h;const a=Be(e.landscape.options);this.applyHeightMaps(a,e.landscape.heightMaps,!0);const s=new Fe(e,this.renderingView,a,this.assetManagerService,this.assetsService,this.shaders,t=>{(e.materialAssignments??[]).filter(e=>null!=e.materialId).forEach(e=>this.applyMaterial(t,e))});return this.landscapeManagers.push(s),s.refreshGeometry(),a}applyHeightMaps(e,t,a=!1){const s=new Ne(e.sections);for(const e of t??[]){const t=s.find(e.x,e.y);if(!t)return;const a=t.geometry.getAttribute("position");for(const t of e.points)a.setY(t.i,t.y);a.needsUpdate=!0}const r=e.sections;r.forEach(e=>{e.geometry.computeBoundsTree(),e.geometry.computeVertexNormals()}),this.inEditor&&!a||setTimeout(()=>_e(r),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&&He.includes(e)){const s=await prepareShapeParameters(a??{}),r=e+JSON.stringify(a);if(!this.geometryCache.has(r)){const t=Ge[e].geometry(s);t.computeTangents(),this.geometryCache.set(r,t)}this.collisionShapeCache.has(r)||this.collisionShapeCache.set(r,Ge[e].collision(s));return new ze(this.geometryCache.get(r),t,this.collisionShapeCache.get(r))}if(this.inEditor)throw new Error(`Unsupported shape '${e}'`);console.warn(`Failed to create shape. Unsupported shape '${e}'. This might be because the hology/core library is not compatible with the editor version.`)}async createFromAsset(e,t){const a=await this.assetsService.getAsset(e.assetId);if(null==a)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);let{scene:s}=await this.assetManagerService.getMesh(a,{mergeGeomtries:!0});if(!1!==t?.assignMaterials)try{await Promise.all(Dt(e.materialAssignments,a.materialAssignments).map(e=>this.applyMaterial(s,e)))}catch(t){console.error("Failed to apply material"+t,e)}const r=e.receiveShadow??!!a.receiveShadow,i=e.castShadow??!!a.castShadow;return s.receiveShadow=r,gt(s,i,r),e.collisionDetection||(s.collisionShapes=[]),null!=e.physics&&!0!==this.inEditor&&(s.physics=e.physics),this.applyVertexMaterials(e,s),s.traverse(e=>{e instanceof m&&"computeBoundsTree"in e.geometry&&null==e.geometry.boundsTree&&e.geometry.computeBoundsTree()}),s}async createFromPrefab(e,t,a){const s=await this.assetsService.getAsset(e.assetId);if(null==s)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);null==t&&(t={sceneObjectChain:[]}),t.sceneObjectChain.push(e.id);const{object:r}=await this.createFromPrefabAsset(s,t,a,e);return t.sceneObjectChain.pop(),r}async createFromPrefabAsset(e,t,a,s,r=!0){const i=new h;null!=s&&this.applyTransform(s,i),null!=a&&a.add(i),await Promise.all(e.prefab.objects.filter(e=>"global_fog"!==e.type&&"world_env"!==e.type).map(e=>this.materialize(e,i,!0,structuredClone(t))));const n=t.sceneObjectChain.join("/"),o=Array.from(this.materializedActors.entries()).filter(([e,a])=>e.startsWith(n)&&e.split("/").length-1===t.sceneObjectChain.length);let l;if(o.forEach(e=>{}),null!=e.prefab?.mainActorId){const a=t.sceneObjectChain.join("/")+"/"+e.prefab.mainActorId;l=this.materializedActors.get(a)}r||await this.initActorsPostInit(o);const c=Array.from(this.materializedActors.entries()).filter(([e,t])=>e.startsWith(n)).map(([,e])=>e);if(null!=e.prefab?.mainActorId&&null!=s){const a=t.sceneObjectChain.join("/"),s=a+"/"+e.prefab.mainActorId;this.prefabInstanceExposedActorMap.set(a,s)}return{object:i,actors:c,mainActor:l}}async createParticleSystem(e){await this.assetsService.getAsset(e.assetId);return new y}async createLight(e){if("point"===e.light.type){const t=new w(e.light.point.color,e.light.point.intensity,e.light.point.distance,e.light.point.decay);if(t.castShadow=e.light.point.castShadow??!0,this.inEditor){const e=(new r.TextureLoader).load("assets/light-bulb-icon.webp"),a=new r.SpriteMaterial({map:e,alphaTest:.5}),s=new nt(a);s.scale.multiplyScalar(.6),t.add(s)}return t}if("spot"===e.light.type){const t=new r.SpotLight(e.light.spot.color,e.light.spot.intensity,e.light.spot.distance,e.light.spot.angle,e.light.spot.penumbra,e.light.spot.decay);if(t.castShadow=e.light.spot.castShadow??!0,t.target=new y,t.target.position.set(0,-1,0),t.add(t.target),this.inEditor){const e=(new r.TextureLoader).load("assets/light-bulb-icon.webp"),a=new r.SpriteMaterial({map:e,alphaTest:.5}),s=new nt(a);s.scale.multiplyScalar(.6),t.add(s),t.add(new r.SpotLightHelper(t))}return t}return"directional"===e.light.type?(this.applyDirectionalLight(e.light.directional,e),new h):"ambient"===e.light.type?(this.applyDirectionalAmbientLight(null,e.light.ambient,e),new h):void 0}applyDirectionalAmbientLight(e,t,a){const s=this.scene.children.find(e=>e.name===Je);null!=s?(s.intensity=t.intensity,s.color.set(t.color),s.groundColor.set(t.color),s.userData.src=a,s.userData.volumetricIntensity=t.volumetricIntensity):console.warn("Couldn't find ambient light")}applyDirectionalLight(e,t){for(const a of this.renderingView.csm.lights)a.intensity=e.intensity,a.color.set(e.color),a.castShadow=e.castShadow,a.userData.src=t,a.userData.volumetricIntensity=e.volumetricIntensity;this.renderingView.csm.lightDirection.fromArray(e.direction).normalize()}dispose(){this.updateSubscription.unsubscribe(),this.createAssetSubscription.unsubscribe(),this.materializedActors.forEach(e=>e.disposed.next(!0)),this.materializedActors.clear()}};ft=e([ee(),t("design:paramtypes",[v,Object,Ve,Te,he,Array,Array,Object,Array])],ft);export{ft as SceneMaterializer};function gt(e,t,a){e.castShadow=t,e.receiveShadow=a,e.traverse(e=>{e.castShadow=t,e.receiveShadow=a})}const yt=new Map,wt=new Map,Mt=new u({color:16711935}),vt=new Map;export async function materialFromAsset(e,t,a,s,r,i=!0){const n=JSON.stringify(e.material)+t?._id;return i&&yt.has(n)?yt.get(n):i&&wt.has(n)?await wt.get(n):wt.set(n,_materialFromAsset(n,e,t,a,s,r,i)).get(n)}export async function _materialFromAsset(e,t,a,s,i,o,l=!0){const c={opacity:t.material.params?.opacity??1,map:null,emissive:t.material.params?.emissive??null,metalness:t.material.params?.metalness??0,flatShading:t.material.params?.flatShading??!1,color:new n(t.material.params?.color),transparent:null!=t.material.params?.opacity&&t.material.params?.opacity<1},h={};if(null!=t.material.params?.map){const e=t.material.params.map,a=await s.getAsset(e);null!=a&&(c.map=await i.getTexture(a))}let p;switch(t.material.type){case"phong":p=new f({...c,...h});break;case"water":p=Le(c,a);break;case"grassFoliage":p=Ue({color:c.color,map:c.map},a);break;case"grass":p=$e({...c,colorTwo:new n(t.material.params.colorTwo),colorThree:new n(t.material.params.colorThree)},a);break;case"standard":case"unlit":case"toon":case"layered":case"lambert":case"shader":case"landscape":case"landscape-composite":case"decal-unlit":case"decal-standard":const e={standard:mt?fe:we,lambert:fe,unlit:Me,toon:ot,layered:st,landscape:ye,"landscape-composite":ge,"decal-unlit":Ze,"decal-standard":Ke}[t.material.type]??o.find(e=>e.name==t.material.shader)?.type;if(e){try{let r=new e;const n=await prepareClassParameters(t.material?.shaderParams??{},e,s,i,null,a,o);Object.assign(r,n),p=r.build()}catch(e){console.log("Shader runtime error: "+e),vt.has(t.material.shader)||vt.set(t.material.shader,Mt.clone()),p=vt.get(t.material.shader)}p.userData.customShaderName=t.material.shader}else console.warn("Missing shader implementation with name "+t.material.shader),p=Mt;break;default:throw new Error("Unsupported material type"+t.material.type)}return a?.csm.setupMaterial(p),null!=a&&yt.set(e,p),p.side=t.material.side??p.side??r.FrontSide,p.transparent=(t.material.transparent??c.transparent??!1)||p.transparent,p.alphaTest=t.material.alphaTest??p.alphaTest??0,null!=t.material.blending&&(p.blending=le[t.material.blending]??r.NormalBlending),t.material.bloom&&(p.userData.hasBloom=!0),t.material.reflective&&(p.userData.reflective=!0),!0===t.material.outlines&&(p.userData.outlineParameters={},null!=t.material.outlineParams&&(null!=t.material.outlineParams.color&&(p.userData.outlineParameters.color=new n(t.material.outlineParams.color).toArray()),null!=t.material.outlineParams.thickness&&(p.userData.outlineParameters.thickness=t.material.outlineParams.thickness))),p.userData.assetId=t.id,wt.delete(e),p}export async function prepareClassParameters(e,t,a,s,r,i,n,o,l){const c={};for(const[t,h]of Object.entries(e)){if(!1===h.override)continue;const e=await At(t,h,a,s,r,i,n,o,void 0,void 0,l);null!=e&&(c[t]=e)}return c}export async function prepareShapeParameters(e,t,a){const s={};for(const[r,i]of Object.entries(e)){const e=await At(r,i,t,a,null,void 0,void 0,void 0,void 0,void 0);null!=e&&(s[r]=e)}return s}const bt=new Map;async function At(e,t,a,s,r,i,l,c,h=t.value,p=t.type,d){if(null==t||null==h||""===h)return null;switch(p){case Re.Array:if(Array.isArray(h)&&"element"in t)return await Promise.all(h.map(n=>At(e,t,a,s,r,i,l,c,n,t.element,d)));break;case Re.Number:case Re.FloatNode:let p;if("string"==typeof h?p=parseFloat(h):"number"==typeof h&&(p=h),t.type===Re.FloatNode){if("object"==typeof h&&"a"in h&&"b"in h){const e=h;if(null==e.a)return null;const t="string"==typeof e.a?parseFloat(e.a):e.a;if(null==e.b)return t;const a="string"==typeof e.b?parseFloat(e.b):e.b,s=function(e){let t=bt.get(e);return null==t&&(t=pe(Ye.decode(e)),bt.set(e,t)),t}(e.easing),r=s.sample(de(me.energy));return F(O(t),O(a),r)}return O(p)}return p;case Re.Texture:let m=await s.getTexture(await a.getAsset(h));return"envmap"===e.toLowerCase()&&null!=i&&(m=i.getEnvTexture(m)),m;case Re.Sampler2DNode:return R(await s.getTexture(await a.getAsset(h)));case Re.Boolean:return h;case Re.BooleanNode:return C(h);case Re.Vector2:case Re.Vec2Node:if("object"==typeof h){const e=h instanceof Array?(new A).fromArray(h):new A(h.x,h.y);return t.type===Re.Vec2Node?q(e):e}return null;case Re.Vector3:case Re.Vec3Node:if("object"==typeof h){const e=h instanceof Array?(new S).fromArray(h):new S(h.x,h.y,h.z);return t.type===Re.Vec3Node?Y(e):e}return null;case Re.Color:case Re.RgbNode:const u=new n(h);return t.type===Re.RgbNode?N(u):u;case Re.String:return h;case Re.BaseActor:const f=h;if(null==r&&console.warn("Class parameters can not be prepared as actors are not passed in"),null==f)return null;if("object"==typeof f&&null!=f.type&&null!=f.id){if("actor"===f.type)return r?.get(f.id)??null;if("prefab"===f.type){const e=d?d(f.id):null;if(null!=e)return r?.get(e)??null;const t=[];for(const[e,a]of r?.entries()??[])e.startsWith(f.id+"/")&&t.push(a);return 1===t.length?t[0]:null}}if("string"==typeof f){const e=r?.get(f);if(null!=e)return e;const t=d?d(f):null;if(null!=t)return r?.get(t)??null;const a=[];for(const[e,t]of r?.entries()??[])e.startsWith(f+"/")&&a.push(t);return 1===a.length?a[0]:null}return null;case Re.Euler:const g=h;return(new o).fromArray(g);case Re.Object3D:return(await s.getMesh(await a.getAsset(h))).scene;case Re.Material:return await materialFromAsset(await a.getAsset(h),i,a,s,l);case Re.AudioBuffer:return await s.getAudio(await a.getAsset(h));case Re.VisualEffect:const y=await a.getAsset(h);if(null==c){console.error("Can not create instance of visual effect because missing actor provider");break}if("vfx"in y)return new ae(c,y);console.error("Using a non-vfx asset for visual effect parameter");break;case Re.Prefab:{const e=await a.getAsset(h);return null==e?(console.error("Using a non-prefab asset for prefab parameter",h),null):new se(e)}case Re.PrefabActor:{const e=await a.getAsset(h);return null==e?(console.error("Using a non-prefab asset for prefab parameter",h),null):new re(new se(e))}case Re.Curve:return Ye.decode(h);case Re.ColorLayer:case Re.MaskLayer:if(rt(h)){const e=await Qe.decode(h,async e=>await s.getTexture(await a.getAsset(e))),t=await prepareClassParameters(h.params,null,a,s);return Object.assign(e,t),e}return console.warn("Expecting color layer but got",h),null;case Re.AnimationClip:{const e="string"==typeof h?h:"object"==typeof h&&null!=h?h.assetId:null;if(null==e)return console.warn("Invalid animation clip asset id value",h),null;return await s.getAnimationClip(await a.getAsset(e))}}return null}function St(e){e.updateWorldMatrix(!0,!0),e.updateMatrix(),e.traverse(e=>{e.matrixAutoUpdate=!1,e.matrixWorldNeedsUpdate=!1});const t=e.updateMatrixWorld;e.updateMatrixWorld=function(){t.apply(e),e.updateMatrixWorld=function(){}}}function xt(e){return"linear"===e.type?new l(new n(e.color),e.near??100,e.far??1e3):"density"===e.type?new c(e.color,e.density):void console.warn("Invalid fog type",e)}new g({color:4229780});async function It(e,t,a,s){null==s&&(s=(new d).identity());const i=s.clone().multiply(jt(e,new r.Matrix4));if(null!=e.children&&e.children.length>0)for(let a=e.children.length-1;a>=0;a--)await It(e.children[a],t,e,i);await t(e,a,s)}function jt(e,t){return null==e.position||null==e.rotation||null==e.scale?t.identity():t.compose((new S).fromArray(e.position),(new M).setFromEuler((new o).fromArray(e.rotation)),(new S).fromArray(e.scale))}export function toSerializedParamType(e){const t=e.constructor.prototype;return t instanceof Number||e===Number?Re.Number:t instanceof k||"function"==typeof e.prototype.isFloat?Re.FloatNode:t instanceof b||e===b||e.isTexture?Re.Texture:t instanceof ue||e===L?Re.Sampler2DNode:t instanceof Boolean||e===Boolean?Re.Boolean:t instanceof T?Re.BooleanNode:t instanceof n||e==n?Re.Color:t instanceof U||"function"==typeof e.prototype.isRgb?Re.RgbNode:t instanceof A||e==A?Re.Vector2:t instanceof X||"function"==typeof e.prototype.isVec2?Re.Vec2Node:t instanceof S||e==S?Re.Vector3:t instanceof Z||"function"==typeof e.prototype.isVec3?Re.Vec3Node:t instanceof String||e===String?Re.String:t instanceof ie||e==ie||e.prototype instanceof ie||e.prototype==ie?Re.BaseActor:t instanceof o||e==o?Re.Euler:t instanceof y||e==y?Re.Object3D:t instanceof p||e==p?Re.Material:t instanceof AudioBuffer||e==AudioBuffer?Re.AudioBuffer:t instanceof ae||e==ae?Re.VisualEffect:t instanceof se||e==se?Re.Prefab:t instanceof re||e==re?Re.PrefabActor:t instanceof Ye||e==Ye?Re.Curve:t instanceof Qe||e==Qe?Re.ColorLayer:t instanceof at||e==at?Re.MaskLayer:t instanceof r.AnimationClip||e==r.AnimationClip?Re.AnimationClip:void console.warn("Failed to map parameter type to serialized version",{type:e})}export function prepareCustomParams(e,t,a={}){return Object.fromEntries(e.map(e=>{const s=e.options.array?Re.Array:toSerializedParamType(e.type),r=e.options.array?toSerializedParamType(e.type):void 0,i=t[e.name];let n=i?.override;void 0===n&&null!=i&&(n=!0);const o=a[e.name]??customParameterDefaultValueByType.get(toSerializedParamType(e.type)),l=!1!==n||e.options.array?i?.value??(e.options.array?[]:o):o;return[e.name,{type:s,...r?{element:r}:{},value:l,override:n}]}))}export function prepareCustomParamsFromType(e,t,a=null){const s=ve(e);if(0===s.length)return{};let r;null!=a?ce(a,()=>{r=a.get(e)}):r=new e;const i={};for(const e of s){const t=r[e.name];if(null!=t&&!0!==e.options.array){const a=serializeCustomParameter(e.type,t);null!=a&&(i[e.name]=a)}}return prepareCustomParams(s,t,i)}export function serializeCustomParameter(e,t){function a(){console.error("Failed to serialize value",{type:e,value:t})}switch(e){case Number:case Boolean:return t;case A:return t instanceof A?t.toArray():void a();case S:return t instanceof S?t.toArray():void a();case x:return t instanceof x?t.toArray():void a();case n:return t instanceof n?"#"+t.getHexString():"string"==typeof t?t:"number"==typeof t?"#"+new n(t).getHexString():void a();case String:return t;case o:return t instanceof o?t.toArray():void a();case se:return t instanceof se?t.asset?.id??null:void a()}}function Dt(e,t){return function(e,t,a){const s=[],r=new Set;for(const i of[...e??[],...t??[]]){const e=a(i);r.has(e)||(r.add(e),s.push(i))}return s}((e??[]).filter(e=>Pt(e.materialId)),(t??[]).filter(e=>Pt(e.materialId)),e=>e.color+e.name)}function Pt(e){return"null"!=e&&null!=e}export const customParameterDefaultValueByType=new Map([[Re.RgbNode,"#000000"],[Re.Color,"#000000"],[Re.Vector4,[0,0,0,0]],[Re.Vec4Node,[0,0,0,0]],[Re.Vector3,[0,0,0]],[Re.Vec3Node,[0,0,0]],[Re.Vector2,[0,0]],[Re.Vec2Node,[0,0]],[Re.Euler,[0,0,0,"XYZ"]],[Re.Array,[]],[Re.ColorLayer,et],[Re.MaskLayer,tt]]);let Ct=new n,Et=new n;function Tt(e,t){return Ct.set(e),Et.set(t),Ct.getHexString()==Et.getHexString()}export function applyMaterial(e,t,a,s){const i=[];return e.traverse(async e=>{if(e instanceof m||e.isMesh||e instanceof r.SkinnedMesh||e.isSkinnedMesh)for(const t of xe(e.material))t.hasOwnProperty("color")&&i.push(e)}),Promise.all(i.map(async e=>{if(e.material instanceof Array)for(let r=0;r<e.material.length;r++){const i=e.material[r];if(null==i.color||!(i.color instanceof n))continue;const o="#"+i.color.getHexString(),l=i.name;if(o===t.color&&(i.name===t.name||null==t.name)||e.userData["originalColor_"+r]===t.color&&e.userData["originalMaterialName_"+r]===t.name){const i=await a(t.materialId),n=e.material[r];null!=i&&n.id!=i.id&&(e.material[r]=i,e.userData["originalColor_"+r]=e.userData["originalColor_"+r]??o,e.userData["originalMaterialName_"+r]=e.userData["originalMaterialName_"+r]??l,null!=s&&s.set(e.id+"#"+r,n))}}else if("color"in e.material){const r="#"+e.material.color.getHexString(),i=e.material.name;if(r===t.color&&(e.material.name===t.name||null==t.name)||e.userData.originalColor===t.color&&e.userData.originalName===t.name){const n=await a(t.materialId),o=e.material;null!=n&&(e.material=n,e.userData.originalColor=e.userData.originalColor??r,e.userData.originalMaterialName=e.userData.originalMaterialName??i,null!=s&&(s.has(e.id)||s.set(e.id,o)))}}}))}function Vt(e,t){if(e instanceof r.ShaderMaterial&&t instanceof r.ShaderMaterial){return e.fragmentShader+e.vertexShader==t.fragmentShader+t.vertexShader&&function(e,t){if(e instanceof r.ShaderMaterial&&t instanceof r.ShaderMaterial){for(const a in e.uniforms){if(null==t.uniforms[a])return!1;if(t.uniforms[a].value!==e.uniforms[a].value)return!1}return!0}return!1}(e,t)}return!1}function Ot(e){if(null!=e){for(let t=0;t<e.array.length;t++)e.setX(t,0);e.needsUpdate=!0}}const kt=new WeakMap;function zt(e){let t=kt.get(e);return null==t&&(t=function(e){const t=De(e);if(null==t)return"";return Object.keys(t.geometry.attributes).sort().join(",")}(e),kt.set(e,t)),t}const Ft=new WeakMap;function Bt(e){let t=Ft.get(e);return null==t&&(t=function(e){let t=e.type;e instanceof r.MeshStandardMaterial||(t+=e.id+"");(e instanceof r.MeshBasicMaterial||e instanceof r.MeshLambertMaterial||e instanceof g||e instanceof f)&&(null!=e.map&&(t+="c"+e.map?.id),null!=e.aoMap&&(t+="o"+e.aoMap?.id),null!=e.lightMap&&(t+="l"+e.lightMap?.id),null!=e.envMap&&(t+="v"+e.envMap?.id),null!=e.alphaMap&&(t+="a"+e.alphaMap?.id));e instanceof g&&(null!=e.normalMap&&(t+="n"+e.normalMap?.id),null!=e.roughnessMap&&(t+="r"+e.roughnessMap?.id),null!=e.metalnessMap&&(t+="m"+e.metalnessMap?.id),null!=e.emissiveMap&&(t+="e"+e.emissiveMap?.id));(e instanceof u||e instanceof f)&&null!=e.specularMap&&(t+="s"+e.specularMap?.id);e instanceof r.MeshToonMaterial&&(null!=e.map&&(t+="c"+e.map?.id),null!=e.aoMap&&(t+="o"+e.aoMap?.id),null!=e.lightMap&&(t+="l"+e.lightMap?.id),null!=e.alphaMap&&(t+="a"+e.alphaMap?.id));e instanceof ct&&null!=e.heightMap&&(t+="h"+e.heightMap?.id);if(e instanceof r.ShaderMaterial){t+=e.vertexShader,t+=e.fragmentShader;for(const a in e.uniforms){const s=e.uniforms[a];s&&s.value&&s.value.isTexture&&null!=s.value.id&&(t+="t:"+a+":"+s.value.id)}}null!=e.userData.outlineParameters&&(t+=e.userData.outlineParameters.color,t+=e.userData.outlineParameters.thickness);return t+=e.side,t+=e.transparent?"t":"",t+=e.depthWrite?"dw":"",t+=e.depthTest?"dt":"",t+=e.alphaTest,t}(e),Ft.set(e,t)),t}function Nt(e,t){if(null==e)return null;if(!(e instanceof t))throw new Error(`Value is not an instance of ${t.name}`);return e}const _t=new d,Ut=new o;function $t(e,t){return Ut.copy(e),Ut.x*=-1,Ut.y*=-1,Ut.z*=-1,t.isCubeTexture&&!1===t.isRenderTargetTexture&&(Ut.y*=-1,Ut.z*=-1),(new r.Matrix3).setFromMatrix4(_t.makeRotationFromEuler(Ut))}new x;function Wt(e,t){return e===t||null==e==(null==t)&&("number"==typeof e&&"number"==typeof t?e===t||isNaN(e)&&isNaN(t):e instanceof r.Color&&t instanceof r.Color?e.r===t.r&&e.g===t.g&&e.b===t.b:e instanceof A&&t instanceof A?e.x===t.x&&e.y===t.y:e instanceof S&&t instanceof S?e.x===t.x&&e.y===t.y&&e.z===t.z:e instanceof x&&t instanceof x&&(e.x===t.x&&e.y===t.y&&e.z===t.z&&e.w===t.w))}/*
2
2
  * Copyright (©) 2025 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -2,7 +2,7 @@ import { Side } from 'three';
2
2
  import { BlendingMode, VfxAssetData } from '../effects/vfx/vfx-asset.js';
3
3
  import { AttachedComponent, SceneObject } from './materializer.js';
4
4
  import { LibraryShapeType } from './objects/shapes.js';
5
- export type AssetType = 'mesh' | 'material' | 'shape' | 'particles' | 'light' | 'texture' | 'actor' | 'audio' | 'prefab' | 'vfx';
5
+ export type AssetType = 'mesh' | 'material' | 'shape' | 'particles' | 'light' | 'texture' | 'actor' | 'audio' | 'prefab' | 'vfx' | 'animationclip';
6
6
  export type ShapeType = LibraryShapeType | 'landscape';
7
7
  export type LightType = 'point' | 'spot' | 'directional' | 'ambient';
8
8
  /**
@@ -41,15 +41,31 @@ export declare enum SerializedParamType {
41
41
  Curve = 22,
42
42
  ColorLayer = 23,
43
43
  MaskLayer = 24,
44
- Prefab = 25
44
+ Prefab = 25,
45
+ PrefabActor = 26,
46
+ AnimationClip = 27
45
47
  }
46
48
  export type CustomParamValue = {
47
49
  type: SerializedParamType;
48
50
  value: unknown;
51
+ /**
52
+ * When true, this value explicitly overrides any default.
53
+ * When false or undefined, the parameter uses its default value.
54
+ * Only meaningful in contexts where overrides are supported
55
+ * (prefab instances, actor params with optional).
56
+ */
57
+ override?: boolean;
49
58
  } | {
50
59
  type: SerializedParamType.Array;
51
60
  element: SerializedParamType;
52
61
  value: unknown[];
62
+ /**
63
+ * When true, this value explicitly overrides any default.
64
+ * When false or undefined, the parameter uses its default value.
65
+ * Only meaningful in contexts where overrides are supported
66
+ * (prefab instances, actor params with optional).
67
+ */
68
+ override?: boolean;
53
69
  };
54
70
  /**
55
71
  * This serialized float param value take take multiple forms
@@ -161,7 +177,28 @@ export type Asset = {
161
177
  };
162
178
  /** Prefab settings only for asset type prefab */
163
179
  prefab?: {
180
+ /**
181
+ * Objects that make up the prefab. These are the canonical structural data
182
+ * for the prefab asset. Structure (components, child actors) lives in the
183
+ * prefab and cannot be changed per-instance.
184
+ */
164
185
  objects: SceneObject[];
186
+ /**
187
+ * Optional: the local id (within `objects`) of the single actor that the
188
+ * prefab exposes as its identity. When set, the prefab exposes exactly one
189
+ * actor. Prefab instances behave like instances of that actor type for the
190
+ * purposes of typed references and parameter overrides.
191
+ *
192
+ * Important semantics:
193
+ * - This id is local to the prefab asset's object graph and must not be
194
+ * treated as a global actor id.
195
+ * - A prefab may expose zero or one actor. Multiple exposed actors are not
196
+ * supported.
197
+ * - External references should point to the prefab instance id (not this
198
+ * internal actor id). At runtime, resolving a reference to a prefab
199
+ * instance returns the exposed actor instance inside the prefab.
200
+ */
201
+ mainActorId?: string;
165
202
  };
166
203
  components?: AttachedComponent[];
167
204
  /** Texture settings only for asset type texture */
@@ -172,6 +209,11 @@ export type Asset = {
172
209
  castShadow?: boolean;
173
210
  /** VFX settings only for asset type vfx */
174
211
  vfx?: VfxAssetData;
212
+ /** Settings for animation clips */
213
+ anim?: {
214
+ /** The name of the animation clip */
215
+ clip: string;
216
+ };
175
217
  };
176
218
  export type VfxAsset = Asset & {
177
219
  vfx: VfxAssetData;
@@ -213,4 +255,58 @@ export interface SceneBlobV0 {
213
255
  data: string;
214
256
  sceneId: string;
215
257
  }
258
+ /**
259
+ * A lightweight reference that may point to either a concrete actor id or a
260
+ * prefab instance id. Gameplay code should resolve this transparently:
261
+ * - If it points to an actor id, return that actor.
262
+ * - If it points to a prefab instance id, return the exposed actor instance
263
+ * inside the prefab (if any).
264
+ *
265
+ * Important: Prefab assets internally identify actors using local ids. External
266
+ * references must never store those internal ids directly; they should store
267
+ * the global actor id or the prefab instance id instead.
268
+ */
269
+ export type ActorReference = {
270
+ type: 'actor';
271
+ id: string;
272
+ } | {
273
+ type: 'prefab';
274
+ id: string;
275
+ };
276
+ /**
277
+ * Representation of a prefab instance within a scene. Prefab instances are
278
+ * stable identities that reference a prefab asset and may provide data-only
279
+ * overrides for the prefab's exposed actor.
280
+ *
281
+ * - `params` maps actor parameter paths to serialized values. Only
282
+ * parameter values are allowed to vary per-instance; structural changes are
283
+ * not permitted here.
284
+ */
285
+ export type PrefabInstanceSettings = {
286
+ /**
287
+ * Map from actor parameter path -> serialized value. Keys are editor-specific
288
+ * parameter path strings (for example, a path to the exposed actor's param).
289
+ * Values are serialized using the existing CustomParamValue format where
290
+ * appropriate, or primitives for simple types.
291
+ */
292
+ params?: Record<string, CustomParamValue>;
293
+ /**
294
+ * Per-inner-component overrides for the exposed actor. Stored in the same
295
+ * shape as `ActorSettings.innerParams` so it mirrors actor-local inner
296
+ * parameter groups.
297
+ *
298
+ * Example:
299
+ * [ { path: ['gun','mesh'], params: { color: { type: SerializedParamType.Color, value: '#fff' } } } ]
300
+ */
301
+ innerParams?: {
302
+ path: string[];
303
+ params: Record<string, CustomParamValue>;
304
+ }[];
305
+ /**
306
+ * Optional denormalized copy of the prefab asset's mainActorId to make
307
+ * lookups inexpensive. This is informational and can be derived from the
308
+ * prefab asset; it is not authoritative for prefab structure.
309
+ */
310
+ mainActorId?: string;
311
+ };
216
312
  //# sourceMappingURL=model.d.ts.map
@@ -1,4 +1,4 @@
1
- export var DetailTier;!function(e){e[e.low=0]="low",e[e.medium=1]="medium",e[e.high=2]="high"}(DetailTier||(DetailTier={}));export var SerializedParamType;!function(e){e[e.FloatNode=0]="FloatNode",e[e.Number=1]="Number",e[e.Texture=2]="Texture",e[e.Sampler2DNode=3]="Sampler2DNode",e[e.Boolean=4]="Boolean",e[e.BooleanNode=5]="BooleanNode",e[e.Vector2=6]="Vector2",e[e.Vec2Node=7]="Vec2Node",e[e.Vector3=8]="Vector3",e[e.Vec3Node=9]="Vec3Node",e[e.Color=10]="Color",e[e.RgbNode=11]="RgbNode",e[e.String=12]="String",e[e.BaseActor=13]="BaseActor",e[e.Euler=14]="Euler",e[e.Object3D=15]="Object3D",e[e.Material=16]="Material",e[e.AudioBuffer=17]="AudioBuffer",e[e.Vector4=18]="Vector4",e[e.Vec4Node=19]="Vec4Node",e[e.VisualEffect=20]="VisualEffect",e[e.Array=21]="Array",e[e.Curve=22]="Curve",e[e.ColorLayer=23]="ColorLayer",e[e.MaskLayer=24]="MaskLayer",e[e.Prefab=25]="Prefab"}(SerializedParamType||(SerializedParamType={}));/*
1
+ export var DetailTier;!function(e){e[e.low=0]="low",e[e.medium=1]="medium",e[e.high=2]="high"}(DetailTier||(DetailTier={}));export var SerializedParamType;!function(e){e[e.FloatNode=0]="FloatNode",e[e.Number=1]="Number",e[e.Texture=2]="Texture",e[e.Sampler2DNode=3]="Sampler2DNode",e[e.Boolean=4]="Boolean",e[e.BooleanNode=5]="BooleanNode",e[e.Vector2=6]="Vector2",e[e.Vec2Node=7]="Vec2Node",e[e.Vector3=8]="Vector3",e[e.Vec3Node=9]="Vec3Node",e[e.Color=10]="Color",e[e.RgbNode=11]="RgbNode",e[e.String=12]="String",e[e.BaseActor=13]="BaseActor",e[e.Euler=14]="Euler",e[e.Object3D=15]="Object3D",e[e.Material=16]="Material",e[e.AudioBuffer=17]="AudioBuffer",e[e.Vector4=18]="Vector4",e[e.Vec4Node=19]="Vec4Node",e[e.VisualEffect=20]="VisualEffect",e[e.Array=21]="Array",e[e.Curve=22]="Curve",e[e.ColorLayer=23]="ColorLayer",e[e.MaskLayer=24]="MaskLayer",e[e.Prefab=25]="Prefab",e[e.PrefabActor=26]="PrefabActor",e[e.AnimationClip=27]="AnimationClip"}(SerializedParamType||(SerializedParamType={}));/*
2
2
  * Copyright (©) 2025 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */