@hology/core 0.0.165 → 0.0.166
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/gameplay/actors/actor.js +1 -1
- package/dist/gameplay/actors/internal/component-init.js +1 -1
- package/dist/rendering/fog/volumetric-fog-pass.js +1 -1
- package/dist/rendering.js +1 -1
- package/dist/scene/materializer.d.ts +18 -3
- package/dist/scene/materializer.js +1 -1
- package/dist/scene/storage/storage.js +1 -1
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -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 j,batchingUniformVec2 as I,batchingUniformVec3 as D,batchingUniformVec4 as P,bool as C,BooleanExpression as E,BooleanNode as T,colorToNormal as V,float as k,FloatNode as O,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 je,findFirstVisibleMesh as Ie,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 ke}from"./collision/collision-shape.js";import{LandscapeManager as Oe}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){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.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=>{xt(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?Tt(e.material[s],i)||(e.material[s]=i):Tt(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);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)}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 xt(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!=Ie(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&&Et(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=Ft(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 ke&&(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||$t(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=j(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=I(e);else if(a instanceof r.CompressedArrayTexture)t=j(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),k(u.heightScale)));let o=Bt(p.get("opacity"),O)??k(u.opacity??1);if(null!=u.alphaMap){let e;if(u.alphaMap instanceof r.CompressedArrayTexture){const t=G(u.alphaMap),a=Bt(p.get("alphaMap"),O)??k(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=_(Bt(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=Bt(p.get("map"),O)??k(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=_(Bt(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=Bt(p.get("emissiveMap"),O)??k(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=Bt(p.get("emissiveIntensity"),O)??k(u.emissiveIntensity??1),f=Bt(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=Bt(p.get("normalMap"),O)??k(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=Bt(p.get("roughness"),O)??k(u.roughness??1);if(null!=u.roughnessMap){let e;if(u.roughnessMap instanceof r.CompressedArrayTexture){const t=G(u.roughnessMap),a=Bt(p.get("roughnessMap"),O)??k(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=Bt(p.get("metalness"),O)??k(u.metalness??0);if(null!=u.metalnessMap){let e;if(u.metalnessMap instanceof r.CompressedArrayTexture){const t=G(u.metalnessMap),a=Bt(p.get("metalnessMap"),O)??k(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=k(1);if(null!=u.aoMap){let e;if(u.aoMap instanceof r.CompressedArrayTexture){const t=G(u.aoMap),a=Bt(p.get("aoMap"),O)??k(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=Bt(p.get("aoMapIntensity"),O)??k(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:Ut(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=Ie(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 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 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));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)})}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)),je(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 ke&&(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 xt(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?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 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(Vt(Ue(e,0,!1)),a>0){Vt(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);Vt(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);Vt(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,n;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:n}=await this.createFromActor(e,s));break;case"group":r=new h;break;case"prefab":r=await this.createFromPrefab(e,s);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),null!=e.position&&r.position.fromArray(e.position),null!=e.scale&&r.scale.fromArray(e.scale),null!=e.rotation&&r.rotation.fromArray(e.rotation),a?r.userData._src=e:r.userData.src=e,null!=n&&(r.userData.actor=n),this.inEditor,this.inEditor){let e=null;r instanceof ke&&(e=function(e){if(e instanceof Ve)return new d(new i(...e.offset.toArray()),St);return null}(r.collisionShape)),null!=e&&(e.layers.disable(0),e.layers.enable(18),e.scale.multiplyScalar(1.1),r.add(e))}if(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):t?.add(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||"asset_mesh"!=e.type&&"shape_mesh"!==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")}}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 Oe(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 ke(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){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}`);null==t&&(t={sceneObjectChain:[]}),t.sceneObjectChain.push(e.id);const{object:s}=await this.createFromPrefabAsset(a,t);return t.sceneObjectChain.pop(),s}async createFromPrefabAsset(e,t){const a=new h;await Promise.all(e.prefab.objects.filter(e=>"global_fog"!==e.type&&"world_env"!==e.type).map(e=>this.materialize(e,a,!0,structuredClone(t))));const s=t.sceneObjectChain.join("/"),r=Array.from(this.materializedActors.entries()).filter(([e,a])=>e.startsWith(s)&&e.split("/").length-1===t.sceneObjectChain.length).map(([,e])=>e);r.forEach(e=>{a.add(e.object)}),this.initActorsPostInit(r,structuredClone(t));const i=Array.from(this.materializedActors.entries()).filter(([e,t])=>e.startsWith(s)).map(([,e])=>e);return{object:a,actors:i}}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])],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);return i&&ft.has(n)?ft.get(n):i&>.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(k(t),k(a),r)}return k(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)}const St=new g({color:4229780});async function xt(e,t,a,s){null==s&&(s=(new m).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 xt(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?We.Number:t instanceof O||"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=>Dt(e.materialId)),(t??[]).filter(e=>Dt(e.materialId)),e=>e.color+e.name)}function Dt(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 Pt=new n,Ct=new n;function Et(e,t){return Pt.set(e),Ct.set(t),Pt.getHexString()==Ct.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 Tt(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 Vt(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 Ot(e){let t=kt.get(e);return null==t&&(t=function(e){const t=Ie(e);if(null==t)return"";return Object.keys(t.geometry.attributes).sort().join(",")}(e),kt.set(e,t)),t}const zt=new WeakMap;function Ft(e){let t=zt.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),zt.set(e,t)),t}function Bt(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 Nt=new m,_t=new o;function Ut(e,t){return _t.copy(e),_t.x*=-1,_t.y*=-1,_t.z*=-1,t.isCubeTexture&&!1===t.isRenderTargetTexture&&(_t.y*=-1,_t.z*=-1),(new r.Matrix3).setFromMatrix4(Nt.makeRotationFromEuler(_t))}new x;function $t(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 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 j,batchingUniformVec2 as I,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 je,findFirstVisibleMesh as Ie,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=>{xt(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?Tt(e.material[s],i)||(e.material[s]=i):Tt(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?.attachedComponents??[];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 xt(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!=Ie(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&&Et(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=Ft(o);t+=kt(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||$t(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=j(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=I(e);else if(a instanceof r.CompressedArrayTexture)t=j(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=Bt(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=Bt(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=_(Bt(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=Bt(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=_(Bt(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=Bt(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=Bt(p.get("emissiveIntensity"),k)??O(u.emissiveIntensity??1),f=Bt(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=Bt(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=Bt(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=Bt(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=Bt(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=Bt(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=Bt(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=Bt(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:Ut(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=Ie(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 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 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));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?.attachedComponents?.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)),je(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 xt(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?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 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(Vt(Ue(e,0,!1)),a>0){Vt(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);Vt(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);Vt(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,n;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:n}=await this.createFromActor(e,s));break;case"group":r=new h;break;case"prefab":r=await this.createFromPrefab(e,s);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),null!=e.position&&r.position.fromArray(e.position),null!=e.scale&&r.scale.fromArray(e.scale),null!=e.rotation&&r.rotation.fromArray(e.rotation),a?r.userData._src=e:r.userData.src=e,null!=n&&(r.userData.actor=n),this.inEditor,this.inEditor){let e=null;r instanceof Oe&&(e=function(e){if(e instanceof Ve)return new d(new i(...e.offset.toArray()),St);return null}(r.collisionShape)),null!=e&&(e.layers.disable(0),e.layers.enable(18),e.scale.multiplyScalar(1.1),r.add(e))}if(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):t?.add(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||"asset_mesh"!=e.type&&"shape_mesh"!==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")}}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){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}`);null==t&&(t={sceneObjectChain:[]}),t.sceneObjectChain.push(e.id);const{object:s}=await this.createFromPrefabAsset(a,t);return t.sceneObjectChain.pop(),s}async createFromPrefabAsset(e,t){const a=new h;await Promise.all(e.prefab.objects.filter(e=>"global_fog"!==e.type&&"world_env"!==e.type).map(e=>this.materialize(e,a,!0,structuredClone(t))));const s=t.sceneObjectChain.join("/"),r=Array.from(this.materializedActors.entries()).filter(([e,a])=>e.startsWith(s)&&e.split("/").length-1===t.sceneObjectChain.length).map(([,e])=>e);r.forEach(e=>{a.add(e.object)}),this.initActorsPostInit(r,structuredClone(t));const i=Array.from(this.materializedActors.entries()).filter(([e,t])=>e.startsWith(s)).map(([,e])=>e);return{object:a,actors:i}}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&>.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)}const St=new g({color:4229780});async function xt(e,t,a,s){null==s&&(s=(new m).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 xt(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?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=>Dt(e.materialId)),(t??[]).filter(e=>Dt(e.materialId)),e=>e.color+e.name)}function Dt(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 Pt=new n,Ct=new n;function Et(e,t){return Pt.set(e),Ct.set(t),Pt.getHexString()==Ct.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 Tt(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 Vt(e){if(null!=e){for(let t=0;t<e.array.length;t++)e.setX(t,0);e.needsUpdate=!0}}const Ot=new WeakMap;function kt(e){let t=Ot.get(e);return null==t&&(t=function(e){const t=Ie(e);if(null==t)return"";return Object.keys(t.geometry.attributes).sort().join(",")}(e),Ot.set(e,t)),t}const zt=new WeakMap;function Ft(e){let t=zt.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),zt.set(e,t)),t}function Bt(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 Nt=new m,_t=new o;function Ut(e,t){return _t.copy(e),_t.x*=-1,_t.y*=-1,_t.z*=-1,t.isCubeTexture&&!1===t.isRenderTargetTexture&&(_t.y*=-1,_t.z*=-1),(new r.Matrix3).setFromMatrix4(Nt.makeRotationFromEuler(_t))}new x;function $t(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
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{randomUUID as e}from"../../utils/uuid.js";import{pathJoin as t}from"../../utils/files.js";import{combineLatest as a,EMPTY as i,filter as r,firstValueFrom as s,from as n,map as h,mergeAll as o,mergeMap as l,Observable as c,of as u,startWith as
|
|
1
|
+
import{randomUUID as e}from"../../utils/uuid.js";import{pathJoin as t}from"../../utils/files.js";import{combineLatest as a,EMPTY as i,filter as r,firstValueFrom as s,from as n,map as h,mergeAll as o,mergeMap as l,Observable as c,of as u,startWith as p,Subject as d,switchMap as w,tap as f}from"rxjs";import{sleepDelay as m}from"../../utils/async.js";const y={},v={},j={},b={};null==y.read&&window.require&&(Object.assign(y,window.require("fs")),Object.assign(v,y.promises),Object.assign(j,window.require("path")),Object.assign(b,window.require("chokidar")));const g=null!=y.existsSync;function F(){if(g){const e="--path=",t=window.process.argv.find(t=>t.startsWith(e));return t?t.substring(e.length):""}return""}const x=/^[A-Z]:/;function P(...e){return 0===e.length?"":x.test(e[0])||g?j.join(...e):t(...e)}export class ObjectStorage{get pathResources(){return P(this.path+"-resources")}constructor(e,t){this.name=e,this.filePathFn=t,this.basePathUpdates=new d,this.basePath=this.basePathUpdates.pipe(h(e=>P(F(),e)),f(e=>{this.path=P(e,this.name),O(this.path),this.determineIfMetaFileShouldBeCreated()})),this.loaded=s(this.basePath),this.shouldCreateIndex=!0,this.watchers=[]}setBasePath(e){this.basePathUpdates.next(e)}async determineIfMetaFileShouldBeCreated(){try{(await v.readFile(P(F(),"vite.config.ts"))).toString().includes("hologyBuild")&&(this.shouldCreateIndex=!1)}catch(e){console.warn("Failed to read vite config to determine if meta files should be created")}}async createFolder(e,t=""){S(),await v.mkdir(j.join(this.path,t,e),{recursive:!0})}async deleteFolderForceDangerous(e){await v.rm(j.join(this.path,e),{recursive:!0,force:!0})}async moveFolder(e,t){if(S(),""==e)return void console.warn("Can not move a folder in root");const a=j.resolve(j.join(this.path,t),j.basename(e));if(await C(a)){if(a!==j.resolve(this.path,e))throw new Error("Can not move to directory as a file already exists with the same name")}else{if(function(e,t){const a=j.resolve(e),i=j.resolve(t),r=j.normalize(a)+j.sep;return(j.normalize(i)+j.sep).startsWith(r)}(j.join(this.path,e),j.join(this.path,t)))throw new Error("Can not move a folder into a folder it contains");await v.rename(j.join(this.path,e),a)}}async renameFolder(e,t){await v.rename(j.join(this.path,e),j.resolve(j.dirname(j.join(this.path,e)),t))}async moveToFolder(e,t){if(S(),e.path===t)return;const a=this.privateObjectPath({...e,path:t});await v.rename(this.privateObjectPath(e),a)}getAbsolutePath(e=""){return j.join(this.path,e)}getResourceAbsolutePath(e=""){return j.join(this.pathResources,e)}watchFolders(){const e=v.readdir(this.path,{recursive:!0,withFileTypes:!0});return a([n(e),this.watchDir(this.path).pipe(r(e=>!e.filename.endsWith(".json")),p(null))]).pipe(w(([e,t])=>null!=t?n(v.readdir(this.path,{recursive:!0,withFileTypes:!0})):u(e)),h(e=>Array.from(new Set(e.filter(e=>e.isDirectory()).map(e=>j.relative(this.path,j.join(e.path,e.name)).replace(/^\.$/,"")).values()))))}watch(){S();n(this.loaded).pipe(w(()=>a([this.watchDir(this.pathResources),n(this.getAll())]).pipe(r(([e])=>null!=e),l(([e,t])=>{if("change"===e.event){const a=j.basename(e.filename),i=t.filter(e=>e.fileKey===a);if(i.length>0)return n(i).pipe(l(e=>{const t=this.privateObjectRelativePath(e);return n(this.readFileIfExists(t)).pipe(h(a=>({event:"change",object:a,path:e.path,filename:t})))}))}return i}))));return n(this.loaded).pipe(w(()=>this.watchDir(this.path)),l(e=>{const t={event:e.event,path:j.dirname(e.filename).replace(/^\.$/,""),filename:j.basename(e.filename)};return e.filename.endsWith(".json")?"unlink"!==e.event?n(this.readFileIfExists(e.filename)).pipe(h(e=>({object:e,...t}))):u({object:null,...t}):"change"===e.event?n(this.reloadSubdirectory(e.filename)).pipe(o(),h(e=>({object:e,...t}))):i}))}async reloadSubdirectory(e){return(await this.getAll(e)).filter(t=>t.path.startsWith(e))}async readFileIfExists(e){const t=P(this.path,e);try{const a=await v.readFile(t);return{...JSON.parse(a.toString()),path:j.dirname(e).replace(/^\.$/,""),filename:j.basename(e)}}catch{return console.error("Could not find file at "+t),null}}async getAll(e){if(g){await this.loaded,await O(this.path);const t=(await v.readdir(j.join(this.path,e??""),{recursive:!0,withFileTypes:!0})).filter(e=>e.isFile()&&e.name.endsWith(".json")&&!/^[\._]/.test(e.name)),a=100,i=[];for(let e=0;e<t.length;e+=a){const r=t.slice(e,e+a),s=await Promise.all(r.map(e=>v.readFile(P(e.path,e.name)).then(t=>({...JSON.parse(t.toString()),path:j.relative(this.path,e.path).replace(/^\.$/,""),filename:j.basename(e.path)}))));i.push(...s)}return i}const t=await this.loadIndex();return Promise.all(Object.keys(t).map(e=>this.get(e)))}async get(e){const t=await this.loadIndex(),a=t[e]??Object.values(t).find(t=>t.name===e);if(null==a)return;const i=this.privateObjectPath(a);if(!g)return(await fetch(i)).json();return await I(i)?JSON.parse((await v.readFile(i)).toString()):null}async save(e){return S(),await this.loaded,await v.writeFile(this.privateObjectPath(e),this.serialize(e)),await this.updateIndex(),e}async rename(e,t){const a={...e,name:t},i=this.privateObjectPath(e),r=this.privateObjectPath(a);try{await v.rename(i,r)}catch(e){console.error(e),console.warn("Rename failed, retrying",{currentPath:i,newPath:r}),await m(400),await v.rename(i,r)}return await this.save(a),await this.updateIndex(),a}async delete(e){await v.unlink(this.privateObjectPath(e)),this.updateIndex()}async create(t){S(),await this.loaded,t.id=e();const a=this.privateObjectPath(t);if(await C(a))throw Error(`Can not create because a file already exists at ${a}`);return await v.writeFile(a,this.serialize(t)),await this.updateIndex(),t}prepareCreate(t){return S(),t.id=e(),t}serialize(e){const t={...e};return delete t.path,delete t.filename,JSON.stringify(t,null,2)}async updateIndex(){S();const e=await this.getAll(),t={};for(const a of e)t[a.id]={id:a.id,name:a.name??a.id,path:a.path};if(this.cachedIndex=t,g){if(!this.shouldCreateIndex)return;await v.writeFile(this.indexFilePath,JSON.stringify(t,null,2))}}get indexFilePath(){return P(this.path,"_meta.json")}async loadIndex(){return null==this.cachedIndex&&(g?await this.updateIndex():this.cachedIndex=await(await fetch(this.indexFilePath)).json()),this.cachedIndex}async ensureResourceDir(){await O(P(this.path+"-resources"))}async saveFile(e,t){return S(),await O(P(this.path+"-resources")),v.copyFile(t.path,P(this.path+"-resources",e.fileKey))}async saveExtraFile(e,t){return S(),await O(P(this.path+"-resources")),v.copyFile(e,P(this.path+"-resources",t))}getAssetPath(e){return window&&"function"==typeof window.require?window.require("path").join(this.path+"-resources",e.fileKey):P(this.path+"-resources",e.fileKey)}async replaceFile(e,t){if(await I(t))return v.copyFile(t,P(this.path+"-resources",e.fileKey));console.error("Failed to replace file using path "+t)}async deleteFile(e){if(null==e)return;S();const t=P(this.path+"-resources",e);return await I(t)?v.unlink(t):void 0}privateObjectPath(e){return P(this.path,this.privateObjectRelativePath(e))}privateObjectRelativePath(e){return this.filePathFn?P(e.path??"",this.filePathFn(e)):P(e.path??"",tokenizeName(e.name??e.id)+".json")}watchDir(e){return new c(t=>{const a=b.watch(e,{cwd:e});return a.on("all",(e,a,i)=>{t.next({event:e,filename:a})}),a.on("unlinkDir",e=>{}),a.on("error",()=>{}),this.watchers.push(a),()=>{a.close()}})}}export function tokenizeName(e){return e.trim().replace(/\s/g,"_").replace(/[^a-z0-9_\-\.]/gi,"")}async function O(e){g&&(await I(e)||await v.mkdir(e,{recursive:!0}))}function I(e){return!!g&&new Promise(function(t,a){y.exists(e,function(e){t(e)})})}function S(){if(!g)throw new Error("Must have direct access to filesystem")}async function C(e){try{await v.access(e,v.constants.F_OK)}catch(e){return!1}return!0}/*
|
|
2
2
|
* Copyright (©) 2025 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|