@hology/core 0.0.206 → 0.0.207
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/effects/sequence/sequence-data.d.ts +8 -3
- package/dist/effects/sequence/sequence-data.js +1 -1
- package/dist/effects/sequence/sequence-definitions.js +1 -1
- package/dist/effects/sequence/sequence-player.d.ts +2 -0
- package/dist/effects/sequence/sequence-player.js +1 -1
- package/dist/effects/sequence/sequence-value-lane.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
- package/dist/gameplay/actors/factory.d.ts +1 -0
- package/dist/gameplay/actors/factory.js +1 -1
- package/dist/gameplay/actors/internal/component-init.d.ts +1 -0
- package/dist/gameplay/actors/internal/component-init.js +1 -1
- package/dist/gameplay/animation/anim-sm.d.ts +2 -0
- package/dist/gameplay/animation/anim-sm.js +1 -1
- package/dist/gameplay/services/world.js +1 -1
- package/dist/rendering.d.ts +2 -0
- package/dist/rendering.js +1 -1
- package/dist/scene/materializer.d.ts +2 -0
- package/dist/scene/materializer.js +1 -1
- package/dist/scene/storage/storage.d.ts +1 -0
- package/dist/scene/storage/storage.js +1 -1
- package/dist/shader/graph/compiler.js +1 -1
- package/dist/shader/parameter.js +1 -1
- package/dist/test/data-asset-definition.test.js +1 -1
- package/dist/test/parameter-definition.test.js +1 -1
- package/dist/test/sequence-property-parameters.test.js +1 -1
- package/dist/test/sequence-vfx.test.d.ts +2 -0
- package/dist/test/sequence-vfx.test.js +4 -0
- package/dist/test/storage-case-collision.test.js +1 -1
- package/dist/test/world-lifecycle.test.d.ts +2 -0
- package/dist/test/world-lifecycle.test.js +4 -0
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate as e,__metadata as t}from"tslib";import{ConvexPolyhedronCollisionShape as a,SpriteShader as s}from"@hology/core";import{Subject as r}from"rxjs";import*as n from"three";import{BoxGeometry as i,Color as o,Euler as l,Fog as c,FogExp2 as u,Group as p,Material as h,Matrix4 as d,Mesh as m,MeshLambertMaterial as f,MeshPhongMaterial as g,MeshStandardMaterial as y,Object3D as w,PointLight as v,Quaternion as b,Scene as M,Texture as S,Vector2 as A,Vector3 as x,Vector4 as j}from"three";import{attributes as I,batchingUniformFloat as P,batchingUniformVec2 as C,batchingUniformVec3 as D,batchingUniformVec4 as T,bool as O,BooleanExpression as V,BooleanNode as E,colorToNormal as k,float as F,FloatNode as z,ifDefApply as N,mix as B,NodeShaderMaterial as $,rgb as _,rgba as U,RgbNode as G,select as W,standardMaterial as L,Texture2dLookupNode as R,textureSampler2d as q,textureSampler2dArray as Y,UniformBoolNode as J,UniformFloatNode as H,UniformSampler2dArraySlice as X,UniformVec2Node as K,UniformVec3Node as Z,UniformVec4Node as Q,varying as ee,varyingAttributes as te,varyingTransformed as ae,vec2 as se,Vec2Node as re,vec3 as ne,Vec3Node as ie,vec4 as oe,Vec4Node as le}from"three-shader-graph";import{Service as ce}from"typedi";import{VfxActor as ue}from"../effects/vfx/vfx-actor.js";import{VisualEffect as pe}from"../effects/vfx/vfx-param.js";import{Prefab as he,PrefabOf as de}from"./objects/prefab.js";import{DataAssetRef as me}from"./objects/data-asset.js";import{BaseActor as fe}from"../gameplay/actors/actor.js";import ge from"../gameplay/actors/builtin/index.js";import{ActorComponent as ye}from"../gameplay/actors/component.js";import{PhysicsBodyType as we}from"../gameplay/services/physics/physics-system.js";import{ThreeBlendingMode as ve}from"../effects/vfx/vfx-asset.js";import{withInjectionContext as be}from"../gameplay/inject.js";import{RenderingView as Me}from"../rendering.js";import{curveSampler as Se,oneMinus as Ae,particleUniforms as xe,Sampler2DNode as je}from"../shader-nodes/index.js";import{LambertShader as Ie}from"../shader/builtin/lambert-shader.js";import{LandscapeCompositeShader as Pe}from"../shader/builtin/landscape-composite-shader";import{LandscapeShader as Ce}from"../shader/builtin/landscape-shader.js";import{StandardShader as De}from"../shader/builtin/standard-shader.js";import{UnlitShader as Te}from"../shader/builtin/unlit-shader.js";import{extractShaderParameters as Oe,getDataAssetDefinitionType as Ve,getParameterDefinitionId as Ee,getParameterDefinitionType as ke,isDataAssetDefinitionAbstract as Fe,isParameterDefinitionAbstract as ze,isParameterDefinitionAssignableTo as Ne,isParameterDefinitionStructAssignableTo as Be,shaderParameterUniformName as $e}from"../shader/parameter.js";import{ArrayMap as _e,DefaultMap as Ue,groupBy as Ge}from"../utils/collections.js";import{iterateMaterials as We}from"../utils/materials.js";import{filterChildrenShallow as Le,filterSceneShallow as Re,findFirstVisibleMesh as qe,findFirstVisibleObject as Ye,traverseAsync as Je}from"../utils/three/traverse.js";import{AssetMeshInstance as He,AssetResourceLoader as Xe}from"./asset-resource-loader.js";import{AssetsProvider as Ke}from"./assets-provider.js";import{isCollisionMesh as Ze}from"./collision/collision-shape-import.js";import{BoxCollisionShape as Qe,PhysicalShapeMesh as et}from"./collision/collision-shape.js";import{LandscapeManager as tt}from"./landscape/landscape-manager.js";import{initLandscape as at}from"./landscape/landscape.js";import{SectionGrid as st,smoothNormalsCrossMeshes as rt}from"./landscape/utils.js";import{createGrassFoliageMaterial as nt}from"./materials/grass-foliage.js";import{createGrassMaterial as it}from"./materials/grass.js";import{getMaterialAttribute as ot}from"./materials/utils/material-painting.js";import{SurfaceScatterManager as lt}from"./scatter/surface-scatter-manager.js";import{createWaterMaterial as ct}from"./materials/water.js";import{SerializedParamType as ut}from"./model.js";import{applyRuntimeParamTypeInference as pt,convertConfiguredParamsToRuntimeTypes as ht,convertConfiguredParamValueToRuntimeType as dt,inferRuntimeSerializedParamTypeHint as mt}from"./custom-param-runtime-types.js";import{ShapeLibrary as ft,ShapeLibraryKeys as gt}from"./objects/shapes.js";import{ambientLightName as yt,createSky as wt,defaultSkyMaterial as vt}from"./sky.js";import{Curve2 as bt}from"../utils/curve.js";import{DecalUnlitShader as Mt}from"../shader/builtin/decal-unlit-shader.js";import{DecalStandardShader as St}from"../shader/builtin/decal-standard-shader.js";import{ColorLayer as At,defaultValueColorLayer as xt,defaultValueMaskLayer as jt,MaskLayer as It}from"../shader/color-layer.js";import{LayeredShader as Pt}from"../shader/builtin/layered-shader";import{isColorLayerSerialized as Ct}from"../shader/color-layer";import{FogVolume as Dt}from"../rendering/fog/fog-volume-actor.js";import{UnscaledSprite as Tt}from"../utils/three/unscaled-sprite.js";import{ToonShader as Ot}from"../shader/builtin/toon-shader.js";import{BatchedMesh2 as Vt}from"./batched-mesh-2.js";import{ParallaxStandardMaterial as Et}from"../shader/builtin/standard-shader";import{parallaxOcclusionMapping as kt}from"../shader-nodes/pom.js";import{traverseVisibleEvery as Ft}from"../utils/three/traverse";import{RectAreaLightHelper as zt}from"three/examples/jsm/Addons.js";import{Sequence as Nt}from"../effects/sequence/sequence-data.js";import{applyUvTiling as Bt}from"./../shader/uv-nodes.js";import{buildShaderGraphMaterial as $t,shaderGraphMaterialSideToThree as _t}from"../shader/graph/index.js";export{pt as applyRuntimeParamTypeInference,ht as convertConfiguredParamsToRuntimeTypes,dt as convertConfiguredParamValueToRuntimeType,mt as inferRuntimeSerializedParamTypeHint};const Ut={},Gt=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),Wt=/^((?!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 Lt(e,this.dataProvider,this.assetsService,this.assetManagerService,t,[],[],{create:()=>null,initActor:async()=>{}})}}let Lt=class{constructor(e,t,a,s,i,o,l,c,u=[]){this.scene=e,this.dataProvider=t,this.assetsService=a,this.assetManagerService=s,this.renderingView=i,this.shaders=o,this.actorTypes=l,this.actorProvider=c,this.componentTypes=u,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 n.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=>Va(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 aa(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 aa(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 n.ShaderMaterial)for(const[e,s]of Object.entries(t.uniforms))s.value instanceof n.Texture&&s.value.userData.assetId===a.id&&(t.uniforms[e].value=r);else for(const[e,s]of Object.entries(t))s instanceof n.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===ut.Material&&s.value===a.id){t=!0;break}if(s.type===ut.Array&&"element"in s&&s.element===ut.Material&&s.value.includes(a.id)){t=!0;break}}if(!t)return}const n=await materialFromAsset(this.assets.get(r),this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!1),i=n.userData;n.userData=t.userData,n.userData.hasBloom=i.hasBloom,n.userData.reflective=i.reflective,n.userData.outlineParameters=i.outlineParameters,null!=s?ya(e.material[s],n)||(e.material[s]=n):ya(e.material,n)||(e.material=n,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===ut.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=this.collectAssetMeshIds(this.dataProvider.getObjects());await Promise.all(Array.from(e).map(async e=>{const t=this.assets.get(e);if("mesh"===t?.type)return this.assetManagerService.getMesh(t,{mergeGeomtries:!0})})),this.initTextures()}collectAssetMeshIds(e,t=[],a=new Set){for(const s of e??[])this.collectObjectAssetMeshIds(s,t,a);return a}collectObjectAssetMeshIds(e,t,a){if(this.shouldBeMaterialized(e)&&("asset_mesh"===e.type&&null!=e.assetId&&a.add(e.assetId),null!=e.children&&this.collectAssetMeshIds(e.children,t,a),"prefab"===e.type&&null!=e.assetId&&!t.includes(e.assetId))){const s=this.assets.get(e.assetId);null!=s?.prefab?.objects&&this.collectAssetMeshIds(s.prefab.objects,[...t,e.assetId],a)}}async init(){await this.preInit(),qt.clear(),Yt.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 M;for(const s of this.actorInstances){const r=Ta(s);for(const s of r){const r=s.asset;if(e.has(r.id))continue;e.add(r.id),r.vfx.emitters;const n=await s.create(a);a.add(n.object),a.add(n.particleSystemContainer),n.play(),n.onUpdate(.5),n.stop(),n.pause(),t.push(n)}}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="prefab"===a.type?await this.assetsService.getAsset(a.assetId):null,r=e.split("/"),n=r.slice(0,-1),i=n.join("/"),o=(r[r.length-1],new Map);for(const[e,t]of this.materializedActors)if(o.set(e,t),0===i.length)e.includes("/")||o.set(e,t);else if(e.startsWith(i+"/")){const a=e.slice(i.length+1);a.includes("/")||o.set(a,t)}const l={...s?.actor?.params??{},...a.actor?.params??{}},c=[...a.actor?.innerParams??[]];for(let t=n.length-1;t>=0;t--){const a=n.slice(0,t+1).join("/"),s=this.idToSceneObject.get(a);if("prefab"===s?.type&&null!=s.prefab){const n=await this.assetsService.getAsset(s.assetId);if(null!=n){let i=!1,o=a+"/"+n.prefab?.mainActorId;for(;null!=o;){if(o===e){i=!0;break}o=this.prefabInstanceExposedActorMap.get(o)}if(i&&null!=s.prefab.params&&Object.assign(l,ra(s.prefab.params)),null!=s.prefab.innerParams){const e=r.slice(t+1);for(const t of s.prefab.innerParams){const a=ra(t.params);0!==Object.keys(a).length&&(i?c.push({path:na(t.path,e)?t.path.slice(e.length):t.path,params:a}):na(t.path,e)&&c.push({path:t.path.slice(e.length),params:a}))}}}}}for(const e of c)await this.applyActorComponentParams(t,e.path.slice(),e.params,o);await this.attachEditorComponents(t,a,o);const u=await prepareClassParameters(l,t.constructor,this.assetsService,this.assetManagerService,o,this.renderingView,this.shaders,this.actorProvider,e=>{const t=i.length>0?i+"/"+e:e;return this.prefabInstanceExposedActorMap.get(t)??null},t);Object.assign(t,u);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 n=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,n);Object.assign(n,e)}for(const e of r.innerParams??[])await this.applyActorComponentParams(n,e.path.slice(),e.params,a)}}addVfxChildActors(e,t=e){}async applyActorComponentParams(e,t,a,s){const r=t.length,n=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[n]&&await this.applyActorComponentParams(e[n],t,a,s)}canObjectBeInstanced(e){return e.physics?.type!==we.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=>{!Ze(e)&&e.isMesh&&s.push(e)});const r=1==s.length&&0==s[0].children.length,n=!Wt,i=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||i&&n)&&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)});const e=await this.assetsService.getAssets();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(),qt.clear(),Yt.clear();const e=[],t=new _e,a=new _e,s=new _e;let r=0,i=0,c=0;const u=new Map,p=new Ue(()=>new Map);for(const n of this.dataProvider.getObjects())await aa(n,async(n,l,h)=>{if(!this.shouldBeMaterialized(n))return;const d="asset_mesh"==n.type&&this.canObjectBeInstanced(n)&&await this.canAssetBeInstanced(n),f="shape_mesh"===n.type&&"landscape"!==n.shape&&n.physics?.type!==we.dynamic;if(d||f){if(l&&l.children?.length>0){const e=l.children.findIndex(e=>e.id===n.id);e>=0&&l.children.splice(e,1)}if(f){let e=n.shape+JSON.stringify(n.shapeParams??{})+n.castShadow+n.receiveShadow;const t=n.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===ut.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:{...n,parentTransform:h},color:r}),c++}else{const e=this.assets.get(n.assetId);let s=u.get(n.assetId);if(null==s){const e=await this.createFromAsset(n,{assignMaterials:!1});if(null==e)return;if(s=u.get(n.assetId),null==s){s={useBatchedMesh:null!=qe(e)&&Ft(e,e=>!(e instanceof m)||this.testCanBatch(e.material,e.geometry)),assetMesh:e},u.set(n.assetId,s)}}const o=la(n.materialAssignments,e.materialAssignments);if(s.useBatchedMesh)await Je(s.assetMesh,async t=>{if(!(t instanceof m))return;const s=Array.isArray(t.material)?t.material[0]:t.material,i=await this.resolveMaterialForAssignments(s,o,e);if(null!=i){p.get(n.id).set(t.uuid,i),Oa(t.geometry,i);let e=Sa(i);e+=ba(t),a.push(e,{...n,parentTransform:h,meshUUID:t.uuid}),r++}else console.warn("Can not materialize mesh because missing material",n)});else{const e=n.assetId+JSON.stringify(n.materialAssignments??[]);t.push(e,{...n,parentTransform:h}),i++}}}else null==l&&e.push({...n,parentTransform:h})});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 ${i} 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 u.values())this.prepareCollisionShapesForInstanced(e.assetMesh);console.time("materialize batches");for(const[e,t]of a.entries()){if(0==t.length)continue;let e;u.get(t[0].assetId).assetMesh;e=this.createBatchedMesh(t,p,u);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 He;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=u.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 He;r.add(t),r.userData.src=e[0],a instanceof He&&(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=Ye(a,e=>!Ze(e)&&null!=e.geometry),r=s.material.clone();null!=e[0].color&&null!=r.color&&(r.color=new o(16777215));const i=s.geometry;let c,u;!(Wt||r instanceof $||null==i.index)?(c=new n.BatchedMesh(e.length,i.getAttribute("position").count,i.index.count,r),c.perObjectFrustumCulled=!0,u=c.addGeometry(i)):c=new n.InstancedMesh(i,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 n.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 i;i=c instanceof n.BatchedMesh?c.addInstance(u):t,c.setMatrixAt(i,r),a.color}for(let t=0;t<e.length;t++){const s=e[t],r=new He;r.userData.src=e[0],a instanceof et&&(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 He&&e.collisionShapes.forEach(e=>{e instanceof a&&e.mesh instanceof m&&(e.mesh=e.mesh.geometry)})}testCanBatch(e,t){return!Wt&&(!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 _e;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,i=0,l=0;const c=new Map;for(const[e,t]of s.entries()){const s=t[0].assetId,n=a.get(s);if(null==n){console.warn("Missing batching info for asset id "+s);continue}const o=Ye(n.assetMesh,t=>t instanceof m&&t.uuid===e);if(null==o){console.warn("Missing mesh in batched asset");continue}c.set(e,o);const u=o.geometry.getAttribute("position");null==u&&console.warn("Missing position attribute for batched mesh"),r+=o.geometry.index.count*t.length,i+=u.count*t.length,l+=t.length}const u=["color","map","roughness","roughnessMap","metalness","metalnessMap","opacity","alphaMap","aoMap","aoMapIntensity","normalMap","normalScale","emissive","emissiveIntensity","emissiveMap"];let p=new Map;const h=[];let d=new n.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 n.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 u){let r=e[t];r instanceof n.CompressedArrayTexture&&null!=r.userData.index&&(r=r.userData.index);const i=s.get(t);void 0===i||Da(r,i)?s.set(t,r):a.add(t)}}for(const e of a){let t;const a=f[e];if("number"==typeof a){let a=h.find(e=>e.params.length<4);if(null==a){const t="vp"+h.length;a={name:t,params:[e],node:T(t)},h.push(a)}else a.params.push(e);t=Pa(a.node,a.params.length-1)}else if(a instanceof j)t=T(e);else if(a instanceof x||a instanceof o)t=D(e);else if(a instanceof A)t=C(e);else if(a instanceof n.CompressedArrayTexture)t=P(e+"_i");else if(a instanceof S)continue;p.set(e,t)}let r=te.uv;f instanceof Et&&null!=f.heightMap&&(r=kt(r,q(f.heightMap),F(f.heightScale)));let i=Aa(p.get("opacity"),z)??F(f.opacity??1);if(null!=f.alphaMap){let e;if(f.alphaMap instanceof n.CompressedArrayTexture){const t=Y(f.alphaMap),a=Aa(p.get("alphaMap"),z)??F(f.alphaMap.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.alphaMap).sample(r);i=i.multiply(e.r)}let l=U(Aa(p.get("color"),ie)??f.color,i);if(null!=f.map){let e;if(f.map instanceof n.CompressedArrayTexture){const t=Y(f.map),a=Aa(p.get("map"),z)??F(f.map.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.map).sample(Bt(r,f.map));l=l.multiply(e),i=i.multiply(e.a)}f.vertexColors&&(l=l.multiply(oe(ee(I.color.rgb),1)));let c=U(Aa(p.get("emissive"),ie)??f.emissive,i);if(null!=f.emissiveMap){let e;if(f.emissiveMap instanceof n.CompressedArrayTexture){const t=Y(f.emissiveMap),a=Aa(p.get("emissiveMap"),z)??F(f.emissiveMap.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.emissiveMap).sample(Bt(r,f.emissiveMap));c=c.multiply(e)}const m=Aa(p.get("emissiveIntensity"),z)??F(f.emissiveIntensity??1),g=Aa(p.get("normalScale"),re)??se(f.normalScale??new A(1,1));let y=ae.normal;if(null!=f.normalMap){let e;if(f.normalMap instanceof n.CompressedArrayTexture){const t=Y(f.normalMap),a=Aa(p.get("normalMap"),z)??F(f.normalMap.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.normalMap).sample(Bt(r,f.normalMap));y=k(e.rgb,g.x)}let w=Aa(p.get("roughness"),z)??F(f.roughness??1);if(null!=f.roughnessMap){let e;if(f.roughnessMap instanceof n.CompressedArrayTexture){const t=Y(f.roughnessMap),a=Aa(p.get("roughnessMap"),z)??F(f.roughnessMap.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.roughnessMap).sample(Bt(r,f.roughnessMap));w=w.multiply(e.g)}let v=Aa(p.get("metalness"),z)??F(f.metalness??0);if(null!=f.metalnessMap){let e;if(f.metalnessMap instanceof n.CompressedArrayTexture){const t=Y(f.metalnessMap),a=Aa(p.get("metalnessMap"),z)??F(f.metalnessMap.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.metalnessMap).sample(Bt(r,f.metalnessMap));v=v.multiply(e.b)}let b=F(1);if(null!=f.aoMap){let e;if(f.aoMap instanceof n.CompressedArrayTexture){const t=Y(f.aoMap),a=Aa(p.get("aoMap"),z)??F(f.aoMap.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.aoMap).sample(Bt(r,f.aoMap));b=b.multiply(e.r)}const M=Aa(p.get("aoMapIntensity"),z)??F(f.aoMapIntensity??0);let O=y;!0!==f.userData.disableAO&&(O=N("DOUBLE_SIDED",O,e=>W(new V("gl_FrontFacing"),e,e.multiplyScalar(-1))));const E=new $({color:L({color:l,roughness:w,metalness:v,ambientOcclusion:b,ambientOcclusionIntensity:M,emissive:c,emissiveIntensity:m,normal:O}),normal:y,roughness:w,emissive:c.rgb,transparent:f.transparent,alphaTest:f.alphaTest,envMap:f.envMap,opacity:i});null!=f.envMap&&(E.uniforms.envMapIntensity={value:f.envMapIntensity},E.uniforms.envMapRotation={value:Ia(f.envMapRotation,f.envMap)}),E.envMap=f.envMap,E.side=f.side,d=E}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 Vt(l,i,r,d);for(const e of h)g.initUniform(e.name,4);for(const[e,t]of p.entries()){if(h.some(t=>t.params.includes(e)))continue;let a=1;t instanceof le||t instanceof ie?a=4:t instanceof re&&(a=2),g.initUniform(e,a,0)}for(const[e,r]of s.entries()){const s=r[0].assetId,i=c.get(e);if(null==i){console.error(`Missing single asset mesh for mesh uuid ${e} and asset id ${s}`);continue}if(null==i.geometry){console.error("Missing geometry on mesh mesh");continue}const l=g.addGeometry(i.geometry),u=a.get(s);if(null==u){console.warn("Missing batching info when configuring for asset id "+s);continue}const d=qe(u.assetMesh)?.uuid===e,m=u.assetMesh instanceof He&&d?u.assetMesh.collisionShapes:void 0,f=this.configureBatchedInstancedMesh(r,g,i,l,m);for(let e=0;e<f.length;e++){const a=r[e],s=f[e],i=t.get(a.id).get(a.meshUUID);for(const e of h){let t=Ca.set(0,0,0,0);for(let a=0;a<e.params.length;a++){const s=i[e.params[a]];"number"==typeof s&&t.setComponent(a,s)}g.setUniformAt(e.name,s,t)}for(let e of p.keys()){if(h.some(t=>t.params.includes(e)))continue;let t=i[e];if(t instanceof o&&(t=new x(t.r,t.g,t.b)),t instanceof n.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=Ye(t,e=>!Ze(e)&&null!=e.geometry),s=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(t,la(e[0].materialAssignments,s.materialAssignments),s),a.updateMatrix();const r=a.geometry.clone(),i=a.material;let o;if(o=new n.InstancedMesh(r,i,e.length),this.configureBatchedInstancedMesh(e,o,a),a.material instanceof h&&o.castShadow&&o.receiveShadow&&Array.isArray(i))for(const e of i);return o}configureBatchedInstancedMesh(e,t,a,s,r){const i=[];a.updateWorldMatrix(!0,!0);for(let o=0;o<e.length;o++){let c=o;t instanceof n.BatchedMesh&&(c=t.addInstance(s)),i.push(c);const u=(new n.Matrix4).compose((new x).fromArray(e[o].position),(new b).setFromEuler((new l).fromArray(e[o].rotation)),(new x).fromArray(e[o].scale)),p=(new d).copy(e[o].parentTransform).multiply(u).multiply(a.matrixWorld);t.setMatrixAt(c,p),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 i}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 Re(this.scene,t=>t.userData.src?.assetId==e,e=>null!=e.userData.src)}applyMaterials(e,t,a){return null==t?Promise.resolve([]):Promise.all(t.filter(e=>"null"!==e.materialId).map(t=>this.applyMaterial(e,t,a)))}async applyMaterial(e,t,a){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,{textureFlipY:getConvertedFbxToGlbAssignedMaterialTextureFlipY(a)})}async resolveMaterialForAssignments(e,t,a){let s=e,r=null,n=null;const i=getConvertedFbxToGlbAssignedMaterialTextureFlipY(a);for(const e of t??[]){if(!ha(s,e,r,n))continue;const t=this.assets.get(e.materialId);if(null==t){console.warn("Missing material with id "+e.materialId);continue}let a=await materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!0);null!=a&&(a=ma(a,i)),null!=a&&s.id!==a.id&&(r=r??pa(s),n=n??s.name,s=a)}return s}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(ge));Re(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,Re(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 qt.entries())t.userData.customShaderName&&qt.delete(e);this.landscapeManagers.forEach(t=>t.updateShaders(e)),Re(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 n=!1;if(t.traverseAncestors(e=>{"_hology_transform_group"===e.name&&(n=!0)}),!n){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);la(e.materialAssignments,a.materialAssignments).forEach(e=>this.applyMaterial(t,e,a))}else"shape_mesh"===e.type&&this.applyMaterials(t,e.materialAssignments);if(n||(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 zt&&e.update()})}}else if("landscape"===e.shape){const a=this.landscapeManagers.find(t=>t.source.id===e.id),n=null==a||(s=a.source.landscape.options,r=e.landscape.options,s.density!==r.density||s.sections.x!==r.sections.x||s.sections.y!==r.sections.y);if(this.inEditor&&n){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 u?"density":"linear")!==e.fog.type;this.scene.fog=ta(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 u&&(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 Dt){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)||n||(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 et&&(t.geometry=a.geometry,t.collisionShape=a.collisionShape)}if("shape_mesh"===e.type&&"landscape"!==e.shape)Rt(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;Rt(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,s,r;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:Le(t,t=>t.children?.some(t=>t.id===e.id),()=>!0))[0];return null==t?this.scene:null!=t?Re(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=Ge(e.vertexMaterials,e=>e.m);t.traverse(e=>{if(e instanceof m){if(null==e.geometry)return;if(wa(ot(e,0,!1)),a>0){wa(ot(e,0,!1))}}});const r=new Set;for(const[e,n]of s.entries()){const s=null!=e?t.getObjectByName(e):this.findMeshWithGeometry(t);let i=!1;if(null==s||null==s.geometry)return void console.warn(`Failed to apply vertex materials on mesh with name "${e}"`);const o=ot(s,0,!0);wa(o);for(const e of n)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),i=!0;if(a>0){const e=ot(s,4,!0);wa(e);for(const t of n)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,i=!0}i&&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 n,i;switch(e.type){case"asset_mesh":n=await this.createFromAsset(e);break;case"shape_mesh":n=await this.createFromShape(e);break;case"light":n=await this.createLight(e);break;case"particles":n=await this.createParticleSystem(e),e.collisionDetection=!1;break;case"global_fog":this.scene.fog=ta(e.fog),this.fixFogColor(),n=new p;break;case"sky":this.sky=wt(),this.updateSky(e),n=this.sky;break;case"world_env":this.updateWorldEnv(e),n=new p,this.worldEnvObj=n;break;case"actor":({object:n,actor:i}=await this.createFromActor(e,s));break;case"group":n=new p;break;case"prefab":n=await this.createFromPrefab(e,s,t);break;case"vfx":n=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!=n){if(e.name&&e.name.length>0&&(n.name=e.name),this.applyTransform(e,n),a?n.userData._src=e:n.userData.src=e,null!=i&&(n.userData.actor=i),this.inEditor,this.inEditor,this.objectMap.set(n.uuid,e),this.sceneObjectMap.set(e.id,n),e.physics?.type!==we.dynamic||null==t||this.inEditor?null==t?this.scene.add(n):null==t||"actor"!==e.type||this.inEditor?t?.add(n):(t.add(n),this.scene?.attach(n),console.log(n)):(t.add(n),n.getWorldPosition(n.position),n.getWorldQuaternion(n.quaternion),n.getWorldScale(n.scale),this.scene?.attach(n)),null!=e.children&&await Promise.all(e.children?.map(e=>this.materialize(e,n,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==we.dynamic||ea(n),null!=this.renderingView)return this.renderingView.renderer.shadowMap.needsUpdate=!0,n;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 lt(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 n.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!==vt?(this.sky.material=vt,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=n.BackSide,(e instanceof y||e instanceof n.MeshBasicMaterial||e instanceof n.ShaderMaterial)&&(e.fog=!1),e.depthTest=!1}async createComponent(e,t,a,s){const r=new Ut[a.path+"/"+a.className],n=t.id+s;r.id=n,r.object=e;for(const e of a.params)null!=e.value&&(r[e.name]=e.value);return this.components.push(r),n}async createFromActor(e,t){const a=this.actorTypes.find(t=>t.name===e.actor?.type)?.type??ge[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(ue,(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 p;const a=at(e.landscape.options);this.applyHeightMaps(a,e.landscape.heightMaps,!0);const s=new tt(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 st(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(()=>rt(r),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&>.includes(e)){const s=await prepareShapeParameters(a??{}),r=e+JSON.stringify(a);if(!this.geometryCache.has(r)){const t=ft[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,ft[e].collision(s));return new et(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(la(e.materialAssignments,a.materialAssignments).map(e=>this.applyMaterial(s,e,a)))}catch(t){console.error("Failed to apply material"+t,e)}const r=e.receiveShadow??!!a.receiveShadow,n=e.castShadow??!!a.castShadow;return s.receiveShadow=r,Rt(s,n,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 n=new p;null!=s&&this.applyTransform(s,n),null!=a&&a.add(n),await Promise.all(e.prefab.objects.filter(e=>"global_fog"!==e.type&&"world_env"!==e.type).map(e=>this.materialize(e,n,!0,structuredClone(t))));const i=t.sceneObjectChain.join("/"),o=Array.from(this.materializedActors.entries()).filter(([e,a])=>e.startsWith(i)&&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(i)).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:n,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 n.TextureLoader).load("assets/light-bulb-icon.webp"),a=new n.SpriteMaterial({map:e,alphaTest:.5}),s=new Tt(a);s.scale.multiplyScalar(.6),t.add(s)}return t}if("spot"===e.light.type){const t=new n.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 n.TextureLoader).load("assets/light-bulb-icon.webp"),a=new n.SpriteMaterial({map:e,alphaTest:.5}),s=new Tt(a);s.scale.multiplyScalar(.6),t.add(s),t.add(new n.SpotLightHelper(t))}return t}if("rectArea"===e.light.type){const t=new n.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 n.TextureLoader).load("assets/light-bulb-icon.webp"),a=new n.SpriteMaterial({map:e,alphaTest:.5}),s=new Tt(a);s.scale.multiplyScalar(.6),t.add(s);const r=new zt(t);t.add(r)}return t}return"directional"===e.light.type?(this.applyDirectionalLight(e.light.directional,e),new p):"ambient"===e.light.type?(this.applyDirectionalAmbientLight(null,e.light.ambient,e),new p):void 0}applyDirectionalAmbientLight(e,t,a){const s=this.scene.children.find(e=>e.name===yt);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()}};Lt=e([ce(),t("design:paramtypes",[M,Object,Ke,Xe,Me,Array,Array,Object,Array])],Lt);export{Lt as SceneMaterializer};function Rt(e,t,a){e.castShadow=t,e.receiveShadow=a,e.traverse(e=>{e.castShadow=t,e.receiveShadow=a})}const qt=new Map,Yt=new Map,Jt=new f({color:16711935}),Ht=new Map;export async function materialFromAsset(e,t,a,s,r,n=!0){if(null==e||null==e.material)return console.error("Asset or asset material is null",e),Jt;const i=JSON.stringify(e.material)+t?._id,o=n&&!("shaderGraph"===e.material.type&&"asset"===e.material.shaderGraph?.source);if(o&&qt.has(i))return qt.get(i);if(o&&Yt.has(i))return await Yt.get(i);const l=_materialFromAsset(i,e,t,a,s,r,o);return o?Yt.set(i,l).get(i):l}export async function _materialFromAsset(e,t,a,r,i,l,c=!0){const u={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},p={};if(null!=t.material.params?.map){const e=t.material.params.map,a=await r.getAsset(e);null!=a&&(u.map=await i.getTexture(a))}let h,d,m;switch(t.material.type){case"phong":h=new g({...u,...p});break;case"water":h=ct(u,a);break;case"grassFoliage":h=nt({color:u.color,map:u.map},a);break;case"grass":h=it({...u,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),h=Jt;break}"surface"===e.target&&null!=e.materialOptions?.side&&(d=_t(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,i,a,l),n=t.shaderGraphPreviewNodeId,o=t.trailBillboard;h=$t(e,{parameters:s,previewNodeId:n,trailBillboard:o}),h.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),h=Jt}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:Gt?Ie:De,lambert:Ie,unlit:Te,toon:Ot,layered:Pt,landscape:Ce,"landscape-composite":Pe,"decal-unlit":Mt,"decal-standard":St,sprite:s}[t.material.type]??l.find(e=>e.name==t.material.shader)?.type;if(e){try{let s=new e;const n=await prepareClassParameters(t.material?.shaderParams??{},e,r,i,null,a,l,void 0,void 0,s);Object.assign(s,n),h=s.build()}catch(e){console.log("Shader runtime error: "+e,e),Ht.has(t.material.shader)||Ht.set(t.material.shader,Jt.clone()),h=Ht.get(t.material.shader)}h.userData.customShaderName=t.material.shader}else console.warn("Missing shader implementation with name "+t.material.shader),h=Jt;break;default:throw new Error("Unsupported material type "+t.material.type)}return a?.csm.setupMaterial(h),c&&null!=a&&qt.set(e,h),h.side=d??t.material.side??h.side??n.FrontSide,h.transparent=(m??t.material.transparent??u.transparent??!1)||h.transparent,h.alphaTest=t.material.alphaTest??h.alphaTest??0,null!=t.material.blending&&(h.blending=ve[t.material.blending]??n.NormalBlending),t.material.bloom&&(h.userData.hasBloom=!0),t.material.reflective&&(h.userData.reflective=!0),!0===t.material.outlines&&(h.userData.outlineParameters={},null!=t.material.outlineParams&&(null!=t.material.outlineParams.color&&(h.userData.outlineParameters.color=new o(t.material.outlineParams.color).toArray()),null!=t.material.outlineParams.thickness&&(h.userData.outlineParameters.thickness=t.material.outlineParams.thickness))),h.userData.assetId=t.id,c&&Yt.delete(e),h}export function prepareCustomParamsFromShaderGraph(e,t={}){return Object.fromEntries((e.parameters??[]).map(e=>{const a=function(e){switch(e){case"float":return ut.FloatNode;case"boolean":return ut.BooleanNode;case"texture":return ut.Sampler2DNode;case"vec2":return ut.Vec2Node;case"vec3":return ut.Vec3Node;case"vec4":return ut.Vec4Node;case"color":return ut.RgbNode}}(e.type),s=t[e.name],r=s?.override??null!=s,n=void 0!==e.defaultValue?e.defaultValue:customParameterDefaultValueByType.get(a),i=!1===r?oa(n):s?.value??oa(n);return[e.name,{type:a,value:i,override:r}]}))}export async function prepareShaderGraphParameters(e,t,a,s,r,n){const i={},o=prepareCustomParamsFromShaderGraph(t,e);for(const[e,t]of Object.entries(o)){const o=await Kt(e,t,a,s,null,r,n);null!=o&&(i[e]=o)}return i}export async function prepareClassParameters(e,t,a,s,r,n,i,o,l,c){const u={},{params:p,skipped:h}=ht(e,{parameterType:t,parameterTarget:c,extractPropertyParameters:Oe,toSerializedParamType:toSerializedParamType});for(const e of h)console.warn(`Skipping stored parameter "${e.key}" because it could not be converted from ${ut[e.sourceType]} to ${ut[e.targetType]}`);for(const[e,t]of Object.entries(p)){if(!1===t.override)continue;const c=await Kt(e,t,a,s,r,n,i,o,void 0,void 0,l);null!=c&&(u[e]=c)}return u}export async function prepareShapeParameters(e,t,a){const s={};for(const[r,n]of Object.entries(e)){const e=await Kt(r,n,t,a,null,void 0,void 0,void 0,void 0,void 0);null!=e&&(s[r]=e)}return s}const Xt=new Map;async function Kt(e,t,a,s,r,n,i,c,u=t.value,p=t.type,h,d=(t.type===ut.Struct?t.struct:void 0)){if(null==t||null==u||""===u)return null;switch(p){case ut.Array:if(Array.isArray(u)&&"element"in t)return await Promise.all(u.map(o=>Kt(e,t,a,s,r,n,i,c,o,t.element,h,t.elementStruct)));break;case ut.Number:case ut.FloatNode:let m;if("string"==typeof u?m=parseFloat(u):"number"==typeof u&&(m=u),p===ut.FloatNode){if("object"==typeof u&&"a"in u&&"b"in u){const e=u;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=Xt.get(e);return null==t&&(t=Se(bt.decode(e)),Xt.set(e,t)),t}(e.easing),r=s.sample(Ae(xe.energy));return B(F(t),F(a),r)}return new H($e(e),m,void 0,!1)}return m;case ut.Texture:let f=await s.getTexture(await a.getAsset(u));return"envmap"===e.toLowerCase()&&null!=n&&(f=n.getEnvTexture(f)),f;case ut.Sampler2DNode:const g=await a.getAsset(u);if(null!=g.texture?.textureArrayFileKey){const{texture:e,layerIndex:t}=await s.getTextureArray(g);if(e&&null!=t)return new X(null,e,F(t))}const y=await s.getTexture(g);return y?q(y):null;case ut.Boolean:return u;case ut.BooleanNode:return new J($e(e),u,void 0,!1);case ut.Vector2:case ut.Vec2Node:if("object"==typeof u){const t=u instanceof Array?(new A).fromArray(u):new A(u.x,u.y);return p===ut.Vec2Node?new K($e(e),t,void 0,!1):t}return null;case ut.Vector3:case ut.Vec3Node:if("object"==typeof u){const t=u instanceof Array?(new x).fromArray(u):new x(u.x,u.y,u.z);return p===ut.Vec3Node?new Z($e(e),t,void 0,!1):t}return null;case ut.Vector4:case ut.Vec4Node:if("object"==typeof u){const t=u instanceof Array?(new j).fromArray(u):new j(u.x,u.y,u.z,u.w);return p===ut.Vec4Node?new Q($e(e),t,void 0,!1):t}return null;case ut.Color:case ut.RgbNode:const w=new o(u);return p===ut.RgbNode?new Z($e(e),new x(w.r,w.g,w.b),void 0,!1).rgb:w;case ut.String:return u;case ut.BaseActor:const v=u;if(null==r&&console.warn("Class parameters can not be prepared as actors are not passed in"),null==v)return null;if("object"==typeof v&&null!=v.type&&null!=v.id){if("actor"===v.type)return r?.get(v.id)??null;if("prefab"===v.type){const e=h?h(v.id):null;if(null!=e)return r?.get(e)??null;const t=[];for(const[e,a]of r?.entries()??[])e.startsWith(v.id+"/")&&t.push(a);return 1===t.length?t[0]:null}}if("string"==typeof v){const e=r?.get(v);if(null!=e)return e;const t=h?h(v):null;if(null!=t)return r?.get(t)??null;const a=[];for(const[e,t]of r?.entries()??[])e.startsWith(v+"/")&&a.push(t);return 1===a.length?a[0]:null}return null;case ut.Euler:const b=u;return(new l).fromArray(b);case ut.Object3D:{const e=await a.getAsset(u);return(await s.getMesh(e,{applyMaterials:!0,rescale:!0})).scene}case ut.Material:{if(null==u)return null;const e=await a.getAsset(u);return null==e?(console.warn("Material asset not found for material parameter",u),null):null==e.material?(console.warn("Using a non-material asset for material parameter"),null):await materialFromAsset(e,n,a,s,i)}case ut.AudioBuffer:return await s.getAudio(await a.getAsset(u));case ut.VisualEffect:const M=await a.getAsset(u);if(null==c){console.error("Can not create instance of visual effect because missing actor provider");break}if("vfx"in M)return new pe(c,M);console.error("Using a non-vfx asset for visual effect parameter");break;case ut.Prefab:{const e=await a.getAsset(u);return null==e?(console.error("Using a non-prefab asset for prefab parameter",u),null):new he(e)}case ut.PrefabActor:{const e=await a.getAsset(u);return null==e?(console.error("Using a non-prefab asset for prefab parameter",u),null):new de(new he(e))}case ut.DataAsset:return materializeDataAssetRef(u,a,s,r,n,i,c,h);case ut.Sequence:{const e=await a.getAsset(u);if("sequence"===e.type&&"sequence"in e)return new Nt(e.sequence);console.error("Using a non-sequence asset for sequence parameter");break}case ut.Struct:return async function(e,t,a,s,r,n,i,o,l){const c=Zt(e),u=c?.struct??t;if(null==u)return console.warn("Missing parameter definition id for struct parameter"),null;const p=ke(u);if(null==p)return console.warn(`Unknown parameter definition "${u}"`),null;if(ze(u))return console.warn(`Can not instantiate abstract parameter definition "${u}"`),null;if(null!=t&&u!==t&&!Be(u,t))return console.warn(`Parameter definition "${u}" is not assignable to "${t}"`),null;let h;try{h=new p}catch(e){return console.warn(`Failed to instantiate parameter definition "${u}"`,e),null}const d=function(e){const t=Zt(e);if(null!=t)return t.value;if(Qt(e))return e;if(null!=e&&"object"==typeof e&&Qt(e.params))return e.params;return{}}(c?.value??e),m=await prepareClassParameters(d,null,a,s,r,n,i,o,l,h);return Object.assign(h,m),h}(u,d,a,s,r,n,i,c,h);case ut.Curve:return bt.decode(u);case ut.ColorLayer:case ut.MaskLayer:if(Ct(u)){const e=await At.decode(u,async e=>await s.getTexture(await a.getAsset(e))),t=await prepareClassParameters(u.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",u),null;case ut.AnimationClip:{const e="string"==typeof u?u:"object"==typeof u&&null!=u?u.assetId:null;if(null==e)return console.warn("Invalid animation clip asset id value",u),null;return await s.getAnimationClip(await a.getAsset(e))}}return null}export async function materializeDataAssetRef(e,t,a,s,r,n,i,o){const l="string"==typeof e?e:null!=e&&"object"==typeof e?e.assetId??e.id:null;if(null==l||""===l)return null;const c=await t.getAsset(l);if(null==c)return console.warn(`Data asset "${l}" was not found`),null;if("data"!==c.type||null==c.dataAsset)return console.warn("Using a non-data asset for data asset parameter",l),null;const u=c.dataAsset.definition;if(null==u||""===u)return console.warn(`Missing data asset definition id for asset "${c.id}"`),null;if(Fe(u))return console.warn(`Can not instantiate abstract data asset definition "${u}"`),null;const p=Ve(u);if(null==p)return console.warn(`Unknown data asset definition "${u}"`),null;let h;try{h=new p}catch(e){return console.warn(`Failed to instantiate data asset definition "${u}"`,e),null}const d=c.dataAsset.params??{};if("object"!=typeof d||Array.isArray(d))return console.warn(`Invalid data asset params for asset "${c.id}"`),null;try{const e=await prepareClassParameters(d,null,t,a,s,r,n,i,o,h);Object.assign(h,e)}catch(e){return console.warn(`Failed to materialize data asset "${c.id}"`,e),null}return new me(c,h)}function Zt(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)&&"string"==typeof e.struct&&Qt(e.value)?e:null}function Qt(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)&&Object.values(e).every(e=>null!=e&&"object"==typeof e&&"type"in e)}function ea(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 ta(e){return"linear"===e.type?new c(new o(e.color),e.near??100,e.far??1e3):"density"===e.type?new u(e.color,e.density):void console.warn("Invalid fog type",e)}new y({color:4229780});async function aa(e,t,a,s){null==s&&(s=(new d).identity());const r=s.clone().multiply(sa(e,new n.Matrix4));if(null!=e.children&&e.children.length>0)for(let a=e.children.length-1;a>=0;a--)await aa(e.children[a],t,e,r);await t(e,a,s)}function sa(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){if(null==e)return;const t=e.constructor.prototype;return t instanceof Number||e===Number?ut.Number:t instanceof z||"function"==typeof e.prototype.isFloat?ut.FloatNode:t instanceof S||e===S||e.isTexture?ut.Texture:t instanceof je||e===je||e===R||"function"==typeof e.prototype?.isSampler2D||!0===e.prototype?.isSampler2D?ut.Sampler2DNode:t instanceof Boolean||e===Boolean?ut.Boolean:t instanceof E?ut.BooleanNode:t instanceof o||e==o?ut.Color:t instanceof G||"function"==typeof e.prototype.isRgb?ut.RgbNode:t instanceof A||e==A?ut.Vector2:t instanceof re||"function"==typeof e.prototype.isVec2?ut.Vec2Node:t instanceof x||e==x?ut.Vector3:t instanceof ie||"function"==typeof e.prototype.isVec3?ut.Vec3Node:t instanceof j||e==j?ut.Vector4:t instanceof le||"function"==typeof e.prototype.isVec4?ut.Vec4Node:t instanceof String||e===String?ut.String:t instanceof fe||e==fe||e.prototype instanceof fe||e.prototype==fe?ut.BaseActor:t instanceof l||e==l?ut.Euler:t instanceof w||e==w?ut.Object3D:t instanceof h||e==h?ut.Material:t instanceof AudioBuffer||e==AudioBuffer?ut.AudioBuffer:t instanceof pe||e==pe?ut.VisualEffect:t instanceof he||e==he?ut.Prefab:t instanceof de||e==de?ut.PrefabActor:t instanceof me||e==me?ut.DataAsset:t instanceof bt||e==bt?ut.Curve:t instanceof At||e==At?ut.ColorLayer:t instanceof It||e==It?ut.MaskLayer:t instanceof n.AnimationClip||e==n.AnimationClip?ut.AnimationClip:t instanceof Nt||e==Nt||"SequenceData"===e.name||e.prototype&&"tracks"in e.prototype?ut.Sequence:null!=Ee(e)?ut.Struct:void console.warn("Failed to map parameter type to serialized version",{type:e})}export function getCustomParamTypeInfo(e){const t=toSerializedParamType(e.type),a=t===ut.Struct?Ee(e.type):void 0;return!0===e.options.array?{type:ut.Array,element:t,...null!=a?{elementStruct:a}:{}}:{type:t,...null!=a?{struct:a}:{}}}export function prepareCustomParams(e,t,a={},s={}){return Object.fromEntries(e.map(e=>{const r=getCustomParamTypeInfo(e);let n=r;const i=t[e.name],o=!0===s.treatAllAsOptional||!0===e.options.optional,l=s.missingOverrideDefaultsToOverride??!0;let c=i?.override;void 0===c&&null!=i&&o&&l&&(c=!0),void 0===c&&o&&(c=!1);const u=void 0!==a[e.name]||void 0!==e.options.defaultValue,p=function(e,t){if(e.type!==ut.Struct)return{typeInfo:e,value:t};const a=Zt(t);if(null==a)return{typeInfo:e,value:t};return{typeInfo:{...e,struct:a.struct},value:a.value}}(n,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}const a=toSerializedParamType(e.type);if(a===ut.Struct)return ze(e.type)?{}:prepareCustomParamsFromType(e.type,{});return customParameterDefaultValueByType.get(a)}(e,a));n=function(e,t,a){if(e.type!==ut.Struct||a?.type!==ut.Struct||null==a.struct)return e;const s=t.struct??e.struct;if(null==s||a.struct===s||Be(a.struct,s)||null==ke(a.struct))return{...e,struct:a.struct};return e}(p.typeInfo,r,i);const h=!1!==c||e.options.array?i?.value??function(e,t,a){if(!0===e.options.array)return a?oa(t):[];return oa(t)}(e,p.value,u):oa(p.value);return[e.name,{...n,value:h,override:c}]}))}function ra(e){return null==e?{}:Object.fromEntries(Object.entries(e).filter(([,e])=>function(e){return!0===e?.override}(e)))}function na(e,t){return e.length>=t.length&&t.every((t,a)=>e[a]===t)}export function prepareCustomParamsFromType(e,t,a=null,s={}){const r=Oe(e);if(0===r.length)return{};let n;null!=a?be(a,()=>{n=a.get(e)}):n=new e;const i={};for(const e of r){const t=n[e.name];if(null!=t){const a=ia(e,t);void 0!==a&&(i[e.name]=a)}}return prepareCustomParams(r,t,i,s)}function ia(e,t){return!0===e.options.array?Array.isArray(t)?t.map(t=>serializeCustomParameter(e.type,t)??t):[]:serializeCustomParameter(e.type,t)}function oa(e){return null==e?e:Array.isArray(e)?e.map(e=>oa(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 he:return t instanceof he?t.asset?.id??null:void a();case me:return t instanceof me?t.id:"string"==typeof t?t:void a()}const s=Ee(e);if(null!=s){const r=Zt(t);if(null!=r)return r.struct===s?r.value:r;const n=function(e,t){if(null==t||"object"!=typeof t)return e;const a=t.constructor;return null!=Ee(a)&&Ne(a,e)?a:e}(e,t),i=Ee(n),o=function(e,t){if(null==t)return null;if(Qt(t))return t;if(null!=t&&"object"==typeof t&&Qt(t.params))return t.params;if("object"!=typeof t)return;const a=Oe(e),s={};for(const e of a){const a=t[e.name];if(void 0===a)continue;const r=ia(e,a);void 0!==r&&(s[e.name]=r)}return prepareCustomParams(a,{},s)}(n,t);return void 0!==o?null!=o&&null!=i&&i!==s?{struct:i,value:o}:o:void a()}if(t&&"object"==typeof t&&"tracks"in t&&"duration"in t)return t}function la(e,t){return function(e,t,a){const s=[],r=new Set;for(const n of[...e??[],...t??[]]){const e=a(n);r.has(e)||(r.add(e),s.push(n))}return s}((e??[]).filter(e=>ca(e.materialId)),(t??[]).filter(e=>ca(e.materialId)),e=>e.color+e.name)}function ca(e){return"null"!=e&&null!=e}export const customParameterDefaultValueByType=new Map([[ut.RgbNode,"#000000"],[ut.Color,"#000000"],[ut.String,""],[ut.Vector4,[0,0,0,0]],[ut.Vec4Node,[0,0,0,0]],[ut.Vector3,[0,0,0]],[ut.Vec3Node,[0,0,0]],[ut.Vector2,[0,0]],[ut.Vec2Node,[0,0]],[ut.Euler,[0,0,0,"XYZ"]],[ut.Array,[]],[ut.DataAsset,null],[ut.ColorLayer,xt],[ut.MaskLayer,jt]]);let ua=new o;new o;function pa(e){return null==e?.color?null:(ua.set(e.color),"#"+ua.getHexString())}function ha(e,t,a,s){const r="string"==typeof t.name&&""!==t.name?t.name:null;if(null!=r)return e.name===r||s===r;const n=pa(e);return null!=n&&(n===t.color||a===t.color)}export function applyMaterial(e,t,a,s,r={}){const i=[];return e.traverse(async e=>{if(e instanceof m||e.isMesh||e instanceof n.SkinnedMesh||e.isSkinnedMesh)for(const t of We(e.material))t.hasOwnProperty("color")&&i.push(e)}),Promise.all(i.map(async e=>{if(e.material instanceof Array)for(let n=0;n<e.material.length;n++){const i=e.material[n];if(null==i.color||!(i.color instanceof o))continue;const l=pa(i),c=i.name;if(ha(i,t,e.userData["originalColor_"+n],e.userData["originalMaterialName_"+n])){const i=ma(await a(t.materialId),r.textureFlipY),o=e.material[n];null!=i&&o.id!=i.id&&(e.material[n]=i,e.userData["originalColor_"+n]=e.userData["originalColor_"+n]??l,e.userData["originalMaterialName_"+n]=e.userData["originalMaterialName_"+n]??c,null!=s&&s.set(e.id+"#"+n,o))}}else if("color"in e.material){const n=e.material,i=pa(n),o=n.name;if(ha(n,t,e.userData.originalColor,e.userData.originalMaterialName)){const n=ma(await a(t.materialId),r.textureFlipY),l=e.material;null!=n&&(e.material=n,e.userData.originalColor=e.userData.originalColor??i,e.userData.originalMaterialName=e.userData.originalMaterialName??o,null!=s&&(s.has(e.id)||s.set(e.id,l)))}}}))}const da=new WeakMap;export function getConvertedFbxToGlbAssignedMaterialTextureFlipY(e){const t=e?.mesh?.uvConversion;return"fbx2gltf"===t?.source?!0!==t.flipV&&void 0:!function(e){return"glb"===e?.fileFormat&&!0===e.originalFileKey?.toLowerCase().endsWith(".fbx")}(e)&&void 0}function ma(e,t){if(null==e||null==t||!function(e,t){return function(e){const t=[];for(const[a,s]of Object.entries(e))fa(a,s)&&t.push(s);if(e instanceof n.ShaderMaterial)for(const[a,s]of Object.entries(e.uniforms))fa(a,s.value)&&t.push(s.value);return t}(e).some(e=>e.flipY!==t)}(e,t))return e;let a=da.get(e);null==a&&(a=new Map,da.set(e,a));const s=a.get(t);if(null!=s)return s;const r=e.clone();if(function(e,t){for(const a of Object.keys(e)){const s=e[a];fa(a,s)&&(e[a]=ga(s,t))}}(r,t),r instanceof n.ShaderMaterial){for(const[e,a]of Object.entries(r.uniforms))fa(e,a.value)&&(a.value=ga(a.value,t));r.uniformsNeedUpdate=!0}return r.needsUpdate=!0,a.set(t,r),r}function fa(e,t){const a=t;return(t instanceof S||!0===a?.isTexture)&&!e.toLowerCase().includes("envmap")&&!0!==a.isCompressedTexture&&!0!==a.isCompressedArrayTexture}function ga(e,t){if(e.flipY===t)return e;const a=e.clone();return a.flipY=t,a.userData={...e.userData??{}},a.needsUpdate=!0,a}function ya(e,t){if(e instanceof n.ShaderMaterial&&t instanceof n.ShaderMaterial){return e.fragmentShader+e.vertexShader==t.fragmentShader+t.vertexShader&&function(e,t){if(e instanceof n.ShaderMaterial&&t instanceof n.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 wa(e){if(null!=e){for(let t=0;t<e.array.length;t++)e.setX(t,0);e.needsUpdate=!0}}const va=new WeakMap;function ba(e){let t=va.get(e);return null==t&&(t=function(e){const t=qe(e);if(null==t)return"";return Object.keys(t.geometry.attributes).sort().join(",")}(e),va.set(e,t)),t}const Ma=new WeakMap;function Sa(e){let t=Ma.get(e);return null==t&&(t=function(e){let t=e.type;e instanceof n.MeshStandardMaterial&&!(e instanceof n.MeshPhysicalMaterial)||(t+=e.id+"");(e instanceof n.MeshBasicMaterial||e instanceof n.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 n.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 n.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 Et&&null!=e.heightMap&&(t+="h"+e.heightMap?.id);if(e instanceof n.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),Ma.set(e,t)),t}function Aa(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 xa=new d,ja=new l;function Ia(e,t){return ja.copy(e),ja.x*=-1,ja.y*=-1,ja.z*=-1,t.isCubeTexture&&!1===t.isRenderTargetTexture&&(ja.y*=-1,ja.z*=-1),(new n.Matrix3).setFromMatrix4(xa.makeRotationFromEuler(ja))}function Pa(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 Ca=new j;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 n.Color&&t instanceof n.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 Ta(e){const t=[];for(const[a,s]of Object.entries(e))s instanceof pe?t.push(s):s instanceof ye&&t.push(...Ta(s));return t}function Oa(e,t){if(!(t instanceof n.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 Va(e,t,a){if(t(e))return e;for(const s of e.children??[]){const e=Va(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=>Va(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 n from"three";import{BoxGeometry as i,Color as o,Euler as l,Fog as c,FogExp2 as u,Group as p,Material as h,Matrix4 as d,Mesh as m,MeshLambertMaterial as f,MeshPhongMaterial as g,MeshStandardMaterial as y,Object3D as w,PointLight as v,Quaternion as b,Scene as M,Texture as S,Vector2 as A,Vector3 as x,Vector4 as j}from"three";import{attributes as I,batchingUniformFloat as P,batchingUniformVec2 as C,batchingUniformVec3 as D,batchingUniformVec4 as T,bool as O,BooleanExpression as V,BooleanNode as E,colorToNormal as k,float as F,FloatNode as z,ifDefApply as N,mix as B,NodeShaderMaterial as $,rgb as _,rgba as U,RgbNode as G,select as W,standardMaterial as L,Texture2dLookupNode as R,textureSampler2d as q,textureSampler2dArray as Y,UniformBoolNode as J,UniformFloatNode as H,UniformSampler2dArraySlice as X,UniformVec2Node as K,UniformVec3Node as Z,UniformVec4Node as Q,varying as ee,varyingAttributes as te,varyingTransformed as ae,vec2 as se,Vec2Node as re,vec3 as ne,Vec3Node as ie,vec4 as oe,Vec4Node as le}from"three-shader-graph";import{Service as ce}from"typedi";import{VfxActor as ue}from"../effects/vfx/vfx-actor.js";import{VisualEffect as pe}from"../effects/vfx/vfx-param.js";import{Prefab as he,PrefabOf as de}from"./objects/prefab.js";import{DataAssetRef as me}from"./objects/data-asset.js";import{BaseActor as fe}from"../gameplay/actors/actor.js";import ge from"../gameplay/actors/builtin/index.js";import{ActorComponent as ye}from"../gameplay/actors/component.js";import{PhysicsBodyType as we}from"../gameplay/services/physics/physics-system.js";import{ThreeBlendingMode as ve}from"../effects/vfx/vfx-asset.js";import{withInjectionContext as be}from"../gameplay/inject.js";import{RenderingView as Me}from"../rendering.js";import{curveSampler as Se,oneMinus as Ae,particleUniforms as xe,Sampler2DNode as je}from"../shader-nodes/index.js";import{LambertShader as Ie}from"../shader/builtin/lambert-shader.js";import{LandscapeCompositeShader as Pe}from"../shader/builtin/landscape-composite-shader";import{LandscapeShader as Ce}from"../shader/builtin/landscape-shader.js";import{StandardShader as De}from"../shader/builtin/standard-shader.js";import{UnlitShader as Te}from"../shader/builtin/unlit-shader.js";import{extractShaderParameters as Oe,getDataAssetDefinitionType as Ve,getParameterDefinitionId as Ee,getParameterDefinitionType as ke,isDataAssetDefinitionAbstract as Fe,isParameterDefinitionAbstract as ze,isParameterDefinitionAssignableTo as Ne,isParameterDefinitionStructAssignableTo as Be,shaderParameterUniformName as $e}from"../shader/parameter.js";import{ArrayMap as _e,DefaultMap as Ue,groupBy as Ge}from"../utils/collections.js";import{iterateMaterials as We}from"../utils/materials.js";import{filterChildrenShallow as Le,filterSceneShallow as Re,findFirstVisibleMesh as qe,findFirstVisibleObject as Ye,traverseAsync as Je}from"../utils/three/traverse.js";import{AssetMeshInstance as He,AssetResourceLoader as Xe}from"./asset-resource-loader.js";import{AssetsProvider as Ke}from"./assets-provider.js";import{isCollisionMesh as Ze}from"./collision/collision-shape-import.js";import{BoxCollisionShape as Qe,PhysicalShapeMesh as et}from"./collision/collision-shape.js";import{LandscapeManager as tt}from"./landscape/landscape-manager.js";import{initLandscape as at}from"./landscape/landscape.js";import{SectionGrid as st,smoothNormalsCrossMeshes as rt}from"./landscape/utils.js";import{createGrassFoliageMaterial as nt}from"./materials/grass-foliage.js";import{createGrassMaterial as it}from"./materials/grass.js";import{getMaterialAttribute as ot}from"./materials/utils/material-painting.js";import{SurfaceScatterManager as lt}from"./scatter/surface-scatter-manager.js";import{createWaterMaterial as ct}from"./materials/water.js";import{SerializedParamType as ut}from"./model.js";import{applyRuntimeParamTypeInference as pt,convertConfiguredParamsToRuntimeTypes as ht,convertConfiguredParamValueToRuntimeType as dt,inferRuntimeSerializedParamTypeHint as mt}from"./custom-param-runtime-types.js";import{ShapeLibrary as ft,ShapeLibraryKeys as gt}from"./objects/shapes.js";import{ambientLightName as yt,createSky as wt,defaultSkyMaterial as vt}from"./sky.js";import{Curve2 as bt}from"../utils/curve.js";import{DecalUnlitShader as Mt}from"../shader/builtin/decal-unlit-shader.js";import{DecalStandardShader as St}from"../shader/builtin/decal-standard-shader.js";import{ColorLayer as At,defaultValueColorLayer as xt,defaultValueMaskLayer as jt,MaskLayer as It}from"../shader/color-layer.js";import{LayeredShader as Pt}from"../shader/builtin/layered-shader";import{isColorLayerSerialized as Ct}from"../shader/color-layer";import{FogVolume as Dt}from"../rendering/fog/fog-volume-actor.js";import{UnscaledSprite as Tt}from"../utils/three/unscaled-sprite.js";import{ToonShader as Ot}from"../shader/builtin/toon-shader.js";import{BatchedMesh2 as Vt}from"./batched-mesh-2.js";import{ParallaxStandardMaterial as Et}from"../shader/builtin/standard-shader";import{parallaxOcclusionMapping as kt}from"../shader-nodes/pom.js";import{traverseVisibleEvery as Ft}from"../utils/three/traverse";import{RectAreaLightHelper as zt}from"three/examples/jsm/Addons.js";import{Sequence as Nt}from"../effects/sequence/sequence-data.js";import{applyUvTiling as Bt}from"./../shader/uv-nodes.js";import{buildShaderGraphMaterial as $t,shaderGraphMaterialSideToThree as _t}from"../shader/graph/index.js";export{pt as applyRuntimeParamTypeInference,ht as convertConfiguredParamsToRuntimeTypes,dt as convertConfiguredParamValueToRuntimeType,mt as inferRuntimeSerializedParamTypeHint};const Ut={},Gt=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),Wt=/^((?!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 Lt(e,this.dataProvider,this.assetsService,this.assetManagerService,t,[],[],{create:()=>null,initActor:async()=>{}})}}let Lt=class{constructor(e,t,a,s,i,o,l,c,u=[]){this.scene=e,this.dataProvider=t,this.assetsService=a,this.assetManagerService=s,this.renderingView=i,this.shaders=o,this.actorTypes=l,this.actorProvider=c,this.componentTypes=u,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 n.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=>Va(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 aa(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 aa(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 n.ShaderMaterial)for(const[e,s]of Object.entries(t.uniforms))s.value instanceof n.Texture&&s.value.userData.assetId===a.id&&(t.uniforms[e].value=r);else for(const[e,s]of Object.entries(t))s instanceof n.Texture&&s.userData.assetId===a.id&&(t[e]=r);else console.error("Can not refresh material textures. Texture not found",a)}async getAsset(e){let t=this.assets.get(e);return null==t&&(t=await this.assetsService.getAsset(e),null!=t&&this.assets.set(e,t)),t}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===ut.Material&&s.value===a.id){t=!0;break}if(s.type===ut.Array&&"element"in s&&s.element===ut.Material&&s.value.includes(a.id)){t=!0;break}}if(!t)return}const n=await materialFromAsset(this.assets.get(r),this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!1),i=n.userData;n.userData=t.userData,n.userData.hasBloom=i.hasBloom,n.userData.reflective=i.reflective,n.userData.outlineParameters=i.outlineParameters,null!=s?ya(e.material[s],n)||(e.material[s]=n):ya(e.material,n)||(e.material=n,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===ut.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=this.collectAssetMeshIds(this.dataProvider.getObjects());await Promise.all(Array.from(e).map(async e=>{const t=this.assets.get(e);if("mesh"===t?.type)return this.assetManagerService.getMesh(t,{mergeGeomtries:!0})})),this.initTextures()}collectAssetMeshIds(e,t=[],a=new Set){for(const s of e??[])this.collectObjectAssetMeshIds(s,t,a);return a}collectObjectAssetMeshIds(e,t,a){if(this.shouldBeMaterialized(e)&&("asset_mesh"===e.type&&null!=e.assetId&&a.add(e.assetId),null!=e.children&&this.collectAssetMeshIds(e.children,t,a),"prefab"===e.type&&null!=e.assetId&&!t.includes(e.assetId))){const s=this.assets.get(e.assetId);null!=s?.prefab?.objects&&this.collectAssetMeshIds(s.prefab.objects,[...t,e.assetId],a)}}async init(){await this.preInit(),qt.clear(),Yt.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 M;for(const s of this.actorInstances){const r=Ta(s);for(const s of r){const r=s.asset;if(e.has(r.id))continue;e.add(r.id),r.vfx.emitters;const n=await s.create(a);a.add(n.object),a.add(n.particleSystemContainer),n.play(),n.onUpdate(.5),n.stop(),n.pause(),t.push(n)}}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="prefab"===a.type?await this.assetsService.getAsset(a.assetId):null,r=e.split("/"),n=r.slice(0,-1),i=n.join("/"),o=(r[r.length-1],new Map);for(const[e,t]of this.materializedActors)if(o.set(e,t),0===i.length)e.includes("/")||o.set(e,t);else if(e.startsWith(i+"/")){const a=e.slice(i.length+1);a.includes("/")||o.set(a,t)}const l={...s?.actor?.params??{},...a.actor?.params??{}},c=[...a.actor?.innerParams??[]];for(let t=n.length-1;t>=0;t--){const a=n.slice(0,t+1).join("/"),s=this.idToSceneObject.get(a);if("prefab"===s?.type&&null!=s.prefab){const n=await this.assetsService.getAsset(s.assetId);if(null!=n){let i=!1,o=a+"/"+n.prefab?.mainActorId;for(;null!=o;){if(o===e){i=!0;break}o=this.prefabInstanceExposedActorMap.get(o)}if(i&&null!=s.prefab.params&&Object.assign(l,ra(s.prefab.params)),null!=s.prefab.innerParams){const e=r.slice(t+1);for(const t of s.prefab.innerParams){const a=ra(t.params);0!==Object.keys(a).length&&(i?c.push({path:na(t.path,e)?t.path.slice(e.length):t.path,params:a}):na(t.path,e)&&c.push({path:t.path.slice(e.length),params:a}))}}}}}for(const e of c)await this.applyActorComponentParams(t,e.path.slice(),e.params,o);await this.attachEditorComponents(t,a,o);const u=await prepareClassParameters(l,t.constructor,this.assetsService,this.assetManagerService,o,this.renderingView,this.shaders,this.actorProvider,e=>{const t=i.length>0?i+"/"+e:e;return this.prefabInstanceExposedActorMap.get(t)??null},t);Object.assign(t,u);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 n=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,n);Object.assign(n,e)}for(const e of r.innerParams??[])await this.applyActorComponentParams(n,e.path.slice(),e.params,a)}}addVfxChildActors(e,t=e){}async applyActorComponentParams(e,t,a,s){const r=t.length,n=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[n]&&await this.applyActorComponentParams(e[n],t,a,s)}canObjectBeInstanced(e){return e.physics?.type!==we.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=>{!Ze(e)&&e.isMesh&&s.push(e)});const r=1==s.length&&0==s[0].children.length,n=!Wt,i=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||i&&n)&&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)}),await this.preloadAssets()}async preloadAssets(){const e=await this.assetsService.getAssets();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(),qt.clear(),Yt.clear();const e=[],t=new _e,a=new _e,s=new _e;let r=0,i=0,c=0;const u=new Map,p=new Ue(()=>new Map);for(const n of this.dataProvider.getObjects())await aa(n,async(n,l,h)=>{if(!this.shouldBeMaterialized(n))return;const d="asset_mesh"==n.type&&this.canObjectBeInstanced(n)&&await this.canAssetBeInstanced(n),f="shape_mesh"===n.type&&"landscape"!==n.shape&&n.physics?.type!==we.dynamic;if(d||f){if(l&&l.children?.length>0){const e=l.children.findIndex(e=>e.id===n.id);e>=0&&l.children.splice(e,1)}if(f){let e=n.shape+JSON.stringify(n.shapeParams??{})+n.castShadow+n.receiveShadow;const t=n.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===ut.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:{...n,parentTransform:h},color:r}),c++}else{const e=this.assets.get(n.assetId);let s=u.get(n.assetId);if(null==s){const e=await this.createFromAsset(n,{assignMaterials:!1});if(null==e)return;if(s=u.get(n.assetId),null==s){s={useBatchedMesh:null!=qe(e)&&Ft(e,e=>!(e instanceof m)||this.testCanBatch(e.material,e.geometry)),assetMesh:e},u.set(n.assetId,s)}}const o=la(n.materialAssignments,e.materialAssignments);if(s.useBatchedMesh)await Je(s.assetMesh,async t=>{if(!(t instanceof m))return;const s=Array.isArray(t.material)?t.material[0]:t.material,i=await this.resolveMaterialForAssignments(s,o,e);if(null!=i){p.get(n.id).set(t.uuid,i),Oa(t.geometry,i);let e=Sa(i);e+=ba(t),a.push(e,{...n,parentTransform:h,meshUUID:t.uuid}),r++}else console.warn("Can not materialize mesh because missing material",n)});else{const e=n.assetId+JSON.stringify(n.materialAssignments??[]);t.push(e,{...n,parentTransform:h}),i++}}}else null==l&&e.push({...n,parentTransform:h})});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 ${i} 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 u.values())this.prepareCollisionShapesForInstanced(e.assetMesh);console.time("materialize batches");for(const[e,t]of a.entries()){if(0==t.length)continue;let e;u.get(t[0].assetId).assetMesh;e=this.createBatchedMesh(t,p,u);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 He;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=u.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 He;r.add(t),r.userData.src=e[0],a instanceof He&&(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=Ye(a,e=>!Ze(e)&&null!=e.geometry),r=s.material.clone();null!=e[0].color&&null!=r.color&&(r.color=new o(16777215));const i=s.geometry;let c,u;!(Wt||r instanceof $||null==i.index)?(c=new n.BatchedMesh(e.length,i.getAttribute("position").count,i.index.count,r),c.perObjectFrustumCulled=!0,u=c.addGeometry(i)):c=new n.InstancedMesh(i,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 n.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 i;i=c instanceof n.BatchedMesh?c.addInstance(u):t,c.setMatrixAt(i,r),a.color}for(let t=0;t<e.length;t++){const s=e[t],r=new He;r.userData.src=e[0],a instanceof et&&(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 He&&e.collisionShapes.forEach(e=>{e instanceof a&&e.mesh instanceof m&&(e.mesh=e.mesh.geometry)})}testCanBatch(e,t){return!Wt&&(!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 _e;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,i=0,l=0;const c=new Map;for(const[e,t]of s.entries()){const s=t[0].assetId,n=a.get(s);if(null==n){console.warn("Missing batching info for asset id "+s);continue}const o=Ye(n.assetMesh,t=>t instanceof m&&t.uuid===e);if(null==o){console.warn("Missing mesh in batched asset");continue}c.set(e,o);const u=o.geometry.getAttribute("position");null==u&&console.warn("Missing position attribute for batched mesh"),r+=o.geometry.index.count*t.length,i+=u.count*t.length,l+=t.length}const u=["color","map","roughness","roughnessMap","metalness","metalnessMap","opacity","alphaMap","aoMap","aoMapIntensity","normalMap","normalScale","emissive","emissiveIntensity","emissiveMap"];let p=new Map;const h=[];let d=new n.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 n.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 u){let r=e[t];r instanceof n.CompressedArrayTexture&&null!=r.userData.index&&(r=r.userData.index);const i=s.get(t);void 0===i||Da(r,i)?s.set(t,r):a.add(t)}}for(const e of a){let t;const a=f[e];if("number"==typeof a){let a=h.find(e=>e.params.length<4);if(null==a){const t="vp"+h.length;a={name:t,params:[e],node:T(t)},h.push(a)}else a.params.push(e);t=Pa(a.node,a.params.length-1)}else if(a instanceof j)t=T(e);else if(a instanceof x||a instanceof o)t=D(e);else if(a instanceof A)t=C(e);else if(a instanceof n.CompressedArrayTexture)t=P(e+"_i");else if(a instanceof S)continue;p.set(e,t)}let r=te.uv;f instanceof Et&&null!=f.heightMap&&(r=kt(r,q(f.heightMap),F(f.heightScale)));let i=Aa(p.get("opacity"),z)??F(f.opacity??1);if(null!=f.alphaMap){let e;if(f.alphaMap instanceof n.CompressedArrayTexture){const t=Y(f.alphaMap),a=Aa(p.get("alphaMap"),z)??F(f.alphaMap.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.alphaMap).sample(r);i=i.multiply(e.r)}let l=U(Aa(p.get("color"),ie)??f.color,i);if(null!=f.map){let e;if(f.map instanceof n.CompressedArrayTexture){const t=Y(f.map),a=Aa(p.get("map"),z)??F(f.map.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.map).sample(Bt(r,f.map));l=l.multiply(e),i=i.multiply(e.a)}f.vertexColors&&(l=l.multiply(oe(ee(I.color.rgb),1)));let c=U(Aa(p.get("emissive"),ie)??f.emissive,i);if(null!=f.emissiveMap){let e;if(f.emissiveMap instanceof n.CompressedArrayTexture){const t=Y(f.emissiveMap),a=Aa(p.get("emissiveMap"),z)??F(f.emissiveMap.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.emissiveMap).sample(Bt(r,f.emissiveMap));c=c.multiply(e)}const m=Aa(p.get("emissiveIntensity"),z)??F(f.emissiveIntensity??1),g=Aa(p.get("normalScale"),re)??se(f.normalScale??new A(1,1));let y=ae.normal;if(null!=f.normalMap){let e;if(f.normalMap instanceof n.CompressedArrayTexture){const t=Y(f.normalMap),a=Aa(p.get("normalMap"),z)??F(f.normalMap.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.normalMap).sample(Bt(r,f.normalMap));y=k(e.rgb,g.x)}let w=Aa(p.get("roughness"),z)??F(f.roughness??1);if(null!=f.roughnessMap){let e;if(f.roughnessMap instanceof n.CompressedArrayTexture){const t=Y(f.roughnessMap),a=Aa(p.get("roughnessMap"),z)??F(f.roughnessMap.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.roughnessMap).sample(Bt(r,f.roughnessMap));w=w.multiply(e.g)}let v=Aa(p.get("metalness"),z)??F(f.metalness??0);if(null!=f.metalnessMap){let e;if(f.metalnessMap instanceof n.CompressedArrayTexture){const t=Y(f.metalnessMap),a=Aa(p.get("metalnessMap"),z)??F(f.metalnessMap.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.metalnessMap).sample(Bt(r,f.metalnessMap));v=v.multiply(e.b)}let b=F(1);if(null!=f.aoMap){let e;if(f.aoMap instanceof n.CompressedArrayTexture){const t=Y(f.aoMap),a=Aa(p.get("aoMap"),z)??F(f.aoMap.userData.index??0);e=t.sample(ne(r.x,r.y,a))}else e=q(f.aoMap).sample(Bt(r,f.aoMap));b=b.multiply(e.r)}const M=Aa(p.get("aoMapIntensity"),z)??F(f.aoMapIntensity??0);let O=y;!0!==f.userData.disableAO&&(O=N("DOUBLE_SIDED",O,e=>W(new V("gl_FrontFacing"),e,e.multiplyScalar(-1))));const E=new $({color:L({color:l,roughness:w,metalness:v,ambientOcclusion:b,ambientOcclusionIntensity:M,emissive:c,emissiveIntensity:m,normal:O}),normal:y,roughness:w,emissive:c.rgb,transparent:f.transparent,alphaTest:f.alphaTest,envMap:f.envMap,opacity:i});null!=f.envMap&&(E.uniforms.envMapIntensity={value:f.envMapIntensity},E.uniforms.envMapRotation={value:Ia(f.envMapRotation,f.envMap)}),E.envMap=f.envMap,E.side=f.side,d=E}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 Vt(l,i,r,d);for(const e of h)g.initUniform(e.name,4);for(const[e,t]of p.entries()){if(h.some(t=>t.params.includes(e)))continue;let a=1;t instanceof le||t instanceof ie?a=4:t instanceof re&&(a=2),g.initUniform(e,a,0)}for(const[e,r]of s.entries()){const s=r[0].assetId,i=c.get(e);if(null==i){console.error(`Missing single asset mesh for mesh uuid ${e} and asset id ${s}`);continue}if(null==i.geometry){console.error("Missing geometry on mesh mesh");continue}const l=g.addGeometry(i.geometry),u=a.get(s);if(null==u){console.warn("Missing batching info when configuring for asset id "+s);continue}const d=qe(u.assetMesh)?.uuid===e,m=u.assetMesh instanceof He&&d?u.assetMesh.collisionShapes:void 0,f=this.configureBatchedInstancedMesh(r,g,i,l,m);for(let e=0;e<f.length;e++){const a=r[e],s=f[e],i=t.get(a.id).get(a.meshUUID);for(const e of h){let t=Ca.set(0,0,0,0);for(let a=0;a<e.params.length;a++){const s=i[e.params[a]];"number"==typeof s&&t.setComponent(a,s)}g.setUniformAt(e.name,s,t)}for(let e of p.keys()){if(h.some(t=>t.params.includes(e)))continue;let t=i[e];if(t instanceof o&&(t=new x(t.r,t.g,t.b)),t instanceof n.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=Ye(t,e=>!Ze(e)&&null!=e.geometry),s=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(t,la(e[0].materialAssignments,s.materialAssignments),s),a.updateMatrix();const r=a.geometry.clone(),i=a.material;let o;if(o=new n.InstancedMesh(r,i,e.length),this.configureBatchedInstancedMesh(e,o,a),a.material instanceof h&&o.castShadow&&o.receiveShadow&&Array.isArray(i))for(const e of i);return o}configureBatchedInstancedMesh(e,t,a,s,r){const i=[];a.updateWorldMatrix(!0,!0);for(let o=0;o<e.length;o++){let c=o;t instanceof n.BatchedMesh&&(c=t.addInstance(s)),i.push(c);const u=(new n.Matrix4).compose((new x).fromArray(e[o].position),(new b).setFromEuler((new l).fromArray(e[o].rotation)),(new x).fromArray(e[o].scale)),p=(new d).copy(e[o].parentTransform).multiply(u).multiply(a.matrixWorld);t.setMatrixAt(c,p),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 i}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 Re(this.scene,t=>t.userData.src?.assetId==e,e=>null!=e.userData.src)}applyMaterials(e,t,a){return null==t?Promise.resolve([]):Promise.all(t.filter(e=>"null"!==e.materialId).map(t=>this.applyMaterial(e,t,a)))}async applyMaterial(e,t,a){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,{textureFlipY:getConvertedFbxToGlbAssignedMaterialTextureFlipY(a)})}async resolveMaterialForAssignments(e,t,a){let s=e,r=null,n=null;const i=getConvertedFbxToGlbAssignedMaterialTextureFlipY(a);for(const e of t??[]){if(!ha(s,e,r,n))continue;const t=this.assets.get(e.materialId);if(null==t){console.warn("Missing material with id "+e.materialId);continue}let a=await materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!0);null!=a&&(a=ma(a,i)),null!=a&&s.id!==a.id&&(r=r??pa(s),n=n??s.name,s=a)}return s}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(ge));Re(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,Re(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 qt.entries())t.userData.customShaderName&&qt.delete(e);this.landscapeManagers.forEach(t=>t.updateShaders(e)),Re(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=e.material[t].userData.assetId,s=await this.getAsset(a);null!=s&&this.refreshMaterial(e,e.material[t],s,t)}}else{const t=e.material.userData?.customShaderName;if(null!=t){const t=e.material.userData.assetId,a=await this.getAsset(t);null!=a&&this.refreshMaterial(e,e.material,a)}}})})}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 n=!1;if(t.traverseAncestors(e=>{"_hology_transform_group"===e.name&&(n=!0)}),!n){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);la(e.materialAssignments,a.materialAssignments).forEach(e=>this.applyMaterial(t,e,a))}else"shape_mesh"===e.type&&this.applyMaterials(t,e.materialAssignments);if(n||(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 zt&&e.update()})}}else if("landscape"===e.shape){const a=this.landscapeManagers.find(t=>t.source.id===e.id),n=null==a||(s=a.source.landscape.options,r=e.landscape.options,s.density!==r.density||s.sections.x!==r.sections.x||s.sections.y!==r.sections.y);if(this.inEditor&&n){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 u?"density":"linear")!==e.fog.type;this.scene.fog=ta(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 u&&(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 Dt){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)||n||(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 et&&(t.geometry=a.geometry,t.collisionShape=a.collisionShape)}if("shape_mesh"===e.type&&"landscape"!==e.shape)Rt(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;Rt(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,s,r;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:Le(t,t=>t.children?.some(t=>t.id===e.id),()=>!0))[0];return null==t?this.scene:null!=t?Re(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=Ge(e.vertexMaterials,e=>e.m);t.traverse(e=>{if(e instanceof m){if(null==e.geometry)return;if(wa(ot(e,0,!1)),a>0){wa(ot(e,0,!1))}}});const r=new Set;for(const[e,n]of s.entries()){const s=null!=e?t.getObjectByName(e):this.findMeshWithGeometry(t);let i=!1;if(null==s||null==s.geometry)return void console.warn(`Failed to apply vertex materials on mesh with name "${e}"`);const o=ot(s,0,!0);wa(o);for(const e of n)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),i=!0;if(a>0){const e=ot(s,4,!0);wa(e);for(const t of n)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,i=!0}i&&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 n,i;switch(e.type){case"asset_mesh":n=await this.createFromAsset(e);break;case"shape_mesh":n=await this.createFromShape(e);break;case"light":n=await this.createLight(e);break;case"particles":n=await this.createParticleSystem(e),e.collisionDetection=!1;break;case"global_fog":this.scene.fog=ta(e.fog),this.fixFogColor(),n=new p;break;case"sky":this.sky=wt(),this.updateSky(e),n=this.sky;break;case"world_env":this.updateWorldEnv(e),n=new p,this.worldEnvObj=n;break;case"actor":({object:n,actor:i}=await this.createFromActor(e,s));break;case"group":n=new p;break;case"prefab":n=await this.createFromPrefab(e,s,t);break;case"vfx":n=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!=n){if(e.name&&e.name.length>0&&(n.name=e.name),this.applyTransform(e,n),a?n.userData._src=e:n.userData.src=e,null!=i&&(n.userData.actor=i),this.inEditor,this.inEditor,this.objectMap.set(n.uuid,e),this.sceneObjectMap.set(e.id,n),e.physics?.type!==we.dynamic||null==t||this.inEditor?null==t?this.scene.add(n):null==t||"actor"!==e.type||this.inEditor?t?.add(n):(t.add(n),this.scene?.attach(n),console.log(n)):(t.add(n),n.getWorldPosition(n.position),n.getWorldQuaternion(n.quaternion),n.getWorldScale(n.scale),this.scene?.attach(n)),null!=e.children&&await Promise.all(e.children?.map(e=>this.materialize(e,n,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==we.dynamic||ea(n),null!=this.renderingView)return this.renderingView.renderer.shadowMap.needsUpdate=!0,n;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 lt(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 n.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!==vt?(this.sky.material=vt,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=n.BackSide,(e instanceof y||e instanceof n.MeshBasicMaterial||e instanceof n.ShaderMaterial)&&(e.fog=!1),e.depthTest=!1}async createComponent(e,t,a,s){const r=new Ut[a.path+"/"+a.className],n=t.id+s;r.id=n,r.object=e;for(const e of a.params)null!=e.value&&(r[e.name]=e.value);return this.components.push(r),n}async createFromActor(e,t){const a=this.actorTypes.find(t=>t.name===e.actor?.type)?.type??ge[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(ue,(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 p;const a=at(e.landscape.options);this.applyHeightMaps(a,e.landscape.heightMaps,!0);const s=new tt(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 st(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(()=>rt(r),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&>.includes(e)){const s=await prepareShapeParameters(a??{}),r=e+JSON.stringify(a);if(!this.geometryCache.has(r)){const t=ft[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,ft[e].collision(s));return new et(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(la(e.materialAssignments,a.materialAssignments).map(e=>this.applyMaterial(s,e,a)))}catch(t){console.error("Failed to apply material"+t,e)}const r=e.receiveShadow??!!a.receiveShadow,n=e.castShadow??!!a.castShadow;return s.receiveShadow=r,Rt(s,n,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 n=new p;null!=s&&this.applyTransform(s,n),null!=a&&a.add(n),await Promise.all(e.prefab.objects.filter(e=>"global_fog"!==e.type&&"world_env"!==e.type).map(e=>this.materialize(e,n,!0,structuredClone(t))));const i=t.sceneObjectChain.join("/"),o=Array.from(this.materializedActors.entries()).filter(([e,a])=>e.startsWith(i)&&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(i)).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:n,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 n.TextureLoader).load("assets/light-bulb-icon.webp"),a=new n.SpriteMaterial({map:e,alphaTest:.5}),s=new Tt(a);s.scale.multiplyScalar(.6),t.add(s)}return t}if("spot"===e.light.type){const t=new n.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 n.TextureLoader).load("assets/light-bulb-icon.webp"),a=new n.SpriteMaterial({map:e,alphaTest:.5}),s=new Tt(a);s.scale.multiplyScalar(.6),t.add(s),t.add(new n.SpotLightHelper(t))}return t}if("rectArea"===e.light.type){const t=new n.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 n.TextureLoader).load("assets/light-bulb-icon.webp"),a=new n.SpriteMaterial({map:e,alphaTest:.5}),s=new Tt(a);s.scale.multiplyScalar(.6),t.add(s);const r=new zt(t);t.add(r)}return t}return"directional"===e.light.type?(this.applyDirectionalLight(e.light.directional,e),new p):"ambient"===e.light.type?(this.applyDirectionalAmbientLight(null,e.light.ambient,e),new p):void 0}applyDirectionalAmbientLight(e,t,a){const s=this.scene.children.find(e=>e.name===yt);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()}};Lt=e([ce(),t("design:paramtypes",[M,Object,Ke,Xe,Me,Array,Array,Object,Array])],Lt);export{Lt as SceneMaterializer};function Rt(e,t,a){e.castShadow=t,e.receiveShadow=a,e.traverse(e=>{e.castShadow=t,e.receiveShadow=a})}const qt=new Map,Yt=new Map,Jt=new f({color:16711935}),Ht=new Map;export async function materialFromAsset(e,t,a,s,r,n=!0){if(null==e||null==e.material)return console.error("Asset or asset material is null",e),Jt;const i=JSON.stringify(e.material)+t?._id,o=n&&!("shaderGraph"===e.material.type&&"asset"===e.material.shaderGraph?.source);if(o&&qt.has(i))return qt.get(i);if(o&&Yt.has(i))return await Yt.get(i);const l=_materialFromAsset(i,e,t,a,s,r,o);return o?Yt.set(i,l).get(i):l}export async function _materialFromAsset(e,t,a,r,i,l,c=!0){const u={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},p={};if(null!=t.material.params?.map){const e=t.material.params.map,a=await r.getAsset(e);null!=a&&(u.map=await i.getTexture(a))}let h,d,m;switch(t.material.type){case"phong":h=new g({...u,...p});break;case"water":h=ct(u,a);break;case"grassFoliage":h=nt({color:u.color,map:u.map},a);break;case"grass":h=it({...u,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),h=Jt;break}"surface"===e.target&&null!=e.materialOptions?.side&&(d=_t(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,i,a,l),n=t.shaderGraphPreviewNodeId,o=t.trailBillboard;h=$t(e,{parameters:s,previewNodeId:n,trailBillboard:o}),h.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),h=Jt}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:Gt?Ie:De,lambert:Ie,unlit:Te,toon:Ot,layered:Pt,landscape:Ce,"landscape-composite":Pe,"decal-unlit":Mt,"decal-standard":St,sprite:s}[t.material.type]??l.find(e=>e.name==t.material.shader)?.type;if(e){try{let s=new e;const n=await prepareClassParameters(t.material?.shaderParams??{},e,r,i,null,a,l,void 0,void 0,s);Object.assign(s,n),h=s.build()}catch(e){console.log("Shader runtime error: "+e,e),Ht.has(t.material.shader)||Ht.set(t.material.shader,Jt.clone()),h=Ht.get(t.material.shader)}h.userData.customShaderName=t.material.shader}else console.warn("Missing shader implementation with name "+t.material.shader),h=Jt;break;default:throw new Error("Unsupported material type "+t.material.type)}return a?.csm.setupMaterial(h),c&&null!=a&&qt.set(e,h),h.side=d??t.material.side??h.side??n.FrontSide,h.transparent=(m??t.material.transparent??u.transparent??!1)||h.transparent,h.alphaTest=t.material.alphaTest??h.alphaTest??0,null!=t.material.blending&&(h.blending=ve[t.material.blending]??n.NormalBlending),t.material.bloom&&(h.userData.hasBloom=!0),t.material.reflective&&(h.userData.reflective=!0),!0===t.material.outlines&&(h.userData.outlineParameters={},null!=t.material.outlineParams&&(null!=t.material.outlineParams.color&&(h.userData.outlineParameters.color=new o(t.material.outlineParams.color).toArray()),null!=t.material.outlineParams.thickness&&(h.userData.outlineParameters.thickness=t.material.outlineParams.thickness))),h.userData.assetId=t.id,c&&Yt.delete(e),h}export function prepareCustomParamsFromShaderGraph(e,t={}){return Object.fromEntries((e.parameters??[]).map(e=>{const a=function(e){switch(e){case"float":return ut.FloatNode;case"boolean":return ut.BooleanNode;case"texture":return ut.Sampler2DNode;case"vec2":return ut.Vec2Node;case"vec3":return ut.Vec3Node;case"vec4":return ut.Vec4Node;case"color":return ut.RgbNode}}(e.type),s=t[e.name],r=s?.override??null!=s,n=void 0!==e.defaultValue?e.defaultValue:customParameterDefaultValueByType.get(a),i=!1===r?oa(n):s?.value??oa(n);return[e.name,{type:a,value:i,override:r}]}))}export async function prepareShaderGraphParameters(e,t,a,s,r,n){const i={},o=prepareCustomParamsFromShaderGraph(t,e);for(const[e,t]of Object.entries(o)){const o=await Kt(e,t,a,s,null,r,n);null!=o&&(i[e]=o)}return i}export async function prepareClassParameters(e,t,a,s,r,n,i,o,l,c){const u={},{params:p,skipped:h}=ht(e,{parameterType:t,parameterTarget:c,extractPropertyParameters:Oe,toSerializedParamType:toSerializedParamType});for(const e of h)console.warn(`Skipping stored parameter "${e.key}" because it could not be converted from ${ut[e.sourceType]} to ${ut[e.targetType]}`);for(const[e,t]of Object.entries(p)){if(!1===t.override)continue;const c=await Kt(e,t,a,s,r,n,i,o,void 0,void 0,l);null!=c&&(u[e]=c)}return u}export async function prepareShapeParameters(e,t,a){const s={};for(const[r,n]of Object.entries(e)){const e=await Kt(r,n,t,a,null,void 0,void 0,void 0,void 0,void 0);null!=e&&(s[r]=e)}return s}const Xt=new Map;async function Kt(e,t,a,s,r,n,i,c,u=t.value,p=t.type,h,d=(t.type===ut.Struct?t.struct:void 0)){if(null==t||null==u||""===u)return null;switch(p){case ut.Array:if(Array.isArray(u)&&"element"in t)return await Promise.all(u.map(o=>Kt(e,t,a,s,r,n,i,c,o,t.element,h,t.elementStruct)));break;case ut.Number:case ut.FloatNode:let m;if("string"==typeof u?m=parseFloat(u):"number"==typeof u&&(m=u),p===ut.FloatNode){if("object"==typeof u&&"a"in u&&"b"in u){const e=u;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=Xt.get(e);return null==t&&(t=Se(bt.decode(e)),Xt.set(e,t)),t}(e.easing),r=s.sample(Ae(xe.energy));return B(F(t),F(a),r)}return new H($e(e),m,void 0,!1)}return m;case ut.Texture:let f=await s.getTexture(await a.getAsset(u));return"envmap"===e.toLowerCase()&&null!=n&&(f=n.getEnvTexture(f)),f;case ut.Sampler2DNode:const g=await a.getAsset(u);if(null!=g.texture?.textureArrayFileKey){const{texture:e,layerIndex:t}=await s.getTextureArray(g);if(e&&null!=t)return new X(null,e,F(t))}const y=await s.getTexture(g);return y?q(y):null;case ut.Boolean:return u;case ut.BooleanNode:return new J($e(e),u,void 0,!1);case ut.Vector2:case ut.Vec2Node:if("object"==typeof u){const t=u instanceof Array?(new A).fromArray(u):new A(u.x,u.y);return p===ut.Vec2Node?new K($e(e),t,void 0,!1):t}return null;case ut.Vector3:case ut.Vec3Node:if("object"==typeof u){const t=u instanceof Array?(new x).fromArray(u):new x(u.x,u.y,u.z);return p===ut.Vec3Node?new Z($e(e),t,void 0,!1):t}return null;case ut.Vector4:case ut.Vec4Node:if("object"==typeof u){const t=u instanceof Array?(new j).fromArray(u):new j(u.x,u.y,u.z,u.w);return p===ut.Vec4Node?new Q($e(e),t,void 0,!1):t}return null;case ut.Color:case ut.RgbNode:const w=new o(u);return p===ut.RgbNode?new Z($e(e),new x(w.r,w.g,w.b),void 0,!1).rgb:w;case ut.String:return u;case ut.BaseActor:const v=u;if(null==r&&console.warn("Class parameters can not be prepared as actors are not passed in"),null==v)return null;if("object"==typeof v&&null!=v.type&&null!=v.id){if("actor"===v.type)return r?.get(v.id)??null;if("prefab"===v.type){const e=h?h(v.id):null;if(null!=e)return r?.get(e)??null;const t=[];for(const[e,a]of r?.entries()??[])e.startsWith(v.id+"/")&&t.push(a);return 1===t.length?t[0]:null}}if("string"==typeof v){const e=r?.get(v);if(null!=e)return e;const t=h?h(v):null;if(null!=t)return r?.get(t)??null;const a=[];for(const[e,t]of r?.entries()??[])e.startsWith(v+"/")&&a.push(t);return 1===a.length?a[0]:null}return null;case ut.Euler:const b=u;return(new l).fromArray(b);case ut.Object3D:{const e=await a.getAsset(u);return(await s.getMesh(e,{applyMaterials:!0,rescale:!0})).scene}case ut.Material:{if(null==u)return null;const e=await a.getAsset(u);return null==e?(console.warn("Material asset not found for material parameter",u),null):null==e.material?(console.warn("Using a non-material asset for material parameter"),null):await materialFromAsset(e,n,a,s,i)}case ut.AudioBuffer:return await s.getAudio(await a.getAsset(u));case ut.VisualEffect:const M=await a.getAsset(u);if(null==c){console.error("Can not create instance of visual effect because missing actor provider");break}if("vfx"in M)return new pe(c,M);console.error("Using a non-vfx asset for visual effect parameter");break;case ut.Prefab:{const e=await a.getAsset(u);return null==e?(console.error("Using a non-prefab asset for prefab parameter",u),null):new he(e)}case ut.PrefabActor:{const e=await a.getAsset(u);return null==e?(console.error("Using a non-prefab asset for prefab parameter",u),null):new de(new he(e))}case ut.DataAsset:return materializeDataAssetRef(u,a,s,r,n,i,c,h);case ut.Sequence:{const e=await a.getAsset(u);if("sequence"===e.type&&"sequence"in e)return new Nt(e.sequence);console.error("Using a non-sequence asset for sequence parameter");break}case ut.Struct:return async function(e,t,a,s,r,n,i,o,l){const c=Zt(e),u=c?.struct??t;if(null==u)return console.warn("Missing parameter definition id for struct parameter"),null;const p=ke(u);if(null==p)return console.warn(`Unknown parameter definition "${u}"`),null;if(ze(u))return console.warn(`Can not instantiate abstract parameter definition "${u}"`),null;if(null!=t&&u!==t&&!Be(u,t))return console.warn(`Parameter definition "${u}" is not assignable to "${t}"`),null;let h;try{h=new p}catch(e){return console.warn(`Failed to instantiate parameter definition "${u}"`,e),null}const d=function(e){const t=Zt(e);if(null!=t)return t.value;if(Qt(e))return e;if(null!=e&&"object"==typeof e&&Qt(e.params))return e.params;return{}}(c?.value??e),m=await prepareClassParameters(d,null,a,s,r,n,i,o,l,h);return Object.assign(h,m),h}(u,d,a,s,r,n,i,c,h);case ut.Curve:return bt.decode(u);case ut.ColorLayer:case ut.MaskLayer:if(Ct(u)){const e=await At.decode(u,async e=>await s.getTexture(await a.getAsset(e))),t=await prepareClassParameters(u.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",u),null;case ut.AnimationClip:{const e="string"==typeof u?u:"object"==typeof u&&null!=u?u.assetId:null;if(null==e)return console.warn("Invalid animation clip asset id value",u),null;return await s.getAnimationClip(await a.getAsset(e))}}return null}export async function materializeDataAssetRef(e,t,a,s,r,n,i,o){const l="string"==typeof e?e:null!=e&&"object"==typeof e?e.assetId??e.id:null;if(null==l||""===l)return null;const c=await t.getAsset(l);if(null==c)return console.warn(`Data asset "${l}" was not found`),null;if("data"!==c.type||null==c.dataAsset)return console.warn("Using a non-data asset for data asset parameter",l),null;const u=c.dataAsset.definition;if(null==u||""===u)return console.warn(`Missing data asset definition id for asset "${c.id}"`),null;if(Fe(u))return console.warn(`Can not instantiate abstract data asset definition "${u}"`),null;const p=Ve(u);if(null==p)return console.warn(`Unknown data asset definition "${u}"`),null;let h;try{h=new p}catch(e){return console.warn(`Failed to instantiate data asset definition "${u}"`,e),null}const d=c.dataAsset.params??{};if("object"!=typeof d||Array.isArray(d))return console.warn(`Invalid data asset params for asset "${c.id}"`),null;try{const e=await prepareClassParameters(d,null,t,a,s,r,n,i,o,h);Object.assign(h,e)}catch(e){return console.warn(`Failed to materialize data asset "${c.id}"`,e),null}return new me(c,h)}function Zt(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)&&"string"==typeof e.struct&&Qt(e.value)?e:null}function Qt(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)&&Object.values(e).every(e=>null!=e&&"object"==typeof e&&"type"in e)}function ea(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 ta(e){return"linear"===e.type?new c(new o(e.color),e.near??100,e.far??1e3):"density"===e.type?new u(e.color,e.density):void console.warn("Invalid fog type",e)}new y({color:4229780});async function aa(e,t,a,s){null==s&&(s=(new d).identity());const r=s.clone().multiply(sa(e,new n.Matrix4));if(null!=e.children&&e.children.length>0)for(let a=e.children.length-1;a>=0;a--)await aa(e.children[a],t,e,r);await t(e,a,s)}function sa(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){if(null==e)return;const t=e.constructor.prototype;return t instanceof Number||e===Number?ut.Number:t instanceof z||"function"==typeof e.prototype.isFloat?ut.FloatNode:t instanceof S||e===S||e.isTexture?ut.Texture:t instanceof je||e===je||e===R||"function"==typeof e.prototype?.isSampler2D||!0===e.prototype?.isSampler2D?ut.Sampler2DNode:t instanceof Boolean||e===Boolean?ut.Boolean:t instanceof E?ut.BooleanNode:t instanceof o||e==o?ut.Color:t instanceof G||"function"==typeof e.prototype.isRgb?ut.RgbNode:t instanceof A||e==A?ut.Vector2:t instanceof re||"function"==typeof e.prototype.isVec2?ut.Vec2Node:t instanceof x||e==x?ut.Vector3:t instanceof ie||"function"==typeof e.prototype.isVec3?ut.Vec3Node:t instanceof j||e==j?ut.Vector4:t instanceof le||"function"==typeof e.prototype.isVec4?ut.Vec4Node:t instanceof String||e===String?ut.String:t instanceof fe||e==fe||e.prototype instanceof fe||e.prototype==fe?ut.BaseActor:t instanceof l||e==l?ut.Euler:t instanceof w||e==w?ut.Object3D:t instanceof h||e==h?ut.Material:t instanceof AudioBuffer||e==AudioBuffer?ut.AudioBuffer:t instanceof pe||e==pe?ut.VisualEffect:t instanceof he||e==he?ut.Prefab:t instanceof de||e==de?ut.PrefabActor:t instanceof me||e==me?ut.DataAsset:t instanceof bt||e==bt?ut.Curve:t instanceof At||e==At?ut.ColorLayer:t instanceof It||e==It?ut.MaskLayer:t instanceof n.AnimationClip||e==n.AnimationClip?ut.AnimationClip:t instanceof Nt||e==Nt||"SequenceData"===e.name||e.prototype&&"tracks"in e.prototype?ut.Sequence:null!=Ee(e)?ut.Struct:void console.warn("Failed to map parameter type to serialized version",{type:e})}export function getCustomParamTypeInfo(e){const t=toSerializedParamType(e.type),a=t===ut.Struct?Ee(e.type):void 0;return!0===e.options.array?{type:ut.Array,element:t,...null!=a?{elementStruct:a}:{}}:{type:t,...null!=a?{struct:a}:{}}}export function prepareCustomParams(e,t,a={},s={}){return Object.fromEntries(e.map(e=>{const r=getCustomParamTypeInfo(e);let n=r;const i=t[e.name],o=!0===s.treatAllAsOptional||!0===e.options.optional,l=s.missingOverrideDefaultsToOverride??!0;let c=i?.override;void 0===c&&null!=i&&o&&l&&(c=!0),void 0===c&&o&&(c=!1);const u=void 0!==a[e.name]||void 0!==e.options.defaultValue,p=function(e,t){if(e.type!==ut.Struct)return{typeInfo:e,value:t};const a=Zt(t);if(null==a)return{typeInfo:e,value:t};return{typeInfo:{...e,struct:a.struct},value:a.value}}(n,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}const a=toSerializedParamType(e.type);if(a===ut.Struct)return ze(e.type)?{}:prepareCustomParamsFromType(e.type,{});return customParameterDefaultValueByType.get(a)}(e,a));n=function(e,t,a){if(e.type!==ut.Struct||a?.type!==ut.Struct||null==a.struct)return e;const s=t.struct??e.struct;if(null==s||a.struct===s||Be(a.struct,s)||null==ke(a.struct))return{...e,struct:a.struct};return e}(p.typeInfo,r,i);const h=!1!==c||e.options.array?i?.value??function(e,t,a){if(!0===e.options.array)return a?oa(t):[];return oa(t)}(e,p.value,u):oa(p.value);return[e.name,{...n,value:h,override:c}]}))}function ra(e){return null==e?{}:Object.fromEntries(Object.entries(e).filter(([,e])=>function(e){return!0===e?.override}(e)))}function na(e,t){return e.length>=t.length&&t.every((t,a)=>e[a]===t)}export function prepareCustomParamsFromType(e,t,a=null,s={}){const r=Oe(e);if(0===r.length)return{};let n;null!=a?be(a,()=>{n=a.get(e)}):n=new e;const i={};for(const e of r){const t=n[e.name];if(null!=t){const a=ia(e,t);void 0!==a&&(i[e.name]=a)}}return prepareCustomParams(r,t,i,s)}function ia(e,t){return!0===e.options.array?Array.isArray(t)?t.map(t=>serializeCustomParameter(e.type,t)??t):[]:serializeCustomParameter(e.type,t)}function oa(e){return null==e?e:Array.isArray(e)?e.map(e=>oa(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 he:return t instanceof he?t.asset?.id??null:void a();case me:return t instanceof me?t.id:"string"==typeof t?t:void a()}const s=Ee(e);if(null!=s){const r=Zt(t);if(null!=r)return r.struct===s?r.value:r;const n=function(e,t){if(null==t||"object"!=typeof t)return e;const a=t.constructor;return null!=Ee(a)&&Ne(a,e)?a:e}(e,t),i=Ee(n),o=function(e,t){if(null==t)return null;if(Qt(t))return t;if(null!=t&&"object"==typeof t&&Qt(t.params))return t.params;if("object"!=typeof t)return;const a=Oe(e),s={};for(const e of a){const a=t[e.name];if(void 0===a)continue;const r=ia(e,a);void 0!==r&&(s[e.name]=r)}return prepareCustomParams(a,{},s)}(n,t);return void 0!==o?null!=o&&null!=i&&i!==s?{struct:i,value:o}:o:void a()}if(t&&"object"==typeof t&&"tracks"in t&&"duration"in t)return t}function la(e,t){return function(e,t,a){const s=[],r=new Set;for(const n of[...e??[],...t??[]]){const e=a(n);r.has(e)||(r.add(e),s.push(n))}return s}((e??[]).filter(e=>ca(e.materialId)),(t??[]).filter(e=>ca(e.materialId)),e=>e.color+e.name)}function ca(e){return"null"!=e&&null!=e}export const customParameterDefaultValueByType=new Map([[ut.RgbNode,"#000000"],[ut.Color,"#000000"],[ut.String,""],[ut.Vector4,[0,0,0,0]],[ut.Vec4Node,[0,0,0,0]],[ut.Vector3,[0,0,0]],[ut.Vec3Node,[0,0,0]],[ut.Vector2,[0,0]],[ut.Vec2Node,[0,0]],[ut.Euler,[0,0,0,"XYZ"]],[ut.Array,[]],[ut.DataAsset,null],[ut.ColorLayer,xt],[ut.MaskLayer,jt]]);let ua=new o;new o;function pa(e){return null==e?.color?null:(ua.set(e.color),"#"+ua.getHexString())}function ha(e,t,a,s){const r="string"==typeof t.name&&""!==t.name?t.name:null;if(null!=r)return e.name===r||s===r;const n=pa(e);return null!=n&&(n===t.color||a===t.color)}export function applyMaterial(e,t,a,s,r={}){const i=[];return e.traverse(async e=>{if(e instanceof m||e.isMesh||e instanceof n.SkinnedMesh||e.isSkinnedMesh)for(const t of We(e.material))t.hasOwnProperty("color")&&i.push(e)}),Promise.all(i.map(async e=>{if(e.material instanceof Array)for(let n=0;n<e.material.length;n++){const i=e.material[n];if(null==i.color||!(i.color instanceof o))continue;const l=pa(i),c=i.name;if(ha(i,t,e.userData["originalColor_"+n],e.userData["originalMaterialName_"+n])){const i=ma(await a(t.materialId),r.textureFlipY),o=e.material[n];null!=i&&o.id!=i.id&&(e.material[n]=i,e.userData["originalColor_"+n]=e.userData["originalColor_"+n]??l,e.userData["originalMaterialName_"+n]=e.userData["originalMaterialName_"+n]??c,null!=s&&s.set(e.id+"#"+n,o))}}else if("color"in e.material){const n=e.material,i=pa(n),o=n.name;if(ha(n,t,e.userData.originalColor,e.userData.originalMaterialName)){const n=ma(await a(t.materialId),r.textureFlipY),l=e.material;null!=n&&(e.material=n,e.userData.originalColor=e.userData.originalColor??i,e.userData.originalMaterialName=e.userData.originalMaterialName??o,null!=s&&(s.has(e.id)||s.set(e.id,l)))}}}))}const da=new WeakMap;export function getConvertedFbxToGlbAssignedMaterialTextureFlipY(e){const t=e?.mesh?.uvConversion;return"fbx2gltf"===t?.source?!0!==t.flipV&&void 0:!function(e){return"glb"===e?.fileFormat&&!0===e.originalFileKey?.toLowerCase().endsWith(".fbx")}(e)&&void 0}function ma(e,t){if(null==e||null==t||!function(e,t){return function(e){const t=[];for(const[a,s]of Object.entries(e))fa(a,s)&&t.push(s);if(e instanceof n.ShaderMaterial)for(const[a,s]of Object.entries(e.uniforms))fa(a,s.value)&&t.push(s.value);return t}(e).some(e=>e.flipY!==t)}(e,t))return e;let a=da.get(e);null==a&&(a=new Map,da.set(e,a));const s=a.get(t);if(null!=s)return s;const r=e.clone();if(function(e,t){for(const a of Object.keys(e)){const s=e[a];fa(a,s)&&(e[a]=ga(s,t))}}(r,t),r instanceof n.ShaderMaterial){for(const[e,a]of Object.entries(r.uniforms))fa(e,a.value)&&(a.value=ga(a.value,t));r.uniformsNeedUpdate=!0}return r.needsUpdate=!0,a.set(t,r),r}function fa(e,t){const a=t;return(t instanceof S||!0===a?.isTexture)&&!e.toLowerCase().includes("envmap")&&!0!==a.isCompressedTexture&&!0!==a.isCompressedArrayTexture}function ga(e,t){if(e.flipY===t)return e;const a=e.clone();return a.flipY=t,a.userData={...e.userData??{}},a.needsUpdate=!0,a}function ya(e,t){if(e instanceof n.ShaderMaterial&&t instanceof n.ShaderMaterial){return e.fragmentShader+e.vertexShader==t.fragmentShader+t.vertexShader&&function(e,t){if(e instanceof n.ShaderMaterial&&t instanceof n.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 wa(e){if(null!=e){for(let t=0;t<e.array.length;t++)e.setX(t,0);e.needsUpdate=!0}}const va=new WeakMap;function ba(e){let t=va.get(e);return null==t&&(t=function(e){const t=qe(e);if(null==t)return"";return Object.keys(t.geometry.attributes).sort().join(",")}(e),va.set(e,t)),t}const Ma=new WeakMap;function Sa(e){let t=Ma.get(e);return null==t&&(t=function(e){let t=e.type;e instanceof n.MeshStandardMaterial&&!(e instanceof n.MeshPhysicalMaterial)||(t+=e.id+"");(e instanceof n.MeshBasicMaterial||e instanceof n.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 n.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 n.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 Et&&null!=e.heightMap&&(t+="h"+e.heightMap?.id);if(e instanceof n.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),Ma.set(e,t)),t}function Aa(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 xa=new d,ja=new l;function Ia(e,t){return ja.copy(e),ja.x*=-1,ja.y*=-1,ja.z*=-1,t.isCubeTexture&&!1===t.isRenderTargetTexture&&(ja.y*=-1,ja.z*=-1),(new n.Matrix3).setFromMatrix4(xa.makeRotationFromEuler(ja))}function Pa(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 Ca=new j;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 n.Color&&t instanceof n.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 Ta(e){const t=[];for(const[a,s]of Object.entries(e))s instanceof pe?t.push(s):s instanceof ye&&t.push(...Ta(s));return t}function Oa(e,t){if(!(t instanceof n.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 Va(e,t,a){if(t(e))return e;for(const s of e.children??[]){const e=Va(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=>Va(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
|
*/
|
|
@@ -52,6 +52,7 @@ export declare class ObjectStorage<T extends StorageEntity> {
|
|
|
52
52
|
private reloadSubdirectory;
|
|
53
53
|
private readFileIfExists;
|
|
54
54
|
getAll(relativePath?: string): Promise<T[]>;
|
|
55
|
+
private getObjectFilePaths;
|
|
55
56
|
get(id: string): Promise<T>;
|
|
56
57
|
save(obj: T): Promise<T>;
|
|
57
58
|
rename(obj: T, name: string): Promise<T>;
|
|
@@ -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 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),
|
|
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),I(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(I(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 I(this.path);const t=await this.getObjectFilePaths(e??""),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(this.path,e)).then(t=>({...JSON.parse(t.toString()),path:b.dirname(e).replace(/^\.$/,""),filename:b.basename(e)}))));i.push(...s)}return i}const t=await this.loadIndex();return Promise.all(Object.keys(t).map(e=>this.get(e)))}async getObjectFilePaths(e){const t=this.path,a=b.join(t,e),i=[];return await async function e(a){const n=await y.readdir(a,{withFileTypes:!0});for(const s of n){const n=b.join(a,s.name);s.isDirectory()?await e(n):s.isFile()&&s.name.endsWith(".json")&&!/^[\._]/.test(s.name)&&i.push(b.relative(t,n))}}(a),i}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 I(P(this.path+"-resources"))}async saveFile(e,t){return C(),await I(P(this.path+"-resources")),y.copyFile(t.path,P(this.path+"-resources",e.fileKey))}async saveExtraFile(e,t){return C(),await I(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=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)}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|