@hology/core 0.0.199 → 0.0.200

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/effects/vfx/vfx-asset.d.ts +17 -6
  2. package/dist/effects/vfx/vfx-materializer.js +1 -1
  3. package/dist/effects/vfx/vfx-renderers.js +1 -1
  4. package/dist/gameplay/services/physics/physics-system.js +1 -1
  5. package/dist/scene/custom-param-runtime-types.d.ts +35 -0
  6. package/dist/scene/custom-param-runtime-types.js +4 -0
  7. package/dist/scene/landscape/landscape.js +1 -1
  8. package/dist/scene/materializer.d.ts +19 -3
  9. package/dist/scene/materializer.js +1 -1
  10. package/dist/scene/model.d.ts +13 -5
  11. package/dist/scene/sky.js +1 -1
  12. package/dist/scene/storage/storage.js +1 -1
  13. package/dist/shader/graph/compiler.d.ts +80 -0
  14. package/dist/shader/graph/compiler.js +4 -0
  15. package/dist/shader/graph/index.d.ts +5 -0
  16. package/dist/shader/graph/index.js +4 -0
  17. package/dist/shader/graph/model.d.ts +79 -0
  18. package/dist/shader/graph/model.js +4 -0
  19. package/dist/shader/graph/parameters.d.ts +7 -0
  20. package/dist/shader/graph/parameters.js +4 -0
  21. package/dist/shader/graph/registry.d.ts +17 -0
  22. package/dist/shader/graph/registry.js +4 -0
  23. package/dist/shader/index.d.ts +1 -0
  24. package/dist/shader/index.js +1 -1
  25. package/dist/shader-nodes/bulge.js +1 -1
  26. package/dist/shader-nodes/depth.d.ts +2 -0
  27. package/dist/shader-nodes/depth.js +1 -1
  28. package/dist/shader-nodes/effects.d.ts +5 -0
  29. package/dist/shader-nodes/effects.js +1 -1
  30. package/dist/shader-nodes/gradient-sample.d.ts +16 -0
  31. package/dist/shader-nodes/gradient-sample.js +4 -0
  32. package/dist/shader-nodes/index.d.ts +1 -0
  33. package/dist/shader-nodes/index.js +1 -1
  34. package/dist/shader-nodes/layers.d.ts +6 -3
  35. package/dist/shader-nodes/layers.js +1 -1
  36. package/dist/shader-nodes/math.d.ts +4 -0
  37. package/dist/shader-nodes/math.js +1 -1
  38. package/dist/shader-nodes/particle.d.ts +10 -2
  39. package/dist/shader-nodes/particle.js +1 -1
  40. package/dist/shader-nodes/texture-sequence.d.ts +2 -1
  41. package/dist/shader-nodes/texture-sequence.js +1 -1
  42. package/dist/test/runtime-param-type-inference.test.d.ts +2 -0
  43. package/dist/test/runtime-param-type-inference.test.js +4 -0
  44. package/dist/test/shader-graph.test.d.ts +2 -0
  45. package/dist/test/shader-graph.test.js +4 -0
  46. package/dist/test/storage-case-collision.test.js +1 -1
  47. package/package.json +6 -2
  48. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{ConvexPolyhedronCollisionShape as a,SpriteShader as s}from"@hology/core";import{Subject as r}from"rxjs";import*as i from"three";import{BoxGeometry as n,Color as o,Euler as l,Fog as c,FogExp2 as h,Group as u,Material as p,Matrix4 as d,Mesh as m,MeshLambertMaterial as f,MeshPhongMaterial as g,MeshStandardMaterial as y,Object3D as w,PointLight as M,Quaternion as b,Scene as v,Texture as S,Vector2 as A,Vector3 as x,Vector4 as j}from"three";import{attributes as I,batchingUniformFloat as P,batchingUniformVec2 as D,batchingUniformVec3 as C,batchingUniformVec4 as T,bool as E,BooleanExpression as V,BooleanNode as O,colorToNormal as k,float as z,FloatNode as F,ifDefApply as N,mix as B,NodeShaderMaterial as _,rgb as U,rgba as $,RgbNode as W,select as L,standardMaterial as R,Texture2dLookupNode as q,textureSampler2d as G,textureSampler2dArray as J,UniformSampler2dArraySlice as H,varying as X,varyingAttributes as Y,varyingTransformed as Z,vec2 as K,Vec2Node as Q,vec3 as ee,Vec3Node as te,vec4 as ae,Vec4Node as se}from"three-shader-graph";import{Service as re}from"typedi";import{VfxActor as ie}from"../effects/vfx/vfx-actor.js";import{VisualEffect as ne}from"../effects/vfx/vfx-param.js";import{Prefab as oe,PrefabOf as le}from"./objects/prefab.js";import{BaseActor as ce}from"../gameplay/actors/actor.js";import he from"../gameplay/actors/builtin/index.js";import{ActorComponent as ue}from"../gameplay/actors/component.js";import{PhysicsBodyType as pe}from"../gameplay/services/physics/physics-system.js";import{ThreeBlendingMode as de}from"../effects/vfx/vfx-asset.js";import{withInjectionContext as me}from"../gameplay/inject.js";import{RenderingView as fe}from"../rendering.js";import{curveSampler as ge,oneMinus as ye,particleUniforms as we,Sampler2DNode as Me}from"../shader-nodes/index.js";import{LambertShader as be}from"../shader/builtin/lambert-shader.js";import{LandscapeCompositeShader as ve}from"../shader/builtin/landscape-composite-shader";import{LandscapeShader as Se}from"../shader/builtin/landscape-shader.js";import{StandardShader as Ae}from"../shader/builtin/standard-shader.js";import{UnlitShader as xe}from"../shader/builtin/unlit-shader.js";import{extractShaderParameters as je}from"../shader/parameter.js";import{ArrayMap as Ie,DefaultMap as Pe,groupBy as De}from"../utils/collections.js";import{iterateMaterials as Ce}from"../utils/materials.js";import{filterChildrenShallow as Te,filterSceneShallow as Ee,findFirstVisibleMesh as Ve,findFirstVisibleObject as Oe,traverseAsync as ke}from"../utils/three/traverse.js";import{AssetMeshInstance as ze,AssetResourceLoader as Fe}from"./asset-resource-loader.js";import{AssetsProvider as Ne}from"./assets-provider.js";import{isCollisionMesh as Be}from"./collision/collision-shape-import.js";import{BoxCollisionShape as _e,PhysicalShapeMesh as Ue}from"./collision/collision-shape.js";import{LandscapeManager as $e}from"./landscape/landscape-manager.js";import{initLandscape as We}from"./landscape/landscape.js";import{SectionGrid as Le,smoothNormalsCrossMeshes as Re}from"./landscape/utils.js";import{createGrassFoliageMaterial as qe}from"./materials/grass-foliage.js";import{createGrassMaterial as Ge}from"./materials/grass.js";import{getMaterialAttribute as Je}from"./materials/utils/material-painting.js";import{SurfaceScatterManager as He}from"./scatter/surface-scatter-manager.js";import{createWaterMaterial as Xe}from"./materials/water.js";import{SerializedParamType as Ye}from"./model.js";import{ShapeLibrary as Ze,ShapeLibraryKeys as Ke}from"./objects/shapes.js";import{ambientLightName as Qe,createSky as et,defaultSkyMaterial as tt}from"./sky.js";import{Curve2 as at}from"../utils/curve.js";import{DecalUnlitShader as st}from"../shader/builtin/decal-unlit-shader.js";import{DecalStandardShader as rt}from"../shader/builtin/decal-standard-shader.js";import{ColorLayer as it,defaultValueColorLayer as nt,defaultValueMaskLayer as ot,MaskLayer as lt}from"../shader/color-layer.js";import{LayeredShader as ct}from"../shader/builtin/layered-shader";import{isColorLayerSerialized as ht}from"../shader/color-layer";import{FogVolume as ut}from"../rendering/fog/fog-volume-actor.js";import{UnscaledSprite as pt}from"../utils/three/unscaled-sprite.js";import{ToonShader as dt}from"../shader/builtin/toon-shader.js";import{BatchedMesh2 as mt}from"./batched-mesh-2.js";import{ParallaxStandardMaterial as ft}from"../shader/builtin/standard-shader";import{parallaxOcclusionMapping as gt}from"../shader-nodes/pom.js";import{traverseVisibleEvery as yt}from"../utils/three/traverse";import{RectAreaLightHelper as wt}from"three/examples/jsm/Addons.js";import{Sequence as Mt}from"../effects/sequence/sequence-data.js";import{applyUvTiling as bt}from"./../shader/uv-nodes.js";const vt={},St=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),At=/^((?!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 xt(e,this.dataProvider,this.assetsService,this.assetManagerService,t,[],[],{create:()=>null,initActor:async()=>{}})}}let xt=class{constructor(e,t,a,s,n,o,l,c,h=[]){this.scene=e,this.dataProvider=t,this.assetsService=a,this.assetManagerService=s,this.renderingView=n,this.shaders=o,this.actorTypes=l,this.actorProvider=c,this.componentTypes=h,this.objectMap=new Map,this.sceneObjectMap=new Map,this.components=[],this.landscapeManagers=[],this.materializedActors=new Map,this.idToSceneObject=new Map,this.inEditor=!0,this.updated$=new r,this.removed$=new r,this.error$=new r,this.editorActorParamSnapshot=new Map,this.assets=new Map,this._canBeInstancedCache=new Map,this._originalMaterials=new Map,this.pmremGeneratorResults=new WeakMap,this.prefabInstanceChain=[],this.prefabInstanceExposedActorMap=new Map,this.geometryCache=new Map,this.collisionShapeCache=new Map,this.assetManagerService.materialProvider=async e=>materialFromAsset(this.assets.get(e)??await this.assetsService.getAsset(e),this.renderingView,this.assetsService,this.assetManagerService,this.shaders),this.originalFog=null,t.onCreate(e=>{this.update(e),this.handleSurfaceScatterSceneMutation(e)}),t.onUpdate(e=>{this.update(e),this.handleSurfaceScatterSceneMutation(e)}),t.onRemove(e=>{this.remove(e),this.handleSurfaceScatterSceneMutation(e)}),this.createAssetSubscription=a.onCreate.subscribe(e=>{this.assets.set(e.id,e)}),this.updateSubscription=a.onUpdate.subscribe(async t=>{if(this.assets.set(t.id,t),"material"==t.type)e.traverse(e=>{if(e instanceof i.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)});else if("mesh"==t.type){this.findByAssetId(t.id).forEach(async e=>{this.remove(e.userData.src);const t=await this.materializeAndInitActor(e.userData.src);this.updated$.next({object:t,source:e.userData.src})});for(const e of this.assets.values())if("prefab"==e.type){if(!e.prefab.objects.some(e=>ia(e,e=>e.assetId==t.id,this.assets)))continue;this.findByAssetId(e.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 x,!0)}),null!=this.surfaceScatterManager&&(this.surfaceScatterManager.usesSourceAsset(t.id)||this.surfaceScatterManager.usesScatterAsset(t.id))&&this.surfaceScatterManager.queueRefresh(!0)}else"prefab"===t.type?(this.findByAssetId(t.id).forEach(e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}),(this.surfaceScatterManager?.usesPrefabAsset(t.id)||this.sceneReferencesPrefabAsset(t.id)&&await this.prefabAssetContainsSurfaceScatter(t))&&await this.refreshSurfaceScatterPresence(!0)):"vfx"===t.type?this.dataProvider.getObjects().forEach(e=>{kt(e,(e,a)=>{"vfx"===e.type&&e.assetId===t.id&&(this.remove(e),this.materializeAndInitActor(e))})}):"texture"===t.type&&this.scene.traverse(e=>{if(e instanceof m)if(Array.isArray(e.material))for(let a=0;a<e.material.length;a++)this.refreshMaterialTextures(e,e.material[a],t,a);else this.refreshMaterialTextures(e,e.material,t)})})}async refreshMaterialTextures(e,t,a,s){if("texture"!==a.type)return void console.error("Can not refresh material textures. Asset is not a texture",a);const r=await this.assetManagerService.getTexture(a);if(null!=r)if(t instanceof i.ShaderMaterial)for(const[e,s]of Object.entries(t.uniforms))s.value instanceof i.Texture&&s.value.userData.assetId===a.id&&(t.uniforms[e].value=r);else for(const[e,s]of Object.entries(t))s instanceof i.Texture&&s.userData.assetId===a.id&&(t[e]=r);else console.error("Can not refresh material textures. Texture not found",a)}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===Ye.Material&&s.value===a.id){t=!0;break}if(s.type===Ye.Array&&"element"in s&&s.element===Ye.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?Rt(e.material[s],i)||(e.material[s]=i):Rt(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===Ye.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(),It.clear(),Pt.clear(),await this.prefetchAssets(),await Promise.all(this.dataProvider.getObjects().map(e=>this.materialize(e))),await this.initActorsPostInit(),await this.refreshSurfaceScatterPresence(!0)}async initVfx(){console.time("Init VFX");const e=new Set,t=[],a=new v;for(const s of this.actorInstances){const r=sa(s);for(const s of r){const r=s.asset;if(e.has(r.id))continue;e.add(r.id),r.vfx.emitters;const i=await s.create(a);a.add(i.object),a.add(i.particleSystemContainer),i.play(),i.onUpdate(.5),i.stop(),i.pause(),t.push(i)}}const s=this.renderingView.compileAsync(a);this.renderingView.initTextures(a),await s;for(const e of t)e.onEndPlay(),e.disposed.next(!0),e.object.removeFromParent();console.timeEnd("Init VFX")}async initActorsPostInit(e=Array.from(this.materializedActors.entries())){const t=e.map(async([e,t])=>{const a=t.object.userData.src??t.object.userData._src;if("vfx"===a.type)return Promise.resolve();const s=await this.assetsService.getAsset(a.assetId),r=e.split("/"),i=r.slice(0,-1),n=i.join("/"),o=(r[r.length-1],new Map);for(const[e,t]of this.materializedActors)if(o.set(e,t),0===n.length)e.includes("/")||o.set(e,t);else if(e.startsWith(n+"/")){const a=e.slice(n.length+1);a.includes("/")||o.set(a,t)}const l={...s?.actor?.params??{},...a.actor?.params??{}},c=[...a.actor?.innerParams??[]];for(let t=i.length-1;t>=0;t--){const a=i.slice(0,t+1).join("/"),s=this.idToSceneObject.get(a);if("prefab"===s?.type&&null!=s.prefab){const i=await this.assetsService.getAsset(s.assetId);if(null!=i){let n=!1,o=a+"/"+i.prefab?.mainActorId;for(;null!=o;){if(o===e){n=!0;break}o=this.prefabInstanceExposedActorMap.get(o)}if(n&&null!=s.prefab.params&&Object.assign(l,Nt(s.prefab.params)),null!=s.prefab.innerParams)for(const e of s.prefab.innerParams){const a=r.slice(t+1);e.path.length>=a.length&&e.path.slice(0,a.length).every((e,t)=>e===a[t])&&c.push({path:e.path.slice(a.length),params:e.params})}}}}for(const e of c)await this.applyActorComponentParams(t,e.path.slice(),e.params,o);await this.attachEditorComponents(t,a,o);const h=await prepareClassParameters(l,t.constructor,this.assetsService,this.assetManagerService,o,this.renderingView,this.shaders,this.actorProvider,e=>{const t=n.length>0?n+"/"+e:e;return this.prefabInstanceExposedActorMap.get(t)??null});Object.assign(t,h);try{return await this.actorProvider.initActor(t)}catch(e){console.error(`Failed to initiate actor (name="${a.name}", id=${a.id})`,e)}});return Promise.all(t)}async attachEditorComponents(e,t,a){const s=t.actor?.components??[];for(const r of s){const s=this.componentTypes.find(e=>e.name===r.type);if(null==s){console.warn(`Component type '${r.type}' not found for actor ${t.id}`);continue}const i=e.attach(s.type);if(null!=r.params){const e=await prepareClassParameters(r.params,null,this.assetsService,this.assetManagerService,a,this.renderingView,this.shaders,this.actorProvider,e=>this.prefabInstanceExposedActorMap.get(e)??null);Object.assign(i,e)}for(const e of r.innerParams??[])await this.applyActorComponentParams(i,e.path.slice(),e.params,a)}}addVfxChildActors(e,t=e){}async applyActorComponentParams(e,t,a,s){const r=t.length,i=t.shift();if(0==r){const t=await prepareClassParameters(a,null,this.assetsService,this.assetManagerService,s,this.renderingView,this.shaders,this.actorProvider,e=>this.prefabInstanceExposedActorMap.get(e)??null);for(const[a,s]of Object.entries(t))null!=s&&(e[a]=s)}else null!=e[i]&&await this.applyActorComponentParams(e[i],t,a,s)}canObjectBeInstanced(e){return e.physics?.type!==pe.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=>{!Be(e)&&e.isMesh&&s.push(e)});const r=1==s.length&&0==s[0].children.length,i=!At,n=s.every(e=>!Array.isArray(e.material)||1===e.material.length),o=s.some(e=>e instanceof m&&null!=e.geometry.morphAttributes&&Object.keys(e.geometry.morphAttributes).length>0),l=!0;t=s.length>0&&(r||n&&i)&&l&&!o,this._canBeInstancedCache.set(e.assetId,t)}return t}async preInit(){this.renderingView?.onLoop(()=>{null!=this.sky&&this.renderingView.camera.getWorldPosition(this.sky.position)}),this.assetsService.getAssets().then(e=>{for(const t of e)this.assets.set(t.id,t)})}shouldBeMaterialized(e){if(!1===e.enabled)return!1;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(),It.clear(),Pt.clear();const e=[],t=new Ie,a=new Ie,s=new Ie;let r=0,n=0,c=0;const h=new Map,u=new Pe(()=>new Map);for(const i of this.dataProvider.getObjects())await kt(i,async(i,l,p)=>{if(!this.shouldBeMaterialized(i))return;const d="asset_mesh"==i.type&&this.canObjectBeInstanced(i)&&await this.canAssetBeInstanced(i),f="shape_mesh"===i.type&&"landscape"!==i.shape&&i.physics?.type!==pe.dynamic;if(d||f){if(l&&l.children?.length>0){const e=l.children.findIndex(e=>e.id===i.id);e>=0&&l.children.splice(e,1)}if(f){let e=i.shape+JSON.stringify(i.shapeParams??{})+i.castShadow+i.receiveShadow;const t=i.materialAssignments?.at(0)?.materialId,a=null!=t?this.assets.get(t):null;let r=null;if(!1&&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===Ye.Color&&null!=e.value&&(r=new o(e.value))}}e+=a.material.outlines,null!=a.material.outlineParams&&(e+=JSON.stringify(a.material.outlineParams)),e+=a.material.reflective,e+=a.material.bloom,e+=a.material.side,e+=a.material.side,e+=a.material.transparent,e+=a.material.alphaTest}else e+=t;s.push(e,{object:{...i,parentTransform:p},color:r}),c++}else{const e=this.assets.get(i.assetId);let s=h.get(i.assetId);if(null==s){const e=await this.createFromAsset(i,{assignMaterials:!1});if(null==e)return;if(s=h.get(i.assetId),null==s){s={useBatchedMesh:null!=Ve(e)&&yt(e,e=>!(e instanceof m)||this.testCanBatch(e.material,e.geometry)),assetMesh:e},h.set(i.assetId,s)}}const o=_t(i.materialAssignments,e.materialAssignments);if(s.useBatchedMesh)await ke(s.assetMesh,async e=>{if(!(e instanceof m))return;const t=Array.isArray(e.material)?e.material[0]:e.material,s=await this.resolveMaterialForAssignments(t,o);if(null!=s){u.get(i.id).set(e.uuid,s),ra(e.geometry,s);let t=Xt(s);t+=Jt(e),a.push(t,{...i,parentTransform:p,meshUUID:e.uuid}),r++}else console.warn("Can not materialize mesh because missing material",i)});else{const e=i.assetId+JSON.stringify(i.materialAssignments??[]);t.push(e,{...i,parentTransform:p}),n++}}}else null==l&&e.push({...i,parentTransform:p})});console.log(`Scene init stats: \n Batched Assets: ${a.size} groups containing in total ${r} objects.\n Instanced Assets: ${t.size} groups containing in total ${n} 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,t]of a.entries()){if(0==t.length)continue;let e;h.get(t[0].assetId).assetMesh;e=this.createBatchedMesh(t,u,h);const a=this.assets.get(t[0].assetId);e.castShadow=t[0].castShadow??a.castShadow??!0,e.receiveShadow=t[0].receiveShadow??a.receiveShadow??!0;const s=new ze;s.add(e),s.userData.src=t[0],s.castShadow=!1,s.receiveShadow=!1,this.scene.add(s)}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 ze;r.add(t),r.userData.src=e[0],a instanceof ze&&(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=Oe(a,e=>!Be(e)&&null!=e.geometry),r=s.material.clone();null!=e[0].color&&null!=r.color&&(r.color=new o(16777215));const n=s.geometry;let c,h;!(At||r instanceof _||null==n.index)?(c=new i.BatchedMesh(e.length,n.getAttribute("position").count,n.index.count,r),c.perObjectFrustumCulled=!0,h=c.addGeometry(n)):c=new i.InstancedMesh(n,r,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 i.Matrix4).compose((new x).fromArray(a.object.position),(new b).setFromEuler((new l).fromArray(a.object.rotation)),(new x).fromArray(a.object.scale)),r=(new d).copy(a.object.parentTransform).multiply(s);let n;n=c instanceof i.BatchedMesh?c.addInstance(h):t,c.setMatrixAt(n,r),a.color}for(let t=0;t<e.length;t++){const s=e[t],r=new ze;r.userData.src=e[0],a instanceof Ue&&(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(),await this.initVfx(),await this.refreshSurfaceScatterPresence(!0)}prepareCollisionShapesForInstanced(e){e instanceof ze&&e.collisionShapes.forEach(e=>{e instanceof a&&e.mesh instanceof m&&(e.mesh=e.mesh.geometry)})}testCanBatch(e,t){return!At&&(!Array.isArray(e)||1==e.length)&&this.testCanBatchMaterial(e)}testCanBatchMaterial(e){return null!=(Array.isArray(e)?e[0]:e)}createBatchedMesh(e,t,a){const s=new Ie;for(const t of e)null!=t.meshUUID?s.push(t.meshUUID??t.assetId,t):console.warn("Missing mesh uuid for batching");let r=0,n=0,l=0;const c=new Map;for(const[e,t]of s.entries()){const s=t[0].assetId,i=a.get(s);if(null==i){console.warn("Missing batching info for asset id "+s);continue}const o=Oe(i.assetMesh,t=>t instanceof m&&t.uuid===e);if(null==o){console.warn("Missing mesh in batched asset");continue}c.set(e,o);const h=o.geometry.getAttribute("position");null==h&&console.warn("Missing position attribute for batched mesh"),r+=o.geometry.index.count*t.length,n+=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 u=new Map;const p=[];let d=new i.MeshStandardMaterial({color:"white"});const f=t.get(e[0].id).get(e[0].meshUUID);if(null==f)throw"missing source material";if(f instanceof y&&!(f instanceof i.MeshPhysicalMaterial)){const a=new Set,s=new Map;for(const r of e){const e=t.get(r.id).get(r.meshUUID);if(null==e)throw"missing mat";for(const t of h){let r=e[t];r instanceof i.CompressedArrayTexture&&null!=r.userData.index&&(r=r.userData.index);const n=s.get(t);void 0===n||aa(r,n)?s.set(t,r):a.add(t)}}for(const e of a){let t;const a=f[e];if("number"==typeof a){let a=p.find(e=>e.params.length<4);if(null==a){const t="vp"+p.length;a={name:t,params:[e],node:T(t)},p.push(a)}else a.params.push(e);t=ea(a.node,a.params.length-1)}else if(a instanceof j)t=T(e);else if(a instanceof x||a instanceof o)t=C(e);else if(a instanceof A)t=D(e);else if(a instanceof i.CompressedArrayTexture)t=P(e+"_i");else if(a instanceof S)continue;u.set(e,t)}let r=Y.uv;f instanceof ft&&null!=f.heightMap&&(r=gt(r,G(f.heightMap),z(f.heightScale)));let n=Yt(u.get("opacity"),F)??z(f.opacity??1);if(null!=f.alphaMap){let e;if(f.alphaMap instanceof i.CompressedArrayTexture){const t=J(f.alphaMap),a=Yt(u.get("alphaMap"),F)??z(f.alphaMap.userData.index??0);e=t.sample(ee(r.x,r.y,a))}else e=G(f.alphaMap).sample(r);n=n.multiply(e.r)}let l=$(Yt(u.get("color"),te)??f.color,n);if(null!=f.map){let e;if(f.map instanceof i.CompressedArrayTexture){const t=J(f.map),a=Yt(u.get("map"),F)??z(f.map.userData.index??0);e=t.sample(ee(r.x,r.y,a))}else e=G(f.map).sample(bt(r,f.map));l=l.multiply(e),n=n.multiply(e.a)}f.vertexColors&&(l=l.multiply(ae(X(I.color.rgb),1)));let c=$(Yt(u.get("emissive"),te)??f.emissive,n);if(null!=f.emissiveMap){let e;if(f.emissiveMap instanceof i.CompressedArrayTexture){const t=J(f.emissiveMap),a=Yt(u.get("emissiveMap"),F)??z(f.emissiveMap.userData.index??0);e=t.sample(ee(r.x,r.y,a))}else e=G(f.emissiveMap).sample(bt(r,f.emissiveMap));c=c.multiply(e)}const m=Yt(u.get("emissiveIntensity"),F)??z(f.emissiveIntensity??1),g=Yt(u.get("normalScale"),Q)??K(f.normalScale??new A(1,1));let y=Z.normal;if(null!=f.normalMap){let e;if(f.normalMap instanceof i.CompressedArrayTexture){const t=J(f.normalMap),a=Yt(u.get("normalMap"),F)??z(f.normalMap.userData.index??0);e=t.sample(ee(r.x,r.y,a))}else e=G(f.normalMap).sample(bt(r,f.normalMap));y=k(e.rgb,g.x)}let w=Yt(u.get("roughness"),F)??z(f.roughness??1);if(null!=f.roughnessMap){let e;if(f.roughnessMap instanceof i.CompressedArrayTexture){const t=J(f.roughnessMap),a=Yt(u.get("roughnessMap"),F)??z(f.roughnessMap.userData.index??0);e=t.sample(ee(r.x,r.y,a))}else e=G(f.roughnessMap).sample(bt(r,f.roughnessMap));w=w.multiply(e.g)}let M=Yt(u.get("metalness"),F)??z(f.metalness??0);if(null!=f.metalnessMap){let e;if(f.metalnessMap instanceof i.CompressedArrayTexture){const t=J(f.metalnessMap),a=Yt(u.get("metalnessMap"),F)??z(f.metalnessMap.userData.index??0);e=t.sample(ee(r.x,r.y,a))}else e=G(f.metalnessMap).sample(bt(r,f.metalnessMap));M=M.multiply(e.b)}let b=z(1);if(null!=f.aoMap){let e;if(f.aoMap instanceof i.CompressedArrayTexture){const t=J(f.aoMap),a=Yt(u.get("aoMap"),F)??z(f.aoMap.userData.index??0);e=t.sample(ee(r.x,r.y,a))}else e=G(f.aoMap).sample(bt(r,f.aoMap));b=b.multiply(e.r)}const v=Yt(u.get("aoMapIntensity"),F)??z(f.aoMapIntensity??0);let E=y;!0!==f.userData.disableAO&&(E=N("DOUBLE_SIDED",E,e=>L(new V("gl_FrontFacing"),e,e.multiplyScalar(-1))));const O=new _({color:R({color:l,roughness:w,metalness:M,ambientOcclusion:b,ambientOcclusionIntensity:v,emissive:c,emissiveIntensity:m,normal:E}),normal:y,roughness:w,emissive:c.rgb,transparent:f.transparent,alphaTest:f.alphaTest,envMap:f.envMap,opacity:n});null!=f.envMap&&(O.uniforms.envMapIntensity={value:f.envMapIntensity},O.uniforms.envMapRotation={value:Qt(f.envMapRotation,f.envMap)}),O.envMap=f.envMap,O.side=f.side,d=O}else{d=f;for(const a of e){const e=t.get(a.id).get(a.meshUUID);if(e!=d){console.error(`Different materials in group for object ${a.id} and mesh uuid ${a.meshUUID}`,{objectMaterial:e,sourceMaterial:f});break}}}const g=new mt(l,n,r,d);for(const e of p)g.initUniform(e.name,4);for(const[e,t]of u.entries()){if(p.some(t=>t.params.includes(e)))continue;let a=1;t instanceof se||t instanceof te?a=4:t instanceof Q&&(a=2),g.initUniform(e,a,0)}for(const[e,r]of s.entries()){const s=r[0].assetId,n=c.get(e);if(null==n){console.error(`Missing single asset mesh for mesh uuid ${e} and asset id ${s}`);continue}if(null==n.geometry){console.error("Missing geometry on mesh mesh");continue}const l=g.addGeometry(n.geometry),h=a.get(s);if(null==h){console.warn("Missing batching info when configuring for asset id "+s);continue}const d=Ve(h.assetMesh)?.uuid===e,m=h.assetMesh instanceof ze&&d?h.assetMesh.collisionShapes:void 0,f=this.configureBatchedInstancedMesh(r,g,n,l,m);for(let e=0;e<f.length;e++){const a=r[e],s=f[e],n=t.get(a.id).get(a.meshUUID);for(const e of p){let t=ta.set(0,0,0,0);for(let a=0;a<e.params.length;a++){const s=n[e.params[a]];"number"==typeof s&&t.setComponent(a,s)}g.setUniformAt(e.name,s,t)}for(let e of u.keys()){if(p.some(t=>t.params.includes(e)))continue;let t=n[e];if(t instanceof o&&(t=new x(t.r,t.g,t.b)),t instanceof i.CompressedArrayTexture)t=t.userData.index??0,e+="_i";else if(t instanceof S||null==t)continue;g.setUniformAt(e,s,t)}}}return g}async createInstancedMesh(e,t){const a=Oe(t,e=>!Be(e)&&null!=e.geometry),s=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(t,_t(e[0].materialAssignments,s.materialAssignments)),a.updateMatrix();const r=a.geometry.clone(),n=a.material;let o;if(o=new i.InstancedMesh(r,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,r){const n=[];a.updateWorldMatrix(!0,!0);for(let o=0;o<e.length;o++){let c=o;t instanceof i.BatchedMesh&&(c=t.addInstance(s)),n.push(c);const h=(new i.Matrix4).compose((new x).fromArray(e[o].position),(new b).setFromEuler((new l).fromArray(e[o].rotation)),(new x).fromArray(e[o].scale)),u=(new d).copy(e[o].parentTransform).multiply(h).multiply(a.matrixWorld);t.setMatrixAt(c,u),null==t.userData.hasCollision&&(t.userData.hasCollision=[]),t.userData.hasCollision[c]=!!e[o].collisionDetection,null!=r&&(null==t.userData.collisionShapes&&(t.userData.collisionShapes=[]),t.userData.collisionShapes[c]=r)}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 Ee(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)}async resolveMaterialForAssignments(e,t){let a=e,s=null,r=null;for(const e of t??[]){if(!Lt(a,e,s,r))continue;const t=this.assets.get(e.materialId);if(null==t){console.warn("Missing material with id "+e.materialId);continue}const i=await materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!0);null!=i&&a.id!==i.id&&(s=s??Wt(a),r=r??a.name,a=i)}return a}unapplyMaterials(e){e.traverse(async e=>{if(e instanceof m)if(e.material instanceof Array)for(let t=0;t<e.material.length;t++)e.material[t]=this._originalMaterials.get(e.id+"#"+t)??e.material[t];else e.material=this._originalMaterials.get(e.id)??e.material})}updateActors(e){console.log("update actors"),this.actorTypes=e;const t=new Set(Object.values(he));Ee(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,Ee(this.scene,e=>e.userData.src?.id&&"actor"===e.userData.src.type&&this.materializedActors.has(e.userData.src?.id)&&(e.userData.src.actor?.components?.length??0)>0).forEach(async e=>{this.remove(e.userData.src),await this.materializeAndInitActor(e.userData.src)})}updateShaders(e){this.shaders=e;for(const[e,t]of It.entries())t.userData.customShaderName&&It.delete(e);this.landscapeManagers.forEach(t=>t.updateShaders(e)),Ee(this.scene,e=>!0).forEach(e=>{e.traverse(async e=>{if(e instanceof m)if(Array.isArray(e.material))for(let t=0;t<e.material.length;t++){const a=e.material[t].userData?.customShaderName;if(null!=a){const a=this.assets.get(e.material[t].userData.assetId);this.refreshMaterial(e,e.material[t],a,t)}}else{const t=e.material.userData?.customShaderName;if(null!=t){const t=this.assets.get(e.material.userData.assetId);this.refreshMaterial(e,e.material,t)}}})})}async update(e){if("sky"===e.type&&null!=this.sky&&null!=this.sky.parent)return void this.updateSky(e);if("world_env"===e.type&&null!=this.worldEnvObj)return void this.updateWorldEnv(e);const t=this.sceneObjectMap.get(e.id);if(t){let s=!1;if(t.traverseAncestors(e=>{"_hology_transform_group"===e.name&&(s=!0)}),!s){const a=this.findParent(e);null!=a&&a.uuid!=t.uuid?a.attach(t):console.error("Parent is wrong")}if("prefab"!==e.type&&"group"!==e.type){this.unapplyMaterials(t);this.inEditor&&e.hidden&&!1?t.traverse(e=>{e instanceof m&&(e.material.wireframe=!0)}):t.traverse(e=>{e instanceof m&&(e.material.wireframe=!1)})}if("asset_mesh"===e.type&&t.userData.assetId!==e.assetId){this.remove(e);const t=await this.materializeAndInitActor(e);return void this.updated$.next({object:t,source:e})}if("asset_mesh"===e.type){const a=this.assets.get(e.assetId);_t(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 o(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 o(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 if("directional"===e.light.type)this.applyDirectionalLight(e.light.directional,e);else if("ambient"===e.light.type)this.applyDirectionalAmbientLight(t,e.light.ambient,e);else if("rectArea"===e.light.type){const a=t;a.color=new o(e.light.rectArea.color),a.intensity=e.light.rectArea.intensity,null!=e.scale&&(a.width=e.scale[0],a.height=e.scale[1]),a.children.forEach(e=>{e instanceof wt&&e.update()})}}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 h?"density":"linear")!==e.fog.type;this.scene.fog=Ot(e.fog),t&&(a=this.scene).traverse(e=>{if(e instanceof m){const t=e.material;t instanceof _&&(a.fog instanceof c?(t.uniforms.fogFar.value=a.fog.far,t.uniforms.fogNear.value=a.fog.near):a.fog instanceof h&&(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 ut){const a=await prepareClassParameters(e.actor.params,null,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,[],this.actorProvider,e=>this.prefabInstanceExposedActorMap.get(e)??null);return void Object.assign(t,a)}const a=this.editorActorParamSnapshot.get(e.id);null!=a&&a===JSON.stringify(e.actor)||s||(this.remove(e),await this.materializeAndInitActor(e))}}else if("shape_mesh"===e.type){const a=await this.createMeshByShape(e.shape,t.material,e.shapeParams);t instanceof Ue&&(t.geometry=a.geometry,t.collisionShape=a.collisionShape)}if("shape_mesh"===e.type&&"landscape"!==e.shape)jt(t,e.castShadow,e.receiveShadow);else if("asset_mesh"===e.type){const a=this.assets.get(e.assetId);if(null==a)return void console.error("Asset not found",e.assetId);const s=e.receiveShadow??!!a.receiveShadow,r=e.castShadow??!!a.castShadow;jt(t,r,s)}e.name&&e.name.length>0&&(t.name=e.name),this.updated$.next({object:t,source:e})}else{const t=await this.materializeAndInitActor(e);this.updated$.next({object:t,source:e})}var a;this.renderingView.renderer.shadowMap.needsUpdate=!0}async materializeAndInitActor(e,t=this.findParent(e)){const a=await this.materialize(e,t),s=Array.from(this.materializedActors.entries()).filter(([t])=>t===e.id||t.startsWith(e.id+"/"));return await this.initActorsPostInit(s),a}findParent(e){const t=this.dataProvider.getObjects().flatMap(t=>t.id===e.id?null:Te(t,t=>t.children?.some(t=>t.id===e.id),()=>!0))[0];return null==t?this.scene:null!=t?Ee(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 o(this.scene.fog.color))}findMeshWithGeometry(e){let t;return e.traverse(e=>{e instanceof m&&e.geometry&&(t=e)}),t}applyVertexMaterials(e,t){if(null==e.vertexMaterials||0===e.vertexMaterials.length)return;let a=1;for(const t of e.vertexMaterials)a=Math.max(t.w.length,a);const s=De(e.vertexMaterials,e=>e.m);t.traverse(e=>{if(e instanceof m){if(null==e.geometry)return;if(qt(Je(e,0,!1)),a>0){qt(Je(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=Je(s,0,!0);qt(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=Je(s,4,!0);qt(e);for(const t of i)e.setX(t.i,t.w[4]??0),e.setY(t.i,t.w[5]??0),e.setZ(t.i,t.w[6]??0),e.setW(t.i,t.w[7]??0),e.needsUpdate=!0,n=!0}n&&r.add(e)}this.inEditor&&this.landscapeManagers.filter(t=>t.source.id===e.id).forEach(e=>e.queueRefreshScatter(this.renderingView.camera.position,!0,e=>r.has(e.name)))}async materialize(e,t,a=!1,s){const r=this.getNestedActorId(e.id,s);if(this.idToSceneObject.set(r,e),!this.shouldBeMaterialized(e))return;let i,n;switch(e.type){case"asset_mesh":i=await this.createFromAsset(e);break;case"shape_mesh":i=await this.createFromShape(e);break;case"light":i=await this.createLight(e);break;case"particles":i=await this.createParticleSystem(e),e.collisionDetection=!1;break;case"global_fog":this.scene.fog=Ot(e.fog),this.fixFogColor(),i=new u;break;case"sky":this.sky=et(),this.updateSky(e),i=this.sky;break;case"world_env":this.updateWorldEnv(e),i=new u,this.worldEnvObj=i;break;case"actor":({object:i,actor:n}=await this.createFromActor(e,s));break;case"group":i=new u;break;case"prefab":i=await this.createFromPrefab(e,s,t);break;case"vfx":i=await this.createFromVfx(e,s);break;default: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 or because of an error in the scene data. Scene object: id=${e.id}, name=${e.name}`)}if(null!=i){if(e.name&&e.name.length>0&&(i.name=e.name),this.applyTransform(e,i),a?i.userData._src=e:i.userData.src=e,null!=n&&(i.userData.actor=n),this.inEditor,this.inEditor,this.objectMap.set(i.uuid,e),this.sceneObjectMap.set(e.id,i),e.physics?.type!==pe.dynamic||null==t||this.inEditor?null==t?this.scene.add(i):null==t||"actor"!==e.type||this.inEditor?t?.add(i):(t.add(i),this.scene?.attach(i),console.log(i)):(t.add(i),i.getWorldPosition(i.position),i.getWorldQuaternion(i.quaternion),i.getWorldScale(i.scale),this.scene?.attach(i)),null!=e.children&&await Promise.all(e.children?.map(e=>this.materialize(e,i,a))),this.inEditor||null!=t||"asset_mesh"!=e.type&&"shape_mesh"!==e.type&&"prefab"!==e.type&&"group"!==e.type||"landscape"===e.shape||null!=e.physics?.type&&e.physics.type==pe.dynamic||Vt(i),null!=this.renderingView)return this.renderingView.renderer.shadowMap.needsUpdate=!0,i;console.warn("RenderingView not found in materializer")}}async handleSurfaceScatterSceneMutation(e){const t=this.surfaceScatterManager?.referencesSceneObject(e.id)??!1,a=await this.sceneObjectContainsSurfaceScatter(e);(t||a)&&await this.refreshSurfaceScatterPresence(!0)}async refreshSurfaceScatterPresence(e=!1){return await this.sceneContainsSurfaceScatter()?(null==this.surfaceScatterManager&&(this.surfaceScatterManager=new He(this.scene,this.dataProvider,this.renderingView,this.assetManagerService,this.assetsService)),this.surfaceScatterManager.queueRefresh(e),!0):(this.disposeSurfaceScatterManager(),!1)}disposeSurfaceScatterManager(){null!=this.surfaceScatterManager&&(this.surfaceScatterManager.clear(),this.surfaceScatterManager.stop(),this.surfaceScatterManager=void 0)}async sceneContainsSurfaceScatter(){return this.sceneObjectsContainSurfaceScatter(this.dataProvider.getObjects())}async sceneObjectsContainSurfaceScatter(e,t=[]){for(const a of e??[])if(await this.sceneObjectContainsSurfaceScatter(a,t))return!0;return!1}async sceneObjectContainsSurfaceScatter(e,t=[]){if("asset_mesh"===e.type&&(e.surfaceScatter?.meshes?.length??0)>0)return!0;if(null!=e.children&&await this.sceneObjectsContainSurfaceScatter(e.children,t))return!0;if("prefab"===e.type&&null!=e.assetId){if(t.includes(e.assetId))return!1;const a=this.assets.get(e.assetId)??await this.assetsService.getAsset(e.assetId),s=a?.prefab?.objects;if(null!=s)return this.sceneObjectsContainSurfaceScatter(s,[...t,e.assetId])}return!1}sceneReferencesPrefabAsset(e){const t=(a=[])=>{for(const s of a??[]){if("prefab"===s.type&&s.assetId===e)return!0;if(t(s.children))return!0}return!1};return t(this.dataProvider.getObjects())}async prefabAssetContainsSurfaceScatter(e){return"prefab"===e.type&&null!=e.prefab?.objects&&this.sceneObjectsContainSurfaceScatter(e.prefab.objects,[e.id])}applyTransform(e,t){null!=e.position&&t.position.fromArray(e.position),null!=e.scale&&t.scale.fromArray(e.scale),null!=e.rotation&&t.rotation.fromArray(e.rotation)}updateWorldEnv(e){this.renderingView.aoPass.enabled=e.worldEnv.ao.enabled,this.renderingView.aoPass.blendIntensity=e.worldEnv.ao.blendIntensity,this.renderingView.aoPass.updateGtaoMaterial(e.worldEnv.ao);const t=e.worldEnv.toneMapping;null!=t&&(this.renderingView.baseToneMapping=t.mapping??0,this.renderingView.baseToneMappingExposure=t.exposure??1,this.renderingView.renderer.toneMapping=this.renderingView.baseToneMapping,this.renderingView.renderer.toneMappingExposure=this.renderingView.baseToneMappingExposure);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 i.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.baseToneMapping=0,this.renderingView.baseToneMappingExposure=1,this.renderingView.renderer.toneMapping=this.renderingView.baseToneMapping,this.renderingView.renderer.toneMappingExposure=this.renderingView.baseToneMappingExposure}async updateSky(e){null!=this.sky&&(null==e?.sky?.materialId&&this.sky.material!==tt?(this.sky.material=tt,this.applySkySettings(this.sky.material)):this.sky.material.userData?.assetId!==e.sky.materialId&&this.updateSkyMaterial(e),null!=e.rotation&&this.sky.rotation.fromArray(e.rotation))}async updateSkyMaterial(e){const t=await this.assetsService.getAsset(e.sky.materialId);if(null==t)return void console.warn(`No material asset found for sky with id ${e.sky.materialId}`);const 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=i.BackSide,(e instanceof y||e instanceof i.MeshBasicMaterial||e instanceof i.ShaderMaterial)&&(e.fog=!1),e.depthTest=!1}async createComponent(e,t,a,s){const r=new vt[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??he[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 x).fromArray(e.position),(new l).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(ie,(new x).fromArray(e.position),(new l).fromArray(e.rotation),!1);try{await s.fromAsset(a)}catch(e){return console.error("Failed to create VFX asset",e),null}return s.play(),this.materializedActors.set(this.getNestedActorId(e.id,t),s),null!=s&&(s.object.userData.actor=s),s?.object}async createFromShape(e){const t=this.inEditor&&e.hidden;let a;if("landscape"==e.shape)a=this.createLandscape(e),a.traverse(e=>{e instanceof m&&this._originalMaterials.set(e.id,e.material)});else{let s=new y({name:"Default",color:new o("#aaaaaa"),visible:this.inEditor||!e.hidden,wireframe:!!t});!0===e.collider&&(s.opacity=.3,s.color.set(2517460),s.transparent=!0);const r=await this.createMeshByShape(e.shape,s,e.shapeParams);r.castShadow=e.castShadow??!0,r.receiveShadow=e.castShadow??!1,!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 u;const a=We(e.landscape.options);this.applyHeightMaps(a,e.landscape.heightMaps,!0);const s=new $e(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 Le(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(()=>Re(r),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&&Ke.includes(e)){const s=await prepareShapeParameters(a??{}),r=e+JSON.stringify(a);if(!this.geometryCache.has(r)){const t=Ze[e].geometry(s);(function(e){return null!=e.index&&e.hasAttribute("position")&&e.hasAttribute("normal")&&e.hasAttribute("uv")})(t)&&t.computeTangents(),this.geometryCache.set(r,t)}this.collisionShapeCache.has(r)||this.collisionShapeCache.set(r,Ze[e].collision(s));return new Ue(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=this.assets.get(e.assetId)??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(_t(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,jt(s,i,r),!1!==e.collisionDetection&&!1!==a.collisionDetection||(s.collisionShapes=[]),null!=e.physics&&!0!==this.inEditor&&(s.physics=e.physics),this.applyVertexMaterials(e,s),s.traverse(e=>{e instanceof m&&"computeBoundsTree"in e.geometry&&null==e.geometry.boundsTree&&e.geometry.computeBoundsTree()}),s.userData.assetId=e.assetId,s}async createFromPrefab(e,t,a){const s=await this.assetsService.getAsset(e.assetId);if(null==s)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);null==t&&(t={sceneObjectChain:[]}),t.sceneObjectChain.push(e.id);const{object:r}=await this.createFromPrefabAsset(s,t,a,e);return t.sceneObjectChain.pop(),r}async createFromPrefabAsset(e,t,a,s,r=!0){const i=new u;null!=s&&this.applyTransform(s,i),null!=a&&a.add(i),await Promise.all(e.prefab.objects.filter(e=>"global_fog"!==e.type&&"world_env"!==e.type).map(e=>this.materialize(e,i,!0,structuredClone(t))));const n=t.sceneObjectChain.join("/"),o=Array.from(this.materializedActors.entries()).filter(([e,a])=>e.startsWith(n)&&e.split("/").length-1===t.sceneObjectChain.length);let l;if(o.forEach(e=>{}),null!=e.prefab?.mainActorId){const a=t.sceneObjectChain.join("/")+"/"+e.prefab.mainActorId;l=this.materializedActors.get(a)}r||await this.initActorsPostInit(o);const c=Array.from(this.materializedActors.entries()).filter(([e,t])=>e.startsWith(n)).map(([,e])=>e);if(null!=e.prefab?.mainActorId&&null!=s){const a=t.sceneObjectChain.join("/"),s=a+"/"+e.prefab.mainActorId;this.prefabInstanceExposedActorMap.set(a,s)}return{object:i,actors:c,mainActor:l}}async createParticleSystem(e){await this.assetsService.getAsset(e.assetId);return new w}async createLight(e){if("point"===e.light.type){const t=new M(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 i.TextureLoader).load("assets/light-bulb-icon.webp"),a=new i.SpriteMaterial({map:e,alphaTest:.5}),s=new pt(a);s.scale.multiplyScalar(.6),t.add(s)}return t}if("spot"===e.light.type){const t=new i.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 w,t.target.position.set(0,-1,0),t.add(t.target),this.inEditor){const e=(new i.TextureLoader).load("assets/light-bulb-icon.webp"),a=new i.SpriteMaterial({map:e,alphaTest:.5}),s=new pt(a);s.scale.multiplyScalar(.6),t.add(s),t.add(new i.SpotLightHelper(t))}return t}if("rectArea"===e.light.type){const t=new i.RectAreaLight(e.light.rectArea.color,e.light.rectArea.intensity,e.scale?e.scale[0]:1,e.scale?e.scale[1]:1);if(this.inEditor){const e=(new i.TextureLoader).load("assets/light-bulb-icon.webp"),a=new i.SpriteMaterial({map:e,alphaTest:.5}),s=new pt(a);s.scale.multiplyScalar(.6),t.add(s);const r=new wt(t);t.add(r)}return t}return"directional"===e.light.type?(this.applyDirectionalLight(e.light.directional,e),new u):"ambient"===e.light.type?(this.applyDirectionalAmbientLight(null,e.light.ambient,e),new u):void 0}applyDirectionalAmbientLight(e,t,a){const s=this.scene.children.find(e=>e.name===Qe);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()}};xt=e([re(),t("design:paramtypes",[v,Object,Ne,Fe,fe,Array,Array,Object,Array])],xt);export{xt as SceneMaterializer};function jt(e,t,a){e.castShadow=t,e.receiveShadow=a,e.traverse(e=>{e.castShadow=t,e.receiveShadow=a})}const It=new Map,Pt=new Map,Dt=new f({color:16711935}),Ct=new Map;export async function materialFromAsset(e,t,a,s,r,i=!0){if(null==e||null==e.material)return console.error("Asset or asset material is null",e),Dt;const n=JSON.stringify(e.material)+t?._id;if(i&&It.has(n))return It.get(n);if(i&&Pt.has(n))return await Pt.get(n);const o=_materialFromAsset(n,e,t,a,s,r,i);return i?Pt.set(n,o).get(n):o}export async function _materialFromAsset(e,t,a,r,n,l,c=!0){const h={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 o(t.material.params?.color),transparent:null!=t.material.params?.opacity&&t.material.params?.opacity<1},u={};if(null!=t.material.params?.map){const e=t.material.params.map,a=await r.getAsset(e);null!=a&&(h.map=await n.getTexture(a))}let p;switch(t.material.type){case"phong":p=new g({...h,...u});break;case"water":p=Xe(h,a);break;case"grassFoliage":p=qe({color:h.color,map:h.map},a);break;case"grass":p=Ge({...h,colorTwo:new o(t.material.params.colorTwo),colorThree:new o(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":case"sprite":const e={standard:St?be:Ae,lambert:be,unlit:xe,toon:dt,layered:ct,landscape:Se,"landscape-composite":ve,"decal-unlit":st,"decal-standard":rt,sprite:s}[t.material.type]??l.find(e=>e.name==t.material.shader)?.type;if(e){try{let s=new e;const i=await prepareClassParameters(t.material?.shaderParams??{},e,r,n,null,a,l);Object.assign(s,i),p=s.build()}catch(e){console.log("Shader runtime error: "+e,e),Ct.has(t.material.shader)||Ct.set(t.material.shader,Dt.clone()),p=Ct.get(t.material.shader)}p.userData.customShaderName=t.material.shader}else console.warn("Missing shader implementation with name "+t.material.shader),p=Dt;break;default:throw new Error("Unsupported material type "+t.material.type)}return a?.csm.setupMaterial(p),c&&null!=a&&It.set(e,p),p.side=t.material.side??p.side??i.FrontSide,p.transparent=(t.material.transparent??h.transparent??!1)||p.transparent,p.alphaTest=t.material.alphaTest??p.alphaTest??0,null!=t.material.blending&&(p.blending=de[t.material.blending]??i.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 o(t.material.outlineParams.color).toArray()),null!=t.material.outlineParams.thickness&&(p.userData.outlineParameters.thickness=t.material.outlineParams.thickness))),p.userData.assetId=t.id,c&&Pt.delete(e),p}export async function prepareClassParameters(e,t,a,s,r,i,n,o,l){const c={};for(const[t,h]of Object.entries(e)){if(!1===h.override)continue;const e=await Et(t,h,a,s,r,i,n,o,void 0,void 0,l);null!=e&&(c[t]=e)}return c}export async function prepareShapeParameters(e,t,a){const s={};for(const[r,i]of Object.entries(e)){const e=await Et(r,i,t,a,null,void 0,void 0,void 0,void 0,void 0);null!=e&&(s[r]=e)}return s}const Tt=new Map;async function Et(e,t,a,s,r,i,n,c,h=t.value,u=t.type,p){if(null==t||null==h||""===h)return null;switch(u){case Ye.Array:if(Array.isArray(h)&&"element"in t)return await Promise.all(h.map(o=>Et(e,t,a,s,r,i,n,c,o,t.element,p)));break;case Ye.Number:case Ye.FloatNode:let u;if("string"==typeof h?u=parseFloat(h):"number"==typeof h&&(u=h),t.type===Ye.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=Tt.get(e);return null==t&&(t=ge(at.decode(e)),Tt.set(e,t)),t}(e.easing),r=s.sample(ye(we.energy));return B(z(t),z(a),r)}return z(u)}return u;case Ye.Texture:let d=await s.getTexture(await a.getAsset(h));return"envmap"===e.toLowerCase()&&null!=i&&(d=i.getEnvTexture(d)),d;case Ye.Sampler2DNode:const m=await a.getAsset(h);if(null!=m.texture?.textureArrayFileKey){const{texture:e,layerIndex:t}=await s.getTextureArray(m);if(e&&null!=t)return new H(null,e,z(t))}const f=await s.getTexture(m);return f?G(f):null;case Ye.Boolean:return h;case Ye.BooleanNode:return E(h);case Ye.Vector2:case Ye.Vec2Node:if("object"==typeof h){const e=h instanceof Array?(new A).fromArray(h):new A(h.x,h.y);return t.type===Ye.Vec2Node?K(e):e}return null;case Ye.Vector3:case Ye.Vec3Node:if("object"==typeof h){const e=h instanceof Array?(new x).fromArray(h):new x(h.x,h.y,h.z);return t.type===Ye.Vec3Node?ee(e):e}return null;case Ye.Color:case Ye.RgbNode:const g=new o(h);return t.type===Ye.RgbNode?U(g):g;case Ye.String:return h;case Ye.BaseActor:const y=h;if(null==r&&console.warn("Class parameters can not be prepared as actors are not passed in"),null==y)return null;if("object"==typeof y&&null!=y.type&&null!=y.id){if("actor"===y.type)return r?.get(y.id)??null;if("prefab"===y.type){const e=p?p(y.id):null;if(null!=e)return r?.get(e)??null;const t=[];for(const[e,a]of r?.entries()??[])e.startsWith(y.id+"/")&&t.push(a);return 1===t.length?t[0]:null}}if("string"==typeof y){const e=r?.get(y);if(null!=e)return e;const t=p?p(y):null;if(null!=t)return r?.get(t)??null;const a=[];for(const[e,t]of r?.entries()??[])e.startsWith(y+"/")&&a.push(t);return 1===a.length?a[0]:null}return null;case Ye.Euler:const w=h;return(new l).fromArray(w);case Ye.Object3D:{const e=await a.getAsset(h);return(await s.getMesh(e,{applyMaterials:!0})).scene}case Ye.Material:{if(null==h)return null;const e=await a.getAsset(h);return null==e?(console.warn("Material asset not found for material parameter",h),null):null==e.material?(console.warn("Using a non-material asset for material parameter"),null):await materialFromAsset(e,i,a,s,n)}case Ye.AudioBuffer:return await s.getAudio(await a.getAsset(h));case Ye.VisualEffect:const M=await a.getAsset(h);if(null==c){console.error("Can not create instance of visual effect because missing actor provider");break}if("vfx"in M)return new ne(c,M);console.error("Using a non-vfx asset for visual effect parameter");break;case Ye.Prefab:{const e=await a.getAsset(h);return null==e?(console.error("Using a non-prefab asset for prefab parameter",h),null):new oe(e)}case Ye.PrefabActor:{const e=await a.getAsset(h);return null==e?(console.error("Using a non-prefab asset for prefab parameter",h),null):new le(new oe(e))}case Ye.Sequence:{const e=await a.getAsset(h);if("sequence"===e.type&&"sequence"in e)return new Mt(e.sequence);console.error("Using a non-sequence asset for sequence parameter");break}case Ye.Curve:return at.decode(h);case Ye.ColorLayer:case Ye.MaskLayer:if(ht(h)){const e=await it.decode(h,async e=>await s.getTexture(await a.getAsset(e))),t=await prepareClassParameters(h.params,null,a,s);return Object.assign(e,t),e}return console.warn("Expecting color layer but got",h),null;case Ye.AnimationClip:{const e="string"==typeof h?h:"object"==typeof h&&null!=h?h.assetId:null;if(null==e)return console.warn("Invalid animation clip asset id value",h),null;return await s.getAnimationClip(await a.getAsset(e))}}return null}function Vt(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 Ot(e){return"linear"===e.type?new c(new o(e.color),e.near??100,e.far??1e3):"density"===e.type?new h(e.color,e.density):void console.warn("Invalid fog type",e)}new y({color:4229780});async function kt(e,t,a,s){null==s&&(s=(new d).identity());const r=s.clone().multiply(zt(e,new i.Matrix4));if(null!=e.children&&e.children.length>0)for(let a=e.children.length-1;a>=0;a--)await kt(e.children[a],t,e,r);await t(e,a,s)}function zt(e,t){return null==e.position||null==e.rotation||null==e.scale?t.identity():t.compose((new x).fromArray(e.position),(new b).setFromEuler((new l).fromArray(e.rotation)),(new x).fromArray(e.scale))}export function toSerializedParamType(e){const t=e.constructor.prototype;return t instanceof Number||e===Number?Ye.Number:t instanceof F||"function"==typeof e.prototype.isFloat?Ye.FloatNode:t instanceof S||e===S||e.isTexture?Ye.Texture:t instanceof Me||e===q?Ye.Sampler2DNode:t instanceof Boolean||e===Boolean?Ye.Boolean:t instanceof O?Ye.BooleanNode:t instanceof o||e==o?Ye.Color:t instanceof W||"function"==typeof e.prototype.isRgb?Ye.RgbNode:t instanceof A||e==A?Ye.Vector2:t instanceof Q||"function"==typeof e.prototype.isVec2?Ye.Vec2Node:t instanceof x||e==x?Ye.Vector3:t instanceof te||"function"==typeof e.prototype.isVec3?Ye.Vec3Node:t instanceof String||e===String?Ye.String:t instanceof ce||e==ce||e.prototype instanceof ce||e.prototype==ce?Ye.BaseActor:t instanceof l||e==l?Ye.Euler:t instanceof w||e==w?Ye.Object3D:t instanceof p||e==p?Ye.Material:t instanceof AudioBuffer||e==AudioBuffer?Ye.AudioBuffer:t instanceof ne||e==ne?Ye.VisualEffect:t instanceof oe||e==oe?Ye.Prefab:t instanceof le||e==le?Ye.PrefabActor:t instanceof at||e==at?Ye.Curve:t instanceof it||e==it?Ye.ColorLayer:t instanceof lt||e==lt?Ye.MaskLayer:t instanceof i.AnimationClip||e==i.AnimationClip?Ye.AnimationClip:t instanceof Mt||e==Mt||"SequenceData"===e.name||e.prototype&&"tracks"in e.prototype?Ye.Sequence:void console.warn("Failed to map parameter type to serialized version",{type:e})}export function prepareCustomParams(e,t,a={}){return Object.fromEntries(e.map(e=>{const s=e.options.array?Ye.Array:toSerializedParamType(e.type),r=e.options.array?toSerializedParamType(e.type):void 0,i=t[e.name];let n=i?.override;void 0===n&&null!=i&&!0===e.options.optional&&(n=!0),void 0===n&&!0===e.options.optional&&(n=!1);const o=function(e,t){if(void 0!==t[e.name])return t[e.name];if(void 0!==e.options.defaultValue){const t=serializeCustomParameter(e.type,e.options.defaultValue);return void 0!==t?t:e.options.defaultValue}return customParameterDefaultValueByType.get(toSerializedParamType(e.type))}(e,a),l=!1!==n||e.options.array?i?.value??(e.options.array?[]:Bt(o)):Bt(o);return[e.name,{type:s,...r?{element:r}:{},value:l,override:n}]}))}function Ft(e){return null!=e&&(!1!==e.override&&(!0===e.override||function(e){return null!=e&&(e.type===Ye.Array?Array.isArray(e.value)?e.value.length>0:null!=e.value:null!=e.value&&""!==e.value)}(e)))}function Nt(e){return null==e?{}:Object.fromEntries(Object.entries(e).filter(([,e])=>Ft(e)))}export function prepareCustomParamsFromType(e,t,a=null){const s=je(e);if(0===s.length)return{};let r;null!=a?me(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)}function Bt(e){return null==e?e:Array.isArray(e)?e.map(e=>Bt(e)):"object"==typeof e?"function"==typeof structuredClone?structuredClone(e):JSON.parse(JSON.stringify(e)):e}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 x:return t instanceof x?t.toArray():void a();case j:return t instanceof j?t.toArray():void a();case o:return t instanceof o?"#"+t.getHexString():"string"==typeof t?t:"number"==typeof t?"#"+new o(t).getHexString():void a();case String:return t;case l:return t instanceof l?t.toArray():void a();case oe:return t instanceof oe?t.asset?.id??null:void a()}if(t&&"object"==typeof t&&"tracks"in t&&"duration"in t)return t}function _t(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=>Ut(e.materialId)),(t??[]).filter(e=>Ut(e.materialId)),e=>e.color+e.name)}function Ut(e){return"null"!=e&&null!=e}export const customParameterDefaultValueByType=new Map([[Ye.RgbNode,"#000000"],[Ye.Color,"#000000"],[Ye.Vector4,[0,0,0,0]],[Ye.Vec4Node,[0,0,0,0]],[Ye.Vector3,[0,0,0]],[Ye.Vec3Node,[0,0,0]],[Ye.Vector2,[0,0]],[Ye.Vec2Node,[0,0]],[Ye.Euler,[0,0,0,"XYZ"]],[Ye.Array,[]],[Ye.ColorLayer,nt],[Ye.MaskLayer,ot]]);let $t=new o;new o;function Wt(e){return null==e?.color?null:($t.set(e.color),"#"+$t.getHexString())}function Lt(e,t,a,s){const r=Wt(e);return null!=r&&(r===t.color&&(e.name===t.name||null==t.name)||a===t.color&&s===t.name)}export function applyMaterial(e,t,a,s){const r=[];return e.traverse(async e=>{if(e instanceof m||e.isMesh||e instanceof i.SkinnedMesh||e.isSkinnedMesh)for(const t of Ce(e.material))t.hasOwnProperty("color")&&r.push(e)}),Promise.all(r.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 o))continue;const n=Wt(i),l=i.name;if(Lt(i,t,e.userData["originalColor_"+r],e.userData["originalMaterialName_"+r])){const i=await a(t.materialId),o=e.material[r];null!=i&&o.id!=i.id&&(e.material[r]=i,e.userData["originalColor_"+r]=e.userData["originalColor_"+r]??n,e.userData["originalMaterialName_"+r]=e.userData["originalMaterialName_"+r]??l,null!=s&&s.set(e.id+"#"+r,o))}}else if("color"in e.material){const r=e.material,i=Wt(r),n=r.name;if(Lt(r,t,e.userData.originalColor,e.userData.originalMaterialName)){const r=await a(t.materialId),o=e.material;null!=r&&(e.material=r,e.userData.originalColor=e.userData.originalColor??i,e.userData.originalMaterialName=e.userData.originalMaterialName??n,null!=s&&(s.has(e.id)||s.set(e.id,o)))}}}))}function Rt(e,t){if(e instanceof i.ShaderMaterial&&t instanceof i.ShaderMaterial){return e.fragmentShader+e.vertexShader==t.fragmentShader+t.vertexShader&&function(e,t){if(e instanceof i.ShaderMaterial&&t instanceof i.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 qt(e){if(null!=e){for(let t=0;t<e.array.length;t++)e.setX(t,0);e.needsUpdate=!0}}const Gt=new WeakMap;function Jt(e){let t=Gt.get(e);return null==t&&(t=function(e){const t=Ve(e);if(null==t)return"";return Object.keys(t.geometry.attributes).sort().join(",")}(e),Gt.set(e,t)),t}const Ht=new WeakMap;function Xt(e){let t=Ht.get(e);return null==t&&(t=function(e){let t=e.type;e instanceof i.MeshStandardMaterial&&!(e instanceof i.MeshPhysicalMaterial)||(t+=e.id+"");(e instanceof i.MeshBasicMaterial||e instanceof i.MeshLambertMaterial||e instanceof y||e instanceof g)&&(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 y&&(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 i.MeshPhysicalMaterial&&(null!=e.sheenColorMap&&(t+="sc"+e.sheenColorMap?.id),null!=e.sheenRoughnessMap&&(t+="sr"+e.sheenRoughnessMap?.id));(e instanceof f||e instanceof g)&&null!=e.specularMap&&(t+="s"+e.specularMap?.id);e instanceof i.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 ft&&null!=e.heightMap&&(t+="h"+e.heightMap?.id);if(e instanceof i.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.vertexColors?"vc":"",t+=e.depthWrite?"dw":"",t+=e.depthTest?"dt":"",t+=e.alphaTest?"at":"",t}(e),Ht.set(e,t)),t}function Yt(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 Zt=new d,Kt=new l;function Qt(e,t){return Kt.copy(e),Kt.x*=-1,Kt.y*=-1,Kt.z*=-1,t.isCubeTexture&&!1===t.isRenderTargetTexture&&(Kt.y*=-1,Kt.z*=-1),(new i.Matrix3).setFromMatrix4(Zt.makeRotationFromEuler(Kt))}function ea(e,t){switch(t){case 0:return e.x;case 1:return e.y;case 2:return e.z;case 3:return e.w}}const ta=new j;function aa(e,t){return e===t||null==e==(null==t)&&("number"==typeof e&&"number"==typeof t?e===t||isNaN(e)&&isNaN(t):e instanceof i.Color&&t instanceof i.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 x&&t instanceof x?e.x===t.x&&e.y===t.y&&e.z===t.z:e instanceof j&&t instanceof j&&(e.x===t.x&&e.y===t.y&&e.z===t.z&&e.w===t.w))}function sa(e){const t=[];for(const[a,s]of Object.entries(e))s instanceof ne?t.push(s):s instanceof ue&&t.push(...sa(s));return t}function ra(e,t){if(!(t instanceof i.ShaderMaterial)){if(e.deleteAttribute("uv1"),e.hasAttribute("color")){const t=e.getAttribute("color");let a=!0;for(let e=0;e<t.count;e++)for(let s=0;s<3;s++){if(1!=t.getComponent(e,s)){a=!1;break}}a&&e.deleteAttribute("color")}if(e.hasAttribute("uv2")){null!=t.lightMap&&null!=t.aoMap||e.deleteAttribute("uv2")}}}function ia(e,t,a){if(t(e))return e;for(const s of e.children??[]){const e=ia(s,t,a);if(null!=e)return e}if(null!=a&&"prefab"===e.type){const s=a.get(e.assetId);if(null!=s){const e=s.prefab.objects.find(e=>ia(e,t,a));if(null!=e)return e}}return null}/*
1
+ import{__decorate as e,__metadata as t}from"tslib";import{ConvexPolyhedronCollisionShape as a,SpriteShader as s}from"@hology/core";import{Subject as r}from"rxjs";import*as i from"three";import{BoxGeometry as n,Color as o,Euler as l,Fog as c,FogExp2 as h,Group as u,Material as p,Matrix4 as d,Mesh as m,MeshLambertMaterial as f,MeshPhongMaterial as g,MeshStandardMaterial as y,Object3D as w,PointLight as v,Quaternion as M,Scene as b,Texture as S,Vector2 as A,Vector3 as x,Vector4 as I}from"three";import{attributes as j,batchingUniformFloat as P,batchingUniformVec2 as D,batchingUniformVec3 as C,batchingUniformVec4 as T,bool as V,BooleanExpression as E,BooleanNode as O,colorToNormal as k,float as N,FloatNode as z,ifDefApply as F,mix as B,NodeShaderMaterial as _,rgb as U,rgba as $,RgbNode as G,select as W,standardMaterial as L,Texture2dLookupNode as R,textureSampler2d as q,textureSampler2dArray as J,UniformBoolNode as H,UniformFloatNode as X,UniformSampler2dArraySlice as Y,UniformVec2Node as Z,UniformVec3Node as K,UniformVec4Node as Q,varying as ee,varyingAttributes as te,varyingTransformed as ae,vec2 as se,Vec2Node as re,vec3 as ie,Vec3Node as ne,vec4 as oe,Vec4Node as le}from"three-shader-graph";import{Service as ce}from"typedi";import{VfxActor as he}from"../effects/vfx/vfx-actor.js";import{VisualEffect as ue}from"../effects/vfx/vfx-param.js";import{Prefab as pe,PrefabOf as de}from"./objects/prefab.js";import{BaseActor as me}from"../gameplay/actors/actor.js";import fe from"../gameplay/actors/builtin/index.js";import{ActorComponent as ge}from"../gameplay/actors/component.js";import{PhysicsBodyType as ye}from"../gameplay/services/physics/physics-system.js";import{ThreeBlendingMode as we}from"../effects/vfx/vfx-asset.js";import{withInjectionContext as ve}from"../gameplay/inject.js";import{RenderingView as Me}from"../rendering.js";import{curveSampler as be,oneMinus as Se,particleUniforms as Ae,Sampler2DNode as xe}from"../shader-nodes/index.js";import{LambertShader as Ie}from"../shader/builtin/lambert-shader.js";import{LandscapeCompositeShader as je}from"../shader/builtin/landscape-composite-shader";import{LandscapeShader as Pe}from"../shader/builtin/landscape-shader.js";import{StandardShader as De}from"../shader/builtin/standard-shader.js";import{UnlitShader as Ce}from"../shader/builtin/unlit-shader.js";import{extractShaderParameters as Te}from"../shader/parameter.js";import{ArrayMap as Ve,DefaultMap as Ee,groupBy as Oe}from"../utils/collections.js";import{iterateMaterials as ke}from"../utils/materials.js";import{filterChildrenShallow as Ne,filterSceneShallow as ze,findFirstVisibleMesh as Fe,findFirstVisibleObject as Be,traverseAsync as _e}from"../utils/three/traverse.js";import{AssetMeshInstance as Ue,AssetResourceLoader as $e}from"./asset-resource-loader.js";import{AssetsProvider as Ge}from"./assets-provider.js";import{isCollisionMesh as We}from"./collision/collision-shape-import.js";import{BoxCollisionShape as Le,PhysicalShapeMesh as Re}from"./collision/collision-shape.js";import{LandscapeManager as qe}from"./landscape/landscape-manager.js";import{initLandscape as Je}from"./landscape/landscape.js";import{SectionGrid as He,smoothNormalsCrossMeshes as Xe}from"./landscape/utils.js";import{createGrassFoliageMaterial as Ye}from"./materials/grass-foliage.js";import{createGrassMaterial as Ze}from"./materials/grass.js";import{getMaterialAttribute as Ke}from"./materials/utils/material-painting.js";import{SurfaceScatterManager as Qe}from"./scatter/surface-scatter-manager.js";import{createWaterMaterial as et}from"./materials/water.js";import{SerializedParamType as tt}from"./model.js";import{applyRuntimeParamTypeInference as at,convertConfiguredParamsToRuntimeTypes as st,convertConfiguredParamValueToRuntimeType as rt,inferRuntimeSerializedParamTypeHint as it}from"./custom-param-runtime-types.js";import{ShapeLibrary as nt,ShapeLibraryKeys as ot}from"./objects/shapes.js";import{ambientLightName as lt,createSky as ct,defaultSkyMaterial as ht}from"./sky.js";import{Curve2 as ut}from"../utils/curve.js";import{DecalUnlitShader as pt}from"../shader/builtin/decal-unlit-shader.js";import{DecalStandardShader as dt}from"../shader/builtin/decal-standard-shader.js";import{ColorLayer as mt,defaultValueColorLayer as ft,defaultValueMaskLayer as gt,MaskLayer as yt}from"../shader/color-layer.js";import{LayeredShader as wt}from"../shader/builtin/layered-shader";import{isColorLayerSerialized as vt}from"../shader/color-layer";import{FogVolume as Mt}from"../rendering/fog/fog-volume-actor.js";import{UnscaledSprite as bt}from"../utils/three/unscaled-sprite.js";import{ToonShader as St}from"../shader/builtin/toon-shader.js";import{BatchedMesh2 as At}from"./batched-mesh-2.js";import{ParallaxStandardMaterial as xt}from"../shader/builtin/standard-shader";import{parallaxOcclusionMapping as It}from"../shader-nodes/pom.js";import{traverseVisibleEvery as jt}from"../utils/three/traverse";import{RectAreaLightHelper as Pt}from"three/examples/jsm/Addons.js";import{Sequence as Dt}from"../effects/sequence/sequence-data.js";import{applyUvTiling as Ct}from"./../shader/uv-nodes.js";import{buildShaderGraphMaterial as Tt,shaderGraphMaterialSideToThree as Vt}from"../shader/graph/index.js";export{at as applyRuntimeParamTypeInference,st as convertConfiguredParamsToRuntimeTypes,rt as convertConfiguredParamValueToRuntimeType,it as inferRuntimeSerializedParamTypeHint};const Et={},Ot=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),kt=/^((?!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 Nt(e,this.dataProvider,this.assetsService,this.assetManagerService,t,[],[],{create:()=>null,initActor:async()=>{}})}}let Nt=class{constructor(e,t,a,s,n,o,l,c,h=[]){this.scene=e,this.dataProvider=t,this.assetsService=a,this.assetManagerService=s,this.renderingView=n,this.shaders=o,this.actorTypes=l,this.actorProvider=c,this.componentTypes=h,this.objectMap=new Map,this.sceneObjectMap=new Map,this.components=[],this.landscapeManagers=[],this.materializedActors=new Map,this.idToSceneObject=new Map,this.inEditor=!0,this.updated$=new r,this.removed$=new r,this.error$=new r,this.editorActorParamSnapshot=new Map,this.assets=new Map,this._canBeInstancedCache=new Map,this._originalMaterials=new Map,this.pmremGeneratorResults=new WeakMap,this.prefabInstanceChain=[],this.prefabInstanceExposedActorMap=new Map,this.geometryCache=new Map,this.collisionShapeCache=new Map,this.assetManagerService.materialProvider=async e=>materialFromAsset(this.assets.get(e)??await this.assetsService.getAsset(e),this.renderingView,this.assetsService,this.assetManagerService,this.shaders),this.originalFog=null,t.onCreate(e=>{this.update(e),this.handleSurfaceScatterSceneMutation(e)}),t.onUpdate(e=>{this.update(e),this.handleSurfaceScatterSceneMutation(e)}),t.onRemove(e=>{this.remove(e),this.handleSurfaceScatterSceneMutation(e)}),this.createAssetSubscription=a.onCreate.subscribe(e=>{this.assets.set(e.id,e)}),this.updateSubscription=a.onUpdate.subscribe(async t=>{if(this.assets.set(t.id,t),"material"==t.type)e.traverse(e=>{if(e instanceof i.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)});else if("mesh"==t.type){this.findByAssetId(t.id).forEach(async e=>{this.remove(e.userData.src);const t=await this.materializeAndInitActor(e.userData.src);this.updated$.next({object:t,source:e.userData.src})});for(const e of this.assets.values())if("prefab"==e.type){if(!e.prefab.objects.some(e=>ga(e,e=>e.assetId==t.id,this.assets)))continue;this.findByAssetId(e.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 x,!0)}),null!=this.surfaceScatterManager&&(this.surfaceScatterManager.usesSourceAsset(t.id)||this.surfaceScatterManager.usesScatterAsset(t.id))&&this.surfaceScatterManager.queueRefresh(!0)}else if("prefab"===t.type)this.findByAssetId(t.id).forEach(e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}),(this.surfaceScatterManager?.usesPrefabAsset(t.id)||this.sceneReferencesPrefabAsset(t.id)&&await this.prefabAssetContainsSurfaceScatter(t))&&await this.refreshSurfaceScatterPresence(!0);else if("vfx"===t.type)for(const e of this.dataProvider.getObjects())await Rt(e,async e=>{"vfx"===e.type&&e.assetId===t.id&&(this.remove(e),await this.materializeAndInitActor(e))});else if("texture"===t.type)this.scene.traverse(e=>{if(e instanceof m)if(Array.isArray(e.material))for(let a=0;a<e.material.length;a++)this.refreshMaterialTextures(e,e.material[a],t,a);else this.refreshMaterialTextures(e,e.material,t)});else if("shaderGraph"===t.type){this.scene.traverse(e=>{if(e instanceof m)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)});for(const e of this.dataProvider.getObjects())await Rt(e,async e=>{if("vfx"===e.type&&null!=e.assetId){const a=this.assets.get(e.assetId);null!=a&&this.vfxAssetUsesShaderGraph(a,t.id)&&(this.remove(e),await this.materializeAndInitActor(e))}})}})}async refreshMaterialTextures(e,t,a,s){if("texture"!==a.type)return void console.error("Can not refresh material textures. Asset is not a texture",a);const r=await this.assetManagerService.getTexture(a);if(null!=r)if(t instanceof i.ShaderMaterial)for(const[e,s]of Object.entries(t.uniforms))s.value instanceof i.Texture&&s.value.userData.assetId===a.id&&(t.uniforms[e].value=r);else for(const[e,s]of Object.entries(t))s instanceof i.Texture&&s.userData.assetId===a.id&&(t[e]=r);else console.error("Can not refresh material textures. Texture not found",a)}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&&("shaderGraph"===a.type&&"asset"===e.material?.shaderGraph?.source&&e.material.shaderGraph.assetId===a.id&&(t=!0),!t&&null!=e.material?.shaderParams))for(const s of Object.values(e.material.shaderParams)){if(s.type===tt.Material&&s.value===a.id){t=!0;break}if(s.type===tt.Array&&"element"in s&&s.element===tt.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?ta(e.material[s],i)||(e.material[s]=i):ta(e.material,i)||(e.material=i,e===this.sky&&this.applySkySettings(e.material))}vfxAssetUsesShaderGraph(e,t){return null!=e.vfx&&e.vfx.emitters.some(e=>this.emitterUsesShaderGraph(e,t))}emitterUsesShaderGraph(e,t){const a=e.output;return"shaderGraph"===a.materialSource&&"asset"===a.shaderGraph?.source&&a.shaderGraph.assetId===t||!!e.children&&e.children.some(e=>this.emitterUsesShaderGraph(e,t))}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===tt.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(),Bt.clear(),await this.prefetchAssets(),await Promise.all(this.dataProvider.getObjects().map(e=>this.materialize(e))),await this.initActorsPostInit(),await this.refreshSurfaceScatterPresence(!0)}async initVfx(){console.time("Init VFX");const e=new Set,t=[],a=new b;for(const s of this.actorInstances){const r=ma(s);for(const s of r){const r=s.asset;if(e.has(r.id))continue;e.add(r.id),r.vfx.emitters;const i=await s.create(a);a.add(i.object),a.add(i.particleSystemContainer),i.play(),i.onUpdate(.5),i.stop(),i.pause(),t.push(i)}}const s=this.renderingView.compileAsync(a);this.renderingView.initTextures(a),await s;for(const e of t)e.onEndPlay(),e.disposed.next(!0),e.object.removeFromParent();console.timeEnd("Init VFX")}async initActorsPostInit(e=Array.from(this.materializedActors.entries())){const t=e.map(async([e,t])=>{const a=t.object.userData.src??t.object.userData._src;if("vfx"===a.type)return Promise.resolve();const s=await this.assetsService.getAsset(a.assetId),r=e.split("/"),i=r.slice(0,-1),n=i.join("/"),o=(r[r.length-1],new Map);for(const[e,t]of this.materializedActors)if(o.set(e,t),0===n.length)e.includes("/")||o.set(e,t);else if(e.startsWith(n+"/")){const a=e.slice(n.length+1);a.includes("/")||o.set(a,t)}const l={...s?.actor?.params??{},...a.actor?.params??{}},c=[...a.actor?.innerParams??[]];for(let t=i.length-1;t>=0;t--){const a=i.slice(0,t+1).join("/"),s=this.idToSceneObject.get(a);if("prefab"===s?.type&&null!=s.prefab){const i=await this.assetsService.getAsset(s.assetId);if(null!=i){let n=!1,o=a+"/"+i.prefab?.mainActorId;for(;null!=o;){if(o===e){n=!0;break}o=this.prefabInstanceExposedActorMap.get(o)}if(n&&null!=s.prefab.params&&Object.assign(l,Ht(s.prefab.params)),null!=s.prefab.innerParams)for(const e of s.prefab.innerParams){const a=r.slice(t+1);e.path.length>=a.length&&e.path.slice(0,a.length).every((e,t)=>e===a[t])&&c.push({path:e.path.slice(a.length),params:e.params})}}}}for(const e of c)await this.applyActorComponentParams(t,e.path.slice(),e.params,o);await this.attachEditorComponents(t,a,o);const h=await prepareClassParameters(l,t.constructor,this.assetsService,this.assetManagerService,o,this.renderingView,this.shaders,this.actorProvider,e=>{const t=n.length>0?n+"/"+e:e;return this.prefabInstanceExposedActorMap.get(t)??null},t);Object.assign(t,h);try{return await this.actorProvider.initActor(t)}catch(e){console.error(`Failed to initiate actor (name="${a.name}", id=${a.id})`,e)}});return Promise.all(t)}async attachEditorComponents(e,t,a){const s=t.actor?.components??[];for(const r of s){const s=this.componentTypes.find(e=>e.name===r.type);if(null==s){console.warn(`Component type '${r.type}' not found for actor ${t.id}`);continue}const i=e.attach(s.type);if(null!=r.params){const e=await prepareClassParameters(r.params,null,this.assetsService,this.assetManagerService,a,this.renderingView,this.shaders,this.actorProvider,e=>this.prefabInstanceExposedActorMap.get(e)??null,i);Object.assign(i,e)}for(const e of r.innerParams??[])await this.applyActorComponentParams(i,e.path.slice(),e.params,a)}}addVfxChildActors(e,t=e){}async applyActorComponentParams(e,t,a,s){const r=t.length,i=t.shift();if(0==r){const t=await prepareClassParameters(a,null,this.assetsService,this.assetManagerService,s,this.renderingView,this.shaders,this.actorProvider,e=>this.prefabInstanceExposedActorMap.get(e)??null,e);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!==ye.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=>{!We(e)&&e.isMesh&&s.push(e)});const r=1==s.length&&0==s[0].children.length,i=!kt,n=s.every(e=>!Array.isArray(e.material)||1===e.material.length),o=s.some(e=>e instanceof m&&null!=e.geometry.morphAttributes&&Object.keys(e.geometry.morphAttributes).length>0),l=!0;t=s.length>0&&(r||n&&i)&&l&&!o,this._canBeInstancedCache.set(e.assetId,t)}return t}async preInit(){this.renderingView?.onLoop(()=>{null!=this.sky&&this.renderingView.camera.getWorldPosition(this.sky.position)}),this.assetsService.getAssets().then(e=>{for(const t of e)this.assets.set(t.id,t)})}shouldBeMaterialized(e){if(!1===e.enabled)return!1;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(),Bt.clear();const e=[],t=new Ve,a=new Ve,s=new Ve;let r=0,n=0,c=0;const h=new Map,u=new Ee(()=>new Map);for(const i of this.dataProvider.getObjects())await Rt(i,async(i,l,p)=>{if(!this.shouldBeMaterialized(i))return;const d="asset_mesh"==i.type&&this.canObjectBeInstanced(i)&&await this.canAssetBeInstanced(i),f="shape_mesh"===i.type&&"landscape"!==i.shape&&i.physics?.type!==ye.dynamic;if(d||f){if(l&&l.children?.length>0){const e=l.children.findIndex(e=>e.id===i.id);e>=0&&l.children.splice(e,1)}if(f){let e=i.shape+JSON.stringify(i.shapeParams??{})+i.castShadow+i.receiveShadow;const t=i.materialAssignments?.at(0)?.materialId,a=null!=t?this.assets.get(t):null;let r=null;if(!1&&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===tt.Color&&null!=e.value&&(r=new o(e.value))}}e+=a.material.outlines,null!=a.material.outlineParams&&(e+=JSON.stringify(a.material.outlineParams)),e+=a.material.reflective,e+=a.material.bloom,e+=a.material.side,e+=a.material.side,e+=a.material.transparent,e+=a.material.alphaTest}else e+=t;s.push(e,{object:{...i,parentTransform:p},color:r}),c++}else{const e=this.assets.get(i.assetId);let s=h.get(i.assetId);if(null==s){const e=await this.createFromAsset(i,{assignMaterials:!1});if(null==e)return;if(s=h.get(i.assetId),null==s){s={useBatchedMesh:null!=Fe(e)&&jt(e,e=>!(e instanceof m)||this.testCanBatch(e.material,e.geometry)),assetMesh:e},h.set(i.assetId,s)}}const o=Yt(i.materialAssignments,e.materialAssignments);if(s.useBatchedMesh)await _e(s.assetMesh,async e=>{if(!(e instanceof m))return;const t=Array.isArray(e.material)?e.material[0]:e.material,s=await this.resolveMaterialForAssignments(t,o);if(null!=s){u.get(i.id).set(e.uuid,s),fa(e.geometry,s);let t=na(s);t+=ra(e),a.push(t,{...i,parentTransform:p,meshUUID:e.uuid}),r++}else console.warn("Can not materialize mesh because missing material",i)});else{const e=i.assetId+JSON.stringify(i.materialAssignments??[]);t.push(e,{...i,parentTransform:p}),n++}}}else null==l&&e.push({...i,parentTransform:p})});console.log(`Scene init stats: \n Batched Assets: ${a.size} groups containing in total ${r} objects.\n Instanced Assets: ${t.size} groups containing in total ${n} 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,t]of a.entries()){if(0==t.length)continue;let e;h.get(t[0].assetId).assetMesh;e=this.createBatchedMesh(t,u,h);const a=this.assets.get(t[0].assetId);e.castShadow=t[0].castShadow??a.castShadow??!0,e.receiveShadow=t[0].receiveShadow??a.receiveShadow??!0;const s=new Ue;s.add(e),s.userData.src=t[0],s.castShadow=!1,s.receiveShadow=!1,this.scene.add(s)}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 Ue;r.add(t),r.userData.src=e[0],a instanceof Ue&&(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=Be(a,e=>!We(e)&&null!=e.geometry),r=s.material.clone();null!=e[0].color&&null!=r.color&&(r.color=new o(16777215));const n=s.geometry;let c,h;!(kt||r instanceof _||null==n.index)?(c=new i.BatchedMesh(e.length,n.getAttribute("position").count,n.index.count,r),c.perObjectFrustumCulled=!0,h=c.addGeometry(n)):c=new i.InstancedMesh(n,r,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 i.Matrix4).compose((new x).fromArray(a.object.position),(new M).setFromEuler((new l).fromArray(a.object.rotation)),(new x).fromArray(a.object.scale)),r=(new d).copy(a.object.parentTransform).multiply(s);let n;n=c instanceof i.BatchedMesh?c.addInstance(h):t,c.setMatrixAt(n,r),a.color}for(let t=0;t<e.length;t++){const s=e[t],r=new Ue;r.userData.src=e[0],a instanceof Re&&(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(),await this.initVfx(),await this.refreshSurfaceScatterPresence(!0)}prepareCollisionShapesForInstanced(e){e instanceof Ue&&e.collisionShapes.forEach(e=>{e instanceof a&&e.mesh instanceof m&&(e.mesh=e.mesh.geometry)})}testCanBatch(e,t){return!kt&&(!Array.isArray(e)||1==e.length)&&this.testCanBatchMaterial(e)}testCanBatchMaterial(e){return null!=(Array.isArray(e)?e[0]:e)}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 r=0,n=0,l=0;const c=new Map;for(const[e,t]of s.entries()){const s=t[0].assetId,i=a.get(s);if(null==i){console.warn("Missing batching info for asset id "+s);continue}const o=Be(i.assetMesh,t=>t instanceof m&&t.uuid===e);if(null==o){console.warn("Missing mesh in batched asset");continue}c.set(e,o);const h=o.geometry.getAttribute("position");null==h&&console.warn("Missing position attribute for batched mesh"),r+=o.geometry.index.count*t.length,n+=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 u=new Map;const p=[];let d=new i.MeshStandardMaterial({color:"white"});const f=t.get(e[0].id).get(e[0].meshUUID);if(null==f)throw"missing source material";if(f instanceof y&&!(f instanceof i.MeshPhysicalMaterial)){const a=new Set,s=new Map;for(const r of e){const e=t.get(r.id).get(r.meshUUID);if(null==e)throw"missing mat";for(const t of h){let r=e[t];r instanceof i.CompressedArrayTexture&&null!=r.userData.index&&(r=r.userData.index);const n=s.get(t);void 0===n||da(r,n)?s.set(t,r):a.add(t)}}for(const e of a){let t;const a=f[e];if("number"==typeof a){let a=p.find(e=>e.params.length<4);if(null==a){const t="vp"+p.length;a={name:t,params:[e],node:T(t)},p.push(a)}else a.params.push(e);t=ua(a.node,a.params.length-1)}else if(a instanceof I)t=T(e);else if(a instanceof x||a instanceof o)t=C(e);else if(a instanceof A)t=D(e);else if(a instanceof i.CompressedArrayTexture)t=P(e+"_i");else if(a instanceof S)continue;u.set(e,t)}let r=te.uv;f instanceof xt&&null!=f.heightMap&&(r=It(r,q(f.heightMap),N(f.heightScale)));let n=oa(u.get("opacity"),z)??N(f.opacity??1);if(null!=f.alphaMap){let e;if(f.alphaMap instanceof i.CompressedArrayTexture){const t=J(f.alphaMap),a=oa(u.get("alphaMap"),z)??N(f.alphaMap.userData.index??0);e=t.sample(ie(r.x,r.y,a))}else e=q(f.alphaMap).sample(r);n=n.multiply(e.r)}let l=$(oa(u.get("color"),ne)??f.color,n);if(null!=f.map){let e;if(f.map instanceof i.CompressedArrayTexture){const t=J(f.map),a=oa(u.get("map"),z)??N(f.map.userData.index??0);e=t.sample(ie(r.x,r.y,a))}else e=q(f.map).sample(Ct(r,f.map));l=l.multiply(e),n=n.multiply(e.a)}f.vertexColors&&(l=l.multiply(oe(ee(j.color.rgb),1)));let c=$(oa(u.get("emissive"),ne)??f.emissive,n);if(null!=f.emissiveMap){let e;if(f.emissiveMap instanceof i.CompressedArrayTexture){const t=J(f.emissiveMap),a=oa(u.get("emissiveMap"),z)??N(f.emissiveMap.userData.index??0);e=t.sample(ie(r.x,r.y,a))}else e=q(f.emissiveMap).sample(Ct(r,f.emissiveMap));c=c.multiply(e)}const m=oa(u.get("emissiveIntensity"),z)??N(f.emissiveIntensity??1),g=oa(u.get("normalScale"),re)??se(f.normalScale??new A(1,1));let y=ae.normal;if(null!=f.normalMap){let e;if(f.normalMap instanceof i.CompressedArrayTexture){const t=J(f.normalMap),a=oa(u.get("normalMap"),z)??N(f.normalMap.userData.index??0);e=t.sample(ie(r.x,r.y,a))}else e=q(f.normalMap).sample(Ct(r,f.normalMap));y=k(e.rgb,g.x)}let w=oa(u.get("roughness"),z)??N(f.roughness??1);if(null!=f.roughnessMap){let e;if(f.roughnessMap instanceof i.CompressedArrayTexture){const t=J(f.roughnessMap),a=oa(u.get("roughnessMap"),z)??N(f.roughnessMap.userData.index??0);e=t.sample(ie(r.x,r.y,a))}else e=q(f.roughnessMap).sample(Ct(r,f.roughnessMap));w=w.multiply(e.g)}let v=oa(u.get("metalness"),z)??N(f.metalness??0);if(null!=f.metalnessMap){let e;if(f.metalnessMap instanceof i.CompressedArrayTexture){const t=J(f.metalnessMap),a=oa(u.get("metalnessMap"),z)??N(f.metalnessMap.userData.index??0);e=t.sample(ie(r.x,r.y,a))}else e=q(f.metalnessMap).sample(Ct(r,f.metalnessMap));v=v.multiply(e.b)}let M=N(1);if(null!=f.aoMap){let e;if(f.aoMap instanceof i.CompressedArrayTexture){const t=J(f.aoMap),a=oa(u.get("aoMap"),z)??N(f.aoMap.userData.index??0);e=t.sample(ie(r.x,r.y,a))}else e=q(f.aoMap).sample(Ct(r,f.aoMap));M=M.multiply(e.r)}const b=oa(u.get("aoMapIntensity"),z)??N(f.aoMapIntensity??0);let V=y;!0!==f.userData.disableAO&&(V=F("DOUBLE_SIDED",V,e=>W(new E("gl_FrontFacing"),e,e.multiplyScalar(-1))));const O=new _({color:L({color:l,roughness:w,metalness:v,ambientOcclusion:M,ambientOcclusionIntensity:b,emissive:c,emissiveIntensity:m,normal:V}),normal:y,roughness:w,emissive:c.rgb,transparent:f.transparent,alphaTest:f.alphaTest,envMap:f.envMap,opacity:n});null!=f.envMap&&(O.uniforms.envMapIntensity={value:f.envMapIntensity},O.uniforms.envMapRotation={value:ha(f.envMapRotation,f.envMap)}),O.envMap=f.envMap,O.side=f.side,d=O}else{d=f;for(const a of e){const e=t.get(a.id).get(a.meshUUID);if(e!=d){console.error(`Different materials in group for object ${a.id} and mesh uuid ${a.meshUUID}`,{objectMaterial:e,sourceMaterial:f});break}}}const g=new At(l,n,r,d);for(const e of p)g.initUniform(e.name,4);for(const[e,t]of u.entries()){if(p.some(t=>t.params.includes(e)))continue;let a=1;t instanceof le||t instanceof ne?a=4:t instanceof re&&(a=2),g.initUniform(e,a,0)}for(const[e,r]of s.entries()){const s=r[0].assetId,n=c.get(e);if(null==n){console.error(`Missing single asset mesh for mesh uuid ${e} and asset id ${s}`);continue}if(null==n.geometry){console.error("Missing geometry on mesh mesh");continue}const l=g.addGeometry(n.geometry),h=a.get(s);if(null==h){console.warn("Missing batching info when configuring for asset id "+s);continue}const d=Fe(h.assetMesh)?.uuid===e,m=h.assetMesh instanceof Ue&&d?h.assetMesh.collisionShapes:void 0,f=this.configureBatchedInstancedMesh(r,g,n,l,m);for(let e=0;e<f.length;e++){const a=r[e],s=f[e],n=t.get(a.id).get(a.meshUUID);for(const e of p){let t=pa.set(0,0,0,0);for(let a=0;a<e.params.length;a++){const s=n[e.params[a]];"number"==typeof s&&t.setComponent(a,s)}g.setUniformAt(e.name,s,t)}for(let e of u.keys()){if(p.some(t=>t.params.includes(e)))continue;let t=n[e];if(t instanceof o&&(t=new x(t.r,t.g,t.b)),t instanceof i.CompressedArrayTexture)t=t.userData.index??0,e+="_i";else if(t instanceof S||null==t)continue;g.setUniformAt(e,s,t)}}}return g}async createInstancedMesh(e,t){const a=Be(t,e=>!We(e)&&null!=e.geometry),s=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(t,Yt(e[0].materialAssignments,s.materialAssignments)),a.updateMatrix();const r=a.geometry.clone(),n=a.material;let o;if(o=new i.InstancedMesh(r,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,r){const n=[];a.updateWorldMatrix(!0,!0);for(let o=0;o<e.length;o++){let c=o;t instanceof i.BatchedMesh&&(c=t.addInstance(s)),n.push(c);const h=(new i.Matrix4).compose((new x).fromArray(e[o].position),(new M).setFromEuler((new l).fromArray(e[o].rotation)),(new x).fromArray(e[o].scale)),u=(new d).copy(e[o].parentTransform).multiply(h).multiply(a.matrixWorld);t.setMatrixAt(c,u),null==t.userData.hasCollision&&(t.userData.hasCollision=[]),t.userData.hasCollision[c]=!!e[o].collisionDetection,null!=r&&(null==t.userData.collisionShapes&&(t.userData.collisionShapes=[]),t.userData.collisionShapes[c]=r)}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 ze(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)}async resolveMaterialForAssignments(e,t){let a=e,s=null,r=null;for(const e of t??[]){if(!ea(a,e,s,r))continue;const t=this.assets.get(e.materialId);if(null==t){console.warn("Missing material with id "+e.materialId);continue}const i=await materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!0);null!=i&&a.id!==i.id&&(s=s??Qt(a),r=r??a.name,a=i)}return a}unapplyMaterials(e){e.traverse(async e=>{if(e instanceof m)if(e.material instanceof Array)for(let t=0;t<e.material.length;t++)e.material[t]=this._originalMaterials.get(e.id+"#"+t)??e.material[t];else e.material=this._originalMaterials.get(e.id)??e.material})}updateActors(e){console.log("update actors"),this.actorTypes=e;const t=new Set(Object.values(fe));ze(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,ze(this.scene,e=>e.userData.src?.id&&"actor"===e.userData.src.type&&this.materializedActors.has(e.userData.src?.id)&&(e.userData.src.actor?.components?.length??0)>0).forEach(async e=>{this.remove(e.userData.src),await this.materializeAndInitActor(e.userData.src)})}updateShaders(e){this.shaders=e;for(const[e,t]of Ft.entries())t.userData.customShaderName&&Ft.delete(e);this.landscapeManagers.forEach(t=>t.updateShaders(e)),ze(this.scene,e=>!0).forEach(e=>{e.traverse(async e=>{if(e instanceof m)if(Array.isArray(e.material))for(let t=0;t<e.material.length;t++){const a=e.material[t].userData?.customShaderName;if(null!=a){const a=this.assets.get(e.material[t].userData.assetId);this.refreshMaterial(e,e.material[t],a,t)}}else{const t=e.material.userData?.customShaderName;if(null!=t){const t=this.assets.get(e.material.userData.assetId);this.refreshMaterial(e,e.material,t)}}})})}async update(e){if("sky"===e.type&&null!=this.sky&&null!=this.sky.parent)return void this.updateSky(e);if("world_env"===e.type&&null!=this.worldEnvObj)return void this.updateWorldEnv(e);const t=this.sceneObjectMap.get(e.id);if(t){let s=!1;if(t.traverseAncestors(e=>{"_hology_transform_group"===e.name&&(s=!0)}),!s){const a=this.findParent(e);null!=a&&a.uuid!=t.uuid?a.attach(t):console.error("Parent is wrong")}if("prefab"!==e.type&&"group"!==e.type){this.unapplyMaterials(t);this.inEditor&&e.hidden&&!1?t.traverse(e=>{e instanceof m&&(e.material.wireframe=!0)}):t.traverse(e=>{e instanceof m&&(e.material.wireframe=!1)})}if("asset_mesh"===e.type&&t.userData.assetId!==e.assetId){this.remove(e);const t=await this.materializeAndInitActor(e);return void this.updated$.next({object:t,source:e})}if("asset_mesh"===e.type){const a=this.assets.get(e.assetId);Yt(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 o(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 o(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 if("directional"===e.light.type)this.applyDirectionalLight(e.light.directional,e);else if("ambient"===e.light.type)this.applyDirectionalAmbientLight(t,e.light.ambient,e);else if("rectArea"===e.light.type){const a=t;a.color=new o(e.light.rectArea.color),a.intensity=e.light.rectArea.intensity,null!=e.scale&&(a.width=e.scale[0],a.height=e.scale[1]),a.children.forEach(e=>{e instanceof Pt&&e.update()})}}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 h?"density":"linear")!==e.fog.type;this.scene.fog=Lt(e.fog),t&&(a=this.scene).traverse(e=>{if(e instanceof m){const t=e.material;t instanceof _&&(a.fog instanceof c?(t.uniforms.fogFar.value=a.fog.far,t.uniforms.fogNear.value=a.fog.near):a.fog instanceof h&&(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 Mt){const a=await prepareClassParameters(e.actor.params,null,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,[],this.actorProvider,e=>this.prefabInstanceExposedActorMap.get(e)??null,t);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 Re&&(t.geometry=a.geometry,t.collisionShape=a.collisionShape)}if("shape_mesh"===e.type&&"landscape"!==e.shape)zt(t,e.castShadow,e.receiveShadow);else if("asset_mesh"===e.type){const a=this.assets.get(e.assetId);if(null==a)return void console.error("Asset not found",e.assetId);const s=e.receiveShadow??!!a.receiveShadow,r=e.castShadow??!!a.castShadow;zt(t,r,s)}e.name&&e.name.length>0&&(t.name=e.name),this.updated$.next({object:t,source:e})}else{const t=await this.materializeAndInitActor(e);this.updated$.next({object:t,source:e})}var a;this.renderingView.renderer.shadowMap.needsUpdate=!0}async materializeAndInitActor(e,t=this.findParent(e)){const a=await this.materialize(e,t),s=Array.from(this.materializedActors.entries()).filter(([t])=>t===e.id||t.startsWith(e.id+"/"));return await this.initActorsPostInit(s),a}findParent(e){const t=this.dataProvider.getObjects().flatMap(t=>t.id===e.id?null:Ne(t,t=>t.children?.some(t=>t.id===e.id),()=>!0))[0];return null==t?this.scene:null!=t?ze(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 o(this.scene.fog.color))}findMeshWithGeometry(e){let t;return e.traverse(e=>{e instanceof m&&e.geometry&&(t=e)}),t}applyVertexMaterials(e,t){if(null==e.vertexMaterials||0===e.vertexMaterials.length)return;let a=1;for(const t of e.vertexMaterials)a=Math.max(t.w.length,a);const s=Oe(e.vertexMaterials,e=>e.m);t.traverse(e=>{if(e instanceof m){if(null==e.geometry)return;if(aa(Ke(e,0,!1)),a>0){aa(Ke(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=Ke(s,0,!0);aa(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=Ke(s,4,!0);aa(e);for(const t of i)e.setX(t.i,t.w[4]??0),e.setY(t.i,t.w[5]??0),e.setZ(t.i,t.w[6]??0),e.setW(t.i,t.w[7]??0),e.needsUpdate=!0,n=!0}n&&r.add(e)}this.inEditor&&this.landscapeManagers.filter(t=>t.source.id===e.id).forEach(e=>e.queueRefreshScatter(this.renderingView.camera.position,!0,e=>r.has(e.name)))}async materialize(e,t,a=!1,s){const r=this.getNestedActorId(e.id,s);if(this.idToSceneObject.set(r,e),!this.shouldBeMaterialized(e))return;let i,n;switch(e.type){case"asset_mesh":i=await this.createFromAsset(e);break;case"shape_mesh":i=await this.createFromShape(e);break;case"light":i=await this.createLight(e);break;case"particles":i=await this.createParticleSystem(e),e.collisionDetection=!1;break;case"global_fog":this.scene.fog=Lt(e.fog),this.fixFogColor(),i=new u;break;case"sky":this.sky=ct(),this.updateSky(e),i=this.sky;break;case"world_env":this.updateWorldEnv(e),i=new u,this.worldEnvObj=i;break;case"actor":({object:i,actor:n}=await this.createFromActor(e,s));break;case"group":i=new u;break;case"prefab":i=await this.createFromPrefab(e,s,t);break;case"vfx":i=await this.createFromVfx(e,s);break;default: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 or because of an error in the scene data. Scene object: id=${e.id}, name=${e.name}`)}if(null!=i){if(e.name&&e.name.length>0&&(i.name=e.name),this.applyTransform(e,i),a?i.userData._src=e:i.userData.src=e,null!=n&&(i.userData.actor=n),this.inEditor,this.inEditor,this.objectMap.set(i.uuid,e),this.sceneObjectMap.set(e.id,i),e.physics?.type!==ye.dynamic||null==t||this.inEditor?null==t?this.scene.add(i):null==t||"actor"!==e.type||this.inEditor?t?.add(i):(t.add(i),this.scene?.attach(i),console.log(i)):(t.add(i),i.getWorldPosition(i.position),i.getWorldQuaternion(i.quaternion),i.getWorldScale(i.scale),this.scene?.attach(i)),null!=e.children&&await Promise.all(e.children?.map(e=>this.materialize(e,i,a))),this.inEditor||null!=t||"asset_mesh"!=e.type&&"shape_mesh"!==e.type&&"prefab"!==e.type&&"group"!==e.type||"landscape"===e.shape||null!=e.physics?.type&&e.physics.type==ye.dynamic||Wt(i),null!=this.renderingView)return this.renderingView.renderer.shadowMap.needsUpdate=!0,i;console.warn("RenderingView not found in materializer")}}async handleSurfaceScatterSceneMutation(e){const t=this.surfaceScatterManager?.referencesSceneObject(e.id)??!1,a=await this.sceneObjectContainsSurfaceScatter(e);(t||a)&&await this.refreshSurfaceScatterPresence(!0)}async refreshSurfaceScatterPresence(e=!1){return await this.sceneContainsSurfaceScatter()?(null==this.surfaceScatterManager&&(this.surfaceScatterManager=new Qe(this.scene,this.dataProvider,this.renderingView,this.assetManagerService,this.assetsService)),this.surfaceScatterManager.queueRefresh(e),!0):(this.disposeSurfaceScatterManager(),!1)}disposeSurfaceScatterManager(){null!=this.surfaceScatterManager&&(this.surfaceScatterManager.clear(),this.surfaceScatterManager.stop(),this.surfaceScatterManager=void 0)}async sceneContainsSurfaceScatter(){return this.sceneObjectsContainSurfaceScatter(this.dataProvider.getObjects())}async sceneObjectsContainSurfaceScatter(e,t=[]){for(const a of e??[])if(await this.sceneObjectContainsSurfaceScatter(a,t))return!0;return!1}async sceneObjectContainsSurfaceScatter(e,t=[]){if("asset_mesh"===e.type&&(e.surfaceScatter?.meshes?.length??0)>0)return!0;if(null!=e.children&&await this.sceneObjectsContainSurfaceScatter(e.children,t))return!0;if("prefab"===e.type&&null!=e.assetId){if(t.includes(e.assetId))return!1;const a=this.assets.get(e.assetId)??await this.assetsService.getAsset(e.assetId),s=a?.prefab?.objects;if(null!=s)return this.sceneObjectsContainSurfaceScatter(s,[...t,e.assetId])}return!1}sceneReferencesPrefabAsset(e){const t=(a=[])=>{for(const s of a??[]){if("prefab"===s.type&&s.assetId===e)return!0;if(t(s.children))return!0}return!1};return t(this.dataProvider.getObjects())}async prefabAssetContainsSurfaceScatter(e){return"prefab"===e.type&&null!=e.prefab?.objects&&this.sceneObjectsContainSurfaceScatter(e.prefab.objects,[e.id])}applyTransform(e,t){null!=e.position&&t.position.fromArray(e.position),null!=e.scale&&t.scale.fromArray(e.scale),null!=e.rotation&&t.rotation.fromArray(e.rotation)}updateWorldEnv(e){this.renderingView.aoPass.enabled=e.worldEnv.ao.enabled,this.renderingView.aoPass.blendIntensity=e.worldEnv.ao.blendIntensity,this.renderingView.aoPass.updateGtaoMaterial(e.worldEnv.ao);const t=e.worldEnv.toneMapping;null!=t&&(this.renderingView.baseToneMapping=t.mapping??0,this.renderingView.baseToneMappingExposure=t.exposure??1,this.renderingView.renderer.toneMapping=this.renderingView.baseToneMapping,this.renderingView.renderer.toneMappingExposure=this.renderingView.baseToneMappingExposure);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 i.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.baseToneMapping=0,this.renderingView.baseToneMappingExposure=1,this.renderingView.renderer.toneMapping=this.renderingView.baseToneMapping,this.renderingView.renderer.toneMappingExposure=this.renderingView.baseToneMappingExposure}async updateSky(e){null!=this.sky&&(null==e?.sky?.materialId&&this.sky.material!==ht?(this.sky.material=ht,this.applySkySettings(this.sky.material)):this.sky.material.userData?.assetId!==e.sky.materialId&&this.updateSkyMaterial(e),null!=e.rotation&&this.sky.rotation.fromArray(e.rotation))}async updateSkyMaterial(e){const t=await this.assetsService.getAsset(e.sky.materialId);if(null==t)return void console.warn(`No material asset found for sky with id ${e.sky.materialId}`);const 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=i.BackSide,(e instanceof y||e instanceof i.MeshBasicMaterial||e instanceof i.ShaderMaterial)&&(e.fog=!1),e.depthTest=!1}async createComponent(e,t,a,s){const r=new Et[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??fe[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 x).fromArray(e.position),(new l).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(he,(new x).fromArray(e.position),(new l).fromArray(e.rotation),!1);try{await s.fromAsset(a)}catch(e){return console.error("Failed to create VFX asset",e),null}return s.play(),this.materializedActors.set(this.getNestedActorId(e.id,t),s),null!=s&&(s.object.userData.actor=s),s?.object}async createFromShape(e){const t=this.inEditor&&e.hidden;let a;if("landscape"==e.shape)a=this.createLandscape(e),a.traverse(e=>{e instanceof m&&this._originalMaterials.set(e.id,e.material)});else{let s=new y({name:"Default",color:new o("#aaaaaa"),visible:this.inEditor||!e.hidden,wireframe:!!t});!0===e.collider&&(s.opacity=.3,s.color.set(2517460),s.transparent=!0);const r=await this.createMeshByShape(e.shape,s,e.shapeParams);r.castShadow=e.castShadow??!0,r.receiveShadow=e.castShadow??!1,!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 u;const a=Je(e.landscape.options);this.applyHeightMaps(a,e.landscape.heightMaps,!0);const s=new qe(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 He(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(()=>Xe(r),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&&ot.includes(e)){const s=await prepareShapeParameters(a??{}),r=e+JSON.stringify(a);if(!this.geometryCache.has(r)){const t=nt[e].geometry(s);(function(e){return null!=e.index&&e.hasAttribute("position")&&e.hasAttribute("normal")&&e.hasAttribute("uv")})(t)&&t.computeTangents(),this.geometryCache.set(r,t)}this.collisionShapeCache.has(r)||this.collisionShapeCache.set(r,nt[e].collision(s));return new Re(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=this.assets.get(e.assetId)??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(Yt(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,zt(s,i,r),!1!==e.collisionDetection&&!1!==a.collisionDetection||(s.collisionShapes=[]),null!=e.physics&&!0!==this.inEditor&&(s.physics=e.physics),this.applyVertexMaterials(e,s),s.traverse(e=>{e instanceof m&&"computeBoundsTree"in e.geometry&&null==e.geometry.boundsTree&&e.geometry.computeBoundsTree()}),s.userData.assetId=e.assetId,s}async createFromPrefab(e,t,a){const s=await this.assetsService.getAsset(e.assetId);if(null==s)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);null==t&&(t={sceneObjectChain:[]}),t.sceneObjectChain.push(e.id);const{object:r}=await this.createFromPrefabAsset(s,t,a,e);return t.sceneObjectChain.pop(),r}async createFromPrefabAsset(e,t,a,s,r=!0){const i=new u;null!=s&&this.applyTransform(s,i),null!=a&&a.add(i),await Promise.all(e.prefab.objects.filter(e=>"global_fog"!==e.type&&"world_env"!==e.type).map(e=>this.materialize(e,i,!0,structuredClone(t))));const n=t.sceneObjectChain.join("/"),o=Array.from(this.materializedActors.entries()).filter(([e,a])=>e.startsWith(n)&&e.split("/").length-1===t.sceneObjectChain.length);let l;if(o.forEach(e=>{}),null!=e.prefab?.mainActorId){const a=t.sceneObjectChain.join("/")+"/"+e.prefab.mainActorId;l=this.materializedActors.get(a)}r||await this.initActorsPostInit(o);const c=Array.from(this.materializedActors.entries()).filter(([e,t])=>e.startsWith(n)).map(([,e])=>e);if(null!=e.prefab?.mainActorId&&null!=s){const a=t.sceneObjectChain.join("/"),s=a+"/"+e.prefab.mainActorId;this.prefabInstanceExposedActorMap.set(a,s)}return{object:i,actors:c,mainActor:l}}async createParticleSystem(e){await this.assetsService.getAsset(e.assetId);return new w}async createLight(e){if("point"===e.light.type){const t=new v(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 i.TextureLoader).load("assets/light-bulb-icon.webp"),a=new i.SpriteMaterial({map:e,alphaTest:.5}),s=new bt(a);s.scale.multiplyScalar(.6),t.add(s)}return t}if("spot"===e.light.type){const t=new i.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 w,t.target.position.set(0,-1,0),t.add(t.target),this.inEditor){const e=(new i.TextureLoader).load("assets/light-bulb-icon.webp"),a=new i.SpriteMaterial({map:e,alphaTest:.5}),s=new bt(a);s.scale.multiplyScalar(.6),t.add(s),t.add(new i.SpotLightHelper(t))}return t}if("rectArea"===e.light.type){const t=new i.RectAreaLight(e.light.rectArea.color,e.light.rectArea.intensity,e.scale?e.scale[0]:1,e.scale?e.scale[1]:1);if(this.inEditor){const e=(new i.TextureLoader).load("assets/light-bulb-icon.webp"),a=new i.SpriteMaterial({map:e,alphaTest:.5}),s=new bt(a);s.scale.multiplyScalar(.6),t.add(s);const r=new Pt(t);t.add(r)}return t}return"directional"===e.light.type?(this.applyDirectionalLight(e.light.directional,e),new u):"ambient"===e.light.type?(this.applyDirectionalAmbientLight(null,e.light.ambient,e),new u):void 0}applyDirectionalAmbientLight(e,t,a){const s=this.scene.children.find(e=>e.name===lt);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()}};Nt=e([ce(),t("design:paramtypes",[b,Object,Ge,$e,Me,Array,Array,Object,Array])],Nt);export{Nt as SceneMaterializer};function zt(e,t,a){e.castShadow=t,e.receiveShadow=a,e.traverse(e=>{e.castShadow=t,e.receiveShadow=a})}const Ft=new Map,Bt=new Map,_t=new f({color:16711935}),Ut=new Map;export async function materialFromAsset(e,t,a,s,r,i=!0){if(null==e||null==e.material)return console.error("Asset or asset material is null",e),_t;const n=JSON.stringify(e.material)+t?._id,o=i&&!("shaderGraph"===e.material.type&&"asset"===e.material.shaderGraph?.source);if(o&&Ft.has(n))return Ft.get(n);if(o&&Bt.has(n))return await Bt.get(n);const l=_materialFromAsset(n,e,t,a,s,r,o);return o?Bt.set(n,l).get(n):l}export async function _materialFromAsset(e,t,a,r,n,l,c=!0){const h={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 o(t.material.params?.color),transparent:null!=t.material.params?.opacity&&t.material.params?.opacity<1},u={};if(null!=t.material.params?.map){const e=t.material.params.map,a=await r.getAsset(e);null!=a&&(h.map=await n.getTexture(a))}let p,d,m;switch(t.material.type){case"phong":p=new g({...h,...u});break;case"water":p=et(h,a);break;case"grassFoliage":p=Ye({color:h.color,map:h.map},a);break;case"grass":p=Ze({...h,colorTwo:new o(t.material.params.colorTwo),colorThree:new o(t.material.params.colorThree)},a);break;case"shaderGraph":{const e=await async function(e,t){const a=e.material?.shaderGraph;if("local"===a?.source)return a.graph;if("asset"===a?.source){const e=await t.getAsset(a.assetId);return e?.shaderGraph??null}return e.shaderGraph??null}(t,r);if(null==e){console.warn("Missing shader graph for material "+t.name),p=_t;break}"surface"===e.target&&null!=e.materialOptions?.side&&(d=Vt(e.materialOptions.side)),"decal"===e.target?m=!1:null!=e.materialOptions?.transparent&&(m=e.materialOptions.transparent);try{const s=await prepareShaderGraphParameters(t.material?.shaderParams??{},e,r,n,a,l),i=t.shaderGraphPreviewNodeId,o=t.trailBillboard;p=Tt(e,{parameters:s,previewNodeId:i,trailBillboard:o}),p.userData.customShaderName="asset"===t.material.shaderGraph?.source?`shaderGraph:${t.material.shaderGraph.assetId}`:`shaderGraph:${t.id}`}catch(e){console.log("Shader graph runtime error: "+e,e),p=_t}break}case"standard":case"unlit":case"toon":case"layered":case"lambert":case"shader":case"landscape":case"landscape-composite":case"decal-unlit":case"decal-standard":case"sprite":const e={standard:Ot?Ie:De,lambert:Ie,unlit:Ce,toon:St,layered:wt,landscape:Pe,"landscape-composite":je,"decal-unlit":pt,"decal-standard":dt,sprite:s}[t.material.type]??l.find(e=>e.name==t.material.shader)?.type;if(e){try{let s=new e;const i=await prepareClassParameters(t.material?.shaderParams??{},e,r,n,null,a,l,void 0,void 0,s);Object.assign(s,i),p=s.build()}catch(e){console.log("Shader runtime error: "+e,e),Ut.has(t.material.shader)||Ut.set(t.material.shader,_t.clone()),p=Ut.get(t.material.shader)}p.userData.customShaderName=t.material.shader}else console.warn("Missing shader implementation with name "+t.material.shader),p=_t;break;default:throw new Error("Unsupported material type "+t.material.type)}return a?.csm.setupMaterial(p),c&&null!=a&&Ft.set(e,p),p.side=d??t.material.side??p.side??i.FrontSide,p.transparent=(m??t.material.transparent??h.transparent??!1)||p.transparent,p.alphaTest=t.material.alphaTest??p.alphaTest??0,null!=t.material.blending&&(p.blending=we[t.material.blending]??i.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 o(t.material.outlineParams.color).toArray()),null!=t.material.outlineParams.thickness&&(p.userData.outlineParameters.thickness=t.material.outlineParams.thickness))),p.userData.assetId=t.id,c&&Bt.delete(e),p}export function prepareCustomParamsFromShaderGraph(e,t={}){return Object.fromEntries((e.parameters??[]).map(e=>{const a=function(e){switch(e){case"float":return tt.FloatNode;case"boolean":return tt.BooleanNode;case"texture":return tt.Sampler2DNode;case"vec2":return tt.Vec2Node;case"vec3":return tt.Vec3Node;case"vec4":return tt.Vec4Node;case"color":return tt.RgbNode}}(e.type),s=t[e.name],r=s?.override??null!=s,i=void 0!==e.defaultValue?e.defaultValue:customParameterDefaultValueByType.get(a),n=!1===r?Xt(i):s?.value??Xt(i);return[e.name,{type:a,value:n,override:r}]}))}export async function prepareShaderGraphParameters(e,t,a,s,r,i){const n={},o=prepareCustomParamsFromShaderGraph(t,e);for(const[e,t]of Object.entries(o)){const o=await Gt(e,t,a,s,null,r,i);null!=o&&(n[e]=o)}return n}export async function prepareClassParameters(e,t,a,s,r,i,n,o,l,c){const h={},{params:u,skipped:p}=st(e,{parameterType:t,parameterTarget:c,extractPropertyParameters:Te,toSerializedParamType:toSerializedParamType});for(const e of p)console.warn(`Skipping stored parameter "${e.key}" because it could not be converted from ${tt[e.sourceType]} to ${tt[e.targetType]}`);for(const[e,t]of Object.entries(u)){if(!1===t.override)continue;const c=await Gt(e,t,a,s,r,i,n,o,void 0,void 0,l);null!=c&&(h[e]=c)}return h}export async function prepareShapeParameters(e,t,a){const s={};for(const[r,i]of Object.entries(e)){const e=await Gt(r,i,t,a,null,void 0,void 0,void 0,void 0,void 0);null!=e&&(s[r]=e)}return s}const $t=new Map;async function Gt(e,t,a,s,r,i,n,c,h=t.value,u=t.type,p){if(null==t||null==h||""===h)return null;switch(u){case tt.Array:if(Array.isArray(h)&&"element"in t)return await Promise.all(h.map(o=>Gt(e,t,a,s,r,i,n,c,o,t.element,p)));break;case tt.Number:case tt.FloatNode:let d;if("string"==typeof h?d=parseFloat(h):"number"==typeof h&&(d=h),u===tt.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=$t.get(e);return null==t&&(t=be(ut.decode(e)),$t.set(e,t)),t}(e.easing),r=s.sample(Se(Ae.energy));return B(N(t),N(a),r)}return new X("pu_"+e,d,void 0,!1)}return d;case tt.Texture:let m=await s.getTexture(await a.getAsset(h));return"envmap"===e.toLowerCase()&&null!=i&&(m=i.getEnvTexture(m)),m;case tt.Sampler2DNode:const f=await a.getAsset(h);if(null!=f.texture?.textureArrayFileKey){const{texture:e,layerIndex:t}=await s.getTextureArray(f);if(e&&null!=t)return new Y(null,e,N(t))}const g=await s.getTexture(f);return g?q(g):null;case tt.Boolean:return h;case tt.BooleanNode:return new H("pu_"+e,h,void 0,!1);case tt.Vector2:case tt.Vec2Node:if("object"==typeof h){const t=h instanceof Array?(new A).fromArray(h):new A(h.x,h.y);return u===tt.Vec2Node?new Z("pu_"+e,t,void 0,!1):t}return null;case tt.Vector3:case tt.Vec3Node:if("object"==typeof h){const t=h instanceof Array?(new x).fromArray(h):new x(h.x,h.y,h.z);return u===tt.Vec3Node?new K("pu_"+e,t,void 0,!1):t}return null;case tt.Vector4:case tt.Vec4Node:if("object"==typeof h){const t=h instanceof Array?(new I).fromArray(h):new I(h.x,h.y,h.z,h.w);return u===tt.Vec4Node?new Q("pu_"+e,t,void 0,!1):t}return null;case tt.Color:case tt.RgbNode:const y=new o(h);return u===tt.RgbNode?new K("pu_"+e,new x(y.r,y.g,y.b),void 0,!1).rgb:y;case tt.String:return h;case tt.BaseActor:const w=h;if(null==r&&console.warn("Class parameters can not be prepared as actors are not passed in"),null==w)return null;if("object"==typeof w&&null!=w.type&&null!=w.id){if("actor"===w.type)return r?.get(w.id)??null;if("prefab"===w.type){const e=p?p(w.id):null;if(null!=e)return r?.get(e)??null;const t=[];for(const[e,a]of r?.entries()??[])e.startsWith(w.id+"/")&&t.push(a);return 1===t.length?t[0]:null}}if("string"==typeof w){const e=r?.get(w);if(null!=e)return e;const t=p?p(w):null;if(null!=t)return r?.get(t)??null;const a=[];for(const[e,t]of r?.entries()??[])e.startsWith(w+"/")&&a.push(t);return 1===a.length?a[0]:null}return null;case tt.Euler:const v=h;return(new l).fromArray(v);case tt.Object3D:{const e=await a.getAsset(h);return(await s.getMesh(e,{applyMaterials:!0})).scene}case tt.Material:{if(null==h)return null;const e=await a.getAsset(h);return null==e?(console.warn("Material asset not found for material parameter",h),null):null==e.material?(console.warn("Using a non-material asset for material parameter"),null):await materialFromAsset(e,i,a,s,n)}case tt.AudioBuffer:return await s.getAudio(await a.getAsset(h));case tt.VisualEffect:const M=await a.getAsset(h);if(null==c){console.error("Can not create instance of visual effect because missing actor provider");break}if("vfx"in M)return new ue(c,M);console.error("Using a non-vfx asset for visual effect parameter");break;case tt.Prefab:{const e=await a.getAsset(h);return null==e?(console.error("Using a non-prefab asset for prefab parameter",h),null):new pe(e)}case tt.PrefabActor:{const e=await a.getAsset(h);return null==e?(console.error("Using a non-prefab asset for prefab parameter",h),null):new de(new pe(e))}case tt.Sequence:{const e=await a.getAsset(h);if("sequence"===e.type&&"sequence"in e)return new Dt(e.sequence);console.error("Using a non-sequence asset for sequence parameter");break}case tt.Curve:return ut.decode(h);case tt.ColorLayer:case tt.MaskLayer:if(vt(h)){const e=await mt.decode(h,async e=>await s.getTexture(await a.getAsset(e))),t=await prepareClassParameters(h.params,null,a,s,void 0,void 0,void 0,void 0,void 0,e);return Object.assign(e,t),e}return console.warn("Expecting color layer but got",h),null;case tt.AnimationClip:{const e="string"==typeof h?h:"object"==typeof h&&null!=h?h.assetId:null;if(null==e)return console.warn("Invalid animation clip asset id value",h),null;return await s.getAnimationClip(await a.getAsset(e))}}return null}function Wt(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 Lt(e){return"linear"===e.type?new c(new o(e.color),e.near??100,e.far??1e3):"density"===e.type?new h(e.color,e.density):void console.warn("Invalid fog type",e)}new y({color:4229780});async function Rt(e,t,a,s){null==s&&(s=(new d).identity());const r=s.clone().multiply(qt(e,new i.Matrix4));if(null!=e.children&&e.children.length>0)for(let a=e.children.length-1;a>=0;a--)await Rt(e.children[a],t,e,r);await t(e,a,s)}function qt(e,t){return null==e.position||null==e.rotation||null==e.scale?t.identity():t.compose((new x).fromArray(e.position),(new M).setFromEuler((new l).fromArray(e.rotation)),(new x).fromArray(e.scale))}export function toSerializedParamType(e){const t=e.constructor.prototype;return t instanceof Number||e===Number?tt.Number:t instanceof z||"function"==typeof e.prototype.isFloat?tt.FloatNode:t instanceof S||e===S||e.isTexture?tt.Texture:t instanceof xe||e===xe||e===R||"function"==typeof e.prototype?.isSampler2D||!0===e.prototype?.isSampler2D?tt.Sampler2DNode:t instanceof Boolean||e===Boolean?tt.Boolean:t instanceof O?tt.BooleanNode:t instanceof o||e==o?tt.Color:t instanceof G||"function"==typeof e.prototype.isRgb?tt.RgbNode:t instanceof A||e==A?tt.Vector2:t instanceof re||"function"==typeof e.prototype.isVec2?tt.Vec2Node:t instanceof x||e==x?tt.Vector3:t instanceof ne||"function"==typeof e.prototype.isVec3?tt.Vec3Node:t instanceof I||e==I?tt.Vector4:t instanceof le||"function"==typeof e.prototype.isVec4?tt.Vec4Node:t instanceof String||e===String?tt.String:t instanceof me||e==me||e.prototype instanceof me||e.prototype==me?tt.BaseActor:t instanceof l||e==l?tt.Euler:t instanceof w||e==w?tt.Object3D:t instanceof p||e==p?tt.Material:t instanceof AudioBuffer||e==AudioBuffer?tt.AudioBuffer:t instanceof ue||e==ue?tt.VisualEffect:t instanceof pe||e==pe?tt.Prefab:t instanceof de||e==de?tt.PrefabActor:t instanceof ut||e==ut?tt.Curve:t instanceof mt||e==mt?tt.ColorLayer:t instanceof yt||e==yt?tt.MaskLayer:t instanceof i.AnimationClip||e==i.AnimationClip?tt.AnimationClip:t instanceof Dt||e==Dt||"SequenceData"===e.name||e.prototype&&"tracks"in e.prototype?tt.Sequence:void console.warn("Failed to map parameter type to serialized version",{type:e})}export function prepareCustomParams(e,t,a={}){return Object.fromEntries(e.map(e=>{const s=e.options.array?tt.Array:toSerializedParamType(e.type),r=e.options.array?toSerializedParamType(e.type):void 0,i=t[e.name];let n=i?.override;void 0===n&&null!=i&&!0===e.options.optional&&(n=!0),void 0===n&&!0===e.options.optional&&(n=!1);const o=function(e,t){if(void 0!==t[e.name])return t[e.name];if(void 0!==e.options.defaultValue){const t=serializeCustomParameter(e.type,e.options.defaultValue);return void 0!==t?t:e.options.defaultValue}return customParameterDefaultValueByType.get(toSerializedParamType(e.type))}(e,a),l=!1!==n||e.options.array?i?.value??(e.options.array?[]:Xt(o)):Xt(o);return[e.name,{type:s,...r?{element:r}:{},value:l,override:n}]}))}function Jt(e){return null!=e&&(!1!==e.override&&(!0===e.override||function(e){return null!=e&&(e.type===tt.Array?Array.isArray(e.value)?e.value.length>0:null!=e.value:null!=e.value&&""!==e.value)}(e)))}function Ht(e){return null==e?{}:Object.fromEntries(Object.entries(e).filter(([,e])=>Jt(e)))}export function prepareCustomParamsFromType(e,t,a=null){const s=Te(e);if(0===s.length)return{};let r;null!=a?ve(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)}function Xt(e){return null==e?e:Array.isArray(e)?e.map(e=>Xt(e)):"object"==typeof e?"function"==typeof structuredClone?structuredClone(e):JSON.parse(JSON.stringify(e)):e}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 x:return t instanceof x?t.toArray():void a();case I:return t instanceof I?t.toArray():void a();case o:return t instanceof o?"#"+t.getHexString():"string"==typeof t?t:"number"==typeof t?"#"+new o(t).getHexString():void a();case String:return t;case l:return t instanceof l?t.toArray():void a();case pe:return t instanceof pe?t.asset?.id??null:void a()}if(t&&"object"==typeof t&&"tracks"in t&&"duration"in t)return t}function Yt(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=>Zt(e.materialId)),(t??[]).filter(e=>Zt(e.materialId)),e=>e.color+e.name)}function Zt(e){return"null"!=e&&null!=e}export const customParameterDefaultValueByType=new Map([[tt.RgbNode,"#000000"],[tt.Color,"#000000"],[tt.Vector4,[0,0,0,0]],[tt.Vec4Node,[0,0,0,0]],[tt.Vector3,[0,0,0]],[tt.Vec3Node,[0,0,0]],[tt.Vector2,[0,0]],[tt.Vec2Node,[0,0]],[tt.Euler,[0,0,0,"XYZ"]],[tt.Array,[]],[tt.ColorLayer,ft],[tt.MaskLayer,gt]]);let Kt=new o;new o;function Qt(e){return null==e?.color?null:(Kt.set(e.color),"#"+Kt.getHexString())}function ea(e,t,a,s){const r=Qt(e);return null!=r&&(r===t.color&&(e.name===t.name||null==t.name)||a===t.color&&s===t.name)}export function applyMaterial(e,t,a,s){const r=[];return e.traverse(async e=>{if(e instanceof m||e.isMesh||e instanceof i.SkinnedMesh||e.isSkinnedMesh)for(const t of ke(e.material))t.hasOwnProperty("color")&&r.push(e)}),Promise.all(r.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 o))continue;const n=Qt(i),l=i.name;if(ea(i,t,e.userData["originalColor_"+r],e.userData["originalMaterialName_"+r])){const i=await a(t.materialId),o=e.material[r];null!=i&&o.id!=i.id&&(e.material[r]=i,e.userData["originalColor_"+r]=e.userData["originalColor_"+r]??n,e.userData["originalMaterialName_"+r]=e.userData["originalMaterialName_"+r]??l,null!=s&&s.set(e.id+"#"+r,o))}}else if("color"in e.material){const r=e.material,i=Qt(r),n=r.name;if(ea(r,t,e.userData.originalColor,e.userData.originalMaterialName)){const r=await a(t.materialId),o=e.material;null!=r&&(e.material=r,e.userData.originalColor=e.userData.originalColor??i,e.userData.originalMaterialName=e.userData.originalMaterialName??n,null!=s&&(s.has(e.id)||s.set(e.id,o)))}}}))}function ta(e,t){if(e instanceof i.ShaderMaterial&&t instanceof i.ShaderMaterial){return e.fragmentShader+e.vertexShader==t.fragmentShader+t.vertexShader&&function(e,t){if(e instanceof i.ShaderMaterial&&t instanceof i.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 aa(e){if(null!=e){for(let t=0;t<e.array.length;t++)e.setX(t,0);e.needsUpdate=!0}}const sa=new WeakMap;function ra(e){let t=sa.get(e);return null==t&&(t=function(e){const t=Fe(e);if(null==t)return"";return Object.keys(t.geometry.attributes).sort().join(",")}(e),sa.set(e,t)),t}const ia=new WeakMap;function na(e){let t=ia.get(e);return null==t&&(t=function(e){let t=e.type;e instanceof i.MeshStandardMaterial&&!(e instanceof i.MeshPhysicalMaterial)||(t+=e.id+"");(e instanceof i.MeshBasicMaterial||e instanceof i.MeshLambertMaterial||e instanceof y||e instanceof g)&&(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 y&&(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 i.MeshPhysicalMaterial&&(null!=e.sheenColorMap&&(t+="sc"+e.sheenColorMap?.id),null!=e.sheenRoughnessMap&&(t+="sr"+e.sheenRoughnessMap?.id));(e instanceof f||e instanceof g)&&null!=e.specularMap&&(t+="s"+e.specularMap?.id);e instanceof i.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 xt&&null!=e.heightMap&&(t+="h"+e.heightMap?.id);if(e instanceof i.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.vertexColors?"vc":"",t+=e.depthWrite?"dw":"",t+=e.depthTest?"dt":"",t+=e.alphaTest?"at":"",t}(e),ia.set(e,t)),t}function oa(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 la=new d,ca=new l;function ha(e,t){return ca.copy(e),ca.x*=-1,ca.y*=-1,ca.z*=-1,t.isCubeTexture&&!1===t.isRenderTargetTexture&&(ca.y*=-1,ca.z*=-1),(new i.Matrix3).setFromMatrix4(la.makeRotationFromEuler(ca))}function ua(e,t){switch(t){case 0:return e.x;case 1:return e.y;case 2:return e.z;case 3:return e.w}}const pa=new I;function da(e,t){return e===t||null==e==(null==t)&&("number"==typeof e&&"number"==typeof t?e===t||isNaN(e)&&isNaN(t):e instanceof i.Color&&t instanceof i.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 x&&t instanceof x?e.x===t.x&&e.y===t.y&&e.z===t.z:e instanceof I&&t instanceof I&&(e.x===t.x&&e.y===t.y&&e.z===t.z&&e.w===t.w))}function ma(e){const t=[];for(const[a,s]of Object.entries(e))s instanceof ue?t.push(s):s instanceof ge&&t.push(...ma(s));return t}function fa(e,t){if(!(t instanceof i.ShaderMaterial)){if(e.deleteAttribute("uv1"),e.hasAttribute("color")){const t=e.getAttribute("color");let a=!0;for(let e=0;e<t.count;e++)for(let s=0;s<3;s++){if(1!=t.getComponent(e,s)){a=!1;break}}a&&e.deleteAttribute("color")}if(e.hasAttribute("uv2")){null!=t.lightMap&&null!=t.aoMap||e.deleteAttribute("uv2")}}}function ga(e,t,a){if(t(e))return e;for(const s of e.children??[]){const e=ga(s,t,a);if(null!=e)return e}if(null!=a&&"prefab"===e.type){const s=a.get(e.assetId);if(null!=s){const e=s.prefab.objects.find(e=>ga(e,t,a));if(null!=e)return e}}return null}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,9 +1,10 @@
1
1
  import { EulerOrder, Side } from 'three';
2
2
  import type { SequenceData } from '../effects/sequence/sequence-data.js';
3
- import { BlendingMode, VfxAssetData } from '../effects/vfx/vfx-asset.js';
4
- import { AttachedComponent, SceneObject } from './materializer.js';
5
- import { LibraryShapeType } from './objects/shapes.js';
6
- export type AssetType = 'mesh' | 'material' | 'shape' | 'particles' | 'light' | 'texture' | 'actor' | 'audio' | 'prefab' | 'vfx' | 'animationclip' | 'sequence';
3
+ import type { BlendingMode, VfxAssetData } from '../effects/vfx/vfx-asset.js';
4
+ import type { ShaderGraphDocument, ShaderGraphMaterialReference } from '../shader/graph/model.js';
5
+ import type { AttachedComponent, SceneObject } from './materializer.js';
6
+ import type { LibraryShapeType } from './objects/shapes.js';
7
+ export type AssetType = 'mesh' | 'material' | 'shape' | 'particles' | 'light' | 'texture' | 'actor' | 'audio' | 'prefab' | 'vfx' | 'animationclip' | 'sequence' | 'shaderGraph';
7
8
  export type ShapeType = LibraryShapeType | 'landscape';
8
9
  export type LightType = 'point' | 'spot' | 'directional' | 'ambient' | 'rectArea';
9
10
  /**
@@ -205,6 +206,11 @@ export type Asset = {
205
206
  * See builtInShaders in packages\core\src\shader\builtin\index.ts
206
207
  */
207
208
  shader?: string;
209
+ /**
210
+ * Shader graph materials can either reference a reusable shader graph asset
211
+ * or embed a local one-off graph directly in the material asset.
212
+ */
213
+ shaderGraph?: ShaderGraphMaterialReference;
208
214
  /**
209
215
  * If the material should have bloom enabled meaning that it will be included in
210
216
  * the bloom post processing effect
@@ -280,6 +286,8 @@ export type Asset = {
280
286
  };
281
287
  /** Sequence settings only for asset type sequence */
282
288
  sequence?: SequenceData;
289
+ /** Shader graph settings only for asset type shaderGraph */
290
+ shaderGraph?: ShaderGraphDocument;
283
291
  };
284
292
  export type VfxAsset = Asset & {
285
293
  vfx: VfxAssetData;
@@ -287,7 +295,7 @@ export type VfxAsset = Asset & {
287
295
  export type SequenceAsset = Asset & {
288
296
  sequence: SequenceData;
289
297
  };
290
- export type MaterialType = 'standard' | 'phong' | 'lambert' | 'shader' | 'water' | 'grass' | 'grassFoliage' | 'unlit' | 'landscape' | 'landscape-composite' | 'decal-unlit' | 'decal-standard' | 'layered' | 'toon' | 'sprite';
298
+ export type MaterialType = 'standard' | 'phong' | 'lambert' | 'shader' | 'shaderGraph' | 'water' | 'grass' | 'grassFoliage' | 'unlit' | 'landscape' | 'landscape-composite' | 'decal-unlit' | 'decal-standard' | 'layered' | 'toon' | 'sprite';
291
299
  export type MaterialParameters = {
292
300
  opacity: number;
293
301
  transparent: boolean;
package/dist/scene/sky.js CHANGED
@@ -1,4 +1,4 @@
1
- import*as e from"three";import{AmbientLight as a,FogExp2 as t}from"three";import{attributes as r,NodeShaderMaterial as o,uniforms as i,vec4 as n,varyingVec3 as s,float as h,normalize as d,rgb as m,mix as c,max as w,pow as p}from"three-shader-graph";export function basicSceneSetup(r){!function(t){new a(16777215,.5);var r=new e.HemisphereLight(16777215,273,.5*Math.PI);r.name=ambientLightName,r.position.set(0,100,0),t.add(r);new e.HemisphereLightHelper(r,10);var o=new e.DirectionalLight(16777215,.7);o.position.set(-30,50,30),o.castShadow=!0,o.shadow.mapSize.width=2048,o.shadow.mapSize.height=2048;var i=250;o.shadow.normalBias=.3,o.shadow.camera.left=-i,o.shadow.camera.right=i,o.shadow.camera.top=i,o.shadow.camera.bottom=-i,o.shadow.camera.far=500,o.shadow.bias=-5e-4;new e.DirectionalLightHelper(o,10);var n=new e.PointLight(16777215,1,50);n.castShadow=!0,n.position.set(0,40,0),n.shadow.camera.near=1,n.shadow.camera.far=60,n.shadow.bias=-.005}(r),function(e){e.fog=new t(l,f)}(r)}export const ambientLightName="default_ambient";const l=157554,f=.005;export const defaultSkyMaterial=function(){const a=h(5),t=h(.6),l=new e.Color(16777215),f=new e.Color(13431551),u=s(i.modelMatrix.multiplyVec(n(r.position,1)).xyz),g=d(u.addScalar(a)).y,S=w(p(w(g,h(0)),h(t)),h(0)),y=n(c(m(f),m(l),S),h(1)),b=new o({color:y.rgba});return b.side=e.BackSide,b.depthTest=!1,b.name="default sky",b}();export function createSky(){var a=new e.SphereGeometry(300,10,15),t=new e.Mesh(a,defaultSkyMaterial);return t.renderOrder=-999,t.raycast=()=>{},t.name="default_sky",t}/*
1
+ import*as e from"three";import{AmbientLight as a,FogExp2 as t}from"three";import{attributes as r,NodeShaderMaterial as o,uniforms as i,vec4 as n,varyingVec3 as s,float as h,normalize as d,rgb as m,mix as c,max as w,pow as p}from"three-shader-graph";export function basicSceneSetup(r){!function(t){new a(16777215,.5);var r=new e.HemisphereLight(16777215,273,.5*Math.PI);r.name=ambientLightName,r.position.set(0,100,0),t.add(r);new e.HemisphereLightHelper(r,10);var o=new e.DirectionalLight(16777215,.7);o.position.set(-30,50,30),o.castShadow=!0,o.shadow.mapSize.width=2048,o.shadow.mapSize.height=2048;var i=250;o.shadow.normalBias=.3,o.shadow.camera.left=-i,o.shadow.camera.right=i,o.shadow.camera.top=i,o.shadow.camera.bottom=-i,o.shadow.camera.far=500,o.shadow.bias=-5e-4;new e.DirectionalLightHelper(o,10);var n=new e.PointLight(16777215,1,50);n.castShadow=!0,n.position.set(0,40,0),n.shadow.camera.near=1,n.shadow.camera.far=60,n.shadow.bias=-.005}(r),function(e){e.fog=new t(l,f)}(r)}export const ambientLightName="default_ambient";const l=157554,f=.005;export const defaultSkyMaterial=function(){const a=h(5),t=h(.6),l=new e.Color(16777215),f=new e.Color(13431551),g=s(i.modelMatrix.multiplyVec(n(r.position,1)).xyz),u=d(g.addScalar(a)).y,S=w(p(w(u,h(0)),h(t)),h(0)),y=n(c(m("#"+f.getHexString()),m("#"+l.getHexString()),S),h(1)),b=new o({color:y.rgba});return b.side=e.BackSide,b.depthTest=!1,b.name="default sky",b}();export function createSky(){var a=new e.SphereGeometry(300,10,15),t=new e.Mesh(a,defaultSkyMaterial);return t.renderOrder=-999,t.raycast=()=>{},t.name="default_sky",t}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{randomUUID as e}from"../../utils/uuid.js";import{pathJoin as t}from"../../utils/files.js";import{combineLatest as a,EMPTY as i,filter as n,firstValueFrom as s,from as r,map as h,mergeAll as l,mergeMap as o,Observable as c,of as d,startWith as p,Subject as u,switchMap as f,tap as w}from"rxjs";import{sleepDelay as m}from"../../utils/async.js";const v={},y={},b={},j={};null==v.read&&window.require&&(Object.assign(v,window.require("fs")),Object.assign(y,v.promises),Object.assign(b,window.require("path")),Object.assign(j,window.require("chokidar")));const x=null!=v.existsSync;function F(){if(x){const e="--path=",t=window.process.argv.find(t=>t.startsWith(e));return t?t.substring(e.length):""}return""}const P=/^[A-Z]:/;function g(...e){return 0===e.length?"":P.test(e[0])||x?b.join(...e):t(...e)}export class ObjectStorage{get pathResources(){return g(this.path+"-resources")}constructor(e,t,a=defaultSerializer){this.name=e,this.filePathFn=t,this.serializer=a,this.basePathUpdates=new u,this.basePath=this.basePathUpdates.pipe(h(e=>g(F(),e)),w(e=>{this.path=g(e,this.name),I(this.path),this.determineIfMetaFileShouldBeCreated()})),this.loaded=s(this.basePath),this.shouldCreateIndex=!1}setBasePath(e){this.basePathUpdates.next(e)}async determineIfMetaFileShouldBeCreated(){try{(await y.readFile(g(F(),"vite.config.ts"))).toString().includes("hologyBuild")||(this.shouldCreateIndex=!0)}catch(e){console.warn("Failed to read vite config to determine if meta files should be created")}}async createFolder(e,t=""){C(),await y.mkdir(b.join(this.path,t,e),{recursive:!0})}async deleteFolderForceDangerous(e){await y.rm(b.join(this.path,e),{recursive:!0,force:!0})}async moveFolder(e,t){if(C(),""==e)return void console.warn("Can not move a folder in root");const a=b.resolve(b.join(this.path,t),b.basename(e));if(await E(a)){if(a!==b.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=b.resolve(e),i=b.resolve(t),n=b.normalize(a)+b.sep;return(b.normalize(i)+b.sep).startsWith(n)}(b.join(this.path,e),b.join(this.path,t)))throw new Error("Can not move a folder into a folder it contains");await y.rename(b.join(this.path,e),a)}}async renameFolder(e,t){await y.rename(b.join(this.path,e),b.resolve(b.dirname(b.join(this.path,e)),t))}async moveToFolder(e,t){if(C(),e.path===t)return;await this.assertObjectFilePathAvailable({...e,path:t},e.id);const a=this.privateObjectPath({...e,path:t});await y.rename(this.privateObjectPath(e),a)}getAbsolutePath(e=""){return b.join(this.path,e)}getResourceAbsolutePath(e=""){return b.join(this.pathResources,e)}watchFolders(){const e=y.readdir(this.path,{recursive:!0,withFileTypes:!0});return a([r(e),this.watchDir(this.path).pipe(n(e=>!e.filename.endsWith(".json")),p(null))]).pipe(f(([e,t])=>null!=t?r(y.readdir(this.path,{recursive:!0,withFileTypes:!0})):d(e)),h(e=>Array.from(new Set(e.filter(e=>e.isDirectory()).map(e=>b.relative(this.path,b.join(e.parentPath,e.name)).replace(/^\.$/,"")).values()))))}watch(){C();r(this.loaded).pipe(f(()=>a([this.watchDir(this.pathResources),r(this.getAll())]).pipe(n(([e])=>null!=e),o(([e,t])=>{if("change"===e.event){const a=b.basename(e.filename),i=t.filter(e=>e.fileKey===a);if(i.length>0)return r(i).pipe(o(e=>{const t=this.privateObjectRelativePath(e);return r(this.readFileIfExists(t)).pipe(h(a=>({event:"change",object:a,path:e.path,filename:t})))}))}return i}))));return r(this.loaded).pipe(f(()=>this.watchDir(this.path)),o(e=>{const t={event:e.event,path:b.dirname(e.filename).replace(/^\.$/,""),filename:b.basename(e.filename)};return e.filename.endsWith(".json")?"unlink"!==e.event?r(this.readFileIfExists(e.filename)).pipe(w(e=>{null!=e&&(null==this.cachedIndex&&(this.cachedIndex={}),this.cachedIndex[e.id]={id:e.id,name:e.name??e.id,path:e.path},this.persistIndex())}),h(e=>({object:e,...t}))):d({object:null,...t}).pipe(w(()=>{const t=Object.keys(this.cachedIndex??{}).find(t=>this.privateObjectRelativePath(this.cachedIndex[t])===e.filename);t&&this.removeIndexEntry(t)})):"change"===e.event?r(this.reloadSubdirectory(e.filename)).pipe(l(),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=g(this.path,e);try{const a=await y.readFile(t);return{...JSON.parse(a.toString()),path:b.dirname(e).replace(/^\.$/,""),filename:b.basename(e)}}catch{return console.error("Could not find file at "+t),null}}async getAll(e){if(x){await this.loaded,await I(this.path);const t=(await y.readdir(b.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 n=t.slice(e,e+a),s=await Promise.all(n.map(e=>y.readFile(g(e.parentPath,e.name)).then(t=>({...JSON.parse(t.toString()),path:b.relative(this.path,e.parentPath).replace(/^\.$/,""),filename:b.basename(e.name)}))));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(!x)return(await fetch(i)).json();return await S(i)?{...JSON.parse((await y.readFile(i)).toString()),path:a.path??"",filename:b.basename(this.privateObjectRelativePath(a))}:null}async save(e){if(C(),await this.loaded,null==e.path){const t=(await this.loadIndex())[e.id];null!=t?.path&&(e={...e,path:t.path})}return await this.assertObjectFilePathAvailable(e,e.id),await y.writeFile(this.privateObjectPath(e),this.serialize(e)),await this.addOrUpdateIndexEntry(e),e}async rename(e,t){const a={...e,name:t};await this.assertObjectFilePathAvailable(a,e.id);const i=this.privateObjectPath(e),n=this.privateObjectPath(a);try{await y.rename(i,n)}catch(e){console.error(e),console.warn("Rename failed, retrying",{currentPath:i,newPath:n}),await m(400),await y.rename(i,n)}return await this.save(a),a}async delete(e){await y.unlink(this.privateObjectPath(e)),this.removeIndexEntry(e.id)}async create(t){C(),await this.loaded,t.id=e();const a=this.privateObjectPath(t);if(await this.assertObjectFilePathAvailable(t),await E(a))throw Error(`Can not create because a file already exists at ${a}`);return await y.writeFile(a,this.serialize(t)),await this.addOrUpdateIndexEntry(t),t}prepareCreate(t){return C(),t.id=e(),t}serialize(e){return this.serializer(e)}async addOrUpdateIndexEntry(e){null==this.cachedIndex&&await this.loadIndex(),this.cachedIndex[e.id]={id:e.id,name:e.name??e.id,path:e.path},await this.persistIndex()}removeIndexEntry(e){null!=this.cachedIndex&&delete this.cachedIndex[e],this.persistIndex()}async persistIndex(){x&&this.shouldCreateIndex&&null!=this.cachedIndex&&await y.writeFile(this.indexFilePath,JSON.stringify(this.cachedIndex,null,2))}get indexFilePath(){return g(this.path,"_meta.json")}async loadIndex(){if(null==this.cachedIndex)if(x){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};this.cachedIndex=t,await this.persistIndex()}else this.cachedIndex=await(await fetch(this.indexFilePath)).json();return this.cachedIndex}async ensureResourceDir(){await I(g(this.path+"-resources"))}async saveFile(e,t){return C(),await I(g(this.path+"-resources")),y.copyFile(t.path,g(this.path+"-resources",e.fileKey))}async saveExtraFile(e,t){return C(),await I(g(this.path+"-resources")),y.copyFile(e,g(this.path+"-resources",t))}getAssetPath(e){return window&&"function"==typeof window.require?window.require("path").join(this.path+"-resources",e.fileKey):g(this.path+"-resources",e.fileKey)}async replaceFile(e,t){if(await S(t))return y.copyFile(t,g(this.path+"-resources",e.fileKey));console.error("Failed to replace file using path "+t)}async deleteFile(e){if(null==e)return;C();const t=g(this.path+"-resources",e);return await S(t)?y.unlink(t):void 0}privateObjectPath(e){return g(this.path,this.privateObjectRelativePath(e))}privateObjectRelativePath(e){return this.filePathFn?g(e.path??"",this.filePathFn(e)):g(e.path??"",tokenizeName(e.name??e.id)+".json")}async assertObjectFilePathAvailable(e,t){const a=await this.findObjectFilePathCollision(e,t);if(null!=a)throw Error(`Can not save "${e.name??e.id}" because "${a.name}" already uses the same storage file name. Use a name that differs beyond letter casing.`)}async findObjectFilePathCollision(e,t){const a=O(this.privateObjectRelativePath(e)),i=await this.loadIndex();return Object.values(i).find(e=>e.id!==t&&O(this.privateObjectRelativePath(e))===a)??null}watchDir(e){return new c(t=>{if("win32"===process.platform&&x){const a=v.watch(e,{recursive:!0},(a,i)=>{if(i){const n=b.join(e,i);v.access(n,v.constants.F_OK,e=>{const n=e?"unlink":"rename"===a?"add":"change";t.next({event:n,filename:i})})}});return()=>a.close()}const a=j.watch(e,{cwd:e,ignoreInitial:!0,disableGlobbing:!0});return a.on("all",(e,a,i)=>{t.next({event:e,filename:a})}),a.on("error",()=>{}),()=>{a.close()}})}}export function tokenizeName(e){return e.trim().replace(/\s/g,"_").replace(/[^a-z0-9_\-\.]/gi,"")}function O(e){return e.replace(/\\/g,"/").toLowerCase()}async function I(e){x&&(await S(e)||await y.mkdir(e,{recursive:!0}))}function S(e){return!!x&&new Promise(function(t,a){v.exists(e,function(e){t(e)})})}function C(){if(!x)throw new Error("Must have direct access to filesystem")}async function E(e){try{await y.access(e,y.constants.F_OK)}catch(e){return!1}return!0}export function defaultSerializer(e){const t={...e};return delete t.path,delete t.filename,JSON.stringify(t,null,2)}/*
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 n,firstValueFrom as s,from as r,map as h,mergeAll as o,mergeMap as l,Observable as c,of as d,startWith as p,Subject as u,switchMap as f,tap as w}from"rxjs";import{sleepDelay as m}from"../../utils/async.js";const v={},y={},b={},j={};null==v.read&&window.require&&(Object.assign(v,window.require("fs")),Object.assign(y,v.promises),Object.assign(b,window.require("path")),Object.assign(j,window.require("chokidar")));const x=null!=v.existsSync;function g(){if(x){const e="--path=",t=window.process.argv.find(t=>t.startsWith(e));return t?t.substring(e.length):""}return""}const F=/^[A-Z]:/;function P(...e){return 0===e.length?"":F.test(e[0])||x?b.join(...e):t(...e)}export class ObjectStorage{get pathResources(){return P(this.path+"-resources")}constructor(e,t,a=defaultSerializer){this.name=e,this.filePathFn=t,this.serializer=a,this.basePathUpdates=new u,this.basePath=this.basePathUpdates.pipe(h(e=>P(g(),e)),w(e=>{this.path=P(e,this.name),O(this.path),this.determineIfMetaFileShouldBeCreated()})),this.loaded=s(this.basePath),this.shouldCreateIndex=!1}setBasePath(e){this.basePathUpdates.next(e)}async determineIfMetaFileShouldBeCreated(){if(x)try{const e=["vite.renderer.config.ts","vite.config.ts"];for(const t of e){const e=P(g(),t);if(!await S(e))continue;if((await y.readFile(e)).toString().includes("hologyBuild"))return void(this.shouldCreateIndex=!1)}this.shouldCreateIndex=!0}catch(e){console.warn("Failed to read vite config to determine if meta files should be created")}}async createFolder(e,t=""){C(),await y.mkdir(b.join(this.path,t,e),{recursive:!0})}async deleteFolderForceDangerous(e){await y.rm(b.join(this.path,e),{recursive:!0,force:!0})}async moveFolder(e,t){if(C(),""==e)return void console.warn("Can not move a folder in root");const a=b.resolve(b.join(this.path,t),b.basename(e));if(await E(a)){if(a!==b.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=b.resolve(e),i=b.resolve(t),n=b.normalize(a)+b.sep;return(b.normalize(i)+b.sep).startsWith(n)}(b.join(this.path,e),b.join(this.path,t)))throw new Error("Can not move a folder into a folder it contains");await y.rename(b.join(this.path,e),a)}}async renameFolder(e,t){await y.rename(b.join(this.path,e),b.resolve(b.dirname(b.join(this.path,e)),t))}async moveToFolder(e,t){if(C(),e.path===t)return;await this.assertObjectFilePathAvailable({...e,path:t},e.id);const a=this.privateObjectPath({...e,path:t});await y.rename(this.privateObjectPath(e),a)}getAbsolutePath(e=""){return b.join(this.path,e)}getResourceAbsolutePath(e=""){return b.join(this.pathResources,e)}watchFolders(){return r(this.loaded).pipe(f(()=>r(O(this.path))),f(()=>this.watchDir(this.path).pipe(n(e=>!e.filename.endsWith(".json")),p(null),f(()=>r(y.readdir(this.path,{recursive:!0,withFileTypes:!0}))),h(e=>Array.from(new Set(e.filter(e=>e.isDirectory()).map(e=>b.relative(this.path,b.join(e.parentPath,e.name)).replace(/^\.$/,"")).values()))))))}watch(){C();r(this.loaded).pipe(f(()=>a([this.watchDir(this.pathResources),r(this.getAll())]).pipe(n(([e])=>null!=e),l(([e,t])=>{if("change"===e.event){const a=b.basename(e.filename),i=t.filter(e=>e.fileKey===a);if(i.length>0)return r(i).pipe(l(e=>{const t=this.privateObjectRelativePath(e);return r(this.readFileIfExists(t)).pipe(h(a=>({event:"change",object:a,path:e.path,filename:t})))}))}return i}))));return r(this.loaded).pipe(f(()=>this.watchDir(this.path)),l(e=>{const t={event:e.event,path:b.dirname(e.filename).replace(/^\.$/,""),filename:b.basename(e.filename)};return e.filename.endsWith(".json")?"unlink"!==e.event?r(this.readFileIfExists(e.filename)).pipe(w(e=>{null!=e&&(null==this.cachedIndex&&(this.cachedIndex={}),this.cachedIndex[e.id]={id:e.id,name:e.name??e.id,path:e.path},this.persistIndex())}),h(e=>({object:e,...t}))):d({object:null,...t}).pipe(w(()=>{const t=Object.keys(this.cachedIndex??{}).find(t=>this.privateObjectRelativePath(this.cachedIndex[t])===e.filename);t&&this.removeIndexEntry(t)})):"change"===e.event?r(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 y.readFile(t);return{...JSON.parse(a.toString()),path:b.dirname(e).replace(/^\.$/,""),filename:b.basename(e)}}catch{return console.error("Could not find file at "+t),null}}async getAll(e){if(x){await this.loaded,await O(this.path);const t=(await y.readdir(b.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 n=t.slice(e,e+a),s=await Promise.all(n.map(e=>y.readFile(P(e.parentPath,e.name)).then(t=>({...JSON.parse(t.toString()),path:b.relative(this.path,e.parentPath).replace(/^\.$/,""),filename:b.basename(e.name)}))));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(!x)return(await fetch(i)).json();return await S(i)?{...JSON.parse((await y.readFile(i)).toString()),path:a.path??"",filename:b.basename(this.privateObjectRelativePath(a))}:null}async save(e){if(C(),await this.loaded,null==e.path){const t=(await this.loadIndex())[e.id];null!=t?.path&&(e={...e,path:t.path})}return await this.assertObjectFilePathAvailable(e,e.id),await y.writeFile(this.privateObjectPath(e),this.serialize(e)),await this.addOrUpdateIndexEntry(e),e}async rename(e,t){const a={...e,name:t};await this.assertObjectFilePathAvailable(a,e.id);const i=this.privateObjectPath(e),n=this.privateObjectPath(a);try{await y.rename(i,n)}catch(e){console.error(e),console.warn("Rename failed, retrying",{currentPath:i,newPath:n}),await m(400),await y.rename(i,n)}return await this.save(a),a}async delete(e){await y.unlink(this.privateObjectPath(e)),this.removeIndexEntry(e.id)}async create(t){C(),await this.loaded,t.id=e();const a=this.privateObjectPath(t);if(await this.assertObjectFilePathAvailable(t),await E(a))throw Error(`Can not create because a file already exists at ${a}`);return await y.writeFile(a,this.serialize(t)),await this.addOrUpdateIndexEntry(t),t}prepareCreate(t){return C(),t.id=e(),t}serialize(e){return this.serializer(e)}async addOrUpdateIndexEntry(e){null==this.cachedIndex&&await this.loadIndex(),this.cachedIndex[e.id]={id:e.id,name:e.name??e.id,path:e.path},await this.persistIndex()}removeIndexEntry(e){null!=this.cachedIndex&&delete this.cachedIndex[e],this.persistIndex()}async persistIndex(){x&&this.shouldCreateIndex&&null!=this.cachedIndex&&await y.writeFile(this.indexFilePath,JSON.stringify(this.cachedIndex,null,2))}get indexFilePath(){return P(this.path,"_meta.json")}async loadIndex(){if(null==this.cachedIndex)if(x){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};this.cachedIndex=t,await this.persistIndex()}else this.cachedIndex=await(await fetch(this.indexFilePath)).json();return this.cachedIndex}async ensureResourceDir(){await O(P(this.path+"-resources"))}async saveFile(e,t){return C(),await O(P(this.path+"-resources")),y.copyFile(t.path,P(this.path+"-resources",e.fileKey))}async saveExtraFile(e,t){return C(),await O(P(this.path+"-resources")),y.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 S(t))return y.copyFile(t,P(this.path+"-resources",e.fileKey));console.error("Failed to replace file using path "+t)}async deleteFile(e){if(null==e)return;C();const t=P(this.path+"-resources",e);return await S(t)?y.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")}async assertObjectFilePathAvailable(e,t){const a=await this.findObjectFilePathCollision(e,t);if(null!=a)throw Error(`Can not save "${e.name??e.id}" because "${a.name}" already uses the same storage file name. Use a name that differs beyond letter casing.`)}async findObjectFilePathCollision(e,t){const a=I(this.privateObjectRelativePath(e)),i=await this.loadIndex();return Object.values(i).find(e=>e.id!==t&&I(this.privateObjectRelativePath(e))===a)??null}watchDir(e){return new c(t=>{if("win32"===process.platform&&x){const a=v.watch(e,{recursive:!0},(a,i)=>{if(i){const n=b.join(e,i);v.access(n,v.constants.F_OK,e=>{const n=e?"unlink":"rename"===a?"add":"change";t.next({event:n,filename:i})})}});return()=>a.close()}const a=j.watch(e,{cwd:e,ignoreInitial:!0,disableGlobbing:!0});return a.on("all",(e,a,i)=>{t.next({event:e,filename:a})}),a.on("error",()=>{}),()=>{a.close()}})}}export function tokenizeName(e){return e.trim().replace(/\s/g,"_").replace(/[^a-z0-9_\-\.]/gi,"")}function I(e){return e.replace(/\\/g,"/").toLowerCase()}async function O(e){x&&(await S(e)||await y.mkdir(e,{recursive:!0}))}function S(e){return!!x&&new Promise(function(t,a){v.exists(e,function(e){t(e)})})}function C(){if(!x)throw new Error("Must have direct access to filesystem")}async function E(e){try{await y.access(e,y.constants.F_OK)}catch(e){return!1}return!0}export function defaultSerializer(e){const t={...e};return delete t.path,delete t.filename,JSON.stringify(t,null,2)}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,80 @@
1
+ import { Material, Side } from 'three';
2
+ import { FloatNode, Vec2Node, Vec3Node } from '../../shader-nodes/index.js';
3
+ import type { NodeShaderOutput } from '../shader.js';
4
+ import type { ShaderGraphDocument, ShaderGraphMaterialSide, ShaderGraphNode, ShaderGraphValueType } from './model.js';
5
+ export declare class ShaderGraphCompileError extends Error {
6
+ readonly nodeId?: string;
7
+ readonly port?: string;
8
+ constructor(message: string, nodeId?: string, port?: string);
9
+ }
10
+ export interface ShaderGraphCompileOptions {
11
+ parameters?: Record<string, unknown>;
12
+ }
13
+ export interface ShaderGraphCompileResult {
14
+ output: ShaderGraphNodeShaderOutput;
15
+ nodes: Map<string, CompiledShaderGraphNode>;
16
+ }
17
+ export type ShaderGraphNodeShaderOutput = NodeShaderOutput & {
18
+ metalness?: FloatNode;
19
+ ambientOcclusion?: FloatNode;
20
+ ambientOcclusionIntensity?: FloatNode;
21
+ sheenColor?: Vec3Node;
22
+ sheenRoughness?: FloatNode;
23
+ anisotropy?: FloatNode;
24
+ anisotropyDirection?: Vec2Node;
25
+ bakedLight?: Vec3Node;
26
+ };
27
+ export interface CompiledShaderGraphNode {
28
+ node: ShaderGraphNode;
29
+ outputs: Record<string, CompiledShaderGraphValue>;
30
+ }
31
+ interface CompiledShaderGraphValue {
32
+ type: ShaderGraphValueType;
33
+ value: unknown;
34
+ }
35
+ export declare class ShaderGraphCompiler {
36
+ private readonly graph;
37
+ private readonly options;
38
+ private readonly nodesById;
39
+ private readonly compiled;
40
+ constructor(graph: ShaderGraphDocument, options?: ShaderGraphCompileOptions);
41
+ validate(): void;
42
+ compile(): ShaderGraphCompileResult;
43
+ private validateEdges;
44
+ private compileOutput;
45
+ private applyShadingModel;
46
+ compileNode(id: string): CompiledShaderGraphNode;
47
+ private compileNodeInternal;
48
+ private compileParameterNode;
49
+ private compileBinaryMath;
50
+ private compileUnaryMath;
51
+ private compileBinaryFunction;
52
+ private compilePaintedLayerMix;
53
+ private defaultUV;
54
+ private input;
55
+ private optionalInput;
56
+ private floatInput;
57
+ private boolInput;
58
+ private compileComparison;
59
+ private compileBooleanBinary;
60
+ private resolveOutputBinding;
61
+ private floatOutput;
62
+ private resolveInput;
63
+ private resolveSocket;
64
+ private expectType;
65
+ private expectNumeric;
66
+ private toSampler;
67
+ private toColorOutput;
68
+ private toVec3Output;
69
+ private toMat4Output;
70
+ private output;
71
+ }
72
+ export declare function compileShaderGraph(graph: ShaderGraphDocument, options?: ShaderGraphCompileOptions): ShaderGraphCompileResult;
73
+ export declare function compileShaderGraphPreview(graph: ShaderGraphDocument, selectedNodeId?: string, options?: ShaderGraphCompileOptions): NodeShaderOutput;
74
+ export declare function buildShaderGraphMaterial(graph: ShaderGraphDocument, options?: ShaderGraphCompileOptions & {
75
+ previewNodeId?: string;
76
+ trailBillboard?: boolean;
77
+ }): Material;
78
+ export declare function shaderGraphMaterialSideToThree(side: ShaderGraphMaterialSide | undefined): Side;
79
+ export {};
80
+ //# sourceMappingURL=compiler.d.ts.map