@hology/core 0.0.201 → 0.0.203

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/effects/sequence/sequence-actor.d.ts +1 -1
  2. package/dist/effects/sequence/sequence-actor.js +1 -1
  3. package/dist/effects/sequence/sequence-data.d.ts +81 -8
  4. package/dist/effects/sequence/sequence-data.js +1 -1
  5. package/dist/effects/sequence/sequence-definitions.d.ts +3 -2
  6. package/dist/effects/sequence/sequence-definitions.js +1 -1
  7. package/dist/effects/sequence/sequence-ops.js +1 -1
  8. package/dist/effects/sequence/sequence-player.d.ts +39 -2
  9. package/dist/effects/sequence/sequence-player.js +1 -1
  10. package/dist/effects/vfx/initializsers.d.ts +14 -0
  11. package/dist/effects/vfx/initializsers.js +1 -1
  12. package/dist/effects/vfx/vfx-actor.d.ts +2 -0
  13. package/dist/effects/vfx/vfx-actor.js +1 -1
  14. package/dist/effects/vfx/vfx-defs.d.ts +12 -1
  15. package/dist/effects/vfx/vfx-defs.js +1 -1
  16. package/dist/effects/vfx/vfx-materializer.js +1 -1
  17. package/dist/effects/vfx/zones.d.ts +3 -1
  18. package/dist/effects/vfx/zones.js +1 -1
  19. package/dist/gameplay/services/asset-loader.d.ts +3 -0
  20. package/dist/gameplay/services/asset-loader.js +1 -1
  21. package/dist/rendering/post-process-effect.d.ts +2 -1
  22. package/dist/rendering/post-process-effect.js +1 -1
  23. package/dist/scene/landscape/utils.d.ts +8 -0
  24. package/dist/scene/landscape/utils.js +1 -1
  25. package/dist/scene/materializer.js +1 -1
  26. package/dist/shader/graph/compiler.d.ts +8 -1
  27. package/dist/shader/graph/compiler.js +1 -1
  28. package/dist/shader/graph/model.d.ts +3 -2
  29. package/dist/shader/graph/model.js +1 -1
  30. package/dist/shader/graph/registry.js +1 -1
  31. package/dist/shader/parameter.d.ts +1 -0
  32. package/dist/shader/parameter.js +1 -1
  33. package/dist/shader-nodes/curve-sample.d.ts +1 -0
  34. package/dist/shader-nodes/curve-sample.js +1 -1
  35. package/dist/test/landscape-expansion.test.d.ts +2 -0
  36. package/dist/test/landscape-expansion.test.js +4 -0
  37. package/dist/test/sequence-asset-refresh.test.d.ts +2 -0
  38. package/dist/test/sequence-asset-refresh.test.js +4 -0
  39. package/dist/test/sequence-post-process.test.d.ts +2 -0
  40. package/dist/test/sequence-post-process.test.js +4 -0
  41. package/dist/test/sequence-property-parameters.test.js +1 -1
  42. package/dist/test/shader-graph.test.js +1 -1
  43. package/package.json +2 -2
  44. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,4 @@
1
- import{BehaviorSubject as e,Subject as t}from"rxjs";import*as a from"three";import{AnimationMixer as i,Color as s,Euler as r,Object3D as n,Quaternion as o,Vector2 as l,Vector3 as c,Vector4 as u}from"three";import{VisualEffect as h}from"../../effects/vfx/vfx-param.js";import{BaseActor as p}from"../../gameplay/actors/actor.js";import d from"../../gameplay/actors/builtin/index.js";import{Prefab as f,PrefabOf as m}from"../../scene/objects/prefab.js";import{SerializedParamType as y}from"../../scene/model.js";import{customParamValueNeedsAsyncResolution as C,deserializeCustomParamValue as v,deserializeCustomParamValueSync as g}from"../../scene/custom-param-deserialize.js";import{getAudioParameterDefinition as A}from"./audio-parameters.js";import{Sequence as S}from"./sequence-data.js";import{getSequenceSubTrackDefinition as b,getSequenceTrackDefinition as w}from"./sequence-definitions.js";import{applyInterpolation as k,evaluateCustomParamValueKeyframes as T,evaluateNumericKeyframes as x,findKeyframeSpan as P}from"./sequence-value-lane.js";import{buildRetimedAnimationClip as B,getAnimationClipRetimingSignature as q,isAnimationClipUsingRetiming as I}from"./sequence-animation-retiming.js";import{SkeletonUtils as O}from"three-stdlib";import{CharacterAnimationComponent as M,CharacterMovementComponent as F}from"../../gameplay/actors/index.js";import{RootMotionClip as _}from"../../gameplay/animation/root-motion.js";import{hashCameraShakeSeed as j}from"../../gameplay/services/camera-shake.js";export var SequencePlaybackState;!function(e){e.Stopped="stopped",e.Playing="playing",e.Paused="paused"}(SequencePlaybackState||(SequencePlaybackState={}));export class SequencePlayer{constructor(){this._state=new e(SequencePlaybackState.Stopped),this._time=new e(0),this._duration=0,this._timescale=1,this._loop=!1,this._externalTimeControl=!1,this._inEditor=!1,this.bindings=new Map,this.roleBindings=new Map,this.sequenceData=null,this.onComplete=new t,this.onLoop=new t,this.onTimeUpdate=this._time.asObservable(),this.onStateChange=this._state.asObservable(),this.loopCount=0,this.viewController=null,this._cameraControlEnabled=!1,this._cameraControlTrackId=null,this.sequenceCameras=new Map,this.cameraPlayables=new Map,this.cameraBlendCamera=null,this.cameraBlendSource=null,this.cameraBlendOutSource=null,this.cameraOverrideHandle=null,this.activeCameraClipKey=null,this.cameraBlendOutClipKey=null,this.activeCameraShakeClipKeys=new Set,this.nextCameraShakeClipKeys=new Set,this.audioListener=null,this.audioBuffers=new Map,this.loadingAudioBuffers=new Map,this.animationClips=new Map,this.loadingAnimationClips=new Map,this.retimedAnimationClips=new Map,this.audioByClip=new Map,this.activeAudioClips=new Set,this.audioGainNodes=new Map,this.audioStartInFlight=new Map,this.lastAudioStartAttemptTime=new Map,this.audioStartRetryIntervalSeconds=.25,this.world=null,this.assetLoader=null,this.actorFactory=null,this.vfxService=null,this.spawnedInstances=new Map,this.activeClips=new Set,this.pendingSpawns=new Set,this.vfxActors=new Map,this.activeVfxClips=new Set,this.locatorMarkers=new Map,this.clearCounter=0,this.propertyPathSegments=new Map,this.propertyResolutionCache=new Map,this.propertySnapshots=new Map,this.audioFilters=new Map,this.audioPannerNodes=new Map,this.firedEvents=new Set,this.sequenceEventSyncResolvers={actor:e=>this.resolveSequenceEventActorReference(e)},this.sequenceEventAsyncResolvers={actor:e=>this.resolveSequenceEventActorReference(e),texture:e=>this.assetLoader?.getTextureByAssetId(e)??null,sampler2DNode:e=>this.assetLoader?.getTextureByAssetId(e)??null,object3D:async e=>{const t=await(this.assetLoader?.getModelByAssetId(e));return t?.scene??null},material:e=>this.assetLoader?.getMaterialByAssetId(e)??null,audioBuffer:e=>this.assetLoader?.getAudioByAssetId(e)??null,visualEffect:async e=>{if(!this.assetLoader||!this.actorFactory)return null;const t=await this.assetLoader.getAsset(e);return t?new h(this.actorFactory,t):null},prefab:async e=>{const t=await(this.assetLoader?.getPrefabById(e));return t?new f(t.asset):null},prefabActor:async e=>{const t=await(this.assetLoader?.getPrefabById(e));return t?new m(new f(t.asset)):null},sequence:e=>this.resolveSequenceEventSequence(e),animationClip:e=>this.resolveSequenceEventAnimationClip(e)},this.trackRuntimeEvaluators={object:(e,t,a)=>{t&&this.evaluateObjectTrack(e,t,a)},locator:(e,t,a)=>{t&&this.evaluateLocatorTrack(e,t,a)},camera:(e,t,a)=>this.evaluateCameraTrack(e,a),cameraShake:(e,t,a)=>this.evaluateCameraShakeTrack(e,a),audio:(e,t,a)=>this.evaluateAudioTrack(e,a),vfx:(e,t,a)=>this.evaluateVfxTrack(e,a),spawn:(e,t,a)=>this.evaluateSpawnTrack(e,t,a),group:(e,t,a)=>{if("group"===e.type)for(const t of e.childTracks)this.evaluateTrack(t,a)}},this.subTrackRuntimeEvaluators={transform:(e,t,a)=>{const i=this.getPlayableObject(t);i&&this.evaluateTransformSubTrack(e,i,a)},animation:(e,t,a)=>this.evaluateAnimationSubTrack(e,t,a),visibility:(e,t,a)=>{const i=this.getPlayableObject(t);i&&this.evaluateVisibilitySubTrack(e,i,a)},parameter:(e,t,a)=>this.evaluateParameterSubTrack(e,t.target||null,a),event:(e,t,a)=>this.evaluateEventSubTrack(e,t.target||null,a)}}get state(){return this._state.value}get time(){return this._time.value}get duration(){return this._duration}get timescale(){return this._timescale}set timescale(e){this._timescale=Math.max(.01,e)}get loop(){return this._loop}set loop(e){this._loop=e}get externalTimeControl(){return this._externalTimeControl}set externalTimeControl(e){this._externalTimeControl=e}get inEditor(){return this._inEditor}set inEditor(e){this._inEditor=e,this.updateLocatorMarkerVisibility()}get cameraControlEnabled(){return this._cameraControlEnabled}set cameraControlEnabled(e){this._cameraControlEnabled=e,e||this.releaseCameraOverride()}get cameraControlTrackId(){return this._cameraControlTrackId}set cameraControlTrackId(e){this._cameraControlTrackId!==e&&(this._cameraControlTrackId=e,this.releaseCameraOverride())}setViewController(e){this.viewController&&this.viewController!==e&&this.viewController.clearCameraShakeContributionsForOwner(this),this.viewController=e}setWorld(e){this.world!==e&&(this.restoreAllPropertySnapshots(),this.clearLocatorBindings(),this.clearSequenceCameras(),this.clearCameraShakeContributions(),this.world=e,this.clearCounter++,this.vfxActors.clear(),this.spawnedInstances.clear(),this.bindings.clear(),this.activeClips.clear(),this.activeVfxClips.clear(),this.activeAudioClips.clear(),this.audioStartInFlight.clear(),this.lastAudioStartAttemptTime.clear(),this.loadingAudioBuffers.clear(),this.audioFilters.clear(),this.audioPannerNodes.clear(),this.pendingSpawns.clear(),this.propertyResolutionCache.clear(),this.clearRetimedAnimationClipCache(),this._state.next(SequencePlaybackState.Stopped),this.sequenceData&&this.initializeLocatorBindings())}setAudioListener(e){this.audioListener=e}setAssetLoader(e){if(this.assetLoader=e,this.sequenceData){const e=this.clearCounter;this.preloadSequenceResources(this.sequenceData,e)}}setActorFactory(e){this.actorFactory=e}setVfxService(e){this.vfxService=e}load(e){if(this.stop(),this.clearCounter++,this.clearLocatorBindings(),this.clearSequenceCameras(),this.sequenceData=e,this._duration=e.duration,this._loop=e.loop,this._timescale=e.playbackRate,this.clearRetimedAnimationClipCache(),this.bindings.clear(),this.initializeLocatorBindings(),this.loopCount=0,this.assetLoader){const t=this.clearCounter;this.preloadSequenceResources(e,t)}}preloadSequenceResources(e,t){return Promise.all([this.preloadAudioBuffersForSequence(e,t),this.preloadAnimationClipsForSequence(e,t)]).then(()=>{})}getAudioAssetIdsForSequence(e){const t=new Set;for(const a of e.tracks){if("audio"!==a.type)continue;const e=a;for(const a of e.clips??[])a.audioAssetId&&t.add(a.audioAssetId)}return[...t]}async preloadAudioBuffersForSequence(e,t){if(!this.assetLoader)return;const a=this.getAudioAssetIdsForSequence(e);0!==a.length&&await Promise.all(a.map(async e=>{if(t!==this.clearCounter)return;if(this.audioBuffers.has(e))return;let a=this.loadingAudioBuffers.get(e);a||(a=this.assetLoader.getAudioByAssetId(e),this.loadingAudioBuffers.set(e,a));try{const i=await a;if(t!==this.clearCounter)return;this.audioBuffers.set(e,i)}catch(e){}finally{this.loadingAudioBuffers.get(e)===a&&this.loadingAudioBuffers.delete(e)}}))}getAnimationClipAssetIdsForSequence(e){const t=new Set;for(const a of $(e.tracks))if("subTracks"in a)for(const e of a.subTracks)if("animation"===e.type)for(const a of e.clips)a.animationClipAssetId&&t.add(a.animationClipAssetId);return[...t]}async preloadAnimationClipsForSequence(e,t){if(!this.assetLoader)return;const a=this.getAnimationClipAssetIdsForSequence(e);0!==a.length&&await Promise.all(a.map(async e=>{t===this.clearCounter&&await this.ensureAnimationClip(e)}))}bindRole(e,t){this.roleBindings.set(e,t),this.sequenceData&&this.resolveBindings()}bindObject(e,t){if(this.sequenceData)for(const a of this.sequenceData.tracks)"object"===a.type&&a.targetId===e&&this.createBinding(a,t)}getLocator(e){return this.getLocators(e)[0]??null}getLocators(e){const t=W(e);if(!t||!this.sequenceData)return[];const a=[];for(const e of $(this.sequenceData.tracks)){if("locator"!==e.type)continue;if(W(e.bindingId)!==t)continue;const i=this.bindings.get(e.id),s=i?this.getPlayableObject(i):null;s&&(s.updateWorldMatrix(!0,!1),a.push({trackId:e.id,name:e.name,bindingId:e.bindingId,position:s.getWorldPosition(new c),rotation:s.getWorldQuaternion(new o),scale:s.getWorldScale(new c)}))}return a}resolveBindings(){if(this.sequenceData)for(const e of this.sequenceData.tracks)this.resolveTrackBinding(e)}initializeLocatorBindings(){if(this.sequenceData)for(const e of $(this.sequenceData.tracks)){if("locator"!==e.type||this.bindings.has(e.id))continue;const t=new n;t.name=e.name||"Locator",t.userData.sequenceLocatorTrackId=e.id,this.world?.scene&&null==t.parent&&this.world.scene.add(t);const a=N(e.name);a.visible=this._inEditor,t.add(a),this.locatorMarkers.set(e.id,a),this.disableLocatorInteraction(t),this.createBinding(e,t)}}clearLocatorBindings(){for(const e of this.locatorMarkers.values())X(e);for(const e of this.bindings.values()){if("locator"!==e.track.type)continue;const t=this.getPlayableObject(e);t?.parent&&t.removeFromParent()}this.locatorMarkers.clear()}updateLocatorMarkerVisibility(){for(const e of this.locatorMarkers.values())e.visible=this._inEditor}disableLocatorInteraction(e){e.traverse(e=>{e.raycast=()=>{}})}resolveTrackBinding(e){if("object"===e.type){const t=e;t.role&&this.roleBindings.has(t.role)&&this.createBinding(e,this.roleBindings.get(t.role))}else if("spawn"===e.type){const t=e;t.role&&this.roleBindings.has(t.role)&&this.createBinding(e,this.roleBindings.get(t.role))}else if("group"===e.type)for(const t of e.childTracks)this.resolveTrackBinding(t)}createBinding(e,t){const a=t instanceof p?t.object:t,s=this.bindings.get(e.id),r=null!=s?s.target instanceof p?s.target.object:s.target:null,n=null!=s&&s.target===t&&r===a,o=e.subTracks.some(e=>"animation"===e.type);if(null!=s&&!n){for(const e of s.activeActions.values())e.stop();s.activeActions.clear(),s.mixer?.stopAllAction(),s.charAnimComponent?.stopSequenceAnimation(),s.charAnimComponent=void 0,s.charAnimActionKeys?.clear()}const l=n?s:{track:e,target:t,activeActions:new Map};l.track=e,l.target=t,l.originalTransform={position:a.position.clone(),rotation:a.rotation.clone(),scale:a.scale.clone()},l.originalParent=a.parent,o&&null==l.mixer?l.mixer=new i(a):o||(l.mixer=void 0),this.bindings.set(e.id,l)}play(){this._state.value!==SequencePlaybackState.Playing&&this.sequenceData&&(this._state.value===SequencePlaybackState.Stopped&&(this._time.next(0),this.loopCount=0,this.resolveBindings(),this.captureOriginalTransforms()),this._state.next(SequencePlaybackState.Playing),this.evaluate(this._time.value),this.resumeVfx())}pause(){this._state.value===SequencePlaybackState.Playing&&(this._state.next(SequencePlaybackState.Paused),this.pauseAudio(),this.pauseVfx())}pauseAudio(){for(const e of this.audioByClip.values())e.pause()}pauseVfx(){for(const e of this.vfxActors.values())e.pause()}resumeVfx(){for(const[e,t]of this.vfxActors.entries())(this.activeVfxClips.has(e)||t.getParticleCount()>0)&&t.play()}cancel(){this._state.next(SequencePlaybackState.Stopped),this._time.next(0),this.clearCounter++,this.loopCount=0,this.pauseAudio(),this.releaseCameraOverride(),this.restoreAllPropertySnapshots(),this.stopAllAudio(),this.stopAllAnimations(),this.despawnAll(),this.stopAllVfx(),this.firedEvents.clear(),this.clearCameraShakeContributions()}stop(){this._state.next(SequencePlaybackState.Stopped),this._time.next(0),this.clearCounter++,this.loopCount=0,this.pauseAudio(),this.releaseCameraOverride(),this.restoreAllPropertySnapshots(),this.restoreOriginalTransforms(),this.restoreOriginalParents(),this.stopAllAudio(),this.stopAllAnimations(),this.despawnAll(),this.stopAllVfx(),this.firedEvents.clear(),this.clearCameraShakeContributions()}restart(){this.stop(),this.play()}seek(e){const t=Math.max(0,Math.min(e,this._duration));this._time.next(t),this.evaluate(t)}update(e){if(this._state.value!==SequencePlaybackState.Playing)return;if(!this.sequenceData)return;if(this._externalTimeControl){for(const t of this.bindings.values())t.mixer&&t.mixer.update(e*this._timescale);for(const t of this.spawnedInstances.values())t.mixer&&t.mixer.update(e*this._timescale);return}const t=this._time.value+e*this._timescale;if(t>=this._duration){if(!this._loop)return this._time.next(this._duration),this.evaluate(this._duration),this.releaseCameraOverride(),this.clearCameraShakeContributions(),this.restoreAllPropertySnapshots(),this._state.next(SequencePlaybackState.Stopped),void this.onComplete.next();this.loopCount++,this._time.next(t%this._duration),this.firedEvents.clear(),this.onLoop.next(this.loopCount)}else this._time.next(t);this.evaluate(this._time.value);for(const t of this.bindings.values())t.mixer&&t.mixer.update(e*this._timescale);for(const t of this.spawnedInstances.values())t.mixer&&t.mixer.update(e*this._timescale)}evaluate(e){if(this.sequenceData){this.nextCameraShakeClipKeys.clear();for(const t of this.sequenceData.tracks){if(!t.muted&&("object"===t.type||"locator"===t.type||"camera"===t.type||"spawn"===t.type||"vfx"===t.type)){const e=this.bindings.get(t.id);this.updateTrackParenting(t,e)}this.evaluateTrack(t,e)}this.updateCameraControl(e),this.syncCameraShakeContributions()}}evaluateTrack(e,t){if(e.muted)return;const a=this.bindings.get(e.id);(0,this.trackRuntimeEvaluators[w(e.type).runtimeEvaluator])(e,a,t)}evaluateObjectTrack(e,t,a){this.evaluateSubTracks(e.subTracks,t,a)}evaluateLocatorTrack(e,t,a){this.evaluateSubTracks(e.subTracks,t,a)}getActiveTrackObjects(e){if(!this.sequenceData)return[];const t=$(this.sequenceData.tracks).find(t=>t.id===e);return t?this.getActiveObjectsForTrack(t):[]}evaluateSubTracks(e,t,a){for(const i of e){if(i.muted)continue;(0,this.subTrackRuntimeEvaluators[b(i.type).runtimeEvaluator])(i,t,a)}}evaluateTransformSubTrack(e,t,a){const i=e.keyframes;if(0===i.length)return;const{prev:s,next:r,t:n}=P(i,a);if(s)if(r&&s!==r){const a=k(n,s.interpolation);e.components.position&&s.position&&r.position&&t.position.lerpVectors(Q.fromArray(s.position),Y.fromArray(r.position),a),e.components.rotation&&s.rotation&&r.rotation&&(z.setFromEuler(G.fromArray([...s.rotation,"XYZ"])),H.setFromEuler(J.fromArray([...r.rotation,"XYZ"])),t.quaternion.slerpQuaternions(z,H,a)),e.components.scale&&s.scale&&r.scale&&t.scale.lerpVectors(Q.fromArray(s.scale),Y.fromArray(r.scale),a)}else e.components.position&&s.position&&t.position.fromArray(s.position),e.components.rotation&&s.rotation&&t.rotation.fromArray([...s.rotation,"XYZ"]),e.components.scale&&s.scale&&t.scale.fromArray(s.scale)}evaluateAnimationSubTrack(e,t,i){if(!t.mixer||!t.activeActions)return;if(t.target instanceof p?t.target.object:t.target)for(const s of e.clips){const r=s.startTime+s.duration,n=i>=s.startTime&&i<r,o=`${e.id}-${s.id}`;let l=t.activeActions.get(o),c=!1;if(n){if(!l){c=!0;const e=s.animationClipAssetId;if(null==e)continue;const i=this.animationClips.get(e);if(null==i){this.ensureAnimationClip(e);continue}const r=this.prepareAnimationPlayback(e,i,s),n=t;let u=!1;if(t.target instanceof p){n.charAnimComponent||(n.charAnimComponent=t.target.getComponent(M)??void 0);const a=n.charAnimComponent;if(null!=a){const c=s.rootMotion?I(s)?this.getPlayableAnimationClip(e,i,s,!0):_.fromClip(r.clip,!1):r.clip;if(this._externalTimeControl)l=a.beginExternalAnimationControl(c,{timeScale:r.timeScale});else if(a.play(c,{inPlace:!s.rootMotion,loop:!1,priority:20,timeScale:r.timeScale,fadeTime:s.fadeInDuration??.2,offset:r.startOffset}),l=a.getFullBodyAction(),s.rootMotion){const e=t.target.getComponent(F);e&&e.setRootMotionAction(l,{cancelWithJump:e.allowRootMotionJumpCancel,onJumpCancel:()=>this.cancel()})}t.activeActions.set(o,l),n.charAnimActionKeys||(n.charAnimActionKeys=new Set),n.charAnimActionKeys.add(o),u=!0}}u||(l=t.mixer.clipAction(r.clip),l.setLoop(a.LoopOnce,1),l.clampWhenFinished=!0,l.timeScale=r.timeScale,r.startOffset>0&&(l.time=r.startOffset),t.activeActions.set(o,l),l.play())}if(l){const e=t;if(this._externalTimeControl){e.charAnimComponent?.beginExternalControl();const a=this.getAnimationPlaybackLocalTime(s,i),r=Math.min(a,l.getClip().duration);(c||Math.abs(l.time-r)>.001)&&(l.time=r,l.paused=!1,l.play(),e.charAnimComponent?e.charAnimComponent.getMixer()?.update(0):t.mixer&&t.mixer.update(0))}else e.charAnimComponent?.endExternalControl()}}else if(l){t.activeActions.delete(o);const e=t;e.charAnimActionKeys?.has(o)?(e.charAnimActionKeys.delete(o),l.stop(),0===e.charAnimActionKeys.size&&e.charAnimComponent&&(e.charAnimComponent.stopSequenceAnimation(),e.charAnimComponent=void 0)):(l.stop(),this._externalTimeControl&&t.mixer&&t.mixer.update(0))}}}evaluateVisibilitySubTrack(e,t,a){const i=e.keyframes;if(0===i.length)return;let s=i[0];for(const e of i){if(!(e.time<=a))break;s=e}t.visible=s.visible}evaluatePropertySubTrack(e,t,a){const i=T(e.keyframes,a,{min:e.range?.[0],max:e.range?.[1],stepOnly:L(e)});i&&this.applyResolvedPropertyValue(e,t,i)}evaluateParameterSubTrack(e,t,a){if("audioParameter"===e.type)return;const i=T(e.keyframes,a,"property"===e.type?{min:e.range?.[0],max:e.range?.[1],stepOnly:L(e)}:{});i&&("property"!==e.type?this.applyResolvedMaterialValue(e,t,i):this.applyResolvedPropertyValue(e,t,i))}evaluateEventSubTrack(e,t,a){if(t instanceof p&&this._state.value===SequencePlaybackState.Playing)for(const i of e.events){const s=`${e.id}-${i.id}`;if(a>=i.time&&!this.firedEvents.has(s)){if(this.firedEvents.add(s),i.editorOnly&&!this._inEditor)continue;if(!i.functionName)continue;const e=t[i.functionName];"function"==typeof e?this.invokeSequenceEvent(t,i.functionName,e,i.arguments??[]):console.warn(`Sequence event method '${i.functionName}' not found on actor`)}else i.time>a&&this.firedEvents.delete(s)}}evaluateCameraTrack(e,t){const a=this.ensureSequenceCamera(e);this.applyCameraTrackSettings(e,a),this.evaluateSubTracks(e.subTracks,this.getCameraPlayable(e,a),t),a.updateProjectionMatrix()}evaluateCameraShakeTrack(e,t){if(this.viewController)for(const a of e.clips??[]){if(!this.isCameraShakeClipActive(a,t))continue;const e=t-a.startTime,i=a.id;this.nextCameraShakeClipKeys.add(i),this.viewController.setCameraShakeContribution(this,i,a,e,a.seed??j(a.id))}}getCameraPlayable(e,t){let a=this.cameraPlayables.get(e.id);return a?a.target=t:(a={target:t},this.cameraPlayables.set(e.id,a)),a}ensureSequenceCamera(e){let t=this.sequenceCameras.get(e.id);if(t)null==t.parent&&this.world?.scene.add(t);else{const i=e.cameraSettings??{fov:60,near:.1,far:1e3};t=new a.PerspectiveCamera(i.fov??60,this.getCurrentCameraAspect(),i.near??.1,i.far??1e3),t.name=e.name||"Sequence Camera",t.userData.sequenceCameraTrackId=e.id,t.layers.mask=this.viewController?.getBaseCamera().layers.mask??t.layers.mask,this.sequenceCameras.set(e.id,t),this.world?.scene.add(t)}return t}clearSequenceCameras(){this.releaseCameraOverride();for(const e of this.sequenceCameras.values())e.removeFromParent();this.sequenceCameras.clear(),this.cameraPlayables.clear()}applyCameraTrackSettings(e,t){const a=e.cameraSettings??{fov:60,near:.1,far:1e3};t.fov=a.fov??60,t.near=a.near??.1,t.far=a.far??1e3,t.aspect=this.getCurrentCameraAspect()}getCurrentCameraAspect(){const e=this.viewController?.getBaseCamera();if(e instanceof a.PerspectiveCamera&&Number.isFinite(e.aspect)&&e.aspect>0)return e.aspect;const t=this.viewController?.getSourceCamera();return t instanceof a.PerspectiveCamera&&Number.isFinite(t.aspect)&&t.aspect>0?t.aspect:1}updateCameraControl(e){if(!this._cameraControlEnabled||!this.viewController||!this.sequenceData)return void this.releaseCameraOverride();const t=this.findActiveCameraShot(e);if(t)return void this.updateActiveCameraShot(t,e);const a=this.findBlendOutCameraShot(e);a?this.updateCameraBlendOut(a,e):this.releaseCameraOverride()}findActiveCameraShot(e){if(!this.sequenceData)return null;let t=null;for(const a of $(this.sequenceData.tracks)){if("camera"!==a.type||a.muted||!this.isCameraControlTrackEligible(a))continue;const i=a.clips??[];for(const s of i)this.isCameraClipActive(s,e)&&(t={track:a,clip:s,camera:this.ensureSequenceCamera(a),key:this.getCameraClipKey(a,s)})}return t}findBlendOutCameraShot(e){if(!this.sequenceData)return null;let t=null;for(const a of $(this.sequenceData.tracks)){if("camera"!==a.type||a.muted||!this.isCameraControlTrackEligible(a))continue;const i=a.clips??[];for(const s of i){const i=Math.max(0,s.blendOutDuration??0);if(i<=0)continue;const r=this.getCameraClipEnd(s);e>=r&&e<r+i&&(t={track:a,clip:s,camera:this.ensureSequenceCamera(a),key:this.getCameraClipKey(a,s)})}}return t}isCameraControlTrackEligible(e){return null==this._cameraControlTrackId||e.id===this._cameraControlTrackId}updateActiveCameraShot(e,t){if(!this.viewController)return;const a=this.ensureCameraBlendCamera();this.activeCameraClipKey!==e.key&&(this.copyCameraState(this.viewController.getSourceCamera(),this.ensureCameraBlendSource()),this.activeCameraClipKey=e.key,this.cameraBlendOutClipKey=null);const i=Math.max(0,e.clip.blendInDuration??0),s=i<=0?1:this.evaluateCameraBlendAlpha((t-e.clip.startTime)/i,e.clip);s>=1?this.copyCameraState(e.camera,a):this.blendCameraState(this.ensureCameraBlendSource(),e.camera,a,s),a.updateProjectionMatrix(),this.ensureCameraOverride()}updateCameraBlendOut(e,t){if(!this.viewController)return;const a=this.ensureCameraBlendCamera();if(this.cameraBlendOutClipKey!==e.key){const t=this.activeCameraClipKey===e.key?this.viewController.getSourceCamera():e.camera;this.copyCameraState(t,this.ensureCameraBlendOutSource()),this.activeCameraClipKey=null,this.cameraBlendOutClipKey=e.key}const i=this.getCameraClipEnd(e.clip),s=Math.max(0,e.clip.blendOutDuration??0),r=s<=0?1:this.evaluateCameraBlendAlpha((t-i)/s,e.clip);this.blendCameraState(this.ensureCameraBlendOutSource(),this.viewController.getBaseCamera(),a,r),a.updateProjectionMatrix(),this.ensureCameraOverride()}ensureCameraBlendCamera(){return this.cameraBlendCamera||(this.cameraBlendCamera=new a.PerspectiveCamera(60,this.getCurrentCameraAspect(),.1,1e3),this.cameraBlendCamera.name="Sequence Camera Blend"),this.cameraBlendCamera}ensureCameraBlendSource(){return this.cameraBlendSource||(this.cameraBlendSource=new a.PerspectiveCamera),this.cameraBlendSource}ensureCameraBlendOutSource(){return this.cameraBlendOutSource||(this.cameraBlendOutSource=new a.PerspectiveCamera),this.cameraBlendOutSource}ensureCameraOverride(){this.viewController&&!this.cameraOverrideHandle&&(this.cameraOverrideHandle=this.viewController.pushCameraOverride(this.ensureCameraBlendCamera(),this))}releaseCameraOverride(){this.cameraOverrideHandle?.release(),this.cameraOverrideHandle=null,this.viewController?.releaseCameraOverridesForOwner(this),this.activeCameraClipKey=null,this.cameraBlendOutClipKey=null}isCameraClipActive(e,t){return t>=e.startTime&&t<this.getCameraClipEnd(e)}getCameraClipEnd(e){return e.startTime+Math.max(0,e.duration)}isCameraShakeClipActive(e,t){return t>=e.startTime&&t<this.getCameraShakeClipEnd(e)}getCameraShakeClipEnd(e){return e.startTime+Math.max(0,e.duration)}getCameraClipKey(e,t){return`${e.id}-${t.id}`}evaluateCameraBlendAlpha(e,t){return k(Math.max(0,Math.min(1,e)),t.blendInterpolation??"cubic")}syncCameraShakeContributions(){if(!this.viewController)return this.activeCameraShakeClipKeys.clear(),void this.nextCameraShakeClipKeys.clear();for(const e of this.activeCameraShakeClipKeys)this.nextCameraShakeClipKeys.has(e)||this.viewController.removeCameraShakeContribution(this,e);this.activeCameraShakeClipKeys.clear();for(const e of this.nextCameraShakeClipKeys)this.activeCameraShakeClipKeys.add(e);this.nextCameraShakeClipKeys.clear()}clearCameraShakeContributions(){this.activeCameraShakeClipKeys.clear(),this.nextCameraShakeClipKeys.clear(),this.viewController?.clearCameraShakeContributionsForOwner(this)}copyCameraState(e,t){e.updateWorldMatrix(!0,!1),t.position.copy(e.getWorldPosition(Q)),t.quaternion.copy(e.getWorldQuaternion(z)),t.scale.copy(e.getWorldScale(Y)),e instanceof a.PerspectiveCamera?(t.fov=e.fov,t.near=e.near,t.far=e.far,t.aspect=e.aspect):t.aspect=this.getCurrentCameraAspect(),t.layers.mask=e.layers.mask}blendCameraState(e,t,i,s){e.updateWorldMatrix(!0,!1),t.updateWorldMatrix(!0,!1),i.position.lerpVectors(e.getWorldPosition(Q),t.getWorldPosition(Y),s),i.quaternion.slerpQuaternions(e.getWorldQuaternion(z),t.getWorldQuaternion(H),s),i.scale.lerpVectors(e.getWorldScale(Q),t.getWorldScale(Y),s),e instanceof a.PerspectiveCamera&&t instanceof a.PerspectiveCamera?(i.fov=e.fov+(t.fov-e.fov)*s,i.near=e.near+(t.near-e.near)*s,i.far=e.far+(t.far-e.far)*s,i.aspect=t.aspect):t instanceof a.PerspectiveCamera?(i.fov=t.fov,i.near=t.near,i.far=t.far,i.aspect=t.aspect):i.aspect=this.getCurrentCameraAspect(),i.layers.mask=t.layers.mask}evaluateAudioTrack(e,t){if(!this.assetLoader||!e.clips||0===e.clips.length)return;const a=this._state.value===SequencePlaybackState.Playing,i=this.evaluateAudioSubTracks(e,t);e.volume;for(const s of e.clips){const r=s.startTime+s.duration,n=t>=s.startTime&&t<r,o=`${e.id}-${s.id}`;if(n){if(this.activeAudioClips.has(o)||this.activeAudioClips.add(o),a){const a=this.audioByClip.get(o);a&&a.isPlaying||this.tryStartAudioClip(e,s,o,t,i)}const r=this.audioByClip.get(o);r&&this.applyAudioParameters(r,e,s,o,t,i)}else this.activeAudioClips.has(o)&&(this.activeAudioClips.delete(o),this.lastAudioStartAttemptTime.delete(o),this.audioStartInFlight.delete(o),this.stopAudioClip(o))}}tryStartAudioClip(e,t,a,i,s){if(this.audioStartInFlight.has(a))return;const r=this.lastAudioStartAttemptTime.get(a);if(void 0!==r&&i-r<this.audioStartRetryIntervalSeconds)return;this.lastAudioStartAttemptTime.set(a,i);const n=this.playAudioClip(e,t,a,i,s).catch(()=>{}).finally(()=>{this.audioStartInFlight.get(a)===n&&this.audioStartInFlight.delete(a)});this.audioStartInFlight.set(a,n)}applyAudioParameters(e,t,i,s,r,n){const o=n.volume??1,l=this.stringToRandom(s+t.id),c=i.volumeRandomization?(2*l-1)*i.volumeRandomization:0;let u=1;const h=r-i.startTime;h<i.fadeInDuration&&i.fadeInDuration>0?u=h/i.fadeInDuration:h>i.duration-i.fadeOutDuration&&i.fadeOutDuration>0&&(u=(i.duration-h)/i.fadeOutDuration);const p=Math.max(0,(t.volume??1)*o*(i.volume+c)*u);e.setVolume(p);let d=n.detune??0;if(i.pitchRandomization){d+=(2*this.stringToRandom(s+"_pitch")-1)*i.pitchRandomization}if(e.setDetune(d),e.hasPlaybackControl&&e.setPlaybackRate(i.playbackRate*this.timescale),this.audioListener&&this.audioListener.context){const i=this.audioListener.context,r=[],o=n.lowpass,l=n.highpass;let c=this.audioFilters.get(s);if(void 0!==o||void 0!==l)c||(c=i.createBiquadFilter(),this.audioFilters.set(s,c)),void 0!==o?(c.type="lowpass",c.frequency.value=o):void 0!==l&&(c.type="highpass",c.frequency.value=l),r.push(c);else if(c){try{c.disconnect()}catch{}this.audioFilters.delete(s)}const u=n.pan;if(!t.spatial&&e instanceof a.Audio&&void 0!==u&&"function"==typeof i.createStereoPanner){let e=this.audioPannerNodes.get(s);e||(e=i.createStereoPanner(),this.audioPannerNodes.set(s,e)),e.pan.value=u,r.push(e)}else{const e=this.audioPannerNodes.get(s);if(e){try{e.disconnect()}catch{}this.audioPannerNodes.delete(s)}}e.setFilters(r)}t.spatial&&e instanceof a.PositionalAudio?this.updatePositionalAudioTransform(e,t,i,n.spatialBlend):void 0!==n.pan&&this.audioListener}updatePositionalAudioTransform(e,t,i,s){let r=null,n=null;const o=i.attachedToTrackId||t.parent?.trackId,l=i.attachmentSocketName||t.parent?.socketName;if(o){const e=this.sequenceData?.tracks.find(e=>e.id===o);if(e){const t=this.getActiveObjectsForTrack(e);if(t.length>0){const e=t[0];if(r=Q,n=z,e.getWorldPosition(r),e.getWorldQuaternion(n),l){const t=this.findSocket(e,l);t&&(t.getWorldPosition(r),t.getWorldQuaternion(n))}}}}if(r&&n){const t="number"==typeof s?a.MathUtils.clamp(s,0,1):1;if(t<1&&this.audioListener){const e=Z;this.audioListener.getWorldPosition(e),r=r.clone().lerp(e,1-t)}e.position.copy(r),e.quaternion.copy(n),e.updateMatrixWorld()}}async playAudioClip(e,t,i,s,r){if(!this.assetLoader||!t.audioAssetId||null==this.audioListener)return;if("suspended"===this.audioListener.context.state)try{await this.audioListener.context.resume()}catch(e){return void console.warn("Failed to resume audio context:",e)}this.stopAudioClip(i);const n=this.clearCounter;try{let s=this.audioBuffers.get(t.audioAssetId);if(!s){let e=this.loadingAudioBuffers.get(t.audioAssetId);e||(e=this.assetLoader.getAudioByAssetId(t.audioAssetId),this.loadingAudioBuffers.set(t.audioAssetId,e));try{s=await e,this.audioBuffers.set(t.audioAssetId,s)}finally{this.loadingAudioBuffers.delete(t.audioAssetId)}}if(n!==this.clearCounter)return;const o=this._time.value,l=t.startTime+t.duration;if(!(o>=t.startTime&&o<l))return;const c=Math.max(0,o-t.startTime),u=t.clipStartOffset+c*t.playbackRate;if(u>=s.duration||c>=t.duration)return;let h=this.audioByClip.get(i);const p=!0===e.spatial,d=h&&!0===h.isPositionalAudio;if(h&&p!==d&&(h.isPlaying&&h.stop(),h.disconnect(),this.audioByClip.delete(i),h=void 0),!h){if(p){const e=new a.PositionalAudio(this.audioListener);e.setRefDistance(10),e.setRolloffFactor(1),h=e}else h=new a.Audio(this.audioListener);this.world&&this.world.scene.add(h),this.audioByClip.set(i,h)}Math.min((t.duration-c)/t.playbackRate,(s.duration-u)/t.playbackRate);h.setLoopStart(t.clipStartOffset),h.setLoopEnd(Math.min(t.clipStartOffset+t.duration,s.duration)),h.setLoop(!0),h.setBuffer(s),this.applyAudioParameters(h,e,t,i,o,r),h.isPlaying||h.play()}catch(e){console.error(`Failed to play audio clip ${t.id}:`,e)}}stopAudioClip(e){const t=this.audioByClip.get(e);if(t){try{t.isPlaying&&t.stop()}catch(e){}t.parent&&t.parent.remove(t),this.audioByClip.delete(e)}const a=this.audioGainNodes.get(e);a&&(a.disconnect(),this.audioGainNodes.delete(e));const i=this.audioFilters.get(e);if(i){try{i.disconnect()}catch{}this.audioFilters.delete(e)}const s=this.audioPannerNodes.get(e);if(s){try{s.disconnect()}catch{}this.audioPannerNodes.delete(e)}}stopAllAudio(){for(const e of this.audioByClip.keys())this.stopAudioClip(e);this.activeAudioClips.clear(),this.audioStartInFlight.clear(),this.lastAudioStartAttemptTime.clear()}evaluateVfxTrack(e,t){if(!this.vfxService||!this.world||!e.clips||0===e.clips.length)return;const a=new Set,i=new Map;for(const s of e.clips){const r=this.getVfxClipKey(e,s);i.set(r,s);const n=s.startTime+s.duration;t>=s.startTime&&t<n&&a.add(r)}const s=[];for(const t of this.activeVfxClips)t.startsWith(`${e.id}-`)&&(a.has(t)||s.push(t));for(const e of s)this.activeVfxClips.delete(e);for(const[s,r]of i.entries()){const i=this.vfxActors.get(s);a.has(s)&&!this.activeVfxClips.has(s)?(this.activeVfxClips.add(s),this.ensureVfxActor(e,r,s)):a.has(s)&&i?(this.updateVfxTransform(e,i,t),this._state.value===SequencePlaybackState.Playing&&i.play()):i&&this.applyInactiveVfxClipBehavior(r,i,t)}}getVfxClipKey(e,t){return`${e.id}-${t.id}-${t.vfxAssetId}`}applyInactiveVfxClipBehavior(e,t,a){const i=e.endBehavior??"finish";if("finish"===i)return void t.stop();if("kill"===i)return void t.applyClipEndBehavior(i);const s=e.startTime+e.duration,r=Math.max(a-s,0),n=Math.max(0,e.expireWithinSeconds??.25),o=Math.max(0,n-r);t.applyClipEndBehavior(i,o)}async ensureVfxActor(e,t,a){if(!this.vfxService||!t.vfxAssetId)return;if(this.vfxActors.has(a)){const e=this.vfxActors.get(a);return e.restart(),void e.play()}const i=this.clearCounter;try{const s=await this.vfxService.createFromAssetId(t.vfxAssetId,this.world.scene);if(i!==this.clearCounter)return void(this.world&&this.world.removeActor(s));const{position:r,rotation:n,scale:o}=this.getVfxTransform(e,t.startTime);s.object.position.copy(r),s.object.rotation.copy(n),s.object.scale.copy(o),this.vfxActors.set(a,s),this._state.value===SequencePlaybackState.Playing&&s.play()}catch(e){console.error(`Failed to create VFX actor for clip ${t.id}:`,e)}}getVfxTransform(e,t){const a=new c,i=new r,s=new c(1,1,1),n=e.subTracks.find(e=>"transform"===e.type);if(n&&n.keyframes.length>0){const{prev:e,next:r,t:l}=P(n.keyframes,t);if(e&&(e.position&&a.fromArray(e.position),e.rotation&&i.fromArray([...e.rotation,"XYZ"]),e.scale&&s.fromArray(e.scale)),r&&e!==r&&e.time!==r.time){const t=k(l,e.interpolation);if(e.position&&r.position&&a.lerpVectors(Q.fromArray(e.position),Y.fromArray(r.position),t),e.rotation&&r.rotation){z.setFromEuler(G.fromArray([...e.rotation,"XYZ"])),H.setFromEuler(J.fromArray([...r.rotation,"XYZ"]));const a=new o;a.slerpQuaternions(z,H,t),i.setFromQuaternion(a)}e.scale&&r.scale&&s.lerpVectors(Q.fromArray(e.scale),Y.fromArray(r.scale),t)}}else a.fromArray(e.position),i.fromArray([...e.rotation,"XYZ"]),s.fromArray(e.scale);return{position:a,rotation:i,scale:s}}updateVfxTransform(e,t,a){const{position:i,rotation:s,scale:r}=this.getVfxTransform(e,a);t.object.position.copy(i),t.object.rotation.copy(s),t.object.scale.copy(r)}resolveActorType(e){const t=this.actorFactory.classes[e];if(null!=t)return t;const a=d[e];return a||(console.warn(`Could not resolve actor type: ${e}`),null)}async spawnActorForClip(e,t,a,i){if(!this.world||!e.actorType)return null;const s=this.resolveActorType(e.actorType);if(!s)return null;try{return await this.world.spawnActor(s,a,i)}catch(t){return console.error(`Failed to spawn actor ${e.actorType}:`,t),null}}async spawnPrefabForClip(e,t,a,i){if(!this.world||!this.assetLoader||!e.prefabId)return null;try{const t=await this.assetLoader.getPrefabById(e.prefabId);if(!t)return null;return await this.world.spawnPrefab(t,a,i)}catch(t){return console.error(`Failed to spawn prefab ${e.prefabId}:`,t),null}}async spawnMeshForClip(e,t,a,i){if(!this.world||!this.assetLoader||!e.meshId)return null;try{const t=await this.assetLoader.getAsset(e.meshId),s=await this.assetLoader.getModelByAssetId(e.meshId),r=O.clone(s.scene);if(r.position.copy(a),r.rotation.copy(i),t){await this.assetLoader.applyMaterials(t,r);const e=t.mesh?.rescale;null!=e&&1!==e&&r.scale.multiplyScalar(e)}return this.world.scene.add(r),r}catch(t){return console.error(`Failed to spawn mesh ${e.meshId}:`,t),null}}despawnInstance(e){if(this.restorePropertySnapshotsForInstance(e),this.world)switch(e?.type){case"actor":this.world.removeActor(e.instance);break;case"prefab":this.world.removePrefab(e.instance);break;case"mesh":this.world.scene.remove(e.instance)}}despawnAll(){for(const e of this.spawnedInstances.values())this.despawnInstance(e);this.spawnedInstances.clear(),this.activeClips.clear(),this.pendingSpawns.clear()}getInitialTransform(e,t,a){const i=new c,s=new r,n=e.subTracks.find(e=>"transform"===e.type);if(n&&n.keyframes.length>0){const{prev:e}=P(n.keyframes,a);e&&(e.position&&i.fromArray(e.position),e.rotation&&s.fromArray([...e.rotation,"XYZ"]))}else t.initialPosition&&i.fromArray(t.initialPosition),t.initialRotation&&s.fromArray([...t.initialRotation,"XYZ"]);return{position:i,rotation:s}}evaluateSpawnTrack(e,t,a){if(!e.clips||0===e.clips.length)return;const i=t||this.bindings.get(e.id);if(i&&i.target)for(const t of e.clips){const s=t.startTime+t.duration,r=a>=t.startTime&&a<s,n=`${e.id}-${t.id}`;if(r){this.activeClips.has(n)||(this.activeClips.add(n),this.spawnedInstances.set(n,{type:"proxy",target:i.target}));(i.target instanceof p?i.target.object:i.target)&&this.evaluateSubTracks(e.subTracks,i,a)}else this.activeClips.has(n)&&(this.restorePropertySnapshotsForTarget(i.target),this.activeClips.delete(n),this.spawnedInstances.delete(n))}else for(const t of e.clips){const i=t.startTime+t.duration,s=a>=t.startTime&&a<i,r=`${e.id}-${t.id}`,n=this.spawnedInstances.has(r),o=this.pendingSpawns.has(r);if(!s||n||o){if(s&&n){const t=this.spawnedInstances.get(r);t&&"proxy"!==t.type&&this.evaluateSubTracks(e.subTracks,t,a)}else if(!s&&n){const e=this.spawnedInstances.get(r);e&&(this.despawnInstance(e),this.spawnedInstances.delete(r),this.activeClips.delete(r))}}else{const{position:a,rotation:i}=this.getInitialTransform(e,t,t.startTime);this.pendingSpawns.add(r),this.spawnForClip(e,t,a,i,r)}}}getInstanceObject(e){switch(e.type){case"actor":return e.instance.object;case"prefab":return e.instance.mainActor?.object||e.instance.object;case"mesh":return e.instance;case"proxy":return e.target instanceof p?e.target.object:e.target;default:return null}}async spawnForClip(e,t,a,s,r){const n=this.clearCounter;let o=null;try{switch(e.spawnType){case"actor":const i=await this.spawnActorForClip(e,t,a,s);i&&(o={type:"actor",instance:i});break;case"prefab":const r=await this.spawnPrefabForClip(e,t,a,s);r&&(o={type:"prefab",instance:r});break;case"mesh":const n=await this.spawnMeshForClip(e,t,a,s);n&&(o={type:"mesh",instance:n})}if(n!==this.clearCounter)return void(o&&this.despawnInstance(o));const l=this._time.value,c=l>=t.startTime&&l<t.startTime+t.duration;if(o&&c){const t=this.getInstanceObject(o);"proxy"===o.type||("actor"===o.type?o.target=o.instance:"prefab"===o.type?o.target=o.instance.mainActor||o.instance.object:o.target=t);e.subTracks.some(e=>"animation"===e.type)&&t&&(o.mixer=new i(t),o.activeActions=new Map),this.spawnedInstances.set(r,o),this.activeClips.add(r)}else o&&this.despawnInstance(o)}finally{this.pendingSpawns.delete(r)}}getPlayableObject(e){return e.target instanceof p?e.target.object:e.target??null}applyResolvedPropertyValue(e,t,a){if(!t||!e.propertyPath)return;const i=this.getPropertyResolution(t,e);if(!i)return;const n=this.getPropertySnapshotKey(e);this.capturePropertySnapshot(t,n,i);const o=function(e,t){switch(t.type){case y.Number:return"number"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.Boolean:return"boolean"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.String:return"string"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.Vector2:return function(e,t){const a=R(t,2);if(!a)return{applied:!1};if(e instanceof l)return e.fromArray(a),{applied:!0,value:e};return{applied:!0,value:new l(a[0],a[1])}}(e,t.value);case y.Vector3:return function(e,t){const a=R(t,3);if(!a)return{applied:!1};if(e instanceof c)return e.fromArray(a),{applied:!0,value:e};return{applied:!0,value:new c(a[0],a[1],a[2])}}(e,t.value);case y.Vector4:return function(e,t){const a=R(t,4);if(!a)return{applied:!1};if(e instanceof u)return e.fromArray(a),{applied:!0,value:e};return{applied:!0,value:new u(a[0],a[1],a[2],a[3])}}(e,t.value);case y.Euler:return function(e,t){const a=R(t,3);if(!a)return{applied:!1};const i=Array.isArray(t)&&"string"==typeof t[3]?t[3]:"XYZ";if(e instanceof r)return e.set(a[0],a[1],a[2],i),{applied:!0,value:e};return{applied:!0,value:new r(a[0],a[1],a[2],i)}}(e,t.value);case y.Color:return function(e,t){if(e instanceof s)return V(e,t)?{applied:!0,value:e}:{applied:!1};const a=new s;return V(a,t)?{applied:!0,value:a}:{applied:!1}}(e,t.value);default:return{applied:!1}}}(i.owner[i.key],a);o.applied&&(i.owner[i.key]=o.value)}getPropertyResolution(e,t){const a=e,i=this.getPropertySnapshotKey(t);let s=this.propertyResolutionCache.get(a);if(s||(s=new Map,this.propertyResolutionCache.set(a,s)),s.has(i))return s.get(i)??null;const r=this.getPropertyPathSegments(t.propertyPath);if(0===r.length)return s.set(i,null),null;let n=e;for(let e=0;e<r.length-1;e++){if(!E(n))return s.set(i,null),null;n=n[r[e]]}if(!E(n))return s.set(i,null),null;const o={owner:n,key:r[r.length-1]};return s.set(i,o),o}getPropertyPathSegments(e){const t=this.propertyPathSegments.get(e);if(t)return t;const a=e.split(".").map(e=>e.trim()).filter(Boolean);return this.propertyPathSegments.set(e,a),a}getPropertySnapshotKey(e){return`${e.id}:${e.propertyPath}`}capturePropertySnapshot(e,t,a){const i=e;let s=this.propertySnapshots.get(i);if(s||(s=new Map,this.propertySnapshots.set(i,s)),s.has(t))return;const r=a.owner[a.key];s.set(t,{resolution:a,hadOwnProperty:Object.prototype.hasOwnProperty.call(a.owner,a.key),value:r,valueSnapshot:D(r)})}restorePropertySnapshotsForInstance(e){switch(e.type){case"actor":case"mesh":this.restorePropertySnapshotsForTarget(e.instance);break;case"prefab":this.restorePropertySnapshotsForTarget(e.target??null),this.restorePropertySnapshotsForTarget(e.instance.mainActor??null),this.restorePropertySnapshotsForTarget(e.instance.object);break;case"proxy":this.restorePropertySnapshotsForTarget(e.target)}}restorePropertySnapshotsForTarget(e){if(!e)return;const t=e,a=this.propertySnapshots.get(t);if(a){for(const e of a.values())K(e);this.propertySnapshots.delete(t),this.propertyResolutionCache.delete(t)}}restoreAllPropertySnapshots(){for(const e of Array.from(this.propertySnapshots.keys()))this.restorePropertySnapshotsForTarget(e)}applyResolvedMaterialValue(e,t,a){}async ensureAnimationClip(e){if(!this.assetLoader)return null;const t=this.animationClips.get(e);if(t)return t;const a=this.loadingAnimationClips.get(e);if(a)return a;const i=(async()=>{try{const t=await this.assetLoader.getAnimationClipByAssetId(e);return t&&this.animationClips.set(e,t),t}catch(t){return console.error(`Failed to load animation clip for asset ${e}:`,t),null}finally{this.loadingAnimationClips.get(e)===i&&this.loadingAnimationClips.delete(e)}})();return this.loadingAnimationClips.set(e,i),i}prepareAnimationPlayback(e,t,a){if(!I(a)){let e=t;return a.clipEndOffset>0&&(e=e.clone(),e.duration=Math.max(0,e.duration-a.clipEndOffset)),{clip:e,timeScale:a.playbackRate,startOffset:a.clipStartOffset}}return{clip:this.getPlayableAnimationClip(e,t,a,!1),timeScale:1,startOffset:0}}getPlayableAnimationClip(e,t,a,i){if(!I(a))return i?_.fromClip(t,!1):t;const s=`${a.id}:${i?"root":"base"}`,r=`${q(a)}|${i?"root":"base"}`,n=this.retimedAnimationClips.get(s);if(n&&n.assetId===e&&n.signature===r)return n.clip;const o=B(t,a),l=i?_.fromClip(o,!1):o;return this.retimedAnimationClips.set(s,{assetId:e,signature:r,clip:l}),l}getAnimationPlaybackLocalTime(e,t){const a=Math.max(0,t-e.startTime);return I(e)?a:a*e.playbackRate+e.clipStartOffset}clearRetimedAnimationClipCache(e){if(null!=e)for(const[t,a]of this.retimedAnimationClips.entries())a.assetId===e&&this.retimedAnimationClips.delete(t);else this.retimedAnimationClips.clear()}captureOriginalTransforms(){for(const e of this.bindings.values()){const t=e.target instanceof p?e.target.object:e.target;t&&(e.originalTransform={position:t.position.clone(),rotation:t.rotation.clone(),scale:t.scale.clone()})}}restoreOriginalTransforms(){for(const e of this.bindings.values())if(e.originalTransform){const t=e.target instanceof p?e.target.object:e.target;t&&(t.position.copy(e.originalTransform.position),t.rotation.copy(e.originalTransform.rotation),t.scale.copy(e.originalTransform.scale))}}stopAllAnimations(){for(const e of this.bindings.values()){for(const t of e.activeActions.values())t.stop();e.activeActions.clear(),e.mixer&&e.mixer.stopAllAction(),e.charAnimComponent&&(e.charAnimComponent.stopSequenceAnimation(),e.charAnimComponent=void 0),e.charAnimActionKeys?.clear()}}stopAllVfx(){for(const e of this.vfxActors.values())e.paused||e.stop();this.activeVfxClips.clear()}dispose(){if(this.stop(),this.clearLocatorBindings(),this.clearSequenceCameras(),this.bindings.clear(),this.roleBindings.clear(),this.sequenceData=null,this.world)for(const e of this.vfxActors.values())this.world.removeActor(e);this.vfxActors.clear(),this.stopAllAudio(),this.audioBuffers.clear(),this.loadingAudioBuffers.clear(),this.animationClips.clear(),this.loadingAnimationClips.clear(),this.clearRetimedAnimationClipCache(),this.audioByClip.clear()}updateTrackParenting(e,t){const a=this.getActiveObjectsForTrack(e);if(0===a.length)return;let i=null;const s=e.parent?.trackId;if(s){const t=this.sequenceData?$(this.sequenceData.tracks).find(e=>e.id===s):void 0;if(t){const a=this.getActiveObjectsForTrack(t);if(a.length>0&&(i=a[0],e.parent?.socketName)){const t=this.findSocket(i,e.parent.socketName);t&&(i=t)}}}if(!i&&"camera"===e.type&&e.parentRole&&this.roleBindings.has(e.parentRole)){const t=this.roleBindings.get(e.parentRole);if(i=t instanceof p?t.object:t,e.parentRoleSocketName){const t=this.findSocket(i,e.parentRoleSocketName);t&&(i=t)}}for(const s of a)i?s.parent!==i&&(i.add(s),!t||"object"!==e.type&&"locator"!==e.type||(t.currentParent=i)):t?.currentParent&&t.currentParent===s.parent?this.restoreObjectParent(t,s):s.parent&&s.parent!==this.world?.scene&&"object"!==e.type&&"locator"!==e.type&&this.world?.scene.add(s)}findSocket(e,t){if(e.name===t)return e;if(e instanceof a.SkinnedMesh){const a=e.skeleton.bones.find(e=>e.name===t);if(a)return a}return e.getObjectByName(t)||null}getActiveObjectsForTrack(e){if("object"===e.type){const t=this.bindings.get(e.id);if(t&&t.target)return[t.target instanceof p?t.target.object:t.target]}else if("locator"===e.type){const t=this.bindings.get(e.id);if(t&&t.target instanceof n)return[t.target]}else{if("camera"===e.type)return[this.ensureSequenceCamera(e)];if("spawn"===e.type){const t=[];for(const[a,i]of this.spawnedInstances)if(a.startsWith(e.id+"-")&&this.activeClips.has(a)){const e=this.getInstanceObject(i);e&&t.push(e)}return t}if("vfx"===e.type){const t=[];for(const a of this.activeVfxClips)if(a.startsWith(e.id+"-")){const e=this.vfxActors.get(a);e&&t.push(e.object)}return t}}return[]}restoreObjectParent(e,t){e.originalParent?e.originalParent.add(t):this.world&&this.world.scene.add(t),e.currentParent=void 0}restoreOriginalParents(){for(const e of this.bindings.values())if(e.currentParent){const t=e.target instanceof p?e.target.object:e.target;t&&this.restoreObjectParent(e,t)}}evaluateAudioSubTracks(e,t){const a={};for(const i of e.subTracks)if("audioParameter"===i.type){const e=i,s=A(e.parameter),r=x(e.keyframes,t,{min:s.min,max:s.max});void 0!==r&&(a[e.parameter]=r)}return a}stringToRandom(e){let t=0;for(let a=0;a<e.length;a++){t=(t<<5)-t+e.charCodeAt(a),t&=t}const a=1e4*Math.sin(t);return a-Math.floor(a)}refreshAsset(e){this.assetLoader?.clearCacheById(e),this.animationClips.delete(e),this.loadingAnimationClips.delete(e),this.clearRetimedAnimationClipCache(e),this.vfxService?.clearPool(e);for(const[t,a]of this.vfxActors.entries())t.endsWith(`-${e}`)&&(this.world&&this.world.removeActor(a),this.vfxActors.delete(t),this.activeVfxClips.delete(t));for(const[t,a]of this.spawnedInstances.entries()){const i=t.split("-")[0],s=this.sequenceData?.tracks.find(e=>e.id===i);!s||s.prefabId!==e&&s.meshId!==e||(this.despawnInstance(a),this.spawnedInstances.delete(t),this.activeClips.delete(t))}}async invokeSequenceEvent(e,t,a,i){let s=!1;for(let e=0;e<i.length;e++)if(C(i[e])){s=!0;break}if(s)try{const t=new Array(i.length);for(let e=0;e<i.length;e++)t[e]=v(i[e],this.sequenceEventAsyncResolvers);const s=await Promise.all(t);await a.call(e,...s)}catch(e){console.error(`Failed to call sequence event ${t}:`,e)}else try{const t=new Array(i.length);for(let e=0;e<i.length;e++)t[e]=g(i[e],this.sequenceEventSyncResolvers);a.call(e,...t)}catch(e){console.error(`Failed to call sequence event ${t}:`,e)}}resolveSequenceEventActorReference(e){if(!this.world||null==e)return null;const t=e,a="object"==typeof t&&null!=t?.id?t.id:"string"==typeof t?t:null;if(null==a)return null;for(const e of this.world.actors){const t=e.object.userData.src??e.object.userData._src;if(t?.id===a)return e}return null}resolveSequenceEventSequence(e){return function(e){return"object"==typeof e&&null!=e&&"duration"in e&&"tracks"in e}(e)?new S(e):this.assetLoader&&"string"==typeof e?this.assetLoader.getSequenceById(e):null}async resolveSequenceEventAnimationClip(e){const t="string"==typeof e?e:"object"==typeof e&&null!=e?e.assetId??null:null;return null!=t&&this.assetLoader?this.assetLoader.getAnimationClipByAssetId(t):null}}function L(e){return e.options?.length>0||e.propertyType===y.Boolean||e.propertyType===y.String}function E(e){return"object"==typeof e&&null!=e||"function"==typeof e}function R(e,t){if(!Array.isArray(e)||e.length<t)return null;const a=new Array(t);for(let i=0;i<t;i++){if("number"!=typeof e[i])return null;a[i]=e[i]}return a}function V(e,t){return t instanceof s||"string"==typeof t||"number"==typeof t?(e.set(t),!0):!!(Array.isArray(t)&&t.length>=3)&&(e.setRGB("number"==typeof t[0]?t[0]:0,"number"==typeof t[1]?t[1]:0,"number"==typeof t[2]?t[2]:0),!0)}function D(e){if(e instanceof l||e instanceof c||e instanceof u||e instanceof s||e instanceof r)return e.clone()}function K(e){const{owner:t,key:a}=e.resolution;e.hadOwnProperty?(!function(e,t){if(e instanceof l&&t instanceof l)return e.copy(t),!0;if(e instanceof c&&t instanceof c)return e.copy(t),!0;if(e instanceof u&&t instanceof u)return e.copy(t),!0;if(e instanceof s&&t instanceof s)return e.copy(t),!0;if(e instanceof r&&t instanceof r)return e.copy(t),!0}(e.value,e.valueSnapshot),t[a]=e.value):delete t[a]}function $(e){const t=[];for(const a of e)t.push(a),"group"===a.type&&t.push(...$(a.childTracks));return t}function W(e){if("string"!=typeof e)return null;const t=e.trim();return t.length>0?t:null}function N(e){const t=new a.Group;t.name=`SequenceLocatorMarker:${e}`,t.renderOrder=1e3;const i=new a.AxesHelper(.35);i.renderOrder=1e3;const s=Array.isArray(i.material)?i.material:[i.material];for(const e of s)e.depthTest=!1,e.transparent=!0,e.opacity=.9,e.toneMapped=!1;t.add(i);const r=function(e){if("undefined"==typeof document)return null;const t=document.createElement("canvas");t.width=256,t.height=64;const i=t.getContext("2d");if(!i)return null;i.clearRect(0,0,t.width,t.height),i.fillStyle="rgba(16, 18, 24, 0.78)",function(e,t,a,i,s,r){const n=t+i,o=a+s;e.beginPath(),e.moveTo(t+r,a),e.lineTo(n-r,a),e.quadraticCurveTo(n,a,n,a+r),e.lineTo(n,o-r),e.quadraticCurveTo(n,o,n-r,o),e.lineTo(t+r,o),e.quadraticCurveTo(t,o,t,o-r),e.lineTo(t,a+r),e.quadraticCurveTo(t,a,t+r,a),e.closePath()}(i,0,8,t.width,48,8),i.fill(),i.font="24px sans-serif",i.textAlign="center",i.textBaseline="middle",i.fillStyle="#f8fafc",i.fillText(e||"Locator",t.width/2,t.height/2);const s=new a.CanvasTexture(t);s.needsUpdate=!0;const r=new a.SpriteMaterial({map:s,transparent:!0,depthTest:!1});r.toneMapped=!1;const n=new a.Sprite(r);return n.scale.set(.9,.225,1),n}(e);return r&&(r.position.set(0,.45,0),r.renderOrder=1001,t.add(r)),t.traverse(e=>{e.raycast=()=>{}}),t}function X(e){e.traverse(e=>{const t=e.material;if(Array.isArray(t))for(const e of t)e?.dispose?.(),e?.map?.dispose?.();else t?.dispose?.(),t?.map?.dispose?.()})}const Q=new c,Y=new c,Z=new c,z=new o,H=new o,G=new r,J=new r;/*
1
+ import{BehaviorSubject as e,Subject as t}from"rxjs";import*as a from"three";import{AnimationMixer as s,Color as r,Euler as i,Object3D as n,Quaternion as o,Vector2 as l,Vector3 as c,Vector4 as h}from"three";import{VisualEffect as u}from"../../effects/vfx/vfx-param.js";import{BaseActor as p}from"../../gameplay/actors/actor.js";import d from"../../gameplay/actors/builtin/index.js";import{Prefab as f,PrefabOf as m}from"../../scene/objects/prefab.js";import{SerializedParamType as y}from"../../scene/model.js";import{customParamValueNeedsAsyncResolution as C,deserializeCustomParamValue as g,deserializeCustomParamValueSync as v}from"../../scene/custom-param-deserialize.js";import{getAudioParameterDefinition as A}from"./audio-parameters.js";import{Sequence as S}from"./sequence-data.js";import{getSequenceSubTrackDefinition as w,getSequenceTrackDefinition as P}from"./sequence-definitions.js";import{applyInterpolation as b,evaluateCustomParamValueKeyframes as k,evaluateNumericKeyframes as x,findKeyframeSpan as T}from"./sequence-value-lane.js";import{buildRetimedAnimationClip as I,getAnimationClipRetimingSignature as B,isAnimationClipUsingRetiming as M}from"./sequence-animation-retiming.js";import{SkeletonUtils as q}from"three-stdlib";import{CharacterAnimationComponent as O,CharacterMovementComponent as F}from"../../gameplay/actors/index.js";import{RootMotionClip as E}from"../../gameplay/animation/root-motion.js";import{hashCameraShakeSeed as j}from"../../gameplay/services/camera-shake.js";import{buildShaderGraphPostProcessMaterial as L,shaderGraphPostProcessWeightUniformName as _}from"../../shader/graph/index.js";export var SequencePlaybackState;!function(e){e.Stopped="stopped",e.Playing="playing",e.Paused="paused"}(SequencePlaybackState||(SequencePlaybackState={}));export class SequencePlayer{constructor(){this._state=new e(SequencePlaybackState.Stopped),this._time=new e(0),this._duration=0,this._timescale=1,this._loop=!1,this._externalTimeControl=!1,this._inEditor=!1,this.bindings=new Map,this.roleBindings=new Map,this.sequenceData=null,this.onComplete=new t,this.onLoop=new t,this.onTimeUpdate=this._time.asObservable(),this.onStateChange=this._state.asObservable(),this.loopCount=0,this.viewController=null,this._cameraControlEnabled=!1,this._cameraControlTrackId=null,this.sequenceCameras=new Map,this.cameraPlayables=new Map,this.cameraBlendCamera=null,this.cameraBlendSource=null,this.cameraBlendOutSource=null,this.cameraOverrideHandle=null,this.activeCameraClipKey=null,this.cameraBlendOutClipKey=null,this.activeCameraShakeClipKeys=new Set,this.nextCameraShakeClipKeys=new Set,this.activePostProcessClips=new Map,this.nextPostProcessClipKeys=new Set,this.audioListener=null,this.audioBuffers=new Map,this.loadingAudioBuffers=new Map,this.animationClips=new Map,this.loadingAnimationClips=new Map,this.retimedAnimationClips=new Map,this.audioByClip=new Map,this.activeAudioClips=new Set,this.audioGainNodes=new Map,this.audioStartInFlight=new Map,this.lastAudioStartAttemptTime=new Map,this.audioStartRetryIntervalSeconds=.25,this.world=null,this.assetLoader=null,this.actorFactory=null,this.vfxService=null,this.spawnedInstances=new Map,this.activeClips=new Set,this.pendingSpawns=new Set,this.vfxActors=new Map,this.activeVfxClips=new Set,this.locatorMarkers=new Map,this.clearCounter=0,this.propertyPathSegments=new Map,this.propertyResolutionCache=new Map,this.propertySnapshots=new Map,this.materialResolutionCache=new Map,this.materialSnapshots=new Map,this.audioFilters=new Map,this.audioPannerNodes=new Map,this.firedEvents=new Set,this.sequenceEventSyncResolvers={actor:e=>this.resolveSequenceEventActorReference(e)},this.sequenceEventAsyncResolvers={actor:e=>this.resolveSequenceEventActorReference(e),texture:e=>this.assetLoader?.getTextureByAssetId(e)??null,sampler2DNode:e=>this.assetLoader?.getTextureByAssetId(e)??null,object3D:async e=>{const t=await(this.assetLoader?.getModelByAssetId(e));return t?.scene??null},material:e=>this.assetLoader?.getMaterialByAssetId(e)??null,audioBuffer:e=>this.assetLoader?.getAudioByAssetId(e)??null,visualEffect:async e=>{if(!this.assetLoader||!this.actorFactory)return null;const t=await this.assetLoader.getAsset(e);return t?new u(this.actorFactory,t):null},prefab:async e=>{const t=await(this.assetLoader?.getPrefabById(e));return t?new f(t.asset):null},prefabActor:async e=>{const t=await(this.assetLoader?.getPrefabById(e));return t?new m(new f(t.asset)):null},sequence:e=>this.resolveSequenceEventSequence(e),animationClip:e=>this.resolveSequenceEventAnimationClip(e)},this.trackRuntimeEvaluators={object:(e,t,a)=>{t&&this.evaluateObjectTrack(e,t,a)},locator:(e,t,a)=>{t&&this.evaluateLocatorTrack(e,t,a)},camera:(e,t,a)=>this.evaluateCameraTrack(e,a),cameraShake:(e,t,a)=>this.evaluateCameraShakeTrack(e,a),postProcess:(e,t,a)=>this.evaluatePostProcessTrack(e,a),audio:(e,t,a)=>this.evaluateAudioTrack(e,a),vfx:(e,t,a)=>this.evaluateVfxTrack(e,a),spawn:(e,t,a)=>this.evaluateSpawnTrack(e,t,a),group:(e,t,a)=>{if("group"===e.type)for(const t of e.childTracks)this.evaluateTrack(t,a)}},this.subTrackRuntimeEvaluators={transform:(e,t,a)=>{const s=this.getPlayableObject(t);s&&this.evaluateTransformSubTrack(e,s,a)},animation:(e,t,a)=>this.evaluateAnimationSubTrack(e,t,a),visibility:(e,t,a)=>{const s=this.getPlayableObject(t);s&&this.evaluateVisibilitySubTrack(e,s,a)},parameter:(e,t,a)=>this.evaluateParameterSubTrack(e,t.target||null,a),event:(e,t,a)=>this.evaluateEventSubTrack(e,t.target||null,a)}}get state(){return this._state.value}get time(){return this._time.value}get duration(){return this._duration}get timescale(){return this._timescale}set timescale(e){this._timescale=Math.max(.01,e)}get loop(){return this._loop}set loop(e){this._loop=e}get externalTimeControl(){return this._externalTimeControl}set externalTimeControl(e){this._externalTimeControl=e}get inEditor(){return this._inEditor}set inEditor(e){this._inEditor=e,this.updateLocatorMarkerVisibility()}get cameraControlEnabled(){return this._cameraControlEnabled}set cameraControlEnabled(e){this._cameraControlEnabled=e,e||this.releaseCameraOverride()}get cameraControlTrackId(){return this._cameraControlTrackId}set cameraControlTrackId(e){this._cameraControlTrackId!==e&&(this._cameraControlTrackId=e,this.releaseCameraOverride())}setViewController(e){this.viewController&&this.viewController!==e&&this.viewController.clearCameraShakeContributionsForOwner(this),this.viewController=e}setWorld(e){this.world!==e&&(this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.clearLocatorBindings(),this.clearSequenceCameras(),this.clearCameraShakeContributions(),this.clearPostProcessEffects(),this.world=e,this.clearCounter++,this.vfxActors.clear(),this.spawnedInstances.clear(),this.bindings.clear(),this.activeClips.clear(),this.activeVfxClips.clear(),this.activeAudioClips.clear(),this.audioStartInFlight.clear(),this.lastAudioStartAttemptTime.clear(),this.loadingAudioBuffers.clear(),this.audioFilters.clear(),this.audioPannerNodes.clear(),this.pendingSpawns.clear(),this.propertyResolutionCache.clear(),this.materialResolutionCache.clear(),this.clearRetimedAnimationClipCache(),this._state.next(SequencePlaybackState.Stopped),this.sequenceData&&this.initializeLocatorBindings())}setAudioListener(e){this.audioListener=e}setAssetLoader(e){if(this.assetLoader=e,this.sequenceData){const e=this.clearCounter;this.preloadSequenceResources(this.sequenceData,e)}}setActorFactory(e){this.actorFactory=e}setVfxService(e){this.vfxService=e}load(e){if(this.stop(),this.clearCounter++,this.clearLocatorBindings(),this.clearSequenceCameras(),this.sequenceData=e,this._duration=e.duration,this._loop=e.loop,this._timescale=e.playbackRate,this.clearRetimedAnimationClipCache(),this.bindings.clear(),this.initializeLocatorBindings(),this.loopCount=0,this.assetLoader){const t=this.clearCounter;this.preloadSequenceResources(e,t)}}preloadSequenceResources(e,t){return Promise.all([this.preloadAudioBuffersForSequence(e,t),this.preloadAnimationClipsForSequence(e,t)]).then(()=>{})}getAudioAssetIdsForSequence(e){const t=new Set;for(const a of e.tracks){if("audio"!==a.type)continue;const e=a;for(const a of e.clips??[])a.audioAssetId&&t.add(a.audioAssetId)}return[...t]}async preloadAudioBuffersForSequence(e,t){if(!this.assetLoader)return;const a=this.getAudioAssetIdsForSequence(e);0!==a.length&&await Promise.all(a.map(async e=>{if(t!==this.clearCounter)return;if(this.audioBuffers.has(e))return;let a=this.loadingAudioBuffers.get(e);a||(a=this.assetLoader.getAudioByAssetId(e),this.loadingAudioBuffers.set(e,a));try{const s=await a;if(t!==this.clearCounter)return;this.audioBuffers.set(e,s)}catch(e){}finally{this.loadingAudioBuffers.get(e)===a&&this.loadingAudioBuffers.delete(e)}}))}getAnimationClipAssetIdsForSequence(e){const t=new Set;for(const a of z(e.tracks))if("subTracks"in a)for(const e of a.subTracks)if("animation"===e.type)for(const a of e.clips)a.animationClipAssetId&&t.add(a.animationClipAssetId);return[...t]}async preloadAnimationClipsForSequence(e,t){if(!this.assetLoader)return;const a=this.getAnimationClipAssetIdsForSequence(e);0!==a.length&&await Promise.all(a.map(async e=>{t===this.clearCounter&&await this.ensureAnimationClip(e)}))}bindRole(e,t){this.roleBindings.set(e,t),this.sequenceData&&this.resolveBindings()}bindObject(e,t){if(this.sequenceData)for(const a of this.sequenceData.tracks)"object"===a.type&&a.targetId===e&&this.createBinding(a,t)}getLocator(e){return this.getLocators(e)[0]??null}getLocators(e){const t=H(e);if(!t||!this.sequenceData)return[];const a=[];for(const e of z(this.sequenceData.tracks)){if("locator"!==e.type)continue;if(H(e.bindingId)!==t)continue;const s=this.bindings.get(e.id),r=s?this.getPlayableObject(s):null;r&&(r.updateWorldMatrix(!0,!1),a.push({trackId:e.id,name:e.name,bindingId:e.bindingId,position:r.getWorldPosition(new c),rotation:r.getWorldQuaternion(new o),scale:r.getWorldScale(new c)}))}return a}resolveBindings(){if(this.sequenceData)for(const e of this.sequenceData.tracks)this.resolveTrackBinding(e)}initializeLocatorBindings(){if(this.sequenceData)for(const e of z(this.sequenceData.tracks)){if("locator"!==e.type||this.bindings.has(e.id))continue;const t=new n;t.name=e.name||"Locator",t.userData.sequenceLocatorTrackId=e.id,this.world?.scene&&null==t.parent&&this.world.scene.add(t);const a=J(e.name);a.visible=this._inEditor,t.add(a),this.locatorMarkers.set(e.id,a),this.disableLocatorInteraction(t),this.createBinding(e,t)}}clearLocatorBindings(){for(const e of this.locatorMarkers.values())ee(e);for(const e of this.bindings.values()){if("locator"!==e.track.type)continue;const t=this.getPlayableObject(e);t?.parent&&t.removeFromParent()}this.locatorMarkers.clear()}updateLocatorMarkerVisibility(){for(const e of this.locatorMarkers.values())e.visible=this._inEditor}disableLocatorInteraction(e){e.traverse(e=>{e.raycast=()=>{}})}resolveTrackBinding(e){if("object"===e.type){const t=e;t.role&&this.roleBindings.has(t.role)&&this.createBinding(e,this.roleBindings.get(t.role))}else if("spawn"===e.type){const t=e;t.role&&this.roleBindings.has(t.role)&&this.createBinding(e,this.roleBindings.get(t.role))}else if("group"===e.type)for(const t of e.childTracks)this.resolveTrackBinding(t)}createBinding(e,t){const a=t instanceof p?t.object:t,r=this.bindings.get(e.id),i=null!=r?r.target instanceof p?r.target.object:r.target:null,n=null!=r&&r.target===t&&i===a,o=e.subTracks.some(e=>"animation"===e.type);if(null!=r&&!n){for(const e of r.activeActions.values())e.stop();r.activeActions.clear(),r.mixer?.stopAllAction(),r.charAnimComponent?.stopSequenceAnimation(),r.charAnimComponent=void 0,r.charAnimActionKeys?.clear()}const l=n?r:{track:e,target:t,activeActions:new Map};l.track=e,l.target=t,l.originalTransform={position:a.position.clone(),rotation:a.rotation.clone(),scale:a.scale.clone()},l.originalParent=a.parent,o&&null==l.mixer?l.mixer=new s(a):o||(l.mixer=void 0),this.bindings.set(e.id,l)}play(){this._state.value!==SequencePlaybackState.Playing&&this.sequenceData&&(this._state.value===SequencePlaybackState.Stopped&&(this._time.next(0),this.loopCount=0,this.resolveBindings(),this.captureOriginalTransforms()),this._state.next(SequencePlaybackState.Playing),this.evaluate(this._time.value),this.resumeVfx())}pause(){this._state.value===SequencePlaybackState.Playing&&(this._state.next(SequencePlaybackState.Paused),this.pauseAudio(),this.pauseVfx())}pauseAudio(){for(const e of this.audioByClip.values())e.pause()}pauseVfx(){for(const e of this.vfxActors.values())e.pause()}resumeVfx(){for(const[e,t]of this.vfxActors.entries())(this.activeVfxClips.has(e)||t.getParticleCount()>0)&&t.play()}cancel(){this._state.next(SequencePlaybackState.Stopped),this._time.next(0),this.clearCounter++,this.loopCount=0,this.pauseAudio(),this.releaseCameraOverride(),this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.stopAllAudio(),this.stopAllAnimations(),this.despawnAll(),this.stopAllVfx(),this.firedEvents.clear(),this.clearCameraShakeContributions(),this.clearPostProcessEffects()}stop(){this._state.next(SequencePlaybackState.Stopped),this._time.next(0),this.clearCounter++,this.loopCount=0,this.pauseAudio(),this.releaseCameraOverride(),this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.restoreOriginalTransforms(),this.restoreOriginalParents(),this.stopAllAudio(),this.stopAllAnimations(),this.despawnAll(),this.stopAllVfx(),this.firedEvents.clear(),this.clearCameraShakeContributions(),this.clearPostProcessEffects()}restart(){this.stop(),this.play()}seek(e){const t=Math.max(0,Math.min(e,this._duration));this._time.next(t),this.evaluate(t)}update(e){if(this._state.value!==SequencePlaybackState.Playing)return;if(!this.sequenceData)return;if(this._externalTimeControl){for(const t of this.bindings.values())t.mixer&&t.mixer.update(e*this._timescale);for(const t of this.spawnedInstances.values())t.mixer&&t.mixer.update(e*this._timescale);return}const t=this._time.value+e*this._timescale;if(t>=this._duration){if(!this._loop)return this._time.next(this._duration),this.evaluate(this._duration),this.releaseCameraOverride(),this.clearCameraShakeContributions(),this.clearPostProcessEffects(),this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this._state.next(SequencePlaybackState.Stopped),void this.onComplete.next();this.loopCount++,this._time.next(t%this._duration),this.firedEvents.clear(),this.onLoop.next(this.loopCount)}else this._time.next(t);this.evaluate(this._time.value);for(const t of this.bindings.values())t.mixer&&t.mixer.update(e*this._timescale);for(const t of this.spawnedInstances.values())t.mixer&&t.mixer.update(e*this._timescale)}evaluate(e){if(this.sequenceData){this.nextCameraShakeClipKeys.clear(),this.nextPostProcessClipKeys.clear();for(const t of this.sequenceData.tracks){if(!t.muted&&("object"===t.type||"locator"===t.type||"camera"===t.type||"spawn"===t.type||"vfx"===t.type)){const e=this.bindings.get(t.id);this.updateTrackParenting(t,e)}this.evaluateTrack(t,e)}this.updateCameraControl(e),this.syncCameraShakeContributions(),this.syncPostProcessEffects()}}evaluateTrack(e,t){if(e.muted)return;const a=this.bindings.get(e.id);(0,this.trackRuntimeEvaluators[P(e.type).runtimeEvaluator])(e,a,t)}evaluateObjectTrack(e,t,a){this.evaluateSubTracks(e.subTracks,t,a)}evaluateLocatorTrack(e,t,a){this.evaluateSubTracks(e.subTracks,t,a)}getActiveTrackObjects(e){if(!this.sequenceData)return[];const t=z(this.sequenceData.tracks).find(t=>t.id===e);return t?this.getActiveObjectsForTrack(t):[]}evaluateSubTracks(e,t,a){for(const s of e){if(s.muted)continue;(0,this.subTrackRuntimeEvaluators[w(s.type).runtimeEvaluator])(s,t,a)}}evaluateTransformSubTrack(e,t,a){const s=e.keyframes;if(0===s.length)return;const{prev:r,next:i,t:n}=T(s,a);if(r)if(i&&r!==i){const a=b(n,r.interpolation);e.components.position&&r.position&&i.position&&t.position.lerpVectors(te.fromArray(r.position),ae.fromArray(i.position),a),e.components.rotation&&r.rotation&&i.rotation&&(re.setFromEuler(ne.fromArray([...r.rotation,"XYZ"])),ie.setFromEuler(oe.fromArray([...i.rotation,"XYZ"])),t.quaternion.slerpQuaternions(re,ie,a)),e.components.scale&&r.scale&&i.scale&&t.scale.lerpVectors(te.fromArray(r.scale),ae.fromArray(i.scale),a)}else e.components.position&&r.position&&t.position.fromArray(r.position),e.components.rotation&&r.rotation&&t.rotation.fromArray([...r.rotation,"XYZ"]),e.components.scale&&r.scale&&t.scale.fromArray(r.scale)}evaluateAnimationSubTrack(e,t,s){if(!t.mixer||!t.activeActions)return;if(t.target instanceof p?t.target.object:t.target)for(const r of e.clips){const i=r.startTime+r.duration,n=s>=r.startTime&&s<i,o=`${e.id}-${r.id}`;let l=t.activeActions.get(o),c=!1;if(n){if(!l){c=!0;const e=r.animationClipAssetId;if(null==e)continue;const s=this.animationClips.get(e);if(null==s){this.ensureAnimationClip(e);continue}const i=this.prepareAnimationPlayback(e,s,r),n=t;let h=!1;if(t.target instanceof p){n.charAnimComponent||(n.charAnimComponent=t.target.getComponent(O)??void 0);const a=n.charAnimComponent;if(null!=a){const c=r.rootMotion?M(r)?this.getPlayableAnimationClip(e,s,r,!0):E.fromClip(i.clip,!1):i.clip;if(this._externalTimeControl)l=a.beginExternalAnimationControl(c,{timeScale:i.timeScale});else if(a.play(c,{inPlace:!r.rootMotion,loop:!1,priority:20,timeScale:i.timeScale,fadeTime:r.fadeInDuration??.2,offset:i.startOffset}),l=a.getFullBodyAction(),r.rootMotion){const e=t.target.getComponent(F);e&&e.setRootMotionAction(l,{cancelWithJump:e.allowRootMotionJumpCancel,onJumpCancel:()=>this.cancel()})}t.activeActions.set(o,l),n.charAnimActionKeys||(n.charAnimActionKeys=new Set),n.charAnimActionKeys.add(o),h=!0}}h||(l=t.mixer.clipAction(i.clip),l.setLoop(a.LoopOnce,1),l.clampWhenFinished=!0,l.timeScale=i.timeScale,i.startOffset>0&&(l.time=i.startOffset),t.activeActions.set(o,l),l.play())}if(l){const e=t;if(this._externalTimeControl){e.charAnimComponent?.beginExternalControl();const a=this.getAnimationPlaybackLocalTime(r,s),i=Math.min(a,l.getClip().duration);(c||Math.abs(l.time-i)>.001)&&(l.time=i,l.paused=!1,l.play(),e.charAnimComponent?e.charAnimComponent.getMixer()?.update(0):t.mixer&&t.mixer.update(0))}else e.charAnimComponent?.endExternalControl()}}else if(l){t.activeActions.delete(o);const e=t;e.charAnimActionKeys?.has(o)?(e.charAnimActionKeys.delete(o),l.stop(),0===e.charAnimActionKeys.size&&e.charAnimComponent&&(e.charAnimComponent.stopSequenceAnimation(),e.charAnimComponent=void 0)):(l.stop(),this._externalTimeControl&&t.mixer&&t.mixer.update(0))}}}evaluateVisibilitySubTrack(e,t,a){const s=e.keyframes;if(0===s.length)return;let r=s[0];for(const e of s){if(!(e.time<=a))break;r=e}t.visible=r.visible}evaluatePropertySubTrack(e,t,a){const s=k(e.keyframes,a,{min:e.range?.[0],max:e.range?.[1],stepOnly:R(e)});s&&this.applyResolvedPropertyValue(e,t,s)}evaluateParameterSubTrack(e,t,a){if("audioParameter"===e.type)return;const s=k(e.keyframes,a,"property"===e.type?{min:e.range?.[0],max:e.range?.[1],stepOnly:R(e)}:"material"===e.type?{min:e.range?.[0],max:e.range?.[1],stepOnly:V(e)}:{});s&&("property"!==e.type?this.applyResolvedMaterialValue(e,t,s):this.applyResolvedPropertyValue(e,t,s))}evaluateEventSubTrack(e,t,a){if(t instanceof p&&this._state.value===SequencePlaybackState.Playing)for(const s of e.events){const r=`${e.id}-${s.id}`;if(a>=s.time&&!this.firedEvents.has(r)){if(this.firedEvents.add(r),s.editorOnly&&!this._inEditor)continue;if(!s.functionName)continue;const e=t[s.functionName];"function"==typeof e?this.invokeSequenceEvent(t,s.functionName,e,s.arguments??[]):console.warn(`Sequence event method '${s.functionName}' not found on actor`)}else s.time>a&&this.firedEvents.delete(r)}}evaluateCameraTrack(e,t){const a=this.ensureSequenceCamera(e);this.applyCameraTrackSettings(e,a),this.evaluateSubTracks(e.subTracks,this.getCameraPlayable(e,a),t),a.updateProjectionMatrix()}evaluateCameraShakeTrack(e,t){if(this.viewController)for(const a of e.clips??[]){if(!this.isCameraShakeClipActive(a,t))continue;const e=t-a.startTime,s=a.id;this.nextCameraShakeClipKeys.add(s),this.viewController.setCameraShakeContribution(this,s,a,e,a.seed??j(a.id))}}evaluatePostProcessTrack(e,t){if(this.viewController&&this.assetLoader)for(const a of e.clips??[]){if(!this.isPostProcessClipActive(a,t))continue;const s=this.getPostProcessClipKey(e,a);this.nextPostProcessClipKeys.add(s),this.ensurePostProcessClipEffect(e,a,s);const r=this.activePostProcessClips.get(s);r?.handle&&(r.handle.stage=e.stage,r.handle.priority=e.priority,r.handle.enabled=!0,this.applyPostProcessClipWeight(r.handle,a,t))}}isPostProcessClipActive(e,t){return t>=e.startTime&&t<e.startTime+e.duration}getPostProcessClipKey(e,t){return`${e.id}-${t.id}`}ensurePostProcessClipEffect(e,t,a){const s=t.shaderGraphAssetId;if(!s)return void this.releasePostProcessClipEffect(a);const r=JSON.stringify(t.shaderGraphParams??{}),i=this.activePostProcessClips.get(a);if(i?.assetId===s&&i.paramsSignature===r)return;this.releasePostProcessClipEffect(a);const n={key:a,trackId:e.id,clipId:t.id,assetId:s,paramsSignature:r,version:this.clearCounter};this.activePostProcessClips.set(a,n),this.loadPostProcessClipEffect(e,t,n)}async loadPostProcessClipEffect(e,t,a){if(this.assetLoader&&this.viewController)try{const s=await this.assetLoader.getShaderGraphByAssetId(a.assetId);if(!this.isPostProcessClipEntryCurrent(a))return;if("postProcess"!==s.target)return console.warn(`Sequence post-process clip references shader graph "${a.assetId}" with target "${s.target}"`),void this.releasePostProcessClipEffect(a.key);const r=await this.assetLoader.prepareShaderGraphParameters(s,t.shaderGraphParams??{});if(!this.isPostProcessClipEntryCurrent(a))return;const i=L(s,{parameters:r});if(!this.isPostProcessClipEntryCurrent(a))return void i.dispose();a.handle=this.viewController.addPostProcessEffect(i,{stage:e.stage,priority:e.priority,enabled:!0}),this.applyPostProcessClipWeight(a.handle,t,this._time.value)}catch(e){this.isPostProcessClipEntryCurrent(a)&&this.releasePostProcessClipEffect(a.key),console.error(`Failed to create post-process effect for clip ${t.id}:`,e)}}isPostProcessClipEntryCurrent(e){return this.clearCounter===e.version&&this.activePostProcessClips.get(e.key)===e}applyPostProcessClipWeight(e,t,a){const s=e.material.uniforms?.[_];null!=s&&(s.value=this.getPostProcessClipWeight(t,a),e.material.uniformsNeedUpdate=!0)}getPostProcessClipWeight(e,t){const a=Math.max(0,t-e.startTime),s=Math.max(0,e.startTime+e.duration-t);let r=1;const i=Math.max(0,e.fadeInDuration??0);i>0&&(r=Math.min(r,a/i));const n=Math.max(0,e.fadeOutDuration??0);return n>0&&(r=Math.min(r,s/n)),Math.max(0,Math.min(1,r))}syncPostProcessEffects(){for(const e of Array.from(this.activePostProcessClips.keys()))this.nextPostProcessClipKeys.has(e)||this.releasePostProcessClipEffect(e);this.nextPostProcessClipKeys.clear()}clearPostProcessEffects(){for(const e of Array.from(this.activePostProcessClips.keys()))this.releasePostProcessClipEffect(e);this.nextPostProcessClipKeys.clear()}releasePostProcessClipEffect(e){const t=this.activePostProcessClips.get(e);if(t&&(this.activePostProcessClips.delete(e),t.handle)){const e=t.handle.material;t.handle.dispose(),e.dispose()}}getCameraPlayable(e,t){let a=this.cameraPlayables.get(e.id);return a?a.target=t:(a={target:t},this.cameraPlayables.set(e.id,a)),a}ensureSequenceCamera(e){let t=this.sequenceCameras.get(e.id);if(t)null==t.parent&&this.world?.scene.add(t);else{const s=e.cameraSettings??{fov:60,near:.1,far:1e3};t=new a.PerspectiveCamera(s.fov??60,this.getCurrentCameraAspect(),s.near??.1,s.far??1e3),t.name=e.name||"Sequence Camera",t.userData.sequenceCameraTrackId=e.id,t.layers.mask=this.viewController?.getBaseCamera().layers.mask??t.layers.mask,this.sequenceCameras.set(e.id,t),this.world?.scene.add(t)}return t}clearSequenceCameras(){this.releaseCameraOverride();for(const e of this.sequenceCameras.values())e.removeFromParent();this.sequenceCameras.clear(),this.cameraPlayables.clear()}applyCameraTrackSettings(e,t){const a=e.cameraSettings??{fov:60,near:.1,far:1e3};t.fov=a.fov??60,t.near=a.near??.1,t.far=a.far??1e3,t.aspect=this.getCurrentCameraAspect()}getCurrentCameraAspect(){const e=this.viewController?.getBaseCamera();if(e instanceof a.PerspectiveCamera&&Number.isFinite(e.aspect)&&e.aspect>0)return e.aspect;const t=this.viewController?.getSourceCamera();return t instanceof a.PerspectiveCamera&&Number.isFinite(t.aspect)&&t.aspect>0?t.aspect:1}updateCameraControl(e){if(!this._cameraControlEnabled||!this.viewController||!this.sequenceData)return void this.releaseCameraOverride();const t=this.findActiveCameraShot(e);if(t)return void this.updateActiveCameraShot(t,e);const a=this.findBlendOutCameraShot(e);a?this.updateCameraBlendOut(a,e):this.releaseCameraOverride()}findActiveCameraShot(e){if(!this.sequenceData)return null;let t=null;for(const a of z(this.sequenceData.tracks)){if("camera"!==a.type||a.muted||!this.isCameraControlTrackEligible(a))continue;const s=a.clips??[];for(const r of s)this.isCameraClipActive(r,e)&&(t={track:a,clip:r,camera:this.ensureSequenceCamera(a),key:this.getCameraClipKey(a,r)})}return t}findBlendOutCameraShot(e){if(!this.sequenceData)return null;let t=null;for(const a of z(this.sequenceData.tracks)){if("camera"!==a.type||a.muted||!this.isCameraControlTrackEligible(a))continue;const s=a.clips??[];for(const r of s){const s=Math.max(0,r.blendOutDuration??0);if(s<=0)continue;const i=this.getCameraClipEnd(r);e>=i&&e<i+s&&(t={track:a,clip:r,camera:this.ensureSequenceCamera(a),key:this.getCameraClipKey(a,r)})}}return t}isCameraControlTrackEligible(e){return null==this._cameraControlTrackId||e.id===this._cameraControlTrackId}updateActiveCameraShot(e,t){if(!this.viewController)return;const a=this.ensureCameraBlendCamera();this.activeCameraClipKey!==e.key&&(this.copyCameraState(this.viewController.getSourceCamera(),this.ensureCameraBlendSource()),this.activeCameraClipKey=e.key,this.cameraBlendOutClipKey=null);const s=Math.max(0,e.clip.blendInDuration??0),r=s<=0?1:this.evaluateCameraBlendAlpha((t-e.clip.startTime)/s,e.clip);r>=1?this.copyCameraState(e.camera,a):this.blendCameraState(this.ensureCameraBlendSource(),e.camera,a,r),a.updateProjectionMatrix(),this.ensureCameraOverride()}updateCameraBlendOut(e,t){if(!this.viewController)return;const a=this.ensureCameraBlendCamera();if(this.cameraBlendOutClipKey!==e.key){const t=this.activeCameraClipKey===e.key?this.viewController.getSourceCamera():e.camera;this.copyCameraState(t,this.ensureCameraBlendOutSource()),this.activeCameraClipKey=null,this.cameraBlendOutClipKey=e.key}const s=this.getCameraClipEnd(e.clip),r=Math.max(0,e.clip.blendOutDuration??0),i=r<=0?1:this.evaluateCameraBlendAlpha((t-s)/r,e.clip);this.blendCameraState(this.ensureCameraBlendOutSource(),this.viewController.getBaseCamera(),a,i),a.updateProjectionMatrix(),this.ensureCameraOverride()}ensureCameraBlendCamera(){return this.cameraBlendCamera||(this.cameraBlendCamera=new a.PerspectiveCamera(60,this.getCurrentCameraAspect(),.1,1e3),this.cameraBlendCamera.name="Sequence Camera Blend"),this.cameraBlendCamera}ensureCameraBlendSource(){return this.cameraBlendSource||(this.cameraBlendSource=new a.PerspectiveCamera),this.cameraBlendSource}ensureCameraBlendOutSource(){return this.cameraBlendOutSource||(this.cameraBlendOutSource=new a.PerspectiveCamera),this.cameraBlendOutSource}ensureCameraOverride(){this.viewController&&!this.cameraOverrideHandle&&(this.cameraOverrideHandle=this.viewController.pushCameraOverride(this.ensureCameraBlendCamera(),this))}releaseCameraOverride(){this.cameraOverrideHandle?.release(),this.cameraOverrideHandle=null,this.viewController?.releaseCameraOverridesForOwner(this),this.activeCameraClipKey=null,this.cameraBlendOutClipKey=null}isCameraClipActive(e,t){return t>=e.startTime&&t<this.getCameraClipEnd(e)}getCameraClipEnd(e){return e.startTime+Math.max(0,e.duration)}isCameraShakeClipActive(e,t){return t>=e.startTime&&t<this.getCameraShakeClipEnd(e)}getCameraShakeClipEnd(e){return e.startTime+Math.max(0,e.duration)}getCameraClipKey(e,t){return`${e.id}-${t.id}`}evaluateCameraBlendAlpha(e,t){return b(Math.max(0,Math.min(1,e)),t.blendInterpolation??"cubic")}syncCameraShakeContributions(){if(!this.viewController)return this.activeCameraShakeClipKeys.clear(),void this.nextCameraShakeClipKeys.clear();for(const e of this.activeCameraShakeClipKeys)this.nextCameraShakeClipKeys.has(e)||this.viewController.removeCameraShakeContribution(this,e);this.activeCameraShakeClipKeys.clear();for(const e of this.nextCameraShakeClipKeys)this.activeCameraShakeClipKeys.add(e);this.nextCameraShakeClipKeys.clear()}clearCameraShakeContributions(){this.activeCameraShakeClipKeys.clear(),this.nextCameraShakeClipKeys.clear(),this.viewController?.clearCameraShakeContributionsForOwner(this)}copyCameraState(e,t){e.updateWorldMatrix(!0,!1),t.position.copy(e.getWorldPosition(te)),t.quaternion.copy(e.getWorldQuaternion(re)),t.scale.copy(e.getWorldScale(ae)),e instanceof a.PerspectiveCamera?(t.fov=e.fov,t.near=e.near,t.far=e.far,t.aspect=e.aspect):t.aspect=this.getCurrentCameraAspect(),t.layers.mask=e.layers.mask}blendCameraState(e,t,s,r){e.updateWorldMatrix(!0,!1),t.updateWorldMatrix(!0,!1),s.position.lerpVectors(e.getWorldPosition(te),t.getWorldPosition(ae),r),s.quaternion.slerpQuaternions(e.getWorldQuaternion(re),t.getWorldQuaternion(ie),r),s.scale.lerpVectors(e.getWorldScale(te),t.getWorldScale(ae),r),e instanceof a.PerspectiveCamera&&t instanceof a.PerspectiveCamera?(s.fov=e.fov+(t.fov-e.fov)*r,s.near=e.near+(t.near-e.near)*r,s.far=e.far+(t.far-e.far)*r,s.aspect=t.aspect):t instanceof a.PerspectiveCamera?(s.fov=t.fov,s.near=t.near,s.far=t.far,s.aspect=t.aspect):s.aspect=this.getCurrentCameraAspect(),s.layers.mask=t.layers.mask}evaluateAudioTrack(e,t){if(!this.assetLoader||!e.clips||0===e.clips.length)return;const a=this._state.value===SequencePlaybackState.Playing,s=this.evaluateAudioSubTracks(e,t);e.volume;for(const r of e.clips){const i=r.startTime+r.duration,n=t>=r.startTime&&t<i,o=`${e.id}-${r.id}`;if(n){if(this.activeAudioClips.has(o)||this.activeAudioClips.add(o),a){const a=this.audioByClip.get(o);a&&a.isPlaying||this.tryStartAudioClip(e,r,o,t,s)}const i=this.audioByClip.get(o);i&&this.applyAudioParameters(i,e,r,o,t,s)}else this.activeAudioClips.has(o)&&(this.activeAudioClips.delete(o),this.lastAudioStartAttemptTime.delete(o),this.audioStartInFlight.delete(o),this.stopAudioClip(o))}}tryStartAudioClip(e,t,a,s,r){if(this.audioStartInFlight.has(a))return;const i=this.lastAudioStartAttemptTime.get(a);if(void 0!==i&&s-i<this.audioStartRetryIntervalSeconds)return;this.lastAudioStartAttemptTime.set(a,s);const n=this.playAudioClip(e,t,a,s,r).catch(()=>{}).finally(()=>{this.audioStartInFlight.get(a)===n&&this.audioStartInFlight.delete(a)});this.audioStartInFlight.set(a,n)}applyAudioParameters(e,t,s,r,i,n){const o=n.volume??1,l=this.stringToRandom(r+t.id),c=s.volumeRandomization?(2*l-1)*s.volumeRandomization:0;let h=1;const u=i-s.startTime;u<s.fadeInDuration&&s.fadeInDuration>0?h=u/s.fadeInDuration:u>s.duration-s.fadeOutDuration&&s.fadeOutDuration>0&&(h=(s.duration-u)/s.fadeOutDuration);const p=Math.max(0,(t.volume??1)*o*(s.volume+c)*h);e.setVolume(p);let d=n.detune??0;if(s.pitchRandomization){d+=(2*this.stringToRandom(r+"_pitch")-1)*s.pitchRandomization}if(e.setDetune(d),e.hasPlaybackControl&&e.setPlaybackRate(s.playbackRate*this.timescale),this.audioListener&&this.audioListener.context){const s=this.audioListener.context,i=[],o=n.lowpass,l=n.highpass;let c=this.audioFilters.get(r);if(void 0!==o||void 0!==l)c||(c=s.createBiquadFilter(),this.audioFilters.set(r,c)),void 0!==o?(c.type="lowpass",c.frequency.value=o):void 0!==l&&(c.type="highpass",c.frequency.value=l),i.push(c);else if(c){try{c.disconnect()}catch{}this.audioFilters.delete(r)}const h=n.pan;if(!t.spatial&&e instanceof a.Audio&&void 0!==h&&"function"==typeof s.createStereoPanner){let e=this.audioPannerNodes.get(r);e||(e=s.createStereoPanner(),this.audioPannerNodes.set(r,e)),e.pan.value=h,i.push(e)}else{const e=this.audioPannerNodes.get(r);if(e){try{e.disconnect()}catch{}this.audioPannerNodes.delete(r)}}e.setFilters(i)}t.spatial&&e instanceof a.PositionalAudio?this.updatePositionalAudioTransform(e,t,s,n.spatialBlend):void 0!==n.pan&&this.audioListener}updatePositionalAudioTransform(e,t,s,r){let i=null,n=null;const o=s.attachedToTrackId||t.parent?.trackId,l=s.attachmentSocketName||t.parent?.socketName;if(o){const e=this.sequenceData?.tracks.find(e=>e.id===o);if(e){const t=this.getActiveObjectsForTrack(e);if(t.length>0){const e=t[0];if(i=te,n=re,e.getWorldPosition(i),e.getWorldQuaternion(n),l){const t=this.findSocket(e,l);t&&(t.getWorldPosition(i),t.getWorldQuaternion(n))}}}}if(i&&n){const t="number"==typeof r?a.MathUtils.clamp(r,0,1):1;if(t<1&&this.audioListener){const e=se;this.audioListener.getWorldPosition(e),i=i.clone().lerp(e,1-t)}e.position.copy(i),e.quaternion.copy(n),e.updateMatrixWorld()}}async playAudioClip(e,t,s,r,i){if(!this.assetLoader||!t.audioAssetId||null==this.audioListener)return;if("suspended"===this.audioListener.context.state)try{await this.audioListener.context.resume()}catch(e){return void console.warn("Failed to resume audio context:",e)}this.stopAudioClip(s);const n=this.clearCounter;try{let r=this.audioBuffers.get(t.audioAssetId);if(!r){let e=this.loadingAudioBuffers.get(t.audioAssetId);e||(e=this.assetLoader.getAudioByAssetId(t.audioAssetId),this.loadingAudioBuffers.set(t.audioAssetId,e));try{r=await e,this.audioBuffers.set(t.audioAssetId,r)}finally{this.loadingAudioBuffers.delete(t.audioAssetId)}}if(n!==this.clearCounter)return;const o=this._time.value,l=t.startTime+t.duration;if(!(o>=t.startTime&&o<l))return;const c=Math.max(0,o-t.startTime),h=t.clipStartOffset+c*t.playbackRate;if(h>=r.duration||c>=t.duration)return;let u=this.audioByClip.get(s);const p=!0===e.spatial,d=u&&!0===u.isPositionalAudio;if(u&&p!==d&&(u.isPlaying&&u.stop(),u.disconnect(),this.audioByClip.delete(s),u=void 0),!u){if(p){const e=new a.PositionalAudio(this.audioListener);e.setRefDistance(10),e.setRolloffFactor(1),u=e}else u=new a.Audio(this.audioListener);this.world&&this.world.scene.add(u),this.audioByClip.set(s,u)}Math.min((t.duration-c)/t.playbackRate,(r.duration-h)/t.playbackRate);u.setLoopStart(t.clipStartOffset),u.setLoopEnd(Math.min(t.clipStartOffset+t.duration,r.duration)),u.setLoop(!0),u.setBuffer(r),this.applyAudioParameters(u,e,t,s,o,i),u.isPlaying||u.play()}catch(e){console.error(`Failed to play audio clip ${t.id}:`,e)}}stopAudioClip(e){const t=this.audioByClip.get(e);if(t){try{t.isPlaying&&t.stop()}catch(e){}t.parent&&t.parent.remove(t),this.audioByClip.delete(e)}const a=this.audioGainNodes.get(e);a&&(a.disconnect(),this.audioGainNodes.delete(e));const s=this.audioFilters.get(e);if(s){try{s.disconnect()}catch{}this.audioFilters.delete(e)}const r=this.audioPannerNodes.get(e);if(r){try{r.disconnect()}catch{}this.audioPannerNodes.delete(e)}}stopAllAudio(){for(const e of this.audioByClip.keys())this.stopAudioClip(e);this.activeAudioClips.clear(),this.audioStartInFlight.clear(),this.lastAudioStartAttemptTime.clear()}evaluateVfxTrack(e,t){if(!this.vfxService||!this.world||!e.clips||0===e.clips.length)return;const a=new Set,s=new Map;for(const r of e.clips){const i=this.getVfxClipKey(e,r);s.set(i,r);const n=r.startTime+r.duration;t>=r.startTime&&t<n&&a.add(i)}const r=[];for(const t of this.activeVfxClips)t.startsWith(`${e.id}-`)&&(a.has(t)||r.push(t));for(const e of r)this.activeVfxClips.delete(e);for(const[r,i]of s.entries()){const s=this.vfxActors.get(r);a.has(r)&&!this.activeVfxClips.has(r)?(this.activeVfxClips.add(r),this.ensureVfxActor(e,i,r)):a.has(r)&&s?(this.updateVfxTransform(e,s,t),this._state.value===SequencePlaybackState.Playing&&s.play()):s&&this.applyInactiveVfxClipBehavior(i,s,t)}}getVfxClipKey(e,t){return`${e.id}-${t.id}-${t.vfxAssetId}`}applyInactiveVfxClipBehavior(e,t,a){const s=e.endBehavior??"finish";if("finish"===s)return void t.stop();if("kill"===s)return void t.applyClipEndBehavior(s);const r=e.startTime+e.duration,i=Math.max(a-r,0),n=Math.max(0,e.expireWithinSeconds??.25),o=Math.max(0,n-i);t.applyClipEndBehavior(s,o)}async ensureVfxActor(e,t,a){if(!this.vfxService||!t.vfxAssetId)return;if(this.vfxActors.has(a)){const e=this.vfxActors.get(a);return e.restart(),void e.play()}const s=this.clearCounter;try{const r=await this.vfxService.createFromAssetId(t.vfxAssetId,this.world.scene);if(s!==this.clearCounter)return void(this.world&&this.world.removeActor(r));const{position:i,rotation:n,scale:o}=this.getVfxTransform(e,t.startTime);r.object.position.copy(i),r.object.rotation.copy(n),r.object.scale.copy(o),this.vfxActors.set(a,r),this._state.value===SequencePlaybackState.Playing&&r.play()}catch(e){console.error(`Failed to create VFX actor for clip ${t.id}:`,e)}}getVfxTransform(e,t){const a=new c,s=new i,r=new c(1,1,1),n=e.subTracks.find(e=>"transform"===e.type);if(n&&n.keyframes.length>0){const{prev:e,next:i,t:l}=T(n.keyframes,t);if(e&&(e.position&&a.fromArray(e.position),e.rotation&&s.fromArray([...e.rotation,"XYZ"]),e.scale&&r.fromArray(e.scale)),i&&e!==i&&e.time!==i.time){const t=b(l,e.interpolation);if(e.position&&i.position&&a.lerpVectors(te.fromArray(e.position),ae.fromArray(i.position),t),e.rotation&&i.rotation){re.setFromEuler(ne.fromArray([...e.rotation,"XYZ"])),ie.setFromEuler(oe.fromArray([...i.rotation,"XYZ"]));const a=new o;a.slerpQuaternions(re,ie,t),s.setFromQuaternion(a)}e.scale&&i.scale&&r.lerpVectors(te.fromArray(e.scale),ae.fromArray(i.scale),t)}}else a.fromArray(e.position),s.fromArray([...e.rotation,"XYZ"]),r.fromArray(e.scale);return{position:a,rotation:s,scale:r}}updateVfxTransform(e,t,a){const{position:s,rotation:r,scale:i}=this.getVfxTransform(e,a);t.object.position.copy(s),t.object.rotation.copy(r),t.object.scale.copy(i)}resolveActorType(e){const t=this.actorFactory.classes[e];if(null!=t)return t;const a=d[e];return a||(console.warn(`Could not resolve actor type: ${e}`),null)}async spawnActorForClip(e,t,a,s){if(!this.world||!e.actorType)return null;const r=this.resolveActorType(e.actorType);if(!r)return null;try{return await this.world.spawnActor(r,a,s)}catch(t){return console.error(`Failed to spawn actor ${e.actorType}:`,t),null}}async spawnPrefabForClip(e,t,a,s){if(!this.world||!this.assetLoader||!e.prefabId)return null;try{const t=await this.assetLoader.getPrefabById(e.prefabId);if(!t)return null;return await this.world.spawnPrefab(t,a,s)}catch(t){return console.error(`Failed to spawn prefab ${e.prefabId}:`,t),null}}async spawnMeshForClip(e,t,a,s){if(!this.world||!this.assetLoader||!e.meshId)return null;try{const t=await this.assetLoader.getAsset(e.meshId),r=await this.assetLoader.getModelByAssetId(e.meshId),i=q.clone(r.scene);if(i.position.copy(a),i.rotation.copy(s),t){await this.assetLoader.applyMaterials(t,i);const e=t.mesh?.rescale;null!=e&&1!==e&&i.scale.multiplyScalar(e)}return this.world.scene.add(i),i}catch(t){return console.error(`Failed to spawn mesh ${e.meshId}:`,t),null}}despawnInstance(e){if(this.restorePropertySnapshotsForInstance(e),this.restoreMaterialSnapshotsForInstance(e),this.world)switch(e?.type){case"actor":this.world.removeActor(e.instance);break;case"prefab":this.world.removePrefab(e.instance);break;case"mesh":this.world.scene.remove(e.instance)}}despawnAll(){for(const e of this.spawnedInstances.values())this.despawnInstance(e);this.spawnedInstances.clear(),this.activeClips.clear(),this.pendingSpawns.clear()}getInitialTransform(e,t,a){const s=new c,r=new i,n=e.subTracks.find(e=>"transform"===e.type);if(n&&n.keyframes.length>0){const{prev:e}=T(n.keyframes,a);e&&(e.position&&s.fromArray(e.position),e.rotation&&r.fromArray([...e.rotation,"XYZ"]))}else t.initialPosition&&s.fromArray(t.initialPosition),t.initialRotation&&r.fromArray([...t.initialRotation,"XYZ"]);return{position:s,rotation:r}}evaluateSpawnTrack(e,t,a){if(!e.clips||0===e.clips.length)return;const s=t||this.bindings.get(e.id);if(s&&s.target)for(const t of e.clips){const r=t.startTime+t.duration,i=a>=t.startTime&&a<r,n=`${e.id}-${t.id}`;if(i){this.activeClips.has(n)||(this.activeClips.add(n),this.spawnedInstances.set(n,{type:"proxy",target:s.target}));(s.target instanceof p?s.target.object:s.target)&&this.evaluateSubTracks(e.subTracks,s,a)}else this.activeClips.has(n)&&(this.restorePropertySnapshotsForTarget(s.target),this.restoreMaterialSnapshotsForTarget(s.target),this.activeClips.delete(n),this.spawnedInstances.delete(n))}else for(const t of e.clips){const s=t.startTime+t.duration,r=a>=t.startTime&&a<s,i=`${e.id}-${t.id}`,n=this.spawnedInstances.has(i),o=this.pendingSpawns.has(i);if(!r||n||o){if(r&&n){const t=this.spawnedInstances.get(i);t&&"proxy"!==t.type&&this.evaluateSubTracks(e.subTracks,t,a)}else if(!r&&n){const e=this.spawnedInstances.get(i);e&&(this.despawnInstance(e),this.spawnedInstances.delete(i),this.activeClips.delete(i))}}else{const{position:a,rotation:s}=this.getInitialTransform(e,t,t.startTime);this.pendingSpawns.add(i),this.spawnForClip(e,t,a,s,i)}}}getInstanceObject(e){switch(e.type){case"actor":return e.instance.object;case"prefab":return e.instance.mainActor?.object||e.instance.object;case"mesh":return e.instance;case"proxy":return e.target instanceof p?e.target.object:e.target;default:return null}}async spawnForClip(e,t,a,r,i){const n=this.clearCounter;let o=null;try{switch(e.spawnType){case"actor":const s=await this.spawnActorForClip(e,t,a,r);s&&(o={type:"actor",instance:s});break;case"prefab":const i=await this.spawnPrefabForClip(e,t,a,r);i&&(o={type:"prefab",instance:i});break;case"mesh":const n=await this.spawnMeshForClip(e,t,a,r);n&&(o={type:"mesh",instance:n})}if(n!==this.clearCounter)return void(o&&this.despawnInstance(o));const l=this._time.value,c=l>=t.startTime&&l<t.startTime+t.duration;if(o&&c){const t=this.getInstanceObject(o);"proxy"===o.type||("actor"===o.type?o.target=o.instance:"prefab"===o.type?o.target=o.instance.mainActor||o.instance.object:o.target=t);e.subTracks.some(e=>"animation"===e.type)&&t&&(o.mixer=new s(t),o.activeActions=new Map),this.spawnedInstances.set(i,o),this.activeClips.add(i)}else o&&this.despawnInstance(o)}finally{this.pendingSpawns.delete(i)}}getPlayableObject(e){return e.target instanceof p?e.target.object:e.target??null}applyResolvedPropertyValue(e,t,a){if(!t||!e.propertyPath)return;const s=this.getPropertyResolution(t,e);if(!s)return;const r=this.getPropertySnapshotKey(e);this.capturePropertySnapshot(t,r,s);const n=function(e,t){switch(t.type){case y.Number:return"number"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.Boolean:return"boolean"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.String:return"string"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.Vector2:return $(e,t.value);case y.Vector3:return U(e,t.value);case y.Vector4:return N(e,t.value);case y.Euler:return function(e,t){const a=X(t,3);if(!a)return{applied:!1};const s=Array.isArray(t)&&"string"==typeof t[3]?t[3]:"XYZ";if(e instanceof i)return e.set(a[0],a[1],a[2],s),{applied:!0,value:e};return{applied:!0,value:new i(a[0],a[1],a[2],s)}}(e,t.value);case y.Color:return W(e,t.value);default:return{applied:!1}}}(s.owner[s.key],a);n.applied&&(s.owner[s.key]=n.value)}getPropertyResolution(e,t){const a=e,s=this.getPropertySnapshotKey(t);let r=this.propertyResolutionCache.get(a);if(r||(r=new Map,this.propertyResolutionCache.set(a,r)),r.has(s))return r.get(s)??null;const i=this.getPropertyPathSegments(t.propertyPath);if(0===i.length)return r.set(s,null),null;let n=e;for(let e=0;e<i.length-1;e++){if(!D(n))return r.set(s,null),null;n=n[i[e]]}if(!D(n))return r.set(s,null),null;const o={owner:n,key:i[i.length-1]};return r.set(s,o),o}getPropertyPathSegments(e){const t=this.propertyPathSegments.get(e);if(t)return t;const a=e.split(".").map(e=>e.trim()).filter(Boolean);return this.propertyPathSegments.set(e,a),a}getPropertySnapshotKey(e){return`${e.id}:${e.propertyPath}`}capturePropertySnapshot(e,t,a){const s=e;let r=this.propertySnapshots.get(s);if(r||(r=new Map,this.propertySnapshots.set(s,r)),r.has(t))return;const i=a.owner[a.key];r.set(t,{resolution:a,hadOwnProperty:Object.prototype.hasOwnProperty.call(a.owner,a.key),value:i,valueSnapshot:Y(i)})}restorePropertySnapshotsForInstance(e){switch(e.type){case"actor":case"mesh":this.restorePropertySnapshotsForTarget(e.instance);break;case"prefab":this.restorePropertySnapshotsForTarget(e.target??null),this.restorePropertySnapshotsForTarget(e.instance.mainActor??null),this.restorePropertySnapshotsForTarget(e.instance.object);break;case"proxy":this.restorePropertySnapshotsForTarget(e.target)}}restorePropertySnapshotsForTarget(e){if(!e)return;const t=e,a=this.propertySnapshots.get(t);if(a){for(const e of a.values())Z(e);this.propertySnapshots.delete(t),this.propertyResolutionCache.delete(t)}}restoreAllPropertySnapshots(){for(const e of Array.from(this.propertySnapshots.keys()))this.restorePropertySnapshotsForTarget(e)}restoreMaterialSnapshotsForInstance(e){switch(e.type){case"actor":case"mesh":this.restoreMaterialSnapshotsForTarget(e.instance);break;case"prefab":this.restoreMaterialSnapshotsForTarget(e.target??null),this.restoreMaterialSnapshotsForTarget(e.instance.mainActor??null),this.restoreMaterialSnapshotsForTarget(e.instance.object);break;case"proxy":this.restoreMaterialSnapshotsForTarget(e.target)}}restoreMaterialSnapshotsForTarget(e){if(!e)return;const t=e;this.materialResolutionCache.delete(t);const a=this.materialSnapshots.get(t);if(a){for(const e of a.values())null==e.materialIndex?e.owner.material=e.originalMaterial:Array.isArray(e.owner.material)&&(e.owner.material[e.materialIndex]=e.originalMaterial),e.controlledMaterial!==e.originalMaterial&&e.controlledMaterial.dispose();this.materialSnapshots.delete(t)}}restoreAllMaterialSnapshots(){for(const e of Array.from(this.materialSnapshots.keys()))this.restoreMaterialSnapshotsForTarget(e)}applyResolvedMaterialValue(e,t,a){if(!t||!e.materialAssetId||!e.uniformName)return;const s=this.getMaterialSlotResolutions(t,e);for(const r of s){const s=this.ensureSequenceControlledMaterial(t,r),i=s.uniforms?.[e.uniformName];if(!i)continue;const n=K(i.value,a);n.applied&&(i.value=n.value,s.uniformsNeedUpdate=!0)}}getMaterialSlotResolutions(e,t){const a=e,s=`${t.id}:${t.materialAssetId}`;let r=this.materialResolutionCache.get(a);r||(r=new Map,this.materialResolutionCache.set(a,r));const i=r.get(s);if(i)return i;const n=e instanceof p?e.object:e,o=[];return n.traverse(e=>{const a=e.material;if(Array.isArray(a))for(let s=0;s<a.length;s++){const r=a[s];G(r,t)&&o.push({owner:e,materialIndex:s,material:r,key:`${e.uuid}:${s}`})}else G(a,t)&&o.push({owner:e,materialIndex:null,material:a,key:`${e.uuid}:material`})}),r.set(s,o),o}ensureSequenceControlledMaterial(e,t){const a=e;let s=this.materialSnapshots.get(a);s||(s=new Map,this.materialSnapshots.set(a,s));const r=s.get(t.key);if(r)return r.controlledMaterial;const i=t.material.clone();return null==t.materialIndex?t.owner.material=i:Array.isArray(t.owner.material)&&(t.owner.material[t.materialIndex]=i),s.set(t.key,{owner:t.owner,materialIndex:t.materialIndex,originalMaterial:t.material,controlledMaterial:i}),i}async ensureAnimationClip(e){if(!this.assetLoader)return null;const t=this.animationClips.get(e);if(t)return t;const a=this.loadingAnimationClips.get(e);if(a)return a;const s=(async()=>{try{const t=await this.assetLoader.getAnimationClipByAssetId(e);return t&&this.animationClips.set(e,t),t}catch(t){return console.error(`Failed to load animation clip for asset ${e}:`,t),null}finally{this.loadingAnimationClips.get(e)===s&&this.loadingAnimationClips.delete(e)}})();return this.loadingAnimationClips.set(e,s),s}prepareAnimationPlayback(e,t,a){if(!M(a)){let e=t;return a.clipEndOffset>0&&(e=e.clone(),e.duration=Math.max(0,e.duration-a.clipEndOffset)),{clip:e,timeScale:a.playbackRate,startOffset:a.clipStartOffset}}return{clip:this.getPlayableAnimationClip(e,t,a,!1),timeScale:1,startOffset:0}}getPlayableAnimationClip(e,t,a,s){if(!M(a))return s?E.fromClip(t,!1):t;const r=`${a.id}:${s?"root":"base"}`,i=`${B(a)}|${s?"root":"base"}`,n=this.retimedAnimationClips.get(r);if(n&&n.assetId===e&&n.signature===i)return n.clip;const o=I(t,a),l=s?E.fromClip(o,!1):o;return this.retimedAnimationClips.set(r,{assetId:e,signature:i,clip:l}),l}getAnimationPlaybackLocalTime(e,t){const a=Math.max(0,t-e.startTime);return M(e)?a:a*e.playbackRate+e.clipStartOffset}clearRetimedAnimationClipCache(e){if(null!=e)for(const[t,a]of this.retimedAnimationClips.entries())a.assetId===e&&this.retimedAnimationClips.delete(t);else this.retimedAnimationClips.clear()}captureOriginalTransforms(){for(const e of this.bindings.values()){const t=e.target instanceof p?e.target.object:e.target;t&&(e.originalTransform={position:t.position.clone(),rotation:t.rotation.clone(),scale:t.scale.clone()})}}restoreOriginalTransforms(){for(const e of this.bindings.values())if(e.originalTransform){const t=e.target instanceof p?e.target.object:e.target;t&&(t.position.copy(e.originalTransform.position),t.rotation.copy(e.originalTransform.rotation),t.scale.copy(e.originalTransform.scale))}}stopAllAnimations(){for(const e of this.bindings.values()){for(const t of e.activeActions.values())t.stop();e.activeActions.clear(),e.mixer&&e.mixer.stopAllAction(),e.charAnimComponent&&(e.charAnimComponent.stopSequenceAnimation(),e.charAnimComponent=void 0),e.charAnimActionKeys?.clear()}}stopAllVfx(){for(const e of this.vfxActors.values())e.paused||e.stop();this.activeVfxClips.clear()}dispose(){if(this.stop(),this.clearLocatorBindings(),this.clearSequenceCameras(),this.bindings.clear(),this.roleBindings.clear(),this.sequenceData=null,this.world)for(const e of this.vfxActors.values())this.world.removeActor(e);this.vfxActors.clear(),this.stopAllAudio(),this.audioBuffers.clear(),this.loadingAudioBuffers.clear(),this.animationClips.clear(),this.loadingAnimationClips.clear(),this.clearRetimedAnimationClipCache(),this.audioByClip.clear()}updateTrackParenting(e,t){const a=this.getActiveObjectsForTrack(e);if(0===a.length)return;let s=null;const r=e.parent?.trackId;if(r){const t=this.sequenceData?z(this.sequenceData.tracks).find(e=>e.id===r):void 0;if(t){const a=this.getActiveObjectsForTrack(t);if(a.length>0&&(s=a[0],e.parent?.socketName)){const t=this.findSocket(s,e.parent.socketName);t&&(s=t)}}}if(!s&&"camera"===e.type&&e.parentRole&&this.roleBindings.has(e.parentRole)){const t=this.roleBindings.get(e.parentRole);if(s=t instanceof p?t.object:t,e.parentRoleSocketName){const t=this.findSocket(s,e.parentRoleSocketName);t&&(s=t)}}for(const r of a)s?r.parent!==s&&(s.add(r),!t||"object"!==e.type&&"locator"!==e.type||(t.currentParent=s)):t?.currentParent&&t.currentParent===r.parent?this.restoreObjectParent(t,r):r.parent&&r.parent!==this.world?.scene&&"object"!==e.type&&"locator"!==e.type&&this.world?.scene.add(r)}findSocket(e,t){if(e.name===t)return e;if(e instanceof a.SkinnedMesh){const a=e.skeleton.bones.find(e=>e.name===t);if(a)return a}return e.getObjectByName(t)||null}getActiveObjectsForTrack(e){if("object"===e.type){const t=this.bindings.get(e.id);if(t&&t.target)return[t.target instanceof p?t.target.object:t.target]}else if("locator"===e.type){const t=this.bindings.get(e.id);if(t&&t.target instanceof n)return[t.target]}else{if("camera"===e.type)return[this.ensureSequenceCamera(e)];if("spawn"===e.type){const t=[];for(const[a,s]of this.spawnedInstances)if(a.startsWith(e.id+"-")&&this.activeClips.has(a)){const e=this.getInstanceObject(s);e&&t.push(e)}return t}if("vfx"===e.type){const t=[];for(const a of this.activeVfxClips)if(a.startsWith(e.id+"-")){const e=this.vfxActors.get(a);e&&t.push(e.object)}return t}}return[]}restoreObjectParent(e,t){e.originalParent?e.originalParent.add(t):this.world&&this.world.scene.add(t),e.currentParent=void 0}restoreOriginalParents(){for(const e of this.bindings.values())if(e.currentParent){const t=e.target instanceof p?e.target.object:e.target;t&&this.restoreObjectParent(e,t)}}evaluateAudioSubTracks(e,t){const a={};for(const s of e.subTracks)if("audioParameter"===s.type){const e=s,r=A(e.parameter),i=x(e.keyframes,t,{min:r.min,max:r.max});void 0!==i&&(a[e.parameter]=i)}return a}stringToRandom(e){let t=0;for(let a=0;a<e.length;a++){t=(t<<5)-t+e.charCodeAt(a),t&=t}const a=1e4*Math.sin(t);return a-Math.floor(a)}async refreshAsset(e){let t=!1;this.assetLoader?.clearCacheById(e),this.animationClips.delete(e),this.loadingAnimationClips.delete(e),this.clearRetimedAnimationClipCache(e),this.vfxService?.clearPool(e),t=this.refreshVfxActorsForAssetIds(new Set([e]))||t;for(const[a,s]of this.activePostProcessClips.entries())s.assetId===e&&(this.releasePostProcessClipEffect(a),t=!0);t=this.refreshSpawnedInstancesForClipKeys(this.getSpawnClipKeysForAsset(e))||t;const a=await this.getAssetOrNull(e);return"shaderGraph"===a?.type&&(t=await this.refreshShaderGraphDependentAssets(e)||t),t}refreshVfxActorsForAssetIds(e){let t=!1;for(const[a,s]of this.vfxActors.entries())this.vfxClipKeyUsesAnyAsset(a,e)&&(this.world&&this.world.removeActor(s),this.vfxActors.delete(a),this.activeVfxClips.delete(a),t=!0);return t}vfxClipKeyUsesAnyAsset(e,t){for(const a of t)if(e.endsWith(`-${a}`))return!0;return!1}refreshSpawnedInstancesForClipKeys(e){let t=!1;for(const[a,s]of this.spawnedInstances.entries())e.has(a)&&(this.despawnInstance(s),this.spawnedInstances.delete(a),this.activeClips.delete(a),t=!0);return t}getSpawnClipKeysForAsset(e){const t=new Set;if(!this.sequenceData)return t;for(const a of z(this.sequenceData.tracks))if("spawn"===a.type&&(a.prefabId===e||a.meshId===e))for(const e of a.clips)t.add(`${a.id}-${e.id}`);return t}async refreshShaderGraphDependentAssets(e){const t=await this.findSequenceVfxAssetIdsUsingShaderGraph(e);for(const e of t)this.vfxService?.clearPool(e);const a=this.refreshVfxActorsForAssetIds(t),s=this.refreshSpawnedInstancesForClipKeys(await this.findSpawnClipKeysUsingShaderGraph(e));return a||s}async findSequenceVfxAssetIdsUsingShaderGraph(e){const t=new Set;if(!this.sequenceData)return t;const a=new Map;for(const s of z(this.sequenceData.tracks))if("vfx"===s.type)for(const r of s.clips)null==r.vfxAssetId||t.has(r.vfxAssetId)||await this.assetUsesShaderGraph(r.vfxAssetId,e,a)&&t.add(r.vfxAssetId);return t}async findSpawnClipKeysUsingShaderGraph(e){const t=new Set;if(!this.sequenceData)return t;const a=new Map;for(const s of z(this.sequenceData.tracks))if("spawn"===s.type&&await this.spawnTrackUsesShaderGraph(s,e,a))for(const e of s.clips)t.add(`${s.id}-${e.id}`);return t}async spawnTrackUsesShaderGraph(e,t,a){if(null!=e.meshId&&await this.assetUsesShaderGraph(e.meshId,t,a))return!0;if(null!=e.prefabId&&await this.assetUsesShaderGraph(e.prefabId,t,a))return!0;for(const s of e.subTracks??[])if("material"===s.type&&null!=s.materialAssetId&&await this.assetUsesShaderGraph(s.materialAssetId,t,a))return!0;return!1}assetUsesShaderGraph(e,t,a,s=new Set){if(e===t)return Promise.resolve(!0);if(s.has(e))return Promise.resolve(!1);if(a.has(e))return a.get(e);const r=this.assetUsesShaderGraphUncached(e,t,a,s);return a.set(e,r),r}async assetUsesShaderGraphUncached(e,t,a,s){if(s.has(e))return!1;const r=await this.getAssetOrNull(e);if(null==r)return!1;const i=new Set(s);return i.add(e),!!this.materialAssetUsesShaderGraph(r,t)||("mesh"===r.type?this.materialAssignmentsUseShaderGraph(r.materialAssignments,t,a,i):"prefab"===r.type?this.sceneObjectsUseShaderGraph(r.prefab?.objects,t,a,i):"vfx"===r.type&&this.vfxAssetUsesShaderGraph(r,t,a,i))}materialAssetUsesShaderGraph(e,t){return"shaderGraph"===e.type?e.id===t:"asset"===e.material?.shaderGraph?.source&&e.material.shaderGraph.assetId===t}async materialAssignmentsUseShaderGraph(e,t,a,s){for(const r of e??[])if(null!=r.materialId&&"null"!==r.materialId&&await this.assetUsesShaderGraph(r.materialId,t,a,s))return!0;return!1}async sceneObjectsUseShaderGraph(e,t,a,s){for(const r of e??[]){if(await this.materialAssignmentsUseShaderGraph(r.materialAssignments,t,a,s))return!0;if(null!=r.assetId&&("asset_mesh"===r.type||"prefab"===r.type||"vfx"===r.type)&&await this.assetUsesShaderGraph(r.assetId,t,a,s))return!0;if(await this.sceneObjectsUseShaderGraph(r.children,t,a,s))return!0}return!1}async vfxAssetUsesShaderGraph(e,t,a,s){for(const r of e.vfx?.emitters??[])if(await this.emitterUsesShaderGraph(r,t,a,s))return!0;return!1}async emitterUsesShaderGraph(e,t,a,s){if(await this.emitterOutputUsesShaderGraph(e.output,t,a,s))return!0;for(const r of e.children??[])if(await this.emitterUsesShaderGraph(r,t,a,s))return!0;return!1}async emitterOutputUsesShaderGraph(e,t,a,s){const r=e.materialSource??("asset"===e.shaderGraph?.source?"shaderGraph":void 0);return"shaderGraph"===r&&"asset"===e.shaderGraph?.source&&e.shaderGraph.assetId===t||!("material"!==r||!("material"in e)||null==e.material||!await this.assetUsesShaderGraph(e.material,t,a,s))}async getAssetOrNull(e){if(!this.assetLoader)return null;try{return await this.assetLoader.getAsset(e)??null}catch{return null}}async invokeSequenceEvent(e,t,a,s){let r=!1;for(let e=0;e<s.length;e++)if(C(s[e])){r=!0;break}if(r)try{const t=new Array(s.length);for(let e=0;e<s.length;e++)t[e]=g(s[e],this.sequenceEventAsyncResolvers);const r=await Promise.all(t);await a.call(e,...r)}catch(e){console.error(`Failed to call sequence event ${t}:`,e)}else try{const t=new Array(s.length);for(let e=0;e<s.length;e++)t[e]=v(s[e],this.sequenceEventSyncResolvers);a.call(e,...t)}catch(e){console.error(`Failed to call sequence event ${t}:`,e)}}resolveSequenceEventActorReference(e){if(!this.world||null==e)return null;const t=e,a="object"==typeof t&&null!=t?.id?t.id:"string"==typeof t?t:null;if(null==a)return null;for(const e of this.world.actors){const t=e.object.userData.src??e.object.userData._src;if(t?.id===a)return e}return null}resolveSequenceEventSequence(e){return function(e){return"object"==typeof e&&null!=e&&"duration"in e&&"tracks"in e}(e)?new S(e):this.assetLoader&&"string"==typeof e?this.assetLoader.getSequenceById(e):null}async resolveSequenceEventAnimationClip(e){const t="string"==typeof e?e:"object"==typeof e&&null!=e?e.assetId??null:null;return null!=t&&this.assetLoader?this.assetLoader.getAnimationClipByAssetId(t):null}}function R(e){return e.options?.length>0||e.propertyType===y.Boolean||e.propertyType===y.String}function V(e){return e.valueType===y.Boolean||e.valueType===y.String}function D(e){return"object"==typeof e&&null!=e||"function"==typeof e}function K(e,t){switch(t.type){case y.Number:return"number"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.Boolean:return"boolean"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.Vector2:return $(e,t.value);case y.Vector3:return U(e,t.value);case y.Vector4:return N(e,t.value);case y.Color:return function(e,t){if(e instanceof c){const a=le.set(0);return Q(a,t)?(e.set(a.r,a.g,a.b),{applied:!0,value:e}):{applied:!1}}if(e instanceof h){const a=le.set(0);return Q(a,t)?(e.set(a.r,a.g,a.b,e.w),{applied:!0,value:e}):{applied:!1}}return W(e,t)}(e,t.value);default:return{applied:!1}}}function G(e,t){return function(e){return e instanceof a.Material||!0===e?.isMaterial}(e)&&e.userData?.assetId===t.materialAssetId&&null!=e.uniforms?.[t.uniformName]}function $(e,t){const a=X(t,2);return a?e instanceof l?(e.fromArray(a),{applied:!0,value:e}):{applied:!0,value:new l(a[0],a[1])}:{applied:!1}}function U(e,t){const a=X(t,3);return a?e instanceof c?(e.fromArray(a),{applied:!0,value:e}):{applied:!0,value:new c(a[0],a[1],a[2])}:{applied:!1}}function N(e,t){const a=X(t,4);return a?e instanceof h?(e.fromArray(a),{applied:!0,value:e}):{applied:!0,value:new h(a[0],a[1],a[2],a[3])}:{applied:!1}}function W(e,t){if(e instanceof r)return Q(e,t)?{applied:!0,value:e}:{applied:!1};const a=new r;return Q(a,t)?{applied:!0,value:a}:{applied:!1}}function X(e,t){if(!Array.isArray(e)||e.length<t)return null;const a=new Array(t);for(let s=0;s<t;s++){if("number"!=typeof e[s])return null;a[s]=e[s]}return a}function Q(e,t){return t instanceof r||"string"==typeof t||"number"==typeof t?(e.set(t),!0):!!(Array.isArray(t)&&t.length>=3)&&(e.setRGB("number"==typeof t[0]?t[0]:0,"number"==typeof t[1]?t[1]:0,"number"==typeof t[2]?t[2]:0),!0)}function Y(e){if(e instanceof l||e instanceof c||e instanceof h||e instanceof r||e instanceof i)return e.clone()}function Z(e){const{owner:t,key:a}=e.resolution;e.hadOwnProperty?(!function(e,t){if(e instanceof l&&t instanceof l)return e.copy(t),!0;if(e instanceof c&&t instanceof c)return e.copy(t),!0;if(e instanceof h&&t instanceof h)return e.copy(t),!0;if(e instanceof r&&t instanceof r)return e.copy(t),!0;if(e instanceof i&&t instanceof i)return e.copy(t),!0}(e.value,e.valueSnapshot),t[a]=e.value):delete t[a]}function z(e){const t=[];for(const a of e)t.push(a),"group"===a.type&&t.push(...z(a.childTracks));return t}function H(e){if("string"!=typeof e)return null;const t=e.trim();return t.length>0?t:null}function J(e){const t=new a.Group;t.name=`SequenceLocatorMarker:${e}`,t.renderOrder=1e3;const s=new a.AxesHelper(.35);s.renderOrder=1e3;const r=Array.isArray(s.material)?s.material:[s.material];for(const e of r)e.depthTest=!1,e.transparent=!0,e.opacity=.9,e.toneMapped=!1;t.add(s);const i=function(e){if("undefined"==typeof document)return null;const t=document.createElement("canvas");t.width=256,t.height=64;const s=t.getContext("2d");if(!s)return null;s.clearRect(0,0,t.width,t.height),s.fillStyle="rgba(16, 18, 24, 0.78)",function(e,t,a,s,r,i){const n=t+s,o=a+r;e.beginPath(),e.moveTo(t+i,a),e.lineTo(n-i,a),e.quadraticCurveTo(n,a,n,a+i),e.lineTo(n,o-i),e.quadraticCurveTo(n,o,n-i,o),e.lineTo(t+i,o),e.quadraticCurveTo(t,o,t,o-i),e.lineTo(t,a+i),e.quadraticCurveTo(t,a,t+i,a),e.closePath()}(s,0,8,t.width,48,8),s.fill(),s.font="24px sans-serif",s.textAlign="center",s.textBaseline="middle",s.fillStyle="#f8fafc",s.fillText(e||"Locator",t.width/2,t.height/2);const r=new a.CanvasTexture(t);r.needsUpdate=!0;const i=new a.SpriteMaterial({map:r,transparent:!0,depthTest:!1});i.toneMapped=!1;const n=new a.Sprite(i);return n.scale.set(.9,.225,1),n}(e);return i&&(i.position.set(0,.45,0),i.renderOrder=1001,t.add(i)),t.traverse(e=>{e.raycast=()=>{}}),t}function ee(e){e.traverse(e=>{const t=e.material;if(Array.isArray(t))for(const e of t)e?.dispose?.(),e?.map?.dispose?.();else t?.dispose?.(),t?.map?.dispose?.()})}const te=new c,ae=new c,se=new c,re=new o,ie=new o,ne=new i,oe=new i,le=new r;/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -61,4 +61,18 @@ export declare class RandomVelocity extends Initializer {
61
61
  constructor(min: Vector3, max: Vector3);
62
62
  initialize(target: Particle): void;
63
63
  }
64
+ export declare const alignRotationAxes: readonly ["+X", "-X", "+Y", "-Y", "+Z", "-Z"];
65
+ export type AlignRotationAxis = typeof alignRotationAxes[number];
66
+ export declare const alignRotationModes: readonly ["AwayFromCenter", "TowardsCenter", "AlongVelocity"];
67
+ export type AlignRotationMode = typeof alignRotationModes[number];
68
+ export declare class AlignRotation extends Initializer {
69
+ private axis;
70
+ private mode;
71
+ private offset;
72
+ private center;
73
+ private axisVec;
74
+ constructor(axis: AlignRotationAxis, mode: AlignRotationMode, offset?: Vector3, center?: Vector3);
75
+ private setAxis;
76
+ initialize(particle: Particle): void;
77
+ }
64
78
  //# sourceMappingURL=initializsers.d.ts.map
@@ -1,4 +1,4 @@
1
- import{Vector3 as t}from"three";import{Span as i,Initializer as e}from"@hology/nebula";export class DefaultInitializer extends e{init(t,i){i.parent=t}initialize(t){}}export class Rotation extends e{constructor(t){super(),this.rotation=t}setRotation(t){this.rotation=t.clone()}initialize(t){"number"!=typeof t.rotation&&t.rotation.copy(this.rotation)}}export const randomRotationAxis=["XYZ","X","Y","Z"];export class RandomRotation extends e{constructor(t){super(),this.axis=t}initialize(t){switch(this.axis){case"XYZ":t.rotation.set(this.randomAngle(),this.randomAngle(),this.randomAngle());break;case"X":t.rotation.x=this.randomAngle();break;case"Y":t.rotation.y=this.randomAngle();break;case"Z":t.rotation.z=this.randomAngle()}}randomAngle(){return 2*Math.PI*Math.random()}}export class InitialScale extends e{constructor(t){super(),this.scale=t}setScale(t){this.scale=t}initialize(t){t.scale=this.scale}}export class RandomScale extends e{constructor(t,i){super(),this.min=t,this.max=i}setRange(t,i){this.min=t,this.max=i}initialize(t){t.scale=n(this.min,this.max)}}export class InitialScaleComponents extends e{constructor(t){super(),this.scale=t}setScaleComponents(t){this.scale=t.clone()}initialize(t){t.transform.initialScale=this.scale.clone()}}export class AdditiveVelocity extends e{constructor(t,i){super(),this.min=t,this.max=i}initialize(t){const i=o(this.min),e=null!=this.max?o(this.max):void 0;t.velocity.x+=null!=e?n(i.x,e.x):i.x,t.velocity.y+=null!=e?n(i.y,e.y):i.y,t.velocity.z+=null!=e?n(i.z,e.z):i.z}}export class RandomDirection extends e{constructor(t){super(),this.speed=t}setSpeed(t){this.speed=t}initialize(t){s.set(2*Math.random()-1,2*Math.random()-1,2*Math.random()-1).normalize().multiplyScalar(this.speed),t.velocity.x+=s.x,t.velocity.y+=s.y,t.velocity.z+=s.z}}export class RandomVelocity extends e{constructor(t,e){super(),this.min=t,this.max=e,this.x=new i(this.min.x,this.max.x),this.y=new i(this.min.y,this.max.y),this.z=new i(this.min.z,this.max.z)}initialize(t){t.velocity.x+=this.x.getValue(),t.velocity.y+=this.y.getValue(),t.velocity.z+=this.z.getValue()}}const s=new t;function n(t,i){return Math.random()*(i-t)+t}function o(t){return"function"==typeof t?t():t}/*
1
+ import{Vector3 as t,Quaternion as e,Euler as i}from"three";import{Span as s,Initializer as o}from"@hology/nebula";export class DefaultInitializer extends o{init(t,e){e.parent=t}initialize(t){}}export class Rotation extends o{constructor(t){super(),this.rotation=t}setRotation(t){this.rotation=t.clone()}initialize(t){"number"!=typeof t.rotation&&t.rotation.copy(this.rotation)}}export const randomRotationAxis=["XYZ","X","Y","Z"];export class RandomRotation extends o{constructor(t){super(),this.axis=t}initialize(t){switch(this.axis){case"XYZ":t.rotation.set(this.randomAngle(),this.randomAngle(),this.randomAngle());break;case"X":t.rotation.x=this.randomAngle();break;case"Y":t.rotation.y=this.randomAngle();break;case"Z":t.rotation.z=this.randomAngle()}}randomAngle(){return 2*Math.PI*Math.random()}}export class InitialScale extends o{constructor(t){super(),this.scale=t}setScale(t){this.scale=t}initialize(t){t.scale=this.scale}}export class RandomScale extends o{constructor(t,e){super(),this.min=t,this.max=e}setRange(t,e){this.min=t,this.max=e}initialize(t){t.scale=l(this.min,this.max)}}export class InitialScaleComponents extends o{constructor(t){super(),this.scale=t}setScaleComponents(t){this.scale=t.clone()}initialize(t){t.transform.initialScale=this.scale.clone()}}export class AdditiveVelocity extends o{constructor(t,e){super(),this.min=t,this.max=e}initialize(t){const e=h(this.min),i=null!=this.max?h(this.max):void 0;t.velocity.x+=null!=i?l(e.x,i.x):e.x,t.velocity.y+=null!=i?l(e.y,i.y):e.y,t.velocity.z+=null!=i?l(e.z,i.z):e.z}}export class RandomDirection extends o{constructor(t){super(),this.speed=t}setSpeed(t){this.speed=t}initialize(t){c.set(2*Math.random()-1,2*Math.random()-1,2*Math.random()-1).normalize().multiplyScalar(this.speed),t.velocity.x+=c.x,t.velocity.y+=c.y,t.velocity.z+=c.z}}export class RandomVelocity extends o{constructor(t,e){super(),this.min=t,this.max=e,this.x=new s(this.min.x,this.max.x),this.y=new s(this.min.y,this.max.y),this.z=new s(this.min.z,this.max.z)}initialize(t){t.velocity.x+=this.x.getValue(),t.velocity.y+=this.y.getValue(),t.velocity.z+=this.z.getValue()}}export const alignRotationAxes=["+X","-X","+Y","-Y","+Z","-Z"];export const alignRotationModes=["AwayFromCenter","TowardsCenter","AlongVelocity"];export class AlignRotation extends o{constructor(e,i,s=new t,o=new t){super(),this.axis=e,this.mode=i,this.offset=s,this.center=o,this.axisVec=new t(0,1,0),this.setAxis(e)}setAxis(t){switch(t){case"+X":this.axisVec.set(1,0,0);break;case"-X":this.axisVec.set(-1,0,0);break;case"+Y":this.axisVec.set(0,1,0);break;case"-Y":this.axisVec.set(0,-1,0);break;case"+Z":this.axisVec.set(0,0,1);break;case"-Z":this.axisVec.set(0,0,-1)}}initialize(t){if("number"!=typeof t.rotation){switch(this.mode){case"AwayFromCenter":c.copy(t.position).sub(this.center).normalize();break;case"TowardsCenter":c.copy(t.position).sub(this.center).normalize().multiplyScalar(-1);break;case"AlongVelocity":c.copy(t.velocity).normalize()}c.lengthSq()<1e-4&&c.set(0,1,0),n.setFromUnitVectors(this.axisVec,c),this.offset.lengthSq()>0&&(a.setFromEuler(r.set(this.offset.x,this.offset.y,this.offset.z)),n.multiply(a)),r.setFromQuaternion(n),t.rotation.x=r.x,t.rotation.y=r.y,t.rotation.z=r.z}}}const n=new e,a=new e,r=new i,c=new t;function l(t,e){return Math.random()*(e-t)+t}function h(t){return"function"==typeof t?t():t}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -31,6 +31,8 @@ export declare class VfxActor extends BaseActor {
31
31
  stop(): void;
32
32
  applyClipEndBehavior(behavior: VfxClipEndBehavior | undefined, remainingLifeSeconds?: number): void;
33
33
  restart(): void;
34
+ private restartEmitter;
35
+ private removeEmitterParticlesRecursive;
34
36
  private _worldPos;
35
37
  private _worldRot;
36
38
  private _worldEul;
@@ -1,4 +1,4 @@
1
- import{__decorate as t}from"tslib";import*as s from"three";import{Rate as e}from"@hology/nebula";import{Actor as i,BaseActor as r}from"../../gameplay/actors/actor.js";import{inject as o}from"../../gameplay/inject.js";import{AssetLoader as a}from"../../gameplay/services/asset-loader.js";import{ViewController as n}from"../../gameplay/services/render.js";import{World as h}from"../../gameplay/services/world.js";import{DelayRate as m}from"./rates.js";import{materializeVfx as p}from"./vfx-materializer.js";import{PhysicsSystem as l}from"../../gameplay/services/physics/physics-system.js";import{ShaderProvider as c}from"../../gameplay/services/shader-provider.js";import{AssetResourceLoader as d}from"../../scene/asset-resource-loader.js";import{AssetsProvider as u}from"../../scene/assets-provider.js";import{VfxInputRuntime as y}from"./vfx-input-runtime.js";let f=class extends r{constructor(){super(...arguments),this.timescale=1,this.paused=!0,this.assetLoader=o(a),this.assetManagerService=o(d),this.assetService=o(u),this.world=o(h),this.view=o(n),this.physics=o(l),this.shaderProvider=o(c),this.inputRuntime=new y,this.inputOverrides=new Map,this._worldPos=new s.Vector3,this._worldRot=new s.Quaternion,this._worldEul=new s.Euler,this.max=0}async fromAsset(t,s){if("vfx"!==t.type)throw"Asset must be a VFX asset but is "+t.type;null!=this.system&&(this.system.destroy(),this.system.emitters.forEach(t=>t.reset())),this.sourceAsset=t,this.disposeSystem&&this.disposeSystem(),this.world.scene.add(this.object),this.inputRuntime.setDefinitions(this.sourceAsset.vfx.inputs??[]);for(const[t,s]of this.inputOverrides)this.inputRuntime.setInput(t,s);null!=s&&this.setInputs(s);const{system:e,dispose:i,container:r}=await p(this.sourceAsset,this.object,{getAsset:t=>this.assetLoader.getAsset(t),getMaterial:t=>this.assetLoader.getMaterialByAssetId(t),getTexture:t=>this.assetLoader.getTextureByAssetId(t),getMesh:t=>this.assetLoader.getModelByAssetId(t).then(t=>t.scene)},this.view,this.physics,this.shaderProvider,this.assetService,this.assetManagerService,this.inputRuntime);this.system=e,this.disposeSystem=i,this.particleSystemContainer=r,this.object.visible=!1,this.object.matrixAutoUpdate=!1,this.object.matrixWorldAutoUpdate=!1,this.particleSystemContainer.matrixAutoUpdate=!1,this.particleSystemContainer.matrixWorldAutoUpdate=!1}setInput(t,e){this.inputOverrides.set(t,function(t){if(t instanceof s.Vector3||t instanceof s.Color)return t.clone();if(Array.isArray(t))return[...t];return t}(e)),this.inputRuntime.setInput(t,e)}setInputs(t){for(const[s,e]of Object.entries(t))this.setInput(s,e)}play(){null==this.particleSystemContainer.parent&&this.world.scene.add(this.particleSystemContainer),this.object.matrixAutoUpdate=!0,this.object.matrixWorldAutoUpdate=!0,this.particleSystemContainer.matrixAutoUpdate=!0,this.particleSystemContainer.matrixWorldAutoUpdate=!0,this.object.visible=!0,this.paused=!1;this.system.emitters.every(t=>t.dead)&&this.restart()}pause(){this.paused=!0}stop(){this.system.emitters.forEach(t=>{this.stopEmitterEmission(t)})}applyClipEndBehavior(t,s){const e=t??"finish";if("finish"!==e){if(null!=this.system&&null!=this.system.emitters)for(const t of this.system.emitters)this.applyEmitterClipEndBehavior(t,e,s)}else this.stop()}restart(){if(null!=this.system&&null!=this.system.emitters)for(const t of this.system.emitters){const s=t.rate;s instanceof m?s.restart():s.nextTime=0,t.removeAllParticles()}}onUpdate(t){this.paused||(this.object.getWorldPosition(this._worldPos),this.object.getWorldQuaternion(this._worldRot),this._worldEul.setFromQuaternion(this._worldRot),this.system?.emitters.forEach(t=>{"world"===t._space&&(t.setPosition(this._worldPos),t.setRotation(this._worldEul))}),this.updateSystem(t*this.timescale))}getParticleCount(){return this.system?.getCount()??0}onEndPlay(){this.stop(),null!=this.disposeSystem&&this.disposeSystem()}updateSystem(t){this.system?.update(t)}applyEmitterClipEndBehavior(t,s,e,i=!1){this.stopEmitterEmission(t,i);const r=t.particles??[];if("kill"===s)t.removeAllParticles?.();else{const t=Math.max(0,e??0);for(const s of r)s.life=Math.min(s.life,s.age+t)}const o=t.childEmitters??[];for(const t of o)this.applyEmitterClipEndBehavior(t,s,e,!0)}stopEmitterEmission(t,s=!1){const i=t.rate;i instanceof e&&(i.nextTime=1/0),s&&t.stopEmit?.()}};f=t([i()],f);export{f as VfxActor};/*
1
+ import{__decorate as t}from"tslib";import*as s from"three";import{Rate as e}from"@hology/nebula";import{Actor as i,BaseActor as r}from"../../gameplay/actors/actor.js";import{inject as o}from"../../gameplay/inject.js";import{AssetLoader as a}from"../../gameplay/services/asset-loader.js";import{ViewController as n}from"../../gameplay/services/render.js";import{World as m}from"../../gameplay/services/world.js";import{DelayRate as h}from"./rates.js";import{materializeVfx as l}from"./vfx-materializer.js";import{PhysicsSystem as p}from"../../gameplay/services/physics/physics-system.js";import{ShaderProvider as c}from"../../gameplay/services/shader-provider.js";import{AssetResourceLoader as d}from"../../scene/asset-resource-loader.js";import{AssetsProvider as u}from"../../scene/assets-provider.js";import{VfxInputRuntime as y}from"./vfx-input-runtime.js";let f=class extends r{constructor(){super(...arguments),this.timescale=1,this.paused=!0,this.assetLoader=o(a),this.assetManagerService=o(d),this.assetService=o(u),this.world=o(m),this.view=o(n),this.physics=o(p),this.shaderProvider=o(c),this.inputRuntime=new y,this.inputOverrides=new Map,this._worldPos=new s.Vector3,this._worldRot=new s.Quaternion,this._worldEul=new s.Euler,this.max=0}async fromAsset(t,s){if("vfx"!==t.type)throw"Asset must be a VFX asset but is "+t.type;null!=this.system&&(this.system.destroy(),this.system.emitters.forEach(t=>t.reset())),this.sourceAsset=t,this.disposeSystem&&this.disposeSystem(),this.world.scene.add(this.object),this.inputRuntime.setDefinitions(this.sourceAsset.vfx.inputs??[]);for(const[t,s]of this.inputOverrides)this.inputRuntime.setInput(t,s);null!=s&&this.setInputs(s);const{system:e,dispose:i,container:r}=await l(this.sourceAsset,this.object,{getAsset:t=>this.assetLoader.getAsset(t),getMaterial:t=>this.assetLoader.getMaterialByAssetId(t),getTexture:t=>this.assetLoader.getTextureByAssetId(t),getMesh:t=>this.assetLoader.getModelByAssetId(t).then(t=>t.scene)},this.view,this.physics,this.shaderProvider,this.assetService,this.assetManagerService,this.inputRuntime);this.system=e,this.disposeSystem=i,this.particleSystemContainer=r,this.object.visible=!1,this.object.matrixAutoUpdate=!1,this.object.matrixWorldAutoUpdate=!1,this.particleSystemContainer.matrixAutoUpdate=!1,this.particleSystemContainer.matrixWorldAutoUpdate=!1}setInput(t,e){this.inputOverrides.set(t,function(t){if(t instanceof s.Vector3||t instanceof s.Color)return t.clone();if(Array.isArray(t))return[...t];return t}(e)),this.inputRuntime.setInput(t,e)}setInputs(t){for(const[s,e]of Object.entries(t))this.setInput(s,e)}play(){null==this.particleSystemContainer.parent&&this.world.scene.add(this.particleSystemContainer),this.object.matrixAutoUpdate=!0,this.object.matrixWorldAutoUpdate=!0,this.particleSystemContainer.matrixAutoUpdate=!0,this.particleSystemContainer.matrixWorldAutoUpdate=!0,this.object.visible=!0,this.paused=!1;this.system.emitters.every(t=>t.dead)&&this.restart()}pause(){this.paused=!0}stop(){this.system.emitters.forEach(t=>{this.stopEmitterEmission(t)})}applyClipEndBehavior(t,s){const e=t??"finish";if("finish"!==e){if(null!=this.system&&null!=this.system.emitters)for(const t of this.system.emitters)this.applyEmitterClipEndBehavior(t,e,s)}else this.stop()}restart(){if(null!=this.system&&null!=this.system.emitters)for(const t of this.system.emitters)this.restartEmitter(t)}restartEmitter(t){const s=t.rate;s instanceof h?s.restart():s instanceof e&&(s.nextTime=0),null==t.clearParticlesRecursive?this.removeEmitterParticlesRecursive(t):t.clearParticlesRecursive()}removeEmitterParticlesRecursive(t){const s=t.childEmitters??[];for(const t of s)this.removeEmitterParticlesRecursive(t);t.removeAllParticles?.()}onUpdate(t){this.paused||(this.object.getWorldPosition(this._worldPos),this.object.getWorldQuaternion(this._worldRot),this._worldEul.setFromQuaternion(this._worldRot),this.system?.emitters.forEach(t=>{"world"===t._space&&(t.setPosition(this._worldPos),t.setRotation(this._worldEul))}),this.updateSystem(t*this.timescale))}getParticleCount(){return this.system?.getCount()??0}onEndPlay(){this.stop(),null!=this.disposeSystem&&this.disposeSystem()}updateSystem(t){this.system?.update(t)}applyEmitterClipEndBehavior(t,s,e,i=!1){this.stopEmitterEmission(t,i);const r=t.particles??[];if("kill"===s)t.removeAllParticles?.();else{const t=Math.max(0,e??0);for(const s of r)s.life=Math.min(s.life,s.age+t)}const o=t.childEmitters??[];for(const t of o)this.applyEmitterClipEndBehavior(t,s,e,!0)}stopEmitterEmission(t,s=!1){const i=t.rate;i instanceof e&&(i.nextTime=1/0),s&&t.stopEmit?.()}};f=t([i()],f);export{f as VfxActor};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -97,10 +97,11 @@ declare class PositionBoxDef extends BaseIniDef<PositionBoxDef> {
97
97
  bindingAdapter: VfxBindingAdapter<Position>;
98
98
  make(params?: ParamsType<this>): Initializer;
99
99
  }
100
- declare class PositionSphereDef extends BaseIniDef<PositionBoxDef> {
100
+ declare class PositionSphereDef extends BaseIniDef<PositionSphereDef> {
101
101
  parameters: {
102
102
  position: ShapeParameterDef<Vector3>;
103
103
  radius: FloatParameterDef;
104
+ surface: ShapeParameterDef<boolean>;
104
105
  };
105
106
  bindingAdapter: VfxBindingAdapter<Position>;
106
107
  make(params?: ParamsType<this>): Initializer;
@@ -168,6 +169,15 @@ declare class RandomRotationDef extends BaseIniDef<RandomRotationDef> {
168
169
  };
169
170
  make(params?: ParamsType<this>): Initializer;
170
171
  }
172
+ declare class AlignRotationDef extends BaseIniDef<AlignRotationDef> {
173
+ parameters: {
174
+ mode: SelectParameterDef<string>;
175
+ axis: SelectParameterDef<string>;
176
+ offset: ShapeParameterDef<Vector3>;
177
+ center: ShapeParameterDef<Vector3>;
178
+ };
179
+ make(params?: ParamsType<this>): Initializer;
180
+ }
171
181
  declare class InitialScaleDef extends BaseIniDef<InitialScaleDef> {
172
182
  parameters: {
173
183
  scale: FloatParameterDef;
@@ -369,6 +379,7 @@ declare const vfxInitializsers: {
369
379
  randomVelocity: RandomVelocityDef;
370
380
  radialVelocity: RadialVelocityDef;
371
381
  randomDirection: RandomDirectionDef;
382
+ alignRotation: AlignRotationDef;
372
383
  };
373
384
  declare const vfxBehaviours: {
374
385
  force: ForceDef;
@@ -1,4 +1,4 @@
1
- import{LoopOnce as e,LoopPingPong as t,LoopRepeat as s,MathUtils as n,Vector2 as r,Vector3 as a}from"three";import{Alpha as i,Attraction as o,BoxZone as c,CircleZone as p,Color as d,ease as u,Force as m,Gravity as l,Life as w,LineZone as h,Mass as x,Position as f,RadialVelocity as g,RandomDrift as b,Repulsion as y,Rotate as v,Vector3D as k}from"@hology/nebula";import{AnimationBehavior as A,AxisDirection as z,AxisPlane as R,Disperse as L,FollowParent as D,LinearDamping as S,MoveOverLife as C,OrientAlongVelocity as T,RotatePosition as V,Scale as j,ScaleComponents as B}from"./behaviours.js";import{AdditiveVelocity as O,InitialScale as P,InitialScaleComponents as Y,RandomDirection as F,RandomRotation as X,randomRotationAxis as Z,RandomScale as I,Rotation as M}from"./initializsers.js";import{PointZone as K,SphereZone as W}from"./zones.js";import{WorldCollisionBehaviour as q}from"./vfx-collision-behaviour.js";import{Curve2 as E}from"../../utils/curve.js";import{liveBindingAdapter as G,spawnBindingAdapter as H}from"./vfx-binding-runtime.js";class J{build(e={}){const t=re(e,this.parameters);return this.make(t)}}class N{build(e={}){const t=re(e,this.parameters);return this.make(t)}}function Q(e,t,s){return{type:"number",default:e,float:!0,min:t,max:s}}function U(e,t,s,n){return{...Q(e,s,n),bindable:t}}function $(e){return{type:"vec3",default:(new a).fromArray(e)}}function _(e,t){return{...$(e),bindable:t}}function ee(e){return{type:"color",default:e}}function te(e,t){return{...ee(e),bindable:t}}function se(e,t){return{type:"select",opts:e,default:t}}function ne(){return{type:"curve",default:E.linear()}}function re(e,t){const s={};for(let n in t)null==e[n]?s[n]=t[n].default:s[n]=e[n];return s}function ae(e){return new k(e.x,e.y,e.z)}function ie(e){return new a(n.degToRad(e.x),n.degToRad(e.y),n.degToRad(e.z))}function oe(e){const{x:t,y:s,z:n}=e;return new K(t,s,n)}function ce(e,t){const{x:s,y:n,z:r}=e,{x:a,y:i,z:o}=t;return new c(s,n,r,a,i,o)}function pe(e,t){const{x:s,y:n,z:r}=e;return new W(s,n,r,t)}function de(e,t){return new h(e.x,e.y,e.z,t.x,t.y,t.z)}function ue(e,t,s,r=0){return new p(e.x,e.y,e.z,s,r,n.degToRad(t.x),n.degToRad(t.y),n.degToRad(t.z))}function me(e){return t=>e.getY(t)}const le={lifetime:new class extends N{constructor(){super(...arguments),this.parameters={duration:U(1,"spawn",0,1e5)},this.bindingAdapter=H((e,t)=>{e.resetLife(t.duration)})}make(e={}){return new w(e.duration)}},randomLifetime:new class extends N{constructor(){super(...arguments),this.parameters={minDuration:U(1,"spawn",0,1e5),maxDuration:U(2,"spawn",0,1e5)},this.bindingAdapter=H((e,t)=>{e.resetLife(t.minDuration,t.maxDuration)})}make(e={}){return new w(e.minDuration,e.maxDuration)}},positionPoint:new class extends N{constructor(){super(...arguments),this.parameters={position:_([0,0,0],"spawn")},this.bindingAdapter=H((e,t)=>{e.reset(oe(t.position))})}make(e={}){return new f(oe(e.position))}},positionBox:new class extends N{constructor(){super(...arguments),this.parameters={position:_([0,0,0],"spawn"),dimensions:_([0,0,0],"spawn")},this.bindingAdapter=H((e,t)=>{e.reset(ce(t.position,t.dimensions))})}make(e={}){return new f(ce(e.position,e.dimensions))}},positionSphere:new class extends N{constructor(){super(...arguments),this.parameters={position:_([0,0,0],"spawn"),radius:U(1,"spawn")},this.bindingAdapter=H((e,t)=>{e.reset(pe(t.position,t.radius))})}make(e={}){return new f(pe(e.position,e.radius))}},positionLine:new class extends N{constructor(){super(...arguments),this.parameters={a:_([0,0,0],"spawn"),b:_([0,0,1],"spawn")},this.bindingAdapter=H((e,t)=>{e.reset(de(t.a,t.b))})}make(e={}){return new f(de(e.a,e.b))}},positionCircle:new class extends N{constructor(){super(...arguments),this.parameters={position:_([0,0,0],"spawn"),rotation:_([0,0,0],"spawn"),radius:U(1,"spawn",0,1e4)},this.bindingAdapter=H((e,t)=>{e.reset(ue(t.position,t.rotation,t.radius))})}make(e={}){return new f(ue(e.position,e.rotation,e.radius))}},positionRing:new class extends N{constructor(){super(...arguments),this.parameters={position:_([0,0,0],"spawn"),rotation:_([0,0,0],"spawn"),radius:U(1,"spawn",0,1e4),thickness:U(.2,"spawn",0,1e4)},this.bindingAdapter=H((e,t)=>{e.reset(ue(t.position,t.rotation,t.radius,Math.max(t.thickness,1e-4)))})}make(e={}){return new f(ue(e.position,e.rotation,e.radius,Math.max(e.thickness,1e-4)))}},rotation:new class extends N{constructor(){super(...arguments),this.parameters={rotation:_([0,0,0],"spawn")},this.bindingAdapter=H((e,t)=>{e.setRotation(ie(t.rotation))})}make(e={}){return new M(ie(e.rotation))}},randomRotation:new class extends N{constructor(){super(...arguments),this.parameters={axis:se(Z,"XYZ")}}make(e={}){return new X(e.axis)}},scale:new class extends N{constructor(){super(...arguments),this.parameters={scale:U(1,"spawn")},this.bindingAdapter=H((e,t)=>{e.setScale(t.scale)})}make(e={}){return new P(e.scale)}},scaleComponents:new class extends N{constructor(){super(...arguments),this.parameters={scale:_([1,1,1],"spawn")},this.bindingAdapter=H((e,t)=>{e.setScaleComponents(t.scale)})}make(e={}){return new Y(e.scale)}},randomScale:new class extends N{constructor(){super(...arguments),this.parameters={min:U(1,"spawn"),max:U(1,"spawn")},this.bindingAdapter=H((e,t)=>{e.setRange(t.min,t.max)})}make(e={}){return new I(e.min,e.max)}},mass:new class extends N{constructor(){super(...arguments),this.parameters={min:U(1,"spawn")},this.bindingAdapter=H((e,t)=>{e.resetMass(t.min)})}make(e={}){return new x(e.min)}},velocity:new class extends N{constructor(){super(...arguments),this.parameters={velocity:_([0,0,0],"spawn")},this.bindingAdapter={buildBound:e=>new O(()=>e.get("velocity"))}}make(e={}){const{x:t,y:s,z:n}=e.velocity;return new O(new a(t,s,n))}},randomVelocity:new class extends N{constructor(){super(...arguments),this.parameters={min:_([0,0,0],"spawn"),max:_([0,0,0],"spawn")},this.bindingAdapter={buildBound:e=>new O(()=>e.get("min"),()=>e.get("max"))}}make(e={}){return new O(e.min,e.max)}},radialVelocity:new class extends N{constructor(){super(...arguments),this.parameters={speed:U(1,"spawn"),direction:_([0,1,0],"spawn"),spread:U(0,"spawn")},this.bindingAdapter=H((e,t)=>{e.resetRadialVelocity(t.speed,ae(t.direction),t.spread)})}make(e={}){return new g(e.speed,ae(e.direction),e.spread)}},randomDirection:new class extends N{constructor(){super(...arguments),this.parameters={speed:U(1,"spawn")},this.bindingAdapter=H((e,t)=>{e.setSpeed(t.speed)})}make(e={}){return new F(e.speed)}}},we={force:new class extends J{constructor(){super(...arguments),this.parameters={force:_([0,0,0],"live"),ease:ne()},this.bindingAdapter=G((e,t)=>{const s=t.force;e.setForce(s.x,s.y,s.z)})}make(e={}){return new m(e.force.x,e.force.y,e.force.z,void 0,me(e.ease))}},gravity:new class extends J{constructor(){super(...arguments),this.parameters={gravity:U(8,"live"),easing:ne()},this.bindingAdapter=G((e,t)=>{e.setForce(0,-t.gravity,0)})}make(e={}){return new l(e.gravity,void 0,me(e.easing))}},repulsion:new class extends J{constructor(){super(...arguments),this.parameters={target:_([0,0,0],"live"),force:U(1,"live"),radius:U(1,"live"),easing:ne()},this.bindingAdapter=G((e,t)=>{e.resetAttraction(ae(t.target),t.force,t.radius)})}make(e={}){const t=ae(e.target);return new y(t,e.force,e.radius,void 0,me(e.easing))}},attraction:new class extends J{constructor(){super(...arguments),this.parameters={target:_([0,0,0],"live"),force:U(1,"live"),radius:U(1,"live"),easing:ne()},this.bindingAdapter=G((e,t)=>{e.resetAttraction(ae(t.target),t.force,t.radius)})}make(e={}){const t=ae(e.target);return new o(t,e.force,e.radius,void 0,me(e.easing))}},scale:new class extends J{constructor(){super(...arguments),this.parameters={a:U(1,"spawn"),b:U(1,"spawn"),ease:ne()},this.bindingAdapter=H((e,t)=>{e.setScaleRange(t.a,t.b)})}make(e={}){return new j(e.a,e.b,me(e.ease))}},scaleComponents:new class extends J{constructor(){super(...arguments),this.parameters={a:_([1,1,1],"spawn"),b:_([1,1,1],"spawn"),ease:ne()},this.bindingAdapter=H((e,t)=>{e.setScaleRange(t.a,t.b)})}make(e={}){return new B(e.a,e.b,me(e.ease))}},randomDrift:new class extends J{constructor(){super(...arguments),this.parameters={drift:_([1,1,1],"live"),delay:U(0,"live"),ease:ne()},this.bindingAdapter=G((e,t)=>{const s=t.drift;e.setDrift(s.x,s.y,s.z,t.delay)})}make(e={}){return new b(e.drift.x,e.drift.y,e.drift.z,e.delay,void 0,me(e.ease))}},disperse:new class extends J{constructor(){super(...arguments),this.parameters={distance:U(1,"spawn"),axis:se(["XYZ","XZ","XY","YZ"],"XYZ"),ease:ne()},this.bindingAdapter=H((e,t)=>{e.setDistance(t.distance)})}make(e={}){return new L(e.distance,R[e.axis.toLowerCase()],me(e.ease))}},rotate:new class extends J{constructor(){super(...arguments),this.parameters={rotation:_([0,0,0],"spawn"),ease:ne()},this.bindingAdapter=H((e,t)=>{const s=ie(t.rotation);e.resetRotation(s.x,s.y,s.z)})}make(e={}){const t=ie(e.rotation);return new v(t.x,t.y,t.z,void 0,me(e.ease))}},rotateAdd:new class extends J{constructor(){super(...arguments),this.parameters={rotation:_([0,0,0],"spawn")},this.bindingAdapter=H((e,t)=>{const s=ie(t.rotation);e.resetRotation(s.x,s.y,s.z)})}make(e={}){const t=ie(e.rotation),s=new v(t.x,t.y,t.z,void 0);return s.rotationType="add",s}},changeColor:new class extends J{constructor(){super(...arguments),this.parameters={a:te("#ffffff","spawn"),b:te("#ffffff","spawn"),ease:ne()},this.bindingAdapter=H((e,t)=>{e.resetColor(t.a,t.b)})}make(e={}){return new d(e.a,e.b,void 0,me(e.ease))}},changeOpacity:new class extends J{constructor(){super(...arguments),this.parameters={a:U(1,"spawn",0,1),b:U(0,"spawn",0,1),ease:ne()},this.bindingAdapter=H((e,t)=>{e.resetAlpha(t.a,t.b)})}make(e={}){return new i(e.a,e.b,void 0,me(e.ease))}},vortex:new class extends J{constructor(){super(...arguments),this.parameters={axis:_([0,1,0],"live"),amount:U(1,"live")},this.bindingAdapter=G((e,t)=>{e.setAxisAngle(t.axis,t.amount)})}make(e={}){return new V(e.axis,e.amount)}},moveTo:new class extends J{constructor(){super(...arguments),this.parameters={target:_([0,1,0],"live"),ease:ne()},this.bindingAdapter=G((e,t)=>{const s=t.target;e.setTarget(s.x,s.y,s.z)})}make(e={}){return new C(e.target.x,e.target.y,e.target.z,me(e.ease))}},linearDamping:new class extends J{constructor(){super(...arguments),this.parameters={factor:U(.1,"live",0,1e3)},this.bindingAdapter=G((e,t)=>{e.setFactor(t.factor)})}make(e={}){return new S(e.factor)}},followParent:new class extends J{constructor(){super(...arguments),this.parameters={speed:U(0,"live")},this.bindingAdapter=G((e,t)=>{e.setSpeed(t.speed)})}make(e={}){return new D(e.speed)}},worldCollision:new class extends J{constructor(){super(...arguments),this.parameters={friction:Q(1,0,1),bounce:Q(1,0,1),lifeLoss:Q(0,0)}}make(e={}){return new q(null,e.bounce,e.friction,e.lifeLoss)}},animation:new class extends J{constructor(){var e;super(...arguments),this.parameters={clip:{type:"animationclip",default:null},timeScale:Q(1,0,10),weight:Q(1,0,1),loop:se(["Once","Repeat","PingPong"],"Once"),clampWhenFinished:{...(e=!0,{type:"boolean",default:e}),requires:{loop:"Once"}}}}make(n={}){let r=e;return"Repeat"===n.loop?r=s:"PingPong"===n.loop&&(r=t),new A(n.clip,n.timeScale,n.weight,r,n.clampWhenFinished,u.easeLinear)}}};export const VfxInitializserLibrary=le;export const VfxInitializserLibraryKeys=Object.keys(VfxInitializserLibrary);export const VfxBehaviourLibrary=we;export const VfxBehaviourLibraryKeys=Object.keys(VfxBehaviourLibrary);/*
1
+ import{LoopOnce as e,LoopPingPong as t,LoopRepeat as s,MathUtils as n,Vector2 as r,Vector3 as a}from"three";import{Alpha as i,Attraction as o,BoxZone as c,CircleZone as p,Color as u,ease as d,Force as m,Gravity as l,Life as w,LineZone as h,Mass as f,Position as x,RadialVelocity as g,RandomDrift as b,Repulsion as y,Rotate as k,Vector3D as v}from"@hology/nebula";import{AnimationBehavior as A,AxisDirection as z,AxisPlane as R,Disperse as L,FollowParent as D,LinearDamping as C,MoveOverLife as S,OrientAlongVelocity as T,RotatePosition as V,Scale as j,ScaleComponents as Y}from"./behaviours.js";import{AdditiveVelocity as B,AlignRotation as F,alignRotationAxes as O,alignRotationModes as P,InitialScale as X,InitialScaleComponents as Z,RandomDirection as I,RandomRotation as M,randomRotationAxis as K,RandomScale as W,Rotation as q}from"./initializsers.js";import{PointZone as E,SphereZone as G}from"./zones.js";import{WorldCollisionBehaviour as H}from"./vfx-collision-behaviour.js";import{Curve2 as J}from"../../utils/curve.js";import{liveBindingAdapter as N,spawnBindingAdapter as Q}from"./vfx-binding-runtime.js";class U{build(e={}){const t=ce(e,this.parameters);return this.make(t)}}class ${build(e={}){const t=ce(e,this.parameters);return this.make(t)}}function _(e,t,s){return{type:"number",default:e,float:!0,min:t,max:s}}function ee(e,t,s,n){return{..._(e,s,n),bindable:t}}function te(e){return{type:"boolean",default:e}}function se(e){return{type:"vec3",default:(new a).fromArray(e)}}function ne(e,t){return{...se(e),bindable:t}}function re(e){return{type:"color",default:e}}function ae(e,t){return{...re(e),bindable:t}}function ie(e,t){return{type:"select",opts:e,default:t}}function oe(){return{type:"curve",default:J.linear()}}function ce(e,t){const s={};for(let n in t)null==e[n]?s[n]=t[n].default:s[n]=e[n];return s}function pe(e){return new v(e.x,e.y,e.z)}function ue(e){return new a(n.degToRad(e.x),n.degToRad(e.y),n.degToRad(e.z))}function de(e){const{x:t,y:s,z:n}=e;return new E(t,s,n)}function me(e,t){const{x:s,y:n,z:r}=e,{x:a,y:i,z:o}=t;return new c(s,n,r,a,i,o)}function le(e,t,s=!1){const{x:n,y:r,z:a}=e;return new G(n,r,a,t,s)}function we(e,t){return new h(e.x,e.y,e.z,t.x,t.y,t.z)}function he(e,t,s,r=0){return new p(e.x,e.y,e.z,s,r,n.degToRad(t.x),n.degToRad(t.y),n.degToRad(t.z))}function fe(e){return t=>e.getY(t)}const xe={lifetime:new class extends ${constructor(){super(...arguments),this.parameters={duration:ee(1,"spawn",0,1e5)},this.bindingAdapter=Q((e,t)=>{e.resetLife(t.duration)})}make(e={}){return new w(e.duration)}},randomLifetime:new class extends ${constructor(){super(...arguments),this.parameters={minDuration:ee(1,"spawn",0,1e5),maxDuration:ee(2,"spawn",0,1e5)},this.bindingAdapter=Q((e,t)=>{e.resetLife(t.minDuration,t.maxDuration)})}make(e={}){return new w(e.minDuration,e.maxDuration)}},positionPoint:new class extends ${constructor(){super(...arguments),this.parameters={position:ne([0,0,0],"spawn")},this.bindingAdapter=Q((e,t)=>{e.reset(de(t.position))})}make(e={}){return new x(de(e.position))}},positionBox:new class extends ${constructor(){super(...arguments),this.parameters={position:ne([0,0,0],"spawn"),dimensions:ne([0,0,0],"spawn")},this.bindingAdapter=Q((e,t)=>{e.reset(me(t.position,t.dimensions))})}make(e={}){return new x(me(e.position,e.dimensions))}},positionSphere:new class extends ${constructor(){super(...arguments),this.parameters={position:ne([0,0,0],"spawn"),radius:ee(1,"spawn"),surface:te(!1)},this.bindingAdapter=Q((e,t)=>{e.reset(le(t.position,t.radius,t.surface))})}make(e={}){return new x(le(e.position,e.radius,e.surface))}},positionLine:new class extends ${constructor(){super(...arguments),this.parameters={a:ne([0,0,0],"spawn"),b:ne([0,0,1],"spawn")},this.bindingAdapter=Q((e,t)=>{e.reset(we(t.a,t.b))})}make(e={}){return new x(we(e.a,e.b))}},positionCircle:new class extends ${constructor(){super(...arguments),this.parameters={position:ne([0,0,0],"spawn"),rotation:ne([0,0,0],"spawn"),radius:ee(1,"spawn",0,1e4)},this.bindingAdapter=Q((e,t)=>{e.reset(he(t.position,t.rotation,t.radius))})}make(e={}){return new x(he(e.position,e.rotation,e.radius))}},positionRing:new class extends ${constructor(){super(...arguments),this.parameters={position:ne([0,0,0],"spawn"),rotation:ne([0,0,0],"spawn"),radius:ee(1,"spawn",0,1e4),thickness:ee(.2,"spawn",0,1e4)},this.bindingAdapter=Q((e,t)=>{e.reset(he(t.position,t.rotation,t.radius,Math.max(t.thickness,1e-4)))})}make(e={}){return new x(he(e.position,e.rotation,e.radius,Math.max(e.thickness,1e-4)))}},rotation:new class extends ${constructor(){super(...arguments),this.parameters={rotation:ne([0,0,0],"spawn")},this.bindingAdapter=Q((e,t)=>{e.setRotation(ue(t.rotation))})}make(e={}){return new q(ue(e.rotation))}},randomRotation:new class extends ${constructor(){super(...arguments),this.parameters={axis:ie(K,"XYZ")}}make(e={}){return new M(e.axis)}},scale:new class extends ${constructor(){super(...arguments),this.parameters={scale:ee(1,"spawn")},this.bindingAdapter=Q((e,t)=>{e.setScale(t.scale)})}make(e={}){return new X(e.scale)}},scaleComponents:new class extends ${constructor(){super(...arguments),this.parameters={scale:ne([1,1,1],"spawn")},this.bindingAdapter=Q((e,t)=>{e.setScaleComponents(t.scale)})}make(e={}){return new Z(e.scale)}},randomScale:new class extends ${constructor(){super(...arguments),this.parameters={min:ee(1,"spawn"),max:ee(1,"spawn")},this.bindingAdapter=Q((e,t)=>{e.setRange(t.min,t.max)})}make(e={}){return new W(e.min,e.max)}},mass:new class extends ${constructor(){super(...arguments),this.parameters={min:ee(1,"spawn")},this.bindingAdapter=Q((e,t)=>{e.resetMass(t.min)})}make(e={}){return new f(e.min)}},velocity:new class extends ${constructor(){super(...arguments),this.parameters={velocity:ne([0,0,0],"spawn")},this.bindingAdapter={buildBound:e=>new B(()=>e.get("velocity"))}}make(e={}){const{x:t,y:s,z:n}=e.velocity;return new B(new a(t,s,n))}},randomVelocity:new class extends ${constructor(){super(...arguments),this.parameters={min:ne([0,0,0],"spawn"),max:ne([0,0,0],"spawn")},this.bindingAdapter={buildBound:e=>new B(()=>e.get("min"),()=>e.get("max"))}}make(e={}){return new B(e.min,e.max)}},radialVelocity:new class extends ${constructor(){super(...arguments),this.parameters={speed:ee(1,"spawn"),direction:ne([0,1,0],"spawn"),spread:ee(0,"spawn")},this.bindingAdapter=Q((e,t)=>{e.resetRadialVelocity(t.speed,pe(t.direction),t.spread)})}make(e={}){return new g(e.speed,pe(e.direction),e.spread)}},randomDirection:new class extends ${constructor(){super(...arguments),this.parameters={speed:ee(1,"spawn")},this.bindingAdapter=Q((e,t)=>{e.setSpeed(t.speed)})}make(e={}){return new I(e.speed)}},alignRotation:new class extends ${constructor(){super(...arguments),this.parameters={mode:ie(P,"AwayFromCenter"),axis:ie(O,"+Y"),offset:se([0,0,0]),center:se([0,0,0])}}make(e={}){return new F(e.axis,e.mode,ue(e.offset),e.center)}}},ge={force:new class extends U{constructor(){super(...arguments),this.parameters={force:ne([0,0,0],"live"),ease:oe()},this.bindingAdapter=N((e,t)=>{const s=t.force;e.setForce(s.x,s.y,s.z)})}make(e={}){return new m(e.force.x,e.force.y,e.force.z,void 0,fe(e.ease))}},gravity:new class extends U{constructor(){super(...arguments),this.parameters={gravity:ee(8,"live"),easing:oe()},this.bindingAdapter=N((e,t)=>{e.setForce(0,-t.gravity,0)})}make(e={}){return new l(e.gravity,void 0,fe(e.easing))}},repulsion:new class extends U{constructor(){super(...arguments),this.parameters={target:ne([0,0,0],"live"),force:ee(1,"live"),radius:ee(1,"live"),easing:oe()},this.bindingAdapter=N((e,t)=>{e.resetAttraction(pe(t.target),t.force,t.radius)})}make(e={}){const t=pe(e.target);return new y(t,e.force,e.radius,void 0,fe(e.easing))}},attraction:new class extends U{constructor(){super(...arguments),this.parameters={target:ne([0,0,0],"live"),force:ee(1,"live"),radius:ee(1,"live"),easing:oe()},this.bindingAdapter=N((e,t)=>{e.resetAttraction(pe(t.target),t.force,t.radius)})}make(e={}){const t=pe(e.target);return new o(t,e.force,e.radius,void 0,fe(e.easing))}},scale:new class extends U{constructor(){super(...arguments),this.parameters={a:ee(1,"spawn"),b:ee(1,"spawn"),ease:oe()},this.bindingAdapter=Q((e,t)=>{e.setScaleRange(t.a,t.b)})}make(e={}){return new j(e.a,e.b,fe(e.ease))}},scaleComponents:new class extends U{constructor(){super(...arguments),this.parameters={a:ne([1,1,1],"spawn"),b:ne([1,1,1],"spawn"),ease:oe()},this.bindingAdapter=Q((e,t)=>{e.setScaleRange(t.a,t.b)})}make(e={}){return new Y(e.a,e.b,fe(e.ease))}},randomDrift:new class extends U{constructor(){super(...arguments),this.parameters={drift:ne([1,1,1],"live"),delay:ee(0,"live"),ease:oe()},this.bindingAdapter=N((e,t)=>{const s=t.drift;e.setDrift(s.x,s.y,s.z,t.delay)})}make(e={}){return new b(e.drift.x,e.drift.y,e.drift.z,e.delay,void 0,fe(e.ease))}},disperse:new class extends U{constructor(){super(...arguments),this.parameters={distance:ee(1,"spawn"),axis:ie(["XYZ","XZ","XY","YZ"],"XYZ"),ease:oe()},this.bindingAdapter=Q((e,t)=>{e.setDistance(t.distance)})}make(e={}){return new L(e.distance,R[e.axis.toLowerCase()],fe(e.ease))}},rotate:new class extends U{constructor(){super(...arguments),this.parameters={rotation:ne([0,0,0],"spawn"),ease:oe()},this.bindingAdapter=Q((e,t)=>{const s=ue(t.rotation);e.resetRotation(s.x,s.y,s.z)})}make(e={}){const t=ue(e.rotation);return new k(t.x,t.y,t.z,void 0,fe(e.ease))}},rotateAdd:new class extends U{constructor(){super(...arguments),this.parameters={rotation:ne([0,0,0],"spawn")},this.bindingAdapter=Q((e,t)=>{const s=ue(t.rotation);e.resetRotation(s.x,s.y,s.z)})}make(e={}){const t=ue(e.rotation),s=new k(t.x,t.y,t.z,void 0);return s.rotationType="add",s}},changeColor:new class extends U{constructor(){super(...arguments),this.parameters={a:ae("#ffffff","spawn"),b:ae("#ffffff","spawn"),ease:oe()},this.bindingAdapter=Q((e,t)=>{e.resetColor(t.a,t.b)})}make(e={}){return new u(e.a,e.b,void 0,fe(e.ease))}},changeOpacity:new class extends U{constructor(){super(...arguments),this.parameters={a:ee(1,"spawn",0,1),b:ee(0,"spawn",0,1),ease:oe()},this.bindingAdapter=Q((e,t)=>{e.resetAlpha(t.a,t.b)})}make(e={}){return new i(e.a,e.b,void 0,fe(e.ease))}},vortex:new class extends U{constructor(){super(...arguments),this.parameters={axis:ne([0,1,0],"live"),amount:ee(1,"live")},this.bindingAdapter=N((e,t)=>{e.setAxisAngle(t.axis,t.amount)})}make(e={}){return new V(e.axis,e.amount)}},moveTo:new class extends U{constructor(){super(...arguments),this.parameters={target:ne([0,1,0],"live"),ease:oe()},this.bindingAdapter=N((e,t)=>{const s=t.target;e.setTarget(s.x,s.y,s.z)})}make(e={}){return new S(e.target.x,e.target.y,e.target.z,fe(e.ease))}},linearDamping:new class extends U{constructor(){super(...arguments),this.parameters={factor:ee(.1,"live",0,1e3)},this.bindingAdapter=N((e,t)=>{e.setFactor(t.factor)})}make(e={}){return new C(e.factor)}},followParent:new class extends U{constructor(){super(...arguments),this.parameters={speed:ee(0,"live")},this.bindingAdapter=N((e,t)=>{e.setSpeed(t.speed)})}make(e={}){return new D(e.speed)}},worldCollision:new class extends U{constructor(){super(...arguments),this.parameters={friction:_(1,0,1),bounce:_(1,0,1),lifeLoss:_(0,0)}}make(e={}){return new H(null,e.bounce,e.friction,e.lifeLoss)}},animation:new class extends U{constructor(){super(...arguments),this.parameters={clip:{type:"animationclip",default:null},timeScale:_(1,0,10),weight:_(1,0,1),loop:ie(["Once","Repeat","PingPong"],"Once"),clampWhenFinished:{...te(!0),requires:{loop:"Once"}}}}make(n={}){let r=e;return"Repeat"===n.loop?r=s:"PingPong"===n.loop&&(r=t),new A(n.clip,n.timeScale,n.weight,r,n.clampWhenFinished,d.easeLinear)}}};export const VfxInitializserLibrary=xe;export const VfxInitializserLibraryKeys=Object.keys(VfxInitializserLibrary);export const VfxBehaviourLibrary=ge;export const VfxBehaviourLibraryKeys=Object.keys(VfxBehaviourLibrary);/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import e,{Behaviour as t,Body as a,Emitter as r,Rate as s}from"@hology/nebula";import*as n from"three";import{Object3D as i}from"three";import{AttributeVec3Node as o,AttributeVec4Node as l,NodeShaderMaterial as c,RgbNode as u,UniformFloatNode as p,UniformVec3Node as d,Vec3ExpressionNode as h,Vec4Node as m,attributeFloat as f,attributeVec3 as y,attributeVec4 as w,attributes as g,clamp as b,float as v,glslFunction as A,lambertMaterial as E,log as M,pow as x,rgb as I,rgba as S,smoothstep as T,standardMaterial as P,textureSampler2d as B,uniformFloat as C,uniforms as R,varying as k,varyingAttributes as j,varyingVec3 as G,varyingVec4 as V}from"three-shader-graph";import{prepareClassParameters as D,prepareShaderGraphParameters as F,prepareShapeParameters as z}from"../../scene/materializer.js";import{SerializedParamType as O}from"../../scene/model.js";import{ShapeLibrary as L}from"../../scene/objects/shapes.js";import{fragmentLinearEyeDepth as Q,linearEyeDepth as W}from"../../shader-nodes/depth.js";import{particleEnergyUniformName as H,particleTimeUniformName as U,particleUniforms as q,particleVelcoityUniformName as J}from"../../shader-nodes/particle.js";import{sampleFlipbook as N}from"../../shader-nodes/texture-sequence.js";import{DefaultInitializer as X}from"./initializsers.js";import{DelayRate as K,OnceRate as Y}from"./rates.js";import{StretchedSprite as _}from"./stretched-sprite.js";import{ThreeBlendingMode as Z}from"./vfx-asset.js";import{VfxBehaviourLibrary as $,VfxInitializserLibrary as ee}from"./vfx-defs.js";import{MultiRenderer as te}from"./vfx-renderers.js";import{WorldCollisionBehaviour as ae}from"./vfx-collision-behaviour.js";import{getSpritePosition as re,SpriteNodeShaderMaterial as se}from"../../shader/sprite-shader.js";import{DecalUnlitShader as ne}from"../../shader/builtin/decal-unlit-shader.js";import{DecalStandardShader as ie}from"../../shader/builtin/decal-standard-shader.js";import{createBoundBehaviour as oe,createBoundInitializer as le}from"./vfx-binding-runtime.js";import{buildShaderGraphMaterial as ce}from"../../shader/graph/index.js";export async function materializeVfx(t,a,r,s,o,l,c,u,p){let d=a;for(;null!=d.parent;)d=d.parent;const h=new i;h.name="particle system local",a.add(h);const m=new i;m.name="particle system world";const f=new te(m,h,n,s),y=new e;return(await Promise.all(t.vfx.emitters.slice().sort((e,t)=>(t.output.renderOrder??0)-(e.output.renderOrder??0)).map(async e=>{const t=await ue(e,r,c,u,y,o,l,p);return t.setParentRecursive(y),t.emit()}))).forEach(e=>y.addEmitter(e)),y.addRenderer(f).emit({onEnd:()=>{}}),{container:m,system:y,dispose:()=>{m.removeFromParent(),h.removeFromParent(),f.dispose()}}}async function ue(e,t,r,u,v,x,I,P){const G=function(e){let t;switch(e.rate.type){case"continuous":t=new K(e.rate.delay??0,e.rate.count,e.rate.time,e.rate.duration);break;case"once":t=new Y(e.rate.delay??0,e.rate.count);break;default:console.warn(`Failed to configure rate for emitter: ${JSON.stringify(e)}`),t=new s(0,1/0)}return t}(e);let D;switch(e.output.type){case"decal":D=new a(await async function(e,t,a,r,s){if("shaderGraph"===me(e)){const t=await he(e,"decal",a,r,s);if(null!=t){const a=new n.Mesh(new n.BoxGeometry(1,1,1),t);return null!=e.renderOrder&&(a.renderOrder=e.renderOrder),a}}const i=!1!==e.unlit?new ne:new ie;i.color=new n.Color(e.color),i instanceof ne?i.intensity=e.intensity??1:i.emissiveIntensity=e.intensity??1;if(e.colorMap){const a=await t.getTexture(e.colorMap);i.colorMap=a}if(e.alphaMap){const a=await t.getTexture(e.alphaMap);i.alphaMap=a}const o=i.build();o.blending=Z[e.blendingMode]??n.NormalBlending,o.transparent=!0,o.side=n.BackSide,o.depthTest=!1,null!=o&&!0===e.bloom&&(o.userData.hasBloom=!0);o.defines.IS_PARTICLE="";const l=new n.BoxGeometry(1,1,1),c=new n.Mesh(l,o);null!=e.renderOrder&&(c.renderOrder=e.renderOrder);return c}(e.output,t,r,u,I));break;case"sprite":D=new a(await async function(e,t,a,r,s){let i=null;const o=me(e);"shaderGraph"===o&&(i=await he(e,"sprite",a,r,s));null==i&&"shader"===o&&null!=e.shader&&(i=await de(e,t,s));null==i&&(i=await async function(e,t){const a=null!=e.texture?await t.getTexture(e.texture):pe,r=B(a);let s=r.sample(j.uv);e.flipbook?.enabled&&(s=N(r,g.uv,e.flipbook.columns,e.flipbook.rows,q.time,e.flipbook.fps,e.flipbook.mode));const i=new p("rotation",0),o=new d("color").rgb,l=C("opacity",1),c=W.subtract(Q).divide(W);let u=l;switch(e.opacityChannel??"red"){case"none":break;case"red":u=u.multiply(s.r);break;case"alpha":u=u.multiply(s.a)}if("number"==typeof e.softness&&e.softness>0){const t=b(c,0,1e3);u=u.multiply(T(0,.2*e.softness,t))}const h=re(i),m=S(o.multiply(s.rgb).multiplyScalar(e.intensity??1),u);var f=new se({color:m,emissive:m.rgb.multiplyScalar(u),transparent:!0,position:h,alphaTest:1e-4,uniforms:{color:{value:new n.Color(e.color)}}});f.alphaHash=!0,null!=f&&!0===e.bloom&&(f.userData.hasBloom=!0);return f.blending=Z[e.blendingMode]??n.NormalBlending,f}(e,t));fe(i,e);const l=new n.Mesh(new n.PlaneGeometry(1,1),i);return l.name="sprite",l}(e.output,t,r,u,I));break;case"stretchedSprite":D=new a(await async function(e,t){"shaderGraph"===me(e)&&console.warn("Shader graph materials are not supported for stretched sprite VFX outputs yet. Falling back to the default stretched sprite material.");const a=null!=e.texture?await t.getTexture(e.texture):pe,r=B(a).sample(j.uv),s=V(new l("color")),i=s.rgb.multiply(r.rgb);let o=s.w;switch(e.opacityChannel??"red"){case"none":break;case"red":o=o.multiply(r.r);break;case"alpha":o=o.multiply(r.a)}if("number"==typeof e.softness&&e.softness>0){const t=W.subtract(Q).divide(M(W)),a=b(t,0,1e3);o=o.multiply(T(0,.2*e.softness,a))}const c=A(m,{position:g.position,offset:y("offset"),modelViewMatrix:R.modelViewMatrix,velocity:w("velocity"),size:y("size"),rotation:f("rotation")},"\n float lengthFactor = velocity.w;\n float avgSize = (size.x + size.y) * 0.5;\n\n vec4 mvPosition = modelViewMatrix * vec4( offset , 1.0 );\n vec3 viewVelocity = normalMatrix * velocity.xyz;\n float vlength = length(viewVelocity); \n mvPosition.xyz += position.y * normalize(cross(mvPosition.xyz, viewVelocity)) * avgSize; \n mvPosition.xyz -= (position.x + 0.5) * viewVelocity * (1.0 + lengthFactor / vlength) * avgSize;\n return projectionMatrix * mvPosition;\n ");var u=new se({color:S(i.multiplyScalar(e.intensity??1),o),alphaTest:.1,transparent:!0,position:c,uniforms:{color:{value:new n.Color(e.color)}}});null!=u&&!0===e.bloom&&(u.userData.hasBloom=!0);u.blending=Z[e.blendingMode]??n.NormalBlending;const p=new _(new n.PlaneGeometry(1,1),u);return p.scaleFactor=e.scale,p}(e.output,t));break;case"shape":D=new a(await async function(e,t,a,r,s){if(null==e.shape)return console.log("Shape is null"),new i;const l=L[e.shape];if(null==l)return console.error(`No shape with type ${e.shape}`),new i;const u=z(e.params??{}),p=l.geometry(u);let d=null;const m=me(e);"shaderGraph"===m&&(d=await he(e,"surface",a,r,s));null==d&&"shader"===m&&null!=e.shader&&(d=await de(e,t,s));null==d&&(d="material"===m&&null!=e.material?ye(await t.getMaterial(e.material)):function(){const e=k(new h("instanceColor")).rgb,t=k(new o("particleData")).x;return new c({color:E({color:e}).rgb.rgba(t),opacity:t,transparent:!0})}());return fe(d,e),new n.Mesh(p,d)}(e.output,t,r,u,I));break;case"mesh":D=new a(await async function(e,t,a,r,s){if(null==e.assetId)return console.warn("Can't use mesh as particle without asset id"),new i;const o=await t.getMesh(e.assetId),l=await t.getAsset(e.assetId),c=me(e);if("shaderGraph"===c||"shader"===c||"material"===c){let i;"shaderGraph"===c?i=await he(e,"surface",a,r,s):"shader"===c&&null!=e.shader?i=await de(e,t,s):"material"===c&&null!=e.material&&(i=ye(await t.getMaterial(e.material))),fe(i,e),o.traverse(e=>{e instanceof n.Mesh&&null!=i&&(e.material=i)})}else{const e=[];if(null!=l.materialAssignments)for(const a of l.materialAssignments)o.traverse(r=>{r instanceof n.Mesh&&r.material instanceof n.Material&&r.material.color instanceof n.Color&&(r.material.name!=a.name&&null!=a.name||"#"+r.material.color.getHexString()!==a.color||e.push(t.getMaterial(a.materialId).then(e=>r.material=e)))});await Promise.all(e)}const u=[];if(o.traverse(e=>{e instanceof n.Mesh&&u.push(e)}),1===u.length){const e=u[0];return e.updateWorldMatrix(!0,!0),e.updateMatrixWorld(),e.matrix.copy(e.matrixWorld),e.matrixWorld.decompose(e.position,e.quaternion,e.scale),e.removeFromParent(),e}return o}(e.output,t,r,u,I));break;case"trail":{const s="shaderGraph"===me(e.output)?await he(e.output,"trail",r,u,I,{trailBillboard:e.output.billboard??!1}):null;D=new a({type:"trail",taper:e.output.taper,headGeometry:null,material:s instanceof n.ShaderMaterial?s:void 0,dragTexture:!1,texture:null!=e.output.texture?await t.getTexture(e.output.texture):null,opacityChannel:e.output.opacityChannel,color:e.output.color,colorEnd:e.output.colorEnd,intensity:e.output.intensity??1,intensityEnd:e.output.intensityEnd??1,length:e.output.length,opacityStart:e.output.opacityStart,opacityEnd:e.output.opacityEnd,bloom:e.output.bloom,scrollSpeed:e.output.scrollSpeed,width:e.output.width,billboard:e.output.billboard??!1});break}default:console.error("Failed to create particly system body: "+JSON.stringify(e))}const F=new ge;F.parent=v,F.setRate(G),F._space=e.output.space;const H=await Promise.all(e.initializers.filter(e=>!1!==e.enabled).filter(e=>null!=ee[e.type]).map(async e=>{const t=ee[e.type],a=await z(e.params??{});return le(t,e.params??{},a,P)}));H.push(D,new X),F.addInitializers(H);const U=await Promise.all(e.behaviours.filter(e=>!1!==e.enabled).filter(e=>null!=$[e.type]).map(async e=>{const t=$[e.type];for(const[a,r]of Object.entries(e.params))t.parameters&&null!=t.parameters[a]&&"curve"===t.parameters[a].type&&r.type!==O.Curve&&(r.type=O.Curve);const a=await z(e.params??{},r,u);return oe(t,e.params??{},a,P)}).sort((e,t)=>e instanceof ae?1:0));U.push(new we);for(const e of U)e instanceof ae&&(e.physics=x);F.addBehaviours(U);for(const a of e.children){const e=await ue(a,t,r,u,v,x,I,P),s=new EmitterPool(()=>{const t=e.clone();return t.onExpired=()=>{const e=F.childEmitters.findIndex(e=>e.id===t.id);-1!=e&&F.childEmitters.splice(e,1),s.release(t)},t}),n=F.eventDispatcher,i=new Map;F.bindEmitterEvent=!0,n.addEventListener("PARTICLE_DEAD",e=>{const t=i.get(e.id);if(null!=t){const e=F.childEmitters.findIndex(e=>e.id===t.id);null!=e&&(t.stopEmit(),F.childEmitters.splice(e,1))}});let o="PARTICLE_CREATED";if("spawnEvent"in a)switch(a.spawnEvent){case"collision":o="PARTICLE_COLLISION";break;case"start":o="PARTICLE_CREATED"}n.addEventListener(o,e=>{const t=s.get();t.age=0,t.totalEmitTimes=-1,t.particles.length=0,t.currentEmitTime=0,t.cID=0,t.eventDispatcher.removeAllEventListeners(),F.childEmitters.push(t),i.set(e.id,t),t.parentParticle=e,t.system=F.system,t.emit()})}return F}const pe=(new n.TextureLoader).load("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJkSURBVHjaxJeJbusgEEW94S1L//83X18M2MSuLd2pbqc4wZGqRLrKBsyZhQHny7Jk73xVL8xpVhWrcmiB5lX+6GJ5YgQ2owbAm8oIwH1VgKZUmGcRqKGGPgtEQQAzGR8hQ59fAmhJHSAagigJ4E7GPWRXOYC6owAd1JM6wDQPADyMWUqZRMqmAojHp1Vn6EQQEgUNMJLnUjMyJsM49wygBkAPw9dVFwXRkncCIIW3GRgoTQUZn6HxCMAFEFd8TwEQ78X4rHbILoAUmeT+RFG4UhQ6MiIAE4W/UsYFjuVjAIa2nIY4q1R0GFtQWG3E84lqw2GO2QOoCKBVu0BAPgDSU0eUDjjQenNkV/AW/pWChhpMTelo1a64AOKM30vk18GzTHXCNtI/Knz3DFBgsUqBGIjTInXRY1yA9xkVoqW5tVq3pDR9A0hfF5BSARmVnh7RMDCaIdcNgbPBkgzn1Bu+SfIEFSpSBmkxyrMicb0fAEuCZrWnN89veA/4XcakrPcjBWzkTuLjlbfTQPOlBhz+HwkqqPXmPQDdrQItxE1moGof1S74j/8txk8EHhTQrAE8qlwfqS5yukm1x/rAJ9Jiaa6nyATqD78aUVBhFo8b1V4DdTXdCW+IxA1zB4JhiOhZMEWO1HqnvdoHZ4FAMIhV9REF8FiUm0jsYPEJx/Fm/N8OhH90HI9YRHesWbXXZwAShU8qThe7H8YAuJmw5yOd989uRINKRTJAhoF8jbqrHKfeCYdIISZfSq26bk/K+yO3YvfKrVgiwQBHnwt8ynPB25+M8hceTt/ybPhnryJ78+tLgAEAuCFyiQgQB30AAAAASUVORK5CYII=");async function de(e,t,a){const r=a.get(e.shader);if(null==r)return console.error("No shader exists with name "+e.shader),new n.Material;const s=new r.type,i=await D(e.shaderParams??{},r.type,t,{getTexture:e=>t.getTexture(e.id),getMaterial:e=>t.getMaterial(e.id),getMesh:e=>t.getMesh(e.id)},void 0,void 0,void 0,void 0,void 0,s);return Object.assign(s,i),s.build()}async function he(e,t,a,r,s,n={}){const i=e.shaderGraph;if("asset"!==i?.source||null==i.assetId)return console.warn(`Missing shader graph asset reference for ${e.type} VFX output`),null;const o=await a.getAsset(i.assetId),l=o?.shaderGraph;if(null==l)return console.warn(`Missing shader graph asset "${i.assetId}" for ${e.type} VFX output`),null;if(l.target!==t)return console.warn(`Shader graph "${o.name}" targets "${l.target}" but ${e.type} VFX output expects "${t}"`),null;try{const t=await F(e.shaderGraphParams??{},l,a,r,void 0,s.shaders),o=ce(l,{parameters:t,trailBillboard:n.trailBillboard});return o.userData.customShaderName=`shaderGraph:${i.assetId}`,fe(o,e),o}catch(e){return console.log("Shader graph VFX runtime error: "+e,e),null}}function me(e){return null!=e.materialSource?e.materialSource:"asset"===e.shaderGraph?.source?"shaderGraph":"shader"in e&&null!=e.shader?"shader":"mesh"!==e.type&&"shape"!==e.type||null==e.material?"default":"material"}function fe(e,t){null!=e&&("bloom"in t&&!0===t.bloom&&(e.userData.hasBloom=!0),"sprite"===t.type?(e.blending=Z[t.blendingMode]??n.NormalBlending,!0===t.lockY&&e instanceof n.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.LOCK_Y_AXIS="")):"decal"===t.type&&(e.blending=Z[t.blendingMode]??n.NormalBlending,e.transparent=!0,e.side=n.BackSide,e.depthTest=!1,e instanceof n.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.IS_PARTICLE="")))}function ye(e){const t=k(new h("instanceColor")).rgb;let a,r=k(new o("particleData")).x;if(e instanceof n.MeshStandardMaterial||e instanceof n.MeshLambertMaterial||e instanceof n.MeshBasicMaterial){let s=t.multiply(I(e.color));null!=e.map&&(s=s.multiply(B(e.map).sample(j.uv).rgb)),null!=e.alphaMap&&(r=r.multiply(B(e.alphaMap).sample(j.uv).r)),e instanceof n.MeshStandardMaterial?a=new c({color:P({color:s,emissive:I(e.emissive),emissiveIntensity:v(e.emissiveIntensity),roughness:e.roughness,metalness:e.metalness}).rgb.rgba(r),emissive:I(e.emissive).multiplyScalar(e.emissiveIntensity),transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}):e instanceof n.MeshLambertMaterial?a=new c({color:E({color:s}).rgb.rgba(r),emissive:I(e.emissive).multiplyScalar(e.emissiveIntensity),transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}):e instanceof n.MeshBasicMaterial&&(a=new c({color:s.rgb.rgba(r),emissive:s.rgb,transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}))}else e instanceof c&&(a=e.clone(),a.defines.IS_PARTICLE="");return null!=a&&(!0===e.userData?.hasBloom&&null!=a&&(a.userData.hasBloom=!0),a.side=e.side,a.transparent=e.transparent),a??e}class we extends t{initialize(e){e.body instanceof n.Object3D&&e.body.traverse(e=>{if(e instanceof n.Mesh){const t=e.material;t instanceof c&&(null!=t.uniforms[H]||null!=t.uniforms[U]||t.uniforms[J])}})}mutate(e,t,a){this.energize(e,t),e.target instanceof i&&e.target.traverse(t=>{if(t instanceof n.Mesh){const a=t.material;a instanceof c&&(null!=a.uniforms[H]&&(a.uniforms[H].value=this.energy),null!=a.uniforms[U]&&(a.uniforms[U].value=e.age),null!=a.uniforms[J]&&(a.uniforms[J].value=e.velocity))}})}}class ge extends r{constructor(){super(...arguments),this.childEmitters=[],this.bindEmitterEvent=!1,this.onExpired=()=>{}}update(e){if(!this.isEmitting&&0===this.particles.length)return;this.age+=e,(this.dead||this.age>=this.life)&&this.destroy(),this.generate(e),this.integrate(e);let t=this.particles.length;for(;t--;){const e=this.particles[t];e.dead&&(this.system&&this.system.dispatch("PARTICLE_DEAD",e),this.bindEmitterEvent&&this.dispatch("PARTICLE_DEAD",e),this.system.pool.expire(e.reset()),this.particles.splice(t,1))}this.updateEmitterBehaviours(e),this.updateChildren(e),this.isEmitting||0!==this.particles.length||this.onExpired()}updateChildren(e){for(const t of this.childEmitters)null!=t.parentParticle?t.position.copy(t.parentParticle.position):t.setPosition(this.position),t.update(e)}clone(){const e=new ge;return e.setRate(this.rate.clone()),e.behaviours=this.behaviours,e.initializers=this.initializers,e._space=this._space,e.body=this.body,e.parent=this.parent,e.system=this.system,e}setParentRecursive(e){this.system=e,this.childEmitters.forEach(t=>t.setParentRecursive(e))}}export class EmitterPool{constructor(e){this.creator=e,this.instances=[]}get(){0==this.instances.length&&this.instances.push(this.creator());return this.instances.pop()}release(e){this.instances.push(e)}dispose(){this.instances.length=0}}/*
1
+ import e,{Behaviour as t,Body as a,Emitter as r,Rate as s}from"@hology/nebula";import*as i from"three";import{Object3D as n}from"three";import{AttributeVec3Node as o,AttributeVec4Node as l,NodeShaderMaterial as c,RgbNode as p,UniformFloatNode as u,UniformVec3Node as h,Vec3ExpressionNode as d,Vec4Node as m,attributeFloat as f,attributeVec3 as y,attributeVec4 as g,attributes as w,clamp as b,float as v,glslFunction as E,lambertMaterial as A,log as M,pow as x,rgb as P,rgba as S,smoothstep as I,standardMaterial as T,textureSampler2d as C,uniformFloat as R,uniforms as B,varying as k,varyingAttributes as j,varyingVec3 as D,varyingVec4 as G}from"three-shader-graph";import{prepareClassParameters as V,prepareShaderGraphParameters as F,prepareShapeParameters as z}from"../../scene/materializer.js";import{SerializedParamType as L}from"../../scene/model.js";import{ShapeLibrary as O}from"../../scene/objects/shapes.js";import{fragmentLinearEyeDepth as W,linearEyeDepth as Q}from"../../shader-nodes/depth.js";import{particleEnergyUniformName as H,particleTimeUniformName as U,particleUniforms as q,particleVelcoityUniformName as J}from"../../shader-nodes/particle.js";import{sampleFlipbook as N}from"../../shader-nodes/texture-sequence.js";import{DefaultInitializer as X}from"./initializsers.js";import{DelayRate as _,OnceRate as K}from"./rates.js";import{StretchedSprite as Y}from"./stretched-sprite.js";import{ThreeBlendingMode as Z}from"./vfx-asset.js";import{VfxBehaviourLibrary as $,VfxInitializserLibrary as ee}from"./vfx-defs.js";import{MultiRenderer as te}from"./vfx-renderers.js";import{WorldCollisionBehaviour as ae}from"./vfx-collision-behaviour.js";import{getSpritePosition as re,SpriteNodeShaderMaterial as se}from"../../shader/sprite-shader.js";import{DecalUnlitShader as ie}from"../../shader/builtin/decal-unlit-shader.js";import{DecalStandardShader as ne}from"../../shader/builtin/decal-standard-shader.js";import{createBoundBehaviour as oe,createBoundInitializer as le}from"./vfx-binding-runtime.js";import{buildShaderGraphMaterial as ce}from"../../shader/graph/index.js";export async function materializeVfx(t,a,r,s,o,l,c,p,u){let h=a;for(;null!=h.parent;)h=h.parent;const d=new n;d.name="particle system local",a.add(d);const m=new n;m.name="particle system world";const f=new te(m,d,i,s),y=new e;return(await Promise.all(t.vfx.emitters.slice().sort((e,t)=>(t.output.renderOrder??0)-(e.output.renderOrder??0)).map(async e=>{const t=await pe(e,r,c,p,y,o,l,u,a);return t.setParentRecursive(y),t.emit()}))).forEach(e=>y.addEmitter(e)),y.addRenderer(f).emit({onEnd:()=>{}}),{container:m,system:y,dispose:()=>{m.removeFromParent(),d.removeFromParent(),f.dispose()}}}async function pe(e,t,r,p,v,x,P,T,D){const V=function(e){let t;switch(e.rate.type){case"continuous":t=new _(e.rate.delay??0,e.rate.count,e.rate.time,e.rate.duration);break;case"once":t=new K(e.rate.delay??0,e.rate.count);break;default:console.warn(`Failed to configure rate for emitter: ${JSON.stringify(e)}`),t=new s(0,1/0)}return t}(e);let F;switch(e.output.type){case"decal":F=new a(await async function(e,t,a,r,s){if("shaderGraph"===me(e)){const t=await de(e,"decal",a,r,s);if(null!=t){const a=new i.Mesh(new i.BoxGeometry(1,1,1),t);return null!=e.renderOrder&&(a.renderOrder=e.renderOrder),a}}const n=!1!==e.unlit?new ie:new ne;n.color=new i.Color(e.color),n instanceof ie?n.intensity=e.intensity??1:n.emissiveIntensity=e.intensity??1;if(e.colorMap){const a=await t.getTexture(e.colorMap);n.colorMap=a}if(e.alphaMap){const a=await t.getTexture(e.alphaMap);n.alphaMap=a}const o=n.build();o.blending=Z[e.blendingMode]??i.NormalBlending,o.transparent=!0,o.side=i.BackSide,o.depthTest=!1,null!=o&&!0===e.bloom&&(o.userData.hasBloom=!0);o.defines.IS_PARTICLE="";const l=new i.BoxGeometry(1,1,1),c=new i.Mesh(l,o);null!=e.renderOrder&&(c.renderOrder=e.renderOrder);return c}(e.output,t,r,p,P));break;case"sprite":F=new a(await async function(e,t,a,r,s){let n=null;const o=me(e);"shaderGraph"===o&&(n=await de(e,"sprite",a,r,s));null==n&&"shader"===o&&null!=e.shader&&(n=await he(e,t,s));null==n&&(n=await async function(e,t){const a=null!=e.texture?await t.getTexture(e.texture):ue,r=C(a);let s=r.sample(j.uv);e.flipbook?.enabled&&(s=N(r,w.uv,e.flipbook.columns,e.flipbook.rows,q.time,e.flipbook.fps,e.flipbook.mode));const n=new u("rotation",0),o=new h("color").rgb,l=R("opacity",1),c=Q.subtract(W).divide(Q);let p=l;switch(e.opacityChannel??"red"){case"none":break;case"red":p=p.multiply(s.r);break;case"alpha":p=p.multiply(s.a)}if("number"==typeof e.softness&&e.softness>0){const t=b(c,0,1e3);p=p.multiply(I(0,.2*e.softness,t))}const d=re(n),m=S(o.multiply(s.rgb).multiplyScalar(e.intensity??1),p);var f=new se({color:m,emissive:m.rgb.multiplyScalar(p),transparent:!0,position:d,alphaTest:1e-4,uniforms:{color:{value:new i.Color(e.color)}}});f.alphaHash=!0,null!=f&&!0===e.bloom&&(f.userData.hasBloom=!0);return f.blending=Z[e.blendingMode]??i.NormalBlending,f}(e,t));fe(n,e);const l=new i.Mesh(new i.PlaneGeometry(1,1),n);return l.name="sprite",l}(e.output,t,r,p,P));break;case"stretchedSprite":F=new a(await async function(e,t){"shaderGraph"===me(e)&&console.warn("Shader graph materials are not supported for stretched sprite VFX outputs yet. Falling back to the default stretched sprite material.");const a=null!=e.texture?await t.getTexture(e.texture):ue,r=C(a).sample(j.uv),s=G(new l("color")),n=s.rgb.multiply(r.rgb);let o=s.w;switch(e.opacityChannel??"red"){case"none":break;case"red":o=o.multiply(r.r);break;case"alpha":o=o.multiply(r.a)}if("number"==typeof e.softness&&e.softness>0){const t=Q.subtract(W).divide(M(Q)),a=b(t,0,1e3);o=o.multiply(I(0,.2*e.softness,a))}const c=E(m,{position:w.position,offset:y("offset"),modelViewMatrix:B.modelViewMatrix,velocity:g("velocity"),size:y("size"),rotation:f("rotation")},"\n float lengthFactor = velocity.w;\n float avgSize = (size.x + size.y) * 0.5;\n\n vec4 mvPosition = modelViewMatrix * vec4( offset , 1.0 );\n vec3 viewVelocity = normalMatrix * velocity.xyz;\n float vlength = length(viewVelocity); \n mvPosition.xyz += position.y * normalize(cross(mvPosition.xyz, viewVelocity)) * avgSize; \n mvPosition.xyz -= (position.x + 0.5) * viewVelocity * (1.0 + lengthFactor / vlength) * avgSize;\n return projectionMatrix * mvPosition;\n ");var p=new se({color:S(n.multiplyScalar(e.intensity??1),o),alphaTest:.1,transparent:!0,position:c,uniforms:{color:{value:new i.Color(e.color)}}});null!=p&&!0===e.bloom&&(p.userData.hasBloom=!0);p.blending=Z[e.blendingMode]??i.NormalBlending;const u=new Y(new i.PlaneGeometry(1,1),p);return u.scaleFactor=e.scale,u}(e.output,t));break;case"shape":F=new a(await async function(e,t,a,r,s){if(null==e.shape)return console.log("Shape is null"),new n;const l=O[e.shape];if(null==l)return console.error(`No shape with type ${e.shape}`),new n;const p=z(e.params??{}),u=l.geometry(p);let h=null;const m=me(e);"shaderGraph"===m&&(h=await de(e,"surface",a,r,s));null==h&&"shader"===m&&null!=e.shader&&(h=await he(e,t,s));null==h&&(h="material"===m&&null!=e.material?ye(await t.getMaterial(e.material)):function(){const e=k(new d("instanceColor")).rgb,t=k(new o("particleData")).x;return new c({color:A({color:e}).rgb.rgba(t),opacity:t,transparent:!0})}());return fe(h,e),new i.Mesh(u,h)}(e.output,t,r,p,P));break;case"mesh":F=new a(await async function(e,t,a,r,s){if(null==e.assetId)return console.warn("Can't use mesh as particle without asset id"),new n;const o=await t.getMesh(e.assetId),l=await t.getAsset(e.assetId),c=me(e);if("shaderGraph"===c||"shader"===c||"material"===c){let n;"shaderGraph"===c?n=await de(e,"surface",a,r,s):"shader"===c&&null!=e.shader?n=await he(e,t,s):"material"===c&&null!=e.material&&(n=ye(await t.getMaterial(e.material))),fe(n,e),o.traverse(e=>{e instanceof i.Mesh&&null!=n&&(e.material=n)})}else{const e=[];if(null!=l.materialAssignments)for(const a of l.materialAssignments)o.traverse(r=>{r instanceof i.Mesh&&r.material instanceof i.Material&&r.material.color instanceof i.Color&&(r.material.name!=a.name&&null!=a.name||"#"+r.material.color.getHexString()!==a.color||e.push(t.getMaterial(a.materialId).then(e=>r.material=e)))});await Promise.all(e)}const p=[];if(o.traverse(e=>{e instanceof i.Mesh&&p.push(e)}),1===p.length){const e=p[0];return e.updateWorldMatrix(!0,!0),e.updateMatrixWorld(),e.matrix.copy(e.matrixWorld),e.matrixWorld.decompose(e.position,e.quaternion,e.scale),e.removeFromParent(),e}return o}(e.output,t,r,p,P));break;case"trail":{const s="shaderGraph"===me(e.output)?await de(e.output,"trail",r,p,P,{trailBillboard:e.output.billboard??!1}):null;F=new a({type:"trail",taper:e.output.taper,headGeometry:null,material:s instanceof i.ShaderMaterial?s:void 0,dragTexture:!1,texture:null!=e.output.texture?await t.getTexture(e.output.texture):null,opacityChannel:e.output.opacityChannel,color:e.output.color,colorEnd:e.output.colorEnd,intensity:e.output.intensity??1,intensityEnd:e.output.intensityEnd??1,length:e.output.length,opacityStart:e.output.opacityStart,opacityEnd:e.output.opacityEnd,bloom:e.output.bloom,scrollSpeed:e.output.scrollSpeed,width:e.output.width,billboard:e.output.billboard??!1});break}default:console.error("Failed to create particly system body: "+JSON.stringify(e))}const H=new we(D);H.parent=v,H.setRate(V),H._space=e.output.space;const U=await Promise.all(e.initializers.filter(e=>!1!==e.enabled).filter(e=>null!=ee[e.type]).map(async e=>{const t=ee[e.type],a=await z(e.params??{});return le(t,e.params??{},a,T)}));U.push(F,new X),H.addInitializers(U);const J=await Promise.all(e.behaviours.filter(e=>!1!==e.enabled).filter(e=>null!=$[e.type]).map(async e=>{const t=$[e.type];for(const[a,r]of Object.entries(e.params))t.parameters&&null!=t.parameters[a]&&"curve"===t.parameters[a].type&&r.type!==L.Curve&&(r.type=L.Curve);const a=await z(e.params??{},r,p);return oe(t,e.params??{},a,T)}).sort((e,t)=>e instanceof ae?1:0));J.push(new ge);for(const e of J)e instanceof ae&&(e.physics=x);H.addBehaviours(J);for(const a of e.children??[]){const e=await pe(a,t,r,p,v,x,P,T,D),s=new EmitterPool(()=>{const t=e.clone();return t.onExpired=()=>{const e=H.childEmitters.findIndex(e=>e.id===t.id);-1!=e&&H.childEmitters.splice(e,1),null!=t.parentParticle&&(n.delete(t.parentParticle.id),t.parentParticle=null),s.release(t)},t}),i=H.eventDispatcher,n=new Map;H.bindEmitterEvent=!0,i.addEventListener("PARTICLE_DEAD",e=>{const t=n.get(e.id);null!=t&&(H.detachChildEmitterFromParticle(t,e),n.delete(e.id))});let o="PARTICLE_CREATED";if("spawnEvent"in a)switch(a.spawnEvent){case"collision":o="PARTICLE_COLLISION";break;case"start":o="PARTICLE_CREATED"}i.addEventListener(o,e=>{const t=s.get();t.age=0,t.totalEmitTimes=-1,t.particles.length=0,t.currentEmitTime=0,t.cID=0,t.eventDispatcher.removeAllEventListeners(),H.childEmitters.push(t),n.set(e.id,t),t.parentParticle=e,t.system=H.system,t.emit()})}return H}const ue=(new i.TextureLoader).load("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJkSURBVHjaxJeJbusgEEW94S1L//83X18M2MSuLd2pbqc4wZGqRLrKBsyZhQHny7Jk73xVL8xpVhWrcmiB5lX+6GJ5YgQ2owbAm8oIwH1VgKZUmGcRqKGGPgtEQQAzGR8hQ59fAmhJHSAagigJ4E7GPWRXOYC6owAd1JM6wDQPADyMWUqZRMqmAojHp1Vn6EQQEgUNMJLnUjMyJsM49wygBkAPw9dVFwXRkncCIIW3GRgoTQUZn6HxCMAFEFd8TwEQ78X4rHbILoAUmeT+RFG4UhQ6MiIAE4W/UsYFjuVjAIa2nIY4q1R0GFtQWG3E84lqw2GO2QOoCKBVu0BAPgDSU0eUDjjQenNkV/AW/pWChhpMTelo1a64AOKM30vk18GzTHXCNtI/Knz3DFBgsUqBGIjTInXRY1yA9xkVoqW5tVq3pDR9A0hfF5BSARmVnh7RMDCaIdcNgbPBkgzn1Bu+SfIEFSpSBmkxyrMicb0fAEuCZrWnN89veA/4XcakrPcjBWzkTuLjlbfTQPOlBhz+HwkqqPXmPQDdrQItxE1moGof1S74j/8txk8EHhTQrAE8qlwfqS5yukm1x/rAJ9Jiaa6nyATqD78aUVBhFo8b1V4DdTXdCW+IxA1zB4JhiOhZMEWO1HqnvdoHZ4FAMIhV9REF8FiUm0jsYPEJx/Fm/N8OhH90HI9YRHesWbXXZwAShU8qThe7H8YAuJmw5yOd989uRINKRTJAhoF8jbqrHKfeCYdIISZfSq26bk/K+yO3YvfKrVgiwQBHnwt8ynPB25+M8hceTt/ybPhnryJ78+tLgAEAuCFyiQgQB30AAAAASUVORK5CYII=");async function he(e,t,a){const r=a.get(e.shader);if(null==r)return console.error("No shader exists with name "+e.shader),new i.Material;const s=new r.type,n=await V(e.shaderParams??{},r.type,t,{getTexture:e=>t.getTexture(e.id),getMaterial:e=>t.getMaterial(e.id),getMesh:e=>t.getMesh(e.id)},void 0,void 0,void 0,void 0,void 0,s);return Object.assign(s,n),s.build()}async function de(e,t,a,r,s,i={}){const n=e.shaderGraph;if("asset"!==n?.source||null==n.assetId)return console.warn(`Missing shader graph asset reference for ${e.type} VFX output`),null;const o=await a.getAsset(n.assetId),l=o?.shaderGraph;if(null==l)return console.warn(`Missing shader graph asset "${n.assetId}" for ${e.type} VFX output`),null;if(l.target!==t)return console.warn(`Shader graph "${o.name}" targets "${l.target}" but ${e.type} VFX output expects "${t}"`),null;try{const t=await F(e.shaderGraphParams??{},l,a,r,void 0,s.shaders),o=ce(l,{parameters:t,trailBillboard:i.trailBillboard});return o.userData.customShaderName=`shaderGraph:${n.assetId}`,fe(o,e),o}catch(e){return console.log("Shader graph VFX runtime error: "+e,e),null}}function me(e){return null!=e.materialSource?e.materialSource:"asset"===e.shaderGraph?.source?"shaderGraph":"shader"in e&&null!=e.shader?"shader":"mesh"!==e.type&&"shape"!==e.type||null==e.material?"default":"material"}function fe(e,t){null!=e&&("bloom"in t&&!0===t.bloom&&(e.userData.hasBloom=!0),"sprite"===t.type?(e.blending=Z[t.blendingMode]??i.NormalBlending,!0===t.lockY&&e instanceof i.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.LOCK_Y_AXIS="")):"decal"===t.type&&(e.blending=Z[t.blendingMode]??i.NormalBlending,e.transparent=!0,e.side=i.BackSide,e.depthTest=!1,e instanceof i.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.IS_PARTICLE="")))}function ye(e){const t=k(new d("instanceColor")).rgb;let a,r=k(new o("particleData")).x;if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshBasicMaterial){let s=t.multiply(P(e.color));null!=e.map&&(s=s.multiply(C(e.map).sample(j.uv).rgb)),null!=e.alphaMap&&(r=r.multiply(C(e.alphaMap).sample(j.uv).r)),e instanceof i.MeshStandardMaterial?a=new c({color:T({color:s,emissive:P(e.emissive),emissiveIntensity:v(e.emissiveIntensity),roughness:e.roughness,metalness:e.metalness}).rgb.rgba(r),emissive:P(e.emissive).multiplyScalar(e.emissiveIntensity),transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}):e instanceof i.MeshLambertMaterial?a=new c({color:A({color:s}).rgb.rgba(r),emissive:P(e.emissive).multiplyScalar(e.emissiveIntensity),transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}):e instanceof i.MeshBasicMaterial&&(a=new c({color:s.rgb.rgba(r),emissive:s.rgb,transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}))}else e instanceof c&&(a=e.clone(),a.defines.IS_PARTICLE="");return null!=a&&(!0===e.userData?.hasBloom&&null!=a&&(a.userData.hasBloom=!0),a.side=e.side,a.transparent=e.transparent),a??e}class ge extends t{initialize(e){e.body instanceof i.Object3D&&e.body.traverse(e=>{if(e instanceof i.Mesh){const t=e.material;t instanceof c&&(null!=t.uniforms[H]||null!=t.uniforms[U]||t.uniforms[J])}})}mutate(e,t,a){this.energize(e,t),e.target instanceof n&&e.target.traverse(t=>{if(t instanceof i.Mesh){const a=t.material;a instanceof c&&(null!=a.uniforms[H]&&(a.uniforms[H].value=this.energy),null!=a.uniforms[U]&&(a.uniforms[U].value=e.age),null!=a.uniforms[J]&&(a.uniforms[J].value=e.velocity))}})}}class we extends r{constructor(e){super(),this.transformRoot=e,this.childEmitters=[],this.bindEmitterEvent=!1,this.onExpired=()=>{}}clearParticlesRecursive(){let e=this.childEmitters.length;for(;e--;){const t=this.childEmitters[e];t.stopEmit(),t.clearParticlesRecursive(),t.onExpired()}this.childEmitters.length=0;let t=this.particles.length;for(;t--;){const e=this.particles[t];this.system?.dispatch("PARTICLE_DEAD",e),this.bindEmitterEvent&&this.dispatch("PARTICLE_DEAD",e),null!=this.system?this.system.pool.expire(e.reset()):e.reset()}this.particles.length=0}detachChildEmitterFromParticle(e,t){this.copyPositionToChildSpace(e,t.position),e.parentParticle=null,e.stopEmit()}update(e){if(!this.isEmitting&&0===this.particles.length&&0===this.childEmitters.length)return;this.age+=e,(this.dead||this.age>=this.life)&&this.destroy(),this.isEmitting&&this.generate(e),this.integrate(e);let t=this.particles.length;for(;t--;){const e=this.particles[t];e.dead&&(this.system&&this.system.dispatch("PARTICLE_DEAD",e),this.bindEmitterEvent&&this.dispatch("PARTICLE_DEAD",e),this.system.pool.expire(e.reset()),this.particles.splice(t,1))}this.updateEmitterBehaviours(e),this.updateChildren(e),this.isEmitting||0!==this.particles.length||0!==this.childEmitters.length||this.onExpired()}updateChildren(e){for(const t of this.childEmitters)null!=t.parentParticle&&this.copyPositionToChildSpace(t,t.parentParticle.position),t.update(e)}copyPositionToChildSpace(e,t){const a=this._space??"world",r=e._space??"world";a!==r&&null!=this.transformRoot?(be.copy(t),"local"===a&&"world"===r?be.applyMatrix4(this.transformRoot.matrixWorld):"world"===a&&"local"===r&&(ve.copy(this.transformRoot.matrixWorld).invert(),be.applyMatrix4(ve)),e.position.copy(be)):e.position.copy(t)}clone(){const e=new we(this.transformRoot);return e.setRate(this.rate.clone()),e.behaviours=this.behaviours,e.initializers=this.initializers,e._space=this._space,e.body=this.body,e.parent=this.parent,e.system=this.system,e}setParentRecursive(e){this.system=e,this.childEmitters.forEach(t=>t.setParentRecursive(e))}}const be=new i.Vector3,ve=new i.Matrix4;export class EmitterPool{constructor(e){this.creator=e,this.instances=[]}get(){0==this.instances.length&&this.instances.push(this.creator());return this.instances.pop()}release(e){this.instances.push(e)}dispose(){this.instances.length=0}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -9,6 +9,7 @@ export declare class SphereZone extends SphereZone_base {
9
9
  private y;
10
10
  private z;
11
11
  private radius;
12
+ private surfaceOnly;
12
13
  private the;
13
14
  private phi;
14
15
  protected random: number;
@@ -20,9 +21,10 @@ export declare class SphereZone extends SphereZone_base {
20
21
  * @param {number} centerY - the sphere's center y coordinate
21
22
  * @param {number} centerZ - the sphere's center z coordinate
22
23
  * @param {number} radius - the sphere's radius value
24
+ * @param {boolean} surfaceOnly - whether to only spawn on the surface
23
25
  * @return void
24
26
  */
25
- constructor(x: number, y: number, z: number, radius: number);
27
+ constructor(x: number, y: number, z: number, radius: number, surfaceOnly?: boolean);
26
28
  /**
27
29
  * Returns true to indicate this is a SphereZone.
28
30
  *
@@ -1,4 +1,4 @@
1
- import{Vector3D as t}from"@hology/nebula";import{SphereZone as s}from"@hology/nebula";const o=Math.PI;export class SphereZone extends(Object.getPrototypeOf(s)){constructor(s,i,e,r){var h,n,a;super("SphereZone"),this.x=s,this.y=i,this.z=e,this.radius=r,this.the=0,this.phi=0,this.vector=new t,this.getPosition=(()=>{var t,s,i;return()=>(this.random=Math.random(),i=this.random*this.radius,t=o*Math.random(),s=2*o*Math.random(),this.vector.x=this.x+i*Math.sin(t)*Math.cos(s),this.vector.y=this.y+i*Math.sin(s)*Math.sin(t),this.vector.z=this.z+i*Math.cos(t),this.vector)})(),this._bound=(n=new t,a=new t,function(t){t.position.distanceTo(this)+t.radius>=this.radius&&(n.copy(t.position).sub(this).normalize(),a.copy(t.velocity),h=2*a.dot(n),t.velocity.sub(n.multiplyScalar(h)))})}isSphereZone(){return!0}_dead(t){t.position.distanceTo(this)-t.radius>this.radius&&(t.dead=!0)}_cross(){console.warn(`${this.constructor.name} does not support the _cross method`)}}export class PointZone extends(Object.getPrototypeOf(s)){constructor(t,s,o){super("PointZone"),this.x=t,this.y=s,this.z=o}isPointZone(){return!0}getPosition(){return this.vector.x=this.x,this.vector.y=this.y,this.vector.z=this.z,this.vector}}/*
1
+ import{Vector3D as t}from"@hology/nebula";import{SphereZone as s}from"@hology/nebula";const o=Math.PI;export class SphereZone extends(Object.getPrototypeOf(s)){constructor(s,i,e,r,h=!1){var n,a,c;super("SphereZone"),this.x=s,this.y=i,this.z=e,this.radius=r,this.surfaceOnly=h,this.the=0,this.phi=0,this.vector=new t,this.getPosition=(()=>{var t,s,i;return()=>(this.random=Math.random(),i=this.surfaceOnly?this.radius:this.random*this.radius,t=o*Math.random(),s=2*o*Math.random(),this.vector.x=this.x+i*Math.sin(t)*Math.cos(s),this.vector.y=this.y+i*Math.sin(s)*Math.sin(t),this.vector.z=this.z+i*Math.cos(t),this.vector)})(),this._bound=(a=new t,c=new t,function(t){t.position.distanceTo(this)+t.radius>=this.radius&&(a.copy(t.position).sub(this).normalize(),c.copy(t.velocity),n=2*c.dot(a),t.velocity.sub(a.multiplyScalar(n)))})}isSphereZone(){return!0}_dead(t){t.position.distanceTo(this)-t.radius>this.radius&&(t.dead=!0)}_cross(){console.warn(`${this.constructor.name} does not support the _cross method`)}}export class PointZone extends(Object.getPrototypeOf(s)){constructor(t,s,o){super("PointZone"),this.x=t,this.y=s,this.z=o}isPointZone(){return!0}getPosition(){return this.vector.x=this.x,this.vector.y=this.y,this.vector.z=this.z,this.vector}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */