@hology/core 0.0.199 → 0.0.201

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 (57) hide show
  1. package/dist/effects/sequence/sequence-action.d.ts +1 -0
  2. package/dist/effects/sequence/sequence-actor.d.ts +5 -0
  3. package/dist/effects/sequence/sequence-actor.js +1 -1
  4. package/dist/effects/sequence/sequence-player.d.ts +6 -0
  5. package/dist/effects/sequence/sequence-player.js +1 -1
  6. package/dist/effects/vfx/trail-renderer.js +1 -1
  7. package/dist/effects/vfx/vfx-asset.d.ts +17 -6
  8. package/dist/effects/vfx/vfx-materializer.js +1 -1
  9. package/dist/effects/vfx/vfx-renderers.js +1 -1
  10. package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
  11. package/dist/gameplay/actors/builtin/components/character/character-movement.d.ts +8 -1
  12. package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
  13. package/dist/gameplay/services/physics/physics-system.js +1 -1
  14. package/dist/scene/custom-param-runtime-types.d.ts +35 -0
  15. package/dist/scene/custom-param-runtime-types.js +4 -0
  16. package/dist/scene/landscape/landscape.js +1 -1
  17. package/dist/scene/materializer.d.ts +19 -3
  18. package/dist/scene/materializer.js +1 -1
  19. package/dist/scene/model.d.ts +13 -5
  20. package/dist/scene/sky.js +1 -1
  21. package/dist/scene/storage/storage.js +1 -1
  22. package/dist/shader/graph/compiler.d.ts +81 -0
  23. package/dist/shader/graph/compiler.js +4 -0
  24. package/dist/shader/graph/index.d.ts +5 -0
  25. package/dist/shader/graph/index.js +4 -0
  26. package/dist/shader/graph/model.d.ts +81 -0
  27. package/dist/shader/graph/model.js +4 -0
  28. package/dist/shader/graph/parameters.d.ts +7 -0
  29. package/dist/shader/graph/parameters.js +4 -0
  30. package/dist/shader/graph/registry.d.ts +22 -0
  31. package/dist/shader/graph/registry.js +4 -0
  32. package/dist/shader/index.d.ts +1 -0
  33. package/dist/shader/index.js +1 -1
  34. package/dist/shader-nodes/bulge.js +1 -1
  35. package/dist/shader-nodes/depth.d.ts +2 -0
  36. package/dist/shader-nodes/depth.js +1 -1
  37. package/dist/shader-nodes/effects.d.ts +5 -0
  38. package/dist/shader-nodes/effects.js +1 -1
  39. package/dist/shader-nodes/gradient-sample.d.ts +16 -0
  40. package/dist/shader-nodes/gradient-sample.js +4 -0
  41. package/dist/shader-nodes/index.d.ts +1 -0
  42. package/dist/shader-nodes/index.js +1 -1
  43. package/dist/shader-nodes/layers.d.ts +6 -3
  44. package/dist/shader-nodes/layers.js +1 -1
  45. package/dist/shader-nodes/math.d.ts +4 -0
  46. package/dist/shader-nodes/math.js +1 -1
  47. package/dist/shader-nodes/particle.d.ts +10 -2
  48. package/dist/shader-nodes/particle.js +1 -1
  49. package/dist/shader-nodes/texture-sequence.d.ts +2 -1
  50. package/dist/shader-nodes/texture-sequence.js +1 -1
  51. package/dist/test/runtime-param-type-inference.test.d.ts +2 -0
  52. package/dist/test/runtime-param-type-inference.test.js +4 -0
  53. package/dist/test/shader-graph.test.d.ts +2 -0
  54. package/dist/test/shader-graph.test.js +4 -0
  55. package/dist/test/storage-case-collision.test.js +1 -1
  56. package/package.json +6 -2
  57. package/tsconfig.tsbuildinfo +1 -1
@@ -10,6 +10,7 @@ export interface SequenceAction extends SequenceLocatorReader {
10
10
  bindRole(role: SequenceRole, target: BaseActor | Object3D): void;
11
11
  play(options?: SequencePlayOptions): void;
12
12
  pause(): void;
13
+ cancel(): void;
13
14
  stop(): void;
14
15
  restart(): void;
15
16
  seek(time: number): void;
@@ -134,6 +134,11 @@ export declare class SequenceActor extends BaseActor implements SequenceAction {
134
134
  * Pause playback
135
135
  */
136
136
  pause(): void;
137
+ /**
138
+ * Cancel playback without restoring the bound actor/object transforms.
139
+ * Useful for gameplay interruptions where movement has already committed.
140
+ */
141
+ cancel(): void;
137
142
  /**
138
143
  * Stop playback and reset to beginning
139
144
  */
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{Actor as s,BaseActor as r}from"../../gameplay/actors/actor.js";import{inject as a}from"../../gameplay/inject.js";import{ViewController as o}from"../../gameplay/services/render.js";import{AssetLoader as i}from"../../gameplay/services/asset-loader.js";import{World as l}from"../../gameplay/services/world.js";import{ActorFactory as n}from"../../gameplay/actors/factory.js";import{VfxService as p}from"../../effects/vfx/vfx-service.js";import{Parameter as c}from"../../shader/parameter.js";import{createSequenceData as h}from"./sequence-data.js";import{SequencePlayer as d,SequencePlaybackState as m}from"./sequence-player.js";import{Subject as y,takeUntil as u}from"rxjs";let b=class extends r{constructor(){super(...arguments),this.sequenceData=h(),this.sequenceAssetId=null,this._cameraControlEnabled=!1,this._cameraControlTrackId=null,this.onComplete=new y,this.onLoop=new y,this.player=new d,this.viewController=a(o),this.assetLoader=a(i),this.world=a(l),this.actorFactory=a(n),this.vfxService=a(p),this.sourceAsset=null}get cameraControlEnabled(){return this._cameraControlEnabled}set cameraControlEnabled(e){this._cameraControlEnabled=e,this.player.cameraControlEnabled=e}get cameraControlTrackId(){return this._cameraControlTrackId}set cameraControlTrackId(e){this._cameraControlTrackId=e,this.player.cameraControlTrackId=e}get timescale(){return this.player.timescale}set timescale(e){this.player.timescale=e}get loop(){return this.player.loop}set loop(e){this.player.loop=e}get state(){return this.player.state}get time(){return this.player.time}get duration(){return this.player.duration}get paused(){return this.player.state===m.Paused}get externalTimeControl(){return this.player.externalTimeControl}set externalTimeControl(e){this.player.externalTimeControl=e}get inEditor(){return this.player.inEditor}set inEditor(e){this.player.inEditor=e}async onInit(){this.player.setWorld(this.world),this.player.setViewController(this.viewController),this.player.setAudioListener(this.viewController.audioListener),this.player.setAssetLoader(this.assetLoader),this.player.setActorFactory(this.actorFactory),this.player.setVfxService(this.vfxService),this.viewController.onUpdate(this).pipe(u(this.disposed)).subscribe(e=>this.player.update(e)),this.player.onComplete.pipe(u(this.disposed)).subscribe(()=>this.onComplete.next()),this.player.onLoop.pipe(u(this.disposed)).subscribe(e=>this.onLoop.next(e)),this.sequenceAssetId?await this.loadFromAssetId(this.sequenceAssetId):this.sequenceData&&this.player.load(this.sequenceData)}async loadFromAsset(e){if("sequence"!==e.type)throw new Error(`Asset must be a sequence asset but is ${e.type}`);this.sourceAsset=e,this.sourceAsset.sequence&&(this.sequenceData=this.sourceAsset.sequence,this.player.load(this.sequenceData))}async loadFromAssetId(e){const t=await this.assetLoader.getAsset(e);t&&await this.loadFromAsset(t)}setSequenceData(e){this.sequenceData=e,this.player.load(e)}bindRole(e,t){this.player.bindRole(e,t)}bindObject(e,t){this.player.bindObject(e,t)}getLocator(e){return this.player.getLocator(e)}getLocators(e){return this.player.getLocators(e)}getActiveTrackObjects(e){return this.player.getActiveTrackObjects(e)}play(e){this.player.cameraControlEnabled=e?.cameraControlEnabled??this.cameraControlEnabled,this.player.play()}pause(){this.player.pause()}stop(){this.player.stop()}restart(){this.player.restart()}seek(e){this.player.seek(e)}refreshAsset(e){this.player.refreshAsset(e)}onUpdate(e){}onEndPlay(){this.player.dispose()}dispose(){this.world.removeActor(this)}};e([c({label:"Sequence Data"}),t("design:type",Object)],b.prototype,"sequenceData",void 0),e([c({label:"Camera Control Enabled"}),t("design:type",Boolean),t("design:paramtypes",[Boolean])],b.prototype,"cameraControlEnabled",null),b=e([s()],b);export{b as SequenceActor};/*
1
+ import{__decorate as e,__metadata as t}from"tslib";import{Actor as s,BaseActor as r}from"../../gameplay/actors/actor.js";import{inject as a}from"../../gameplay/inject.js";import{ViewController as o}from"../../gameplay/services/render.js";import{AssetLoader as i}from"../../gameplay/services/asset-loader.js";import{World as l}from"../../gameplay/services/world.js";import{ActorFactory as n}from"../../gameplay/actors/factory.js";import{VfxService as p}from"../../effects/vfx/vfx-service.js";import{Parameter as c}from"../../shader/parameter.js";import{createSequenceData as h}from"./sequence-data.js";import{SequencePlayer as d,SequencePlaybackState as m}from"./sequence-player.js";import{Subject as y,takeUntil as u}from"rxjs";let b=class extends r{constructor(){super(...arguments),this.sequenceData=h(),this.sequenceAssetId=null,this._cameraControlEnabled=!1,this._cameraControlTrackId=null,this.onComplete=new y,this.onLoop=new y,this.player=new d,this.viewController=a(o),this.assetLoader=a(i),this.world=a(l),this.actorFactory=a(n),this.vfxService=a(p),this.sourceAsset=null}get cameraControlEnabled(){return this._cameraControlEnabled}set cameraControlEnabled(e){this._cameraControlEnabled=e,this.player.cameraControlEnabled=e}get cameraControlTrackId(){return this._cameraControlTrackId}set cameraControlTrackId(e){this._cameraControlTrackId=e,this.player.cameraControlTrackId=e}get timescale(){return this.player.timescale}set timescale(e){this.player.timescale=e}get loop(){return this.player.loop}set loop(e){this.player.loop=e}get state(){return this.player.state}get time(){return this.player.time}get duration(){return this.player.duration}get paused(){return this.player.state===m.Paused}get externalTimeControl(){return this.player.externalTimeControl}set externalTimeControl(e){this.player.externalTimeControl=e}get inEditor(){return this.player.inEditor}set inEditor(e){this.player.inEditor=e}async onInit(){this.player.setWorld(this.world),this.player.setViewController(this.viewController),this.player.setAudioListener(this.viewController.audioListener),this.player.setAssetLoader(this.assetLoader),this.player.setActorFactory(this.actorFactory),this.player.setVfxService(this.vfxService),this.viewController.onUpdate(this).pipe(u(this.disposed)).subscribe(e=>this.player.update(e)),this.player.onComplete.pipe(u(this.disposed)).subscribe(()=>this.onComplete.next()),this.player.onLoop.pipe(u(this.disposed)).subscribe(e=>this.onLoop.next(e)),this.sequenceAssetId?await this.loadFromAssetId(this.sequenceAssetId):this.sequenceData&&this.player.load(this.sequenceData)}async loadFromAsset(e){if("sequence"!==e.type)throw new Error(`Asset must be a sequence asset but is ${e.type}`);this.sourceAsset=e,this.sourceAsset.sequence&&(this.sequenceData=this.sourceAsset.sequence,this.player.load(this.sequenceData))}async loadFromAssetId(e){const t=await this.assetLoader.getAsset(e);t&&await this.loadFromAsset(t)}setSequenceData(e){this.sequenceData=e,this.player.load(e)}bindRole(e,t){this.player.bindRole(e,t)}bindObject(e,t){this.player.bindObject(e,t)}getLocator(e){return this.player.getLocator(e)}getLocators(e){return this.player.getLocators(e)}getActiveTrackObjects(e){return this.player.getActiveTrackObjects(e)}play(e){this.player.cameraControlEnabled=e?.cameraControlEnabled??this.cameraControlEnabled,this.player.play()}pause(){this.player.pause()}cancel(){this.player.cancel()}stop(){this.player.stop()}restart(){this.player.restart()}seek(e){this.player.seek(e)}refreshAsset(e){this.player.refreshAsset(e)}onUpdate(e){}onEndPlay(){this.player.dispose()}dispose(){this.world.removeActor(this)}};e([c({label:"Sequence Data"}),t("design:type",Object)],b.prototype,"sequenceData",void 0),e([c({label:"Camera Control Enabled"}),t("design:type",Boolean),t("design:paramtypes",[Boolean])],b.prototype,"cameraControlEnabled",null),b=e([s()],b);export{b as SequenceActor};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -255,6 +255,12 @@ export declare class SequencePlayer implements SequenceLocatorReader {
255
255
  private pauseAudio;
256
256
  private pauseVfx;
257
257
  private resumeVfx;
258
+ /**
259
+ * Cancel playback and release runtime-owned effects without restoring bound
260
+ * object transforms. Useful for gameplay interrupts where movement/physics
261
+ * has already committed the character's current transform.
262
+ */
263
+ cancel(): void;
258
264
  /**
259
265
  * Stop playback and reset to beginning
260
266
  */
@@ -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 P,findKeyframeSpan as x}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 j}from"../../gameplay/animation/root-motion.js";import{hashCameraShakeSeed as _}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={track:e,target:t,activeActions:new Map,originalTransform:{position:a.position.clone(),rotation:a.rotation.clone(),scale:a.scale.clone()},originalParent:a.parent};e.subTracks.some(e=>"animation"===e.type)&&(s.mixer=new i(a)),this.bindings.set(e.id,s)}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()}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}=x(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(U.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):j.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)}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),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??_(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}=x(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(U.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}=x(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?j.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?j.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=P(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,U=new r;/*
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;/*
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{timeUniforms as t}from"../../shader-nodes/index.js";import*as e from"three";import{NodeShaderMaterial as i,uniformBool as r,uniformFloat as o,uniformVec2 as s,mix as a,uniformVec4 as n,attributeFloat as h,attributeVec3 as l,select as d,float as u,textureSampler2d as c,attributes as m,uniforms as y,rgba as g,vec4 as p,varying as x,vec2 as f,normalize as v,vec3 as b,cross as T,max as C,length as V}from"three-shader-graph";o("trailLength");const P=o("verticesPerNode"),w=o("minID"),F=o("maxID"),I=(o("dragTexture"),o("maxTrailLength")),D=s("textureTileFactor",new e.Vector2(1,1)),N=n("headColor",new e.Vector4),U=n("tailColor",new e.Vector4),A=r("taper",!1),M=(o("scale",1),h("nodeID")),z=h("nodeVertexID"),B=l("nodeCenter"),H=F.subtract(M).divide(F.subtract(w)),S=d(A,H,u(0)),j=x(u(1).subtract(H).multiplyVec4(N).add(H.multiplyVec4(U))),q=v(y.cameraPosition.subtract(B)),L=v(l("nodeTangent")),G=o("width",1),O=v(T(d(V(L).gt(u(.1)),L,b(1,0,0)),q)).multiplyScalar(z.subtract(u(.5))).multiplyScalar(G),Q=p(u(1).subtract(S).multiplyVec3(O).add(C(S,u(1)).multiplyVec3(B)),1),R=p(u(1).subtract(S).multiplyVec3(m.position).add(S.multiplyVec3(B)),1),W=y.projectionMatrix.multiply(y.viewMatrix).multiplyVec(Q),_=y.projectionMatrix.multiply(y.viewMatrix).multiplyVec(R);export const trailUV=x(f(H.multiply(D.x),z.divide(P).multiply(D.y).multiply(2)));export const trailDragUV=x(f(M.divide(I).multiply(D.x),z.divide(P).multiply(D.y).multiply(2)));const k={position:new e.Vector3,direction:new e.Vector3,offset:new e.Vector3,worldOrientation:new e.Vector3,matrix4:new e.Matrix4,quat1:new e.Quaternion,quat2:new e.Quaternion,quaternion:new e.Quaternion,quaternion2:new e.Quaternion,boundingBox:new e.Box3,localHeadGeometry:Array.from({length:128},()=>new e.Vector3)};export class Trail extends e.Object3D{constructor(t,i){super(),this.historyCount=0,this.historyHeadIndex=-1,this.history=[],this.renderNodeCount=0,this.subdivisions=4,this.currentNodeID=0,this.advance=function(){const t=new e.Matrix4;return function(){this.targetObject.updateMatrixWorld(),t.copy(this.targetObject.matrixWorld),this.advanceWithTransform(t),this.updateUniforms()}}(),this.connectNodes=(()=>{const t={attribute:null,offset:0,count:-1};return(e,i)=>{const r=this.geometry.getIndex();for(let t=0;t<this.localHeadGeometry.length-1;t++){const o=this.VerticesPerNode*e+t,s=this.VerticesPerNode*i+t,a=(e*this.FacesPerNode+t*Trail.FacesPerQuad)*Trail.IndicesPerFace;r.array[a]=o,r.array[a+1]=s,r.array[a+2]=o+1,r.array[a+3]=s,r.array[a+4]=s+1,r.array[a+5]=o+1}return r.needsUpdate=!0,r.clearUpdateRanges(),t.attribute=r,t.offset=e*this.FacesPerNode*Trail.IndicesPerFace,t.count=this.FacesPerNode*Trail.IndicesPerFace,t}})(),this.disconnectNodes=(()=>{const t={attribute:null,offset:0,count:-1};return e=>{const i=this.geometry.getIndex();for(let t=0;t<this.localHeadGeometry.length-1;t++){const r=(e*this.FacesPerNode+t*Trail.FacesPerQuad)*Trail.IndicesPerFace;i.array[r]=0,i.array[r+1]=0,i.array[r+2]=0,i.array[r+3]=0,i.array[r+4]=0,i.array[r+5]=0}return i.needsUpdate=!0,i.clearUpdateRanges(),t.attribute=i,t.offset=e*this.FacesPerNode*Trail.IndicesPerFace,t.count=this.FacesPerNode*Trail.IndicesPerFace,t}})(),this.active=!1,this.orientToMovement=!1,i&&(this.orientToMovement=!0),this.scene=t,this.geometry=null,this.mesh=null,this.historyCount=0,this.historyHeadIndex=-1,this.history=[],this.renderNodeCount=0,this.currentNodeID=0,this.advanceFrequency=60,this.advancePeriod=1/this.advanceFrequency,this.lastAdvanceTime=0,this.paused=!1,this.pauseAdvanceUpdateTimeDiff=0}setAdvanceFrequency(t){this.advanceFrequency=t,this.advancePeriod=1/this.advanceFrequency}initialize(t,i,r,o,s,a,n=!1){this.deactivate(),this.destroyMesh(),this.length=i>0?i+1:0,this.dragTexture=r?1:0,this.targetObject=a,this.billboard=n,this.initializeLocalHeadGeometry(o,s),null!=t.uniforms.width&&(t.uniforms.width.value=o),this.renderNodeCount=this.length*this.subdivisions,this.historyCount=0,this.historyHeadIndex=-1,this.history=[];for(let t=0;t<this.length;t++)this.history.push({position:new e.Vector3,tangent:new e.Vector3(1,0,0),transformMatrix:new e.Matrix4,id:-1});this.setAllNodesToCurrentTargetPosition(),this.material=t,this.initializeGeometry(),this.initializeMesh(),this.material.uniforms.dragTexture&&(this.material.uniforms.trailLength.value=0),this.material.uniforms.minID.value=0,this.material.uniforms.maxID.value=0,this.material.uniforms.dragTexture&&(this.material.uniforms.dragTexture.value=this.dragTexture),this.material.uniforms.maxTrailLength&&(this.material.uniforms.maxTrailLength.value=this.length),this.material.uniforms.verticesPerNode&&(this.material.uniforms.verticesPerNode.value=this.VerticesPerNode),this.material.uniforms.textureTileFactor&&(this.material.uniforms.textureTileFactor.value=new e.Vector2(1,1)),this.material.uniforms.scale&&(this.material.uniforms.scale.value=1),this.reset()}initializeLocalHeadGeometry(t,i){if(this.localHeadGeometry=[],i){this.VerticesPerNode=0;for(let t=0;t<i.length&&t<Trail.MaxHeadVertices;t++){const r=i[t];if(r&&r instanceof e.Vector3){const t=new e.Vector3;t.copy(r),this.localHeadGeometry.push(t),this.VerticesPerNode++}}}else{const i=(t||1)/2;this.localHeadGeometry.push(new e.Vector3(-i,0,0)),this.localHeadGeometry.push(new e.Vector3(i,0,0)),this.VerticesPerNode=2}this.FacesPerNode=2*(this.VerticesPerNode-1),this.FaceIndicesPerNode=3*this.FacesPerNode}initializeGeometry(){this.vertexCount=this.renderNodeCount*this.VerticesPerNode,this.faceCount=this.renderNodeCount*this.FacesPerNode;const t=new e.BufferGeometry,i=new Float32Array(this.vertexCount),r=new Float32Array(this.vertexCount*this.VerticesPerNode),o=new Float32Array(this.vertexCount*Trail.PositionComponentCount),s=new Float32Array(this.vertexCount*Trail.PositionComponentCount),a=new Float32Array(this.vertexCount*Trail.UVComponentCount),n=new Uint32Array(this.faceCount*Trail.IndicesPerFace),h=new Float32Array(3*this.vertexCount),l=new e.BufferAttribute(h,3);l.setUsage(e.DynamicDrawUsage),t.setAttribute("nodeTangent",l);const d=new e.BufferAttribute(i,1);d.setUsage(e.DynamicDrawUsage),t.setAttribute("nodeID",d);const u=new e.BufferAttribute(r,1);u.setUsage(e.DynamicDrawUsage),t.setAttribute("nodeVertexID",u);const c=new e.BufferAttribute(s,Trail.PositionComponentCount);c.setUsage(e.DynamicDrawUsage),t.setAttribute("nodeCenter",c);const m=new e.BufferAttribute(o,Trail.PositionComponentCount);m.setUsage(e.DynamicDrawUsage),t.setAttribute("position",m);const y=new e.BufferAttribute(a,Trail.UVComponentCount);y.setUsage(e.DynamicDrawUsage),t.setAttribute("uv",y);const g=new e.BufferAttribute(n,1);g.setUsage(e.DynamicDrawUsage),t.setIndex(g),this.geometry=t}zeroVertices(){const t=this.geometry.getAttribute("position");for(let e=0;e<this.vertexCount;e++){const i=3*e;t.array[i]=0,t.array[i+1]=0,t.array[i+2]=0}t.needsUpdate=!0}zeroIndices(){if(null==this.geometry)throw"Geometry not initialized";const t=this.geometry.getIndex();for(let e=0;e<this.faceCount;e++){const i=3*e;t.array[i]=0,t.array[i+1]=0,t.array[i+2]=0}t.needsUpdate=!0,t.clearUpdateRanges()}formInitialFaces(){this.zeroIndices();const t=this.geometry.getIndex();for(let t=0;t<this.renderNodeCount-1;t++)this.connectNodes(t,t+1);t.needsUpdate=!0,t.clearUpdateRanges()}initializeMesh(){if(null==this.geometry)throw"Geometry not initialized";this.mesh=new e.Mesh(this.geometry,this.material),this.mesh.matrixAutoUpdate=!1,this.mesh.visible=!1}destroyMesh(){this.mesh&&(this.scene.remove(this.mesh),this.mesh=null)}reset(){this.historyCount=0,this.historyHeadIndex=-1,this.currentNodeID=0,this.formInitialFaces(),this.zeroVertices(),this.geometry.setDrawRange(0,0),this.setAllNodesToCurrentTargetPosition(),this.mesh&&(this.mesh.visible=!0)}setAllNodesToCurrentTargetPosition(){if(!this.targetObject)return;this.targetObject.updateMatrixWorld();const t=this.targetObject.matrixWorld,i=(new e.Vector3).setFromMatrixPosition(t),r=new e.Vector3(1,0,0).applyMatrix4(t).normalize();for(let e=0;e<this.length;e++)this.history[e].position.copy(i),this.history[e].tangent.copy(r),this.history[e].transformMatrix.copy(t),this.history[e].id=-1;this.historyCount=0,this.historyHeadIndex=-1}updateUniforms(){if(0===this.historyCount)return;const t=this.getControlPoint(0).id,e=this.getControlPoint(this.historyCount-1).id;this.material.uniforms.minID.value=t,this.material.uniforms.maxID.value=e,this.material.uniforms.trailLength&&(this.material.uniforms.trailLength.value=this.historyCount),this.material.uniforms.maxTrailLength&&(this.material.uniforms.maxTrailLength.value=this.length),this.material.uniforms.verticesPerNode&&(this.material.uniforms.verticesPerNode.value=this.VerticesPerNode)}advanceWithTransform(t){this.historyCount<this.length&&this.historyCount++,this.historyHeadIndex=(this.historyHeadIndex+1)%this.length;const e=this.history[this.historyHeadIndex];if(e.id=this.currentNodeID++,k.position.set(0,0,0).applyMatrix4(t),e.position.copy(k.position),e.transformMatrix.copy(t),this.billboard){const i=this.getControlPoint(this.historyCount-2);i&&!i.position.equals(k.position)?e.tangent.copy(k.position).sub(i.position).normalize():e.tangent.set(1,0,0).applyMatrix4(t).normalize()}this.rebuildGeometry()}updateHead(){if(0===this.historyCount)return;this.targetObject.updateMatrixWorld();const t=this.targetObject.matrixWorld,e=this.history[this.historyHeadIndex];if(k.position.set(0,0,0).applyMatrix4(t),e.position.copy(k.position),e.transformMatrix.copy(t),this.billboard){const i=this.getControlPoint(this.historyCount-2);i&&!i.position.equals(k.position)?e.tangent.copy(k.position).sub(i.position).normalize():e.tangent.set(1,0,0).applyMatrix4(t).normalize()}this.rebuildGeometry()}getControlPoint(t){if(t<0)return this.history[(this.historyHeadIndex-this.historyCount+1+this.length)%this.length];t>=this.historyCount&&(t=this.historyCount-1);const e=(this.historyHeadIndex-this.historyCount+1+this.length)%this.length;return this.history[(e+t)%this.length]}rebuildGeometry(){if(this.historyCount<2)return this.geometry.setDrawRange(0,0),void(this.mesh&&(this.mesh.visible=!1));const t=this.geometry.getAttribute("position"),i=this.geometry.getAttribute("nodeID"),r=this.geometry.getAttribute("nodeVertexID"),o=this.geometry.getAttribute("nodeCenter"),s=this.geometry.getAttribute("nodeTangent"),a=this.historyCount-1,n=a*this.subdivisions+1;let h=0;k.boundingBox.makeEmpty();for(let e=0;e<a;e++){const n=this.getControlPoint(e-1),l=this.getControlPoint(e),d=this.getControlPoint(e+1),u=this.getControlPoint(e+2),c=e===a-1?this.subdivisions+1:this.subdivisions;for(let e=0;e<c;e++){const a=e/this.subdivisions,c=n.position,m=l.position,y=d.position,g=u.position,p=a*a,x=p*a,f=.5*(y.x-c.x),v=.5*(g.x-m.x),b=(2*(m.x-y.x)+f+v)*x+(-3*(m.x-y.x)-2*f-v)*p+f*a+m.x,T=.5*(y.y-c.y),C=.5*(g.y-m.y),V=(2*(m.y-y.y)+T+C)*x+(-3*(m.y-y.y)-2*T-C)*p+T*a+m.y,P=.5*(y.z-c.z),w=.5*(g.z-m.z),F=(2*(m.z-y.z)+P+w)*x+(-3*(m.z-y.z)-2*P-w)*p+P*a+m.z;k.position.set(b,V,F);const I=l.id+(d.id-l.id)*a,D=k.direction.copy(l.tangent).lerp(d.tangent,a).normalize();k.matrix4.copy(l.transformMatrix),k.quat1.setFromRotationMatrix(l.transformMatrix),k.quat2.setFromRotationMatrix(d.transformMatrix),k.quaternion.copy(k.quat1).slerp(k.quat2,a),k.matrix4.makeRotationFromQuaternion(k.quaternion),k.matrix4.setPosition(k.position);for(let e=0;e<this.VerticesPerNode;e++){const n=h*this.VerticesPerNode+e;i.array[n]=I,r.array[n]=e,o.array[3*n]=k.position.x,o.array[3*n+1]=k.position.y,o.array[3*n+2]=k.position.z;const l=k.localHeadGeometry[e].copy(this.localHeadGeometry[e]);if(this.billboard)s.array[3*n]=D.x,s.array[3*n+1]=D.y,s.array[3*n+2]=D.z,k.boundingBox.expandByPoint(k.position);else{if(l.applyMatrix4(k.matrix4),this.orientToMovement){k.worldOrientation.set(0,0,-1).applyQuaternion(k.quaternion);const t=(3*p-2*a)*(m.x-y.x)+(x-p)*v+(3*p-4*a+1)*f,e=(3*p-2*a)*(m.y-y.y)+(x-p)*C+(3*p-4*a+1)*T,i=(3*p-2*a)*(m.z-y.z)+(x-p)*w+(3*p-4*a+1)*P;k.direction.set(t,e,i).normalize(),k.direction.lengthSq()>1e-4&&(k.quaternion2.setFromUnitVectors(k.worldOrientation,k.direction),l.sub(k.position).applyQuaternion(k.quaternion2).add(k.position))}t.array[3*n]=l.x,t.array[3*n+1]=l.y,t.array[3*n+2]=l.z,k.boundingBox.expandByPoint(l)}}h++}}if(i.needsUpdate=!0,r.needsUpdate=!0,o.needsUpdate=!0,this.billboard){s.needsUpdate=!0,this.mesh.frustumCulled=!1;const t=this.material.uniforms.width?.5*this.material.uniforms.width.value:.5;k.boundingBox.min.subScalar(t),k.boundingBox.max.addScalar(t)}else t.needsUpdate=!0;this.geometry.boundingBox=this.geometry.boundingBox||new e.Box3,this.geometry.boundingBox.copy(k.boundingBox),this.geometry.boundingSphere=this.geometry.boundingSphere||new e.Sphere,this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere),this.mesh.visible=!k.boundingBox.isEmpty(),this.geometry.setDrawRange(0,(n-1)*this.FaceIndicesPerNode)}currentTime(){return performance.now()/1e3}pause(){this.paused||(this.paused=!0,this.pauseAdvanceUpdateTimeDiff=this.currentTime()-this.lastAdvanceTime)}resume(){this.paused&&(this.paused=!1,this.lastAdvanceTime=this.currentTime()-this.pauseAdvanceUpdateTimeDiff)}update(){if(!this.paused){const t=this.currentTime();this.lastAdvanceTime||(this.lastAdvanceTime=t),t-this.lastAdvanceTime>this.advancePeriod?(this.advance(),this.lastAdvanceTime=t):this.updateHead()}}deactivate(){this.active&&(this.scene.remove(this.mesh),this.active=!1)}activate(){this.active||(this.scene.add(this.mesh),this.active=!0)}static getTrailShaderNodes(t){return{position:t?W:_,color:j,fraction:H}}static applyTrailShaderParameters(t){t.transparent=!0,t.alphaTest=.5,t.blending=e.CustomBlending,t.blendSrc=e.SrcAlphaFactor,t.blendDst=e.OneMinusSrcAlphaFactor,t.blendEquation=e.AddEquation,t.depthTest=!0,t.depthWrite=!1,t.side=e.DoubleSide}static createBaseMaterial(e,r,o,s=!1){let{position:n}=Trail.getTrailShaderNodes(s),h=a(N,U,H).rgba,l=h.a;if(null!=e){let i=trailUV;null!=r&&(i=i.add(f(t.elapsed.multiply(-r),0)));const s=c(e).sample(i);switch(o??"red"){case"none":break;case"red":l=l.multiply(s.r);break;case"alpha":l=l.multiply(s.a)}h=g(h.rgb.multiply(s.rgb),l)}const d=new i({position:n,opacity:l,color:h});return Trail.applyTrailShaderParameters(d),d}static get MaxHeadVertices(){return 128}static get LocalOrientationTangent(){return Trail._LocalOrientationTangent}static get LocalHeadOrigin(){return Trail._LocalHeadOrigin}static get PositionComponentCount(){return 3}static get UVComponentCount(){return 2}static get IndicesPerFace(){return 3}static get FacesPerQuad(){return 2}}Trail._LocalOrientationTangent=new e.Vector3(1,0,0),Trail._LocalHeadOrigin=new e.Vector3(0,0,0),Trail.Shader={get BaseVertexVars(){return["attribute float nodeID;","attribute float nodeVertexID;","attribute vec3 nodeCenter;","uniform float minID;","uniform float maxID;","uniform float trailLength;","uniform float maxTrailLength;","uniform float verticesPerNode;","uniform vec2 textureTileFactor;","uniform bool taper;","uniform vec4 headColor;","uniform vec4 tailColor;","varying vec4 vColor;"].join("\n")},get TexturedVertexVars(){return[this.BaseVertexVars,"varying vec2 vUV;","uniform float dragTexture;"].join("\n")},BaseFragmentVars:["varying vec4 vColor;","uniform sampler2D trailTexture;"].join("\n"),get TexturedFragmentVars(){return[this.BaseFragmentVars,"varying vec2 vUV;"].join("\n")},get VertexShaderCore(){return["float fraction = (maxID - nodeID) / (maxID - minID);","float fractionSize = taper ? fraction : 0.0;","vColor = (1.0 - fraction) * headColor + fraction * tailColor;","vec4 realPosition = vec4((1.0 - fractionSize) * position.xyz + fractionSize * nodeCenter.xyz, 1.0); "].join("\n")},get BaseVertexShader(){return[this.BaseVertexVars,"void main() { ",this.VertexShaderCore,"gl_Position = projectionMatrix * viewMatrix * realPosition;","}"].join("\n")},get BaseFragmentShader(){return[this.BaseFragmentVars,"void main() { ","gl_FragColor = vColor;","}"].join("\n")},get TexturedVertexShader(){return[this.TexturedVertexVars,"void main() { ",this.VertexShaderCore,"float s = 0.0;","float t = 0.0;","if (dragTexture == 1.0) { "," s = fraction * textureTileFactor.s; "," t = (nodeVertexID / verticesPerNode) * textureTileFactor.t;","} else { "," s = nodeID / maxTrailLength * textureTileFactor.s;"," t = (nodeVertexID / verticesPerNode) * textureTileFactor.t;","}","vUV = vec2(s, t); ","gl_Position = projectionMatrix * viewMatrix * realPosition;","}"].join("\n")},get TexturedFragmentShader(){return[this.TexturedFragmentVars,"void main() { ","vec4 textureColor = texture2D(trailTexture, vUV);","gl_FragColor = vColor * textureColor;","}"].join("\n")}};/*
1
+ import{timeUniforms as t}from"../../shader-nodes/index.js";import*as e from"three";import{NodeShaderMaterial as i,uniformBool as r,uniformFloat as o,uniformVec2 as s,mix as a,uniformVec4 as n,attributeFloat as h,attributeVec3 as l,select as d,float as u,textureSampler2d as c,attributes as m,uniforms as y,rgba as g,vec4 as p,varying as x,vec2 as f,normalize as v,vec3 as b,cross as T,max as C,length as V}from"three-shader-graph";o("trailLength");const P=o("verticesPerNode"),w=o("minID"),F=o("maxID"),I=(o("dragTexture"),o("maxTrailLength")),D=s("textureTileFactor",new e.Vector2(1,1)),N=n("headColor",new e.Vector4),U=n("tailColor",new e.Vector4),A=r("taper",!1),M=(o("scale",1),h("nodeID")),z=h("nodeVertexID"),B=l("nodeCenter"),H=F.subtract(M).divide(F.subtract(w)),S=d(A,H,u(0)),j=x(u(1).subtract(H).multiplyVec4(N).add(H.multiplyVec4(U))),q=v(y.cameraPosition.subtract(B)),L=v(l("nodeTangent")),G=o("width",1),O=v(T(d(V(L).gt(u(.1)),L,b(1,0,0)),q)).multiplyScalar(z.subtract(u(.5))).multiplyScalar(G),Q=p(u(1).subtract(S).multiplyVec3(O).add(C(S,u(1)).multiplyVec3(B)),1),R=p(u(1).subtract(S).multiplyVec3(m.position).add(S.multiplyVec3(B)),1),W=y.projectionMatrix.multiply(y.viewMatrix).multiplyVec(Q),_=y.projectionMatrix.multiply(y.viewMatrix).multiplyVec(R);export const trailUV=x(f(H.multiply(D.x),z.divide(P).multiply(D.y).multiply(2)));export const trailDragUV=x(f(M.divide(I).multiply(D.x),z.divide(P).multiply(D.y).multiply(2)));const k={position:new e.Vector3,direction:new e.Vector3,offset:new e.Vector3,worldOrientation:new e.Vector3,matrix4:new e.Matrix4,quat1:new e.Quaternion,quat2:new e.Quaternion,quaternion:new e.Quaternion,quaternion2:new e.Quaternion,boundingBox:new e.Box3,localHeadGeometry:Array.from({length:128},()=>new e.Vector3)};export class Trail extends e.Object3D{constructor(t,i){super(),this.historyCount=0,this.historyHeadIndex=-1,this.history=[],this.renderNodeCount=0,this.subdivisions=4,this.currentNodeID=0,this.advance=function(){const t=new e.Matrix4;return function(){this.targetObject.updateMatrixWorld(),t.copy(this.targetObject.matrixWorld),this.advanceWithTransform(t),this.updateUniforms()}}(),this.connectNodes=(()=>{const t={attribute:null,offset:0,count:-1};return(e,i)=>{const r=this.geometry.getIndex();for(let t=0;t<this.localHeadGeometry.length-1;t++){const o=this.VerticesPerNode*e+t,s=this.VerticesPerNode*i+t,a=(e*this.FacesPerNode+t*Trail.FacesPerQuad)*Trail.IndicesPerFace;r.array[a]=o,r.array[a+1]=s,r.array[a+2]=o+1,r.array[a+3]=s,r.array[a+4]=s+1,r.array[a+5]=o+1}return r.needsUpdate=!0,r.clearUpdateRanges(),t.attribute=r,t.offset=e*this.FacesPerNode*Trail.IndicesPerFace,t.count=this.FacesPerNode*Trail.IndicesPerFace,t}})(),this.disconnectNodes=(()=>{const t={attribute:null,offset:0,count:-1};return e=>{const i=this.geometry.getIndex();for(let t=0;t<this.localHeadGeometry.length-1;t++){const r=(e*this.FacesPerNode+t*Trail.FacesPerQuad)*Trail.IndicesPerFace;i.array[r]=0,i.array[r+1]=0,i.array[r+2]=0,i.array[r+3]=0,i.array[r+4]=0,i.array[r+5]=0}return i.needsUpdate=!0,i.clearUpdateRanges(),t.attribute=i,t.offset=e*this.FacesPerNode*Trail.IndicesPerFace,t.count=this.FacesPerNode*Trail.IndicesPerFace,t}})(),this.active=!1,this.orientToMovement=!1,i&&(this.orientToMovement=!0),this.scene=t,this.geometry=null,this.mesh=null,this.historyCount=0,this.historyHeadIndex=-1,this.history=[],this.renderNodeCount=0,this.currentNodeID=0,this.advanceFrequency=60,this.advancePeriod=1/this.advanceFrequency,this.lastAdvanceTime=0,this.paused=!1,this.pauseAdvanceUpdateTimeDiff=0}setAdvanceFrequency(t){this.advanceFrequency=t,this.advancePeriod=1/this.advanceFrequency}initialize(t,i,r,o,s,a,n=!1){this.deactivate(),this.destroyMesh(),this.length=i>0?i+1:0,this.dragTexture=r?1:0,this.targetObject=a,this.billboard=n,this.initializeLocalHeadGeometry(o,s),null!=t.uniforms.width&&(t.uniforms.width.value=o),this.renderNodeCount=this.length*this.subdivisions,this.historyCount=0,this.historyHeadIndex=-1,this.history=[];for(let t=0;t<this.length;t++)this.history.push({position:new e.Vector3,tangent:new e.Vector3(1,0,0),transformMatrix:new e.Matrix4,id:-1});this.setAllNodesToCurrentTargetPosition(),this.material=t,this.initializeGeometry(),this.initializeMesh(),this.material.uniforms.dragTexture&&(this.material.uniforms.trailLength.value=0),this.material.uniforms.minID.value=0,this.material.uniforms.maxID.value=0,this.material.uniforms.dragTexture&&(this.material.uniforms.dragTexture.value=this.dragTexture),this.material.uniforms.maxTrailLength&&(this.material.uniforms.maxTrailLength.value=this.length),this.material.uniforms.verticesPerNode&&(this.material.uniforms.verticesPerNode.value=this.VerticesPerNode),this.material.uniforms.textureTileFactor&&(this.material.uniforms.textureTileFactor.value=new e.Vector2(1,1)),this.material.uniforms.scale&&(this.material.uniforms.scale.value=1),this.reset()}initializeLocalHeadGeometry(t,i){if(this.localHeadGeometry=[],i){this.VerticesPerNode=0;for(let t=0;t<i.length&&t<Trail.MaxHeadVertices;t++){const r=i[t];if(r&&r instanceof e.Vector3){const t=new e.Vector3;t.copy(r),this.localHeadGeometry.push(t),this.VerticesPerNode++}}}else{const i=(t||1)/2;this.localHeadGeometry.push(new e.Vector3(-i,0,0)),this.localHeadGeometry.push(new e.Vector3(i,0,0)),this.VerticesPerNode=2}this.FacesPerNode=2*(this.VerticesPerNode-1),this.FaceIndicesPerNode=3*this.FacesPerNode}initializeGeometry(){this.vertexCount=this.renderNodeCount*this.VerticesPerNode,this.faceCount=this.renderNodeCount*this.FacesPerNode;const t=new e.BufferGeometry,i=new Float32Array(this.vertexCount),r=new Float32Array(this.vertexCount*this.VerticesPerNode),o=new Float32Array(this.vertexCount*Trail.PositionComponentCount),s=new Float32Array(this.vertexCount*Trail.PositionComponentCount),a=new Float32Array(this.vertexCount*Trail.UVComponentCount),n=new Uint32Array(this.faceCount*Trail.IndicesPerFace),h=new Float32Array(3*this.vertexCount),l=new e.BufferAttribute(h,3);l.setUsage(e.DynamicDrawUsage),t.setAttribute("nodeTangent",l);const d=new e.BufferAttribute(i,1);d.setUsage(e.DynamicDrawUsage),t.setAttribute("nodeID",d);const u=new e.BufferAttribute(r,1);u.setUsage(e.DynamicDrawUsage),t.setAttribute("nodeVertexID",u);const c=new e.BufferAttribute(s,Trail.PositionComponentCount);c.setUsage(e.DynamicDrawUsage),t.setAttribute("nodeCenter",c);const m=new e.BufferAttribute(o,Trail.PositionComponentCount);m.setUsage(e.DynamicDrawUsage),t.setAttribute("position",m);const y=new e.BufferAttribute(a,Trail.UVComponentCount);y.setUsage(e.DynamicDrawUsage),t.setAttribute("uv",y);const g=new e.BufferAttribute(n,1);g.setUsage(e.DynamicDrawUsage),t.setIndex(g),this.geometry=t}zeroVertices(){const t=this.geometry.getAttribute("position");for(let e=0;e<this.vertexCount;e++){const i=3*e;t.array[i]=0,t.array[i+1]=0,t.array[i+2]=0}t.needsUpdate=!0}zeroIndices(){if(null==this.geometry)throw"Geometry not initialized";const t=this.geometry.getIndex();for(let e=0;e<this.faceCount;e++){const i=3*e;t.array[i]=0,t.array[i+1]=0,t.array[i+2]=0}t.needsUpdate=!0,t.clearUpdateRanges()}formInitialFaces(){this.zeroIndices();const t=this.geometry.getIndex();for(let t=0;t<this.renderNodeCount-1;t++)this.connectNodes(t,t+1);t.needsUpdate=!0,t.clearUpdateRanges()}initializeMesh(){if(null==this.geometry)throw"Geometry not initialized";this.mesh=new e.Mesh(this.geometry,this.material),this.mesh.matrixAutoUpdate=!1,this.mesh.visible=!1}destroyMesh(){this.mesh&&(this.scene.remove(this.mesh),this.mesh=null)}reset(){this.historyCount=0,this.historyHeadIndex=-1,this.currentNodeID=0,this.formInitialFaces(),this.zeroVertices(),this.geometry.setDrawRange(0,0),this.setAllNodesToCurrentTargetPosition(),this.mesh&&(this.mesh.visible=!0)}setAllNodesToCurrentTargetPosition(){if(!this.targetObject)return;this.targetObject.updateMatrixWorld();const t=this.targetObject.matrixWorld,i=(new e.Vector3).setFromMatrixPosition(t),r=new e.Vector3(1,0,0).applyMatrix4(t).normalize();for(let e=0;e<this.length;e++)this.history[e].position.copy(i),this.history[e].tangent.copy(r),this.history[e].transformMatrix.copy(t),this.history[e].id=-1;this.historyCount=0,this.historyHeadIndex=-1}updateUniforms(){if(0===this.historyCount)return;const t=this.getControlPoint(0).id,e=this.getControlPoint(this.historyCount-1).id;this.material.uniforms.minID.value=t,this.material.uniforms.maxID.value=e,this.material.uniforms.trailLength&&(this.material.uniforms.trailLength.value=this.historyCount),this.material.uniforms.maxTrailLength&&(this.material.uniforms.maxTrailLength.value=this.length),this.material.uniforms.verticesPerNode&&(this.material.uniforms.verticesPerNode.value=this.VerticesPerNode)}advanceWithTransform(t){this.historyCount<this.length&&this.historyCount++,this.historyHeadIndex=(this.historyHeadIndex+1)%this.length;const e=this.history[this.historyHeadIndex];if(e.id=this.currentNodeID++,k.position.set(0,0,0).applyMatrix4(t),e.position.copy(k.position),e.transformMatrix.copy(t),this.billboard){const i=this.getControlPoint(this.historyCount-2);i&&!i.position.equals(k.position)?e.tangent.copy(k.position).sub(i.position).normalize():e.tangent.set(1,0,0).applyMatrix4(t).normalize()}this.rebuildGeometry()}updateHead(){if(0===this.historyCount)return;this.targetObject.updateMatrixWorld();const t=this.targetObject.matrixWorld,e=this.history[this.historyHeadIndex];if(k.position.set(0,0,0).applyMatrix4(t),e.position.copy(k.position),e.transformMatrix.copy(t),this.billboard){const i=this.getControlPoint(this.historyCount-2);i&&!i.position.equals(k.position)?e.tangent.copy(k.position).sub(i.position).normalize():e.tangent.set(1,0,0).applyMatrix4(t).normalize()}this.rebuildGeometry()}getControlPoint(t){if(t<0)return this.history[(this.historyHeadIndex-this.historyCount+1+this.length)%this.length];t>=this.historyCount&&(t=this.historyCount-1);const e=(this.historyHeadIndex-this.historyCount+1+this.length)%this.length;return this.history[(e+t)%this.length]}rebuildGeometry(){if(this.historyCount<2)return this.geometry.setDrawRange(0,0),void(this.mesh&&(this.mesh.visible=!1));const t=this.geometry.getAttribute("position"),i=this.geometry.getAttribute("nodeID"),r=this.geometry.getAttribute("nodeVertexID"),o=this.geometry.getAttribute("nodeCenter"),s=this.geometry.getAttribute("nodeTangent"),a=this.historyCount-1,n=a*this.subdivisions+1;let h=0;k.boundingBox.makeEmpty();for(let e=0;e<a;e++){const n=this.getControlPoint(e-1),l=this.getControlPoint(e),d=this.getControlPoint(e+1),u=this.getControlPoint(e+2),c=e===a-1?this.subdivisions+1:this.subdivisions;for(let e=0;e<c;e++){const a=e/this.subdivisions,c=n.position,m=l.position,y=d.position,g=u.position,p=a*a,x=p*a,f=.5*(y.x-c.x),v=.5*(g.x-m.x),b=(2*(m.x-y.x)+f+v)*x+(-3*(m.x-y.x)-2*f-v)*p+f*a+m.x,T=.5*(y.y-c.y),C=.5*(g.y-m.y),V=(2*(m.y-y.y)+T+C)*x+(-3*(m.y-y.y)-2*T-C)*p+T*a+m.y,P=.5*(y.z-c.z),w=.5*(g.z-m.z),F=(2*(m.z-y.z)+P+w)*x+(-3*(m.z-y.z)-2*P-w)*p+P*a+m.z;k.position.set(b,V,F);const I=l.id+(d.id-l.id)*a,D=k.direction.copy(l.tangent).lerp(d.tangent,a).normalize();k.matrix4.copy(l.transformMatrix),k.quat1.setFromRotationMatrix(l.transformMatrix),k.quat2.setFromRotationMatrix(d.transformMatrix),k.quaternion.copy(k.quat1).slerp(k.quat2,a),k.matrix4.makeRotationFromQuaternion(k.quaternion),k.matrix4.setPosition(k.position);for(let e=0;e<this.VerticesPerNode;e++){const n=h*this.VerticesPerNode+e;i.array[n]=I,r.array[n]=e,o.array[3*n]=k.position.x,o.array[3*n+1]=k.position.y,o.array[3*n+2]=k.position.z;const l=k.localHeadGeometry[e].copy(this.localHeadGeometry[e]);if(this.billboard)s.array[3*n]=D.x,s.array[3*n+1]=D.y,s.array[3*n+2]=D.z,k.boundingBox.expandByPoint(k.position);else{if(l.applyMatrix4(k.matrix4),this.orientToMovement){k.worldOrientation.set(0,0,-1).applyQuaternion(k.quaternion);const t=(3*p-2*a)*(m.x-y.x)+(x-p)*v+(3*p-4*a+1)*f,e=(3*p-2*a)*(m.y-y.y)+(x-p)*C+(3*p-4*a+1)*T,i=(3*p-2*a)*(m.z-y.z)+(x-p)*w+(3*p-4*a+1)*P;k.direction.set(t,e,i).normalize(),k.direction.lengthSq()>1e-4&&(k.quaternion2.setFromUnitVectors(k.worldOrientation,k.direction),l.sub(k.position).applyQuaternion(k.quaternion2).add(k.position))}t.array[3*n]=l.x,t.array[3*n+1]=l.y,t.array[3*n+2]=l.z,k.boundingBox.expandByPoint(l)}}h++}}if(i.needsUpdate=!0,r.needsUpdate=!0,o.needsUpdate=!0,this.billboard){s.needsUpdate=!0,this.mesh.frustumCulled=!1;const t=this.material.uniforms.width?.5*this.material.uniforms.width.value:.5;k.boundingBox.min.subScalar(t),k.boundingBox.max.addScalar(t)}else t.needsUpdate=!0;this.geometry.boundingBox=this.geometry.boundingBox||new e.Box3,this.geometry.boundingBox.copy(k.boundingBox),this.geometry.boundingSphere=this.geometry.boundingSphere||new e.Sphere,this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere),this.mesh.visible=!k.boundingBox.isEmpty(),this.geometry.setDrawRange(0,(n-1)*this.FaceIndicesPerNode)}currentTime(){return performance.now()/1e3}pause(){this.paused||(this.paused=!0,this.pauseAdvanceUpdateTimeDiff=this.currentTime()-this.lastAdvanceTime)}resume(){this.paused&&(this.paused=!1,this.lastAdvanceTime=this.currentTime()-this.pauseAdvanceUpdateTimeDiff)}update(){if(!this.paused){const t=this.currentTime();this.lastAdvanceTime||(this.lastAdvanceTime=t),t-this.lastAdvanceTime>this.advancePeriod?(this.advance(),this.lastAdvanceTime=t):this.updateHead()}}deactivate(){this.active&&(this.scene.remove(this.mesh),this.active=!1)}activate(){this.active||(this.scene.add(this.mesh),this.active=!0)}static getTrailShaderNodes(t){return{position:t?W:_,color:j,fraction:H}}static applyTrailShaderParameters(t){t.transparent=!0,t.alphaTest=.1,t.blending=e.CustomBlending,t.blendSrc=e.SrcAlphaFactor,t.blendDst=e.OneMinusSrcAlphaFactor,t.blendEquation=e.AddEquation,t.depthTest=!0,t.depthWrite=!1,t.side=e.DoubleSide}static createBaseMaterial(e,r,o,s=!1){let{position:n}=Trail.getTrailShaderNodes(s),h=a(N,U,H).rgba,l=h.a;if(null!=e){let i=trailUV;null!=r&&(i=i.add(f(t.elapsed.multiply(-r),0)));const s=c(e).sample(i);switch(o??"red"){case"none":break;case"red":l=l.multiply(s.r);break;case"alpha":l=l.multiply(s.a)}h=g(h.rgb.multiply(s.rgb),l)}const d=new i({position:n,opacity:l,color:h});return Trail.applyTrailShaderParameters(d),d}static get MaxHeadVertices(){return 128}static get LocalOrientationTangent(){return Trail._LocalOrientationTangent}static get LocalHeadOrigin(){return Trail._LocalHeadOrigin}static get PositionComponentCount(){return 3}static get UVComponentCount(){return 2}static get IndicesPerFace(){return 3}static get FacesPerQuad(){return 2}}Trail._LocalOrientationTangent=new e.Vector3(1,0,0),Trail._LocalHeadOrigin=new e.Vector3(0,0,0),Trail.Shader={get BaseVertexVars(){return["attribute float nodeID;","attribute float nodeVertexID;","attribute vec3 nodeCenter;","uniform float minID;","uniform float maxID;","uniform float trailLength;","uniform float maxTrailLength;","uniform float verticesPerNode;","uniform vec2 textureTileFactor;","uniform bool taper;","uniform vec4 headColor;","uniform vec4 tailColor;","varying vec4 vColor;"].join("\n")},get TexturedVertexVars(){return[this.BaseVertexVars,"varying vec2 vUV;","uniform float dragTexture;"].join("\n")},BaseFragmentVars:["varying vec4 vColor;","uniform sampler2D trailTexture;"].join("\n"),get TexturedFragmentVars(){return[this.BaseFragmentVars,"varying vec2 vUV;"].join("\n")},get VertexShaderCore(){return["float fraction = (maxID - nodeID) / (maxID - minID);","float fractionSize = taper ? fraction : 0.0;","vColor = (1.0 - fraction) * headColor + fraction * tailColor;","vec4 realPosition = vec4((1.0 - fractionSize) * position.xyz + fractionSize * nodeCenter.xyz, 1.0); "].join("\n")},get BaseVertexShader(){return[this.BaseVertexVars,"void main() { ",this.VertexShaderCore,"gl_Position = projectionMatrix * viewMatrix * realPosition;","}"].join("\n")},get BaseFragmentShader(){return[this.BaseFragmentVars,"void main() { ","gl_FragColor = vColor;","}"].join("\n")},get TexturedVertexShader(){return[this.TexturedVertexVars,"void main() { ",this.VertexShaderCore,"float s = 0.0;","float t = 0.0;","if (dragTexture == 1.0) { "," s = fraction * textureTileFactor.s; "," t = (nodeVertexID / verticesPerNode) * textureTileFactor.t;","} else { "," s = nodeID / maxTrailLength * textureTileFactor.s;"," t = (nodeVertexID / verticesPerNode) * textureTileFactor.t;","}","vUV = vec2(s, t); ","gl_Position = projectionMatrix * viewMatrix * realPosition;","}"].join("\n")},get TexturedFragmentShader(){return[this.TexturedFragmentVars,"void main() { ","vec4 textureColor = texture2D(trailTexture, vUV);","gl_FragColor = vColor * textureColor;","}"].join("\n")}};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -48,6 +48,17 @@ export type OutputCustomShader = {
48
48
  shader: string;
49
49
  shaderParams: Record<string, CustomParamValue>;
50
50
  };
51
+ export type OutputMaterialSource = 'default' | 'material' | 'shader' | 'shaderGraph';
52
+ export type OutputShaderGraph = {
53
+ shaderGraph: {
54
+ source: 'asset';
55
+ assetId: AssetId;
56
+ };
57
+ shaderGraphParams?: Record<string, CustomParamValue>;
58
+ };
59
+ export type OutputMaterialSourceSettings = {
60
+ materialSource?: OutputMaterialSource;
61
+ } & Partial<OutputShaderGraph>;
51
62
  export declare const VfxEffectInputTypes: readonly ["number", "vec3", "color"];
52
63
  export type VfxEffectInputType = (typeof VfxEffectInputTypes)[number];
53
64
  export type VfxEffectInputValue = number | [number, number, number] | string;
@@ -73,7 +84,7 @@ export type SpriteOutput = {
73
84
  flipbook?: FlipbookSettings;
74
85
  bloom: boolean;
75
86
  lockY?: boolean;
76
- } & CommonOutput & Partial<OutputCustomShader> & OutputTextureSetting;
87
+ } & CommonOutput & Partial<OutputCustomShader> & OutputTextureSetting & OutputMaterialSourceSettings;
77
88
  export type DecalOutput = {
78
89
  type: 'decal';
79
90
  colorMap: string;
@@ -84,7 +95,7 @@ export type DecalOutput = {
84
95
  blendingMode: BlendingMode;
85
96
  bloom: boolean;
86
97
  renderOrder?: number;
87
- } & CommonOutput & OutputTextureSetting;
98
+ } & CommonOutput & OutputTextureSetting & OutputMaterialSourceSettings;
88
99
  export type StretchedSpriteOutput = {
89
100
  type: 'stretchedSprite';
90
101
  texture: string;
@@ -94,13 +105,13 @@ export type StretchedSpriteOutput = {
94
105
  scale: number;
95
106
  softness: number;
96
107
  bloom: boolean;
97
- } & CommonOutput & Partial<OutputCustomShader> & OutputTextureSetting;
108
+ } & CommonOutput & Partial<OutputCustomShader> & OutputTextureSetting & OutputMaterialSourceSettings;
98
109
  export type MeshOutput = {
99
110
  type: 'mesh';
100
111
  assetId: AssetId;
101
112
  material?: AssetId;
102
113
  bloom?: boolean;
103
- } & CommonOutput & Partial<OutputCustomShader>;
114
+ } & CommonOutput & Partial<OutputCustomShader> & OutputMaterialSourceSettings;
104
115
  export type TrailOutput = {
105
116
  type: 'trail';
106
117
  length: number;
@@ -116,14 +127,14 @@ export type TrailOutput = {
116
127
  scrollSpeed?: number;
117
128
  width?: number;
118
129
  billboard?: boolean;
119
- } & CommonOutput & Partial<OutputCustomShader> & OutputTextureSetting;
130
+ } & CommonOutput & Partial<OutputCustomShader> & OutputTextureSetting & OutputMaterialSourceSettings;
120
131
  export type ShapeOutput = {
121
132
  type: 'shape';
122
133
  shape: LibraryShapeType;
123
134
  params: Record<string, CustomParamValue>;
124
135
  material: AssetId;
125
136
  bloom?: boolean;
126
- } & CommonOutput & OutputCustomShader;
137
+ } & CommonOutput & Partial<OutputCustomShader> & OutputMaterialSourceSettings;
127
138
  export type EmitterOutput = SpriteOutput | MeshOutput | ShapeOutput | StretchedSpriteOutput | TrailOutput | DecalOutput;
128
139
  export type EmitterData = {
129
140
  id: string;
@@ -1,4 +1,4 @@
1
- import e,{Behaviour as t,Body as a,Emitter as s,Rate as n}from"@hology/nebula";import*as i from"three";import{Object3D as r}from"three";import{AttributeVec3Node as o,AttributeVec4Node as l,NodeShaderMaterial as c,RgbNode as u,UniformFloatNode as p,UniformVec3Node as m,Vec3ExpressionNode as h,Vec4Node as d,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 T,smoothstep as P,standardMaterial as S,textureSampler2d as B,uniformFloat as C,uniforms as R,varying as k,varyingAttributes as j,varyingVec3 as D,varyingVec4 as z}from"three-shader-graph";import{prepareClassParameters as V,prepareShapeParameters as F}from"../../scene/materializer.js";import{SerializedParamType as L}from"../../scene/model.js";import{ShapeLibrary as O}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 G}from"../../shader-nodes/particle.js";import{sampleFlipbook as J}from"../../shader-nodes/texture-sequence.js";import{DefaultInitializer as N}from"./initializsers.js";import{DelayRate as K,OnceRate as Y}from"./rates.js";import{StretchedSprite as X}from"./stretched-sprite.js";import{ThreeBlendingMode as Z}from"./vfx-asset.js";import{VfxBehaviourLibrary as _,VfxInitializserLibrary as $}from"./vfx-defs.js";import{MultiRenderer as ee}from"./vfx-renderers.js";import{WorldCollisionBehaviour as te}from"./vfx-collision-behaviour.js";import{getSpritePosition as ae,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 re,createBoundInitializer as oe}from"./vfx-binding-runtime.js";export async function materializeVfx(t,a,s,n,o,l,c,u,p){let m=a;for(;null!=m.parent;)m=m.parent;const h=new r;h.name="particle system local",a.add(h);const d=new r;d.name="particle system world";const f=new ee(d,h,i,n),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 le(e,s,c,u,y,o,l,p);return t.setParentRecursive(y),t.emit()}))).forEach(e=>y.addEmitter(e)),y.addRenderer(f).emit({onEnd:()=>{}}),{container:d,system:y,dispose:()=>{d.removeFromParent(),h.removeFromParent(),f.dispose()}}}async function le(e,t,s,u,v,x,I,S){const D=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 n(0,1/0)}return t}(e);let V;switch(e.output.type){case"decal":V=new a(await async function(e,t){const a=!1!==e.unlit?new ne:new ie;a.color=new i.Color(e.color),a instanceof ne?a.intensity=e.intensity??1:a.emissiveIntensity=e.intensity??1;if(e.colorMap){const s=await t.getTexture(e.colorMap);a.colorMap=s}if(e.alphaMap){const s=await t.getTexture(e.alphaMap);a.alphaMap=s}const s=a.build();s.blending=Z[e.blendingMode]??i.NormalBlending,s.transparent=!0,s.side=i.BackSide,s.depthTest=!1,null!=s&&!0===e.bloom&&(s.userData.hasBloom=!0);s.defines.IS_PARTICLE="";const n=new i.BoxGeometry(1,1,1),r=new i.Mesh(n,s);null!=e.renderOrder&&(r.renderOrder=e.renderOrder);return r}(e.output,t));break;case"sprite":V=new a(await async function(e,t,a){let s=null;s=null!=e.shader?await ue(e,t,a):await async function(e,t){const a=null!=e.texture?await t.getTexture(e.texture):ce,s=B(a);let n=s.sample(j.uv);e.flipbook?.enabled&&(n=J(s,g.uv,e.flipbook.columns,e.flipbook.rows,q.time,e.flipbook.fps,e.flipbook.mode));const r=new p("rotation",0),o=new m("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(n.r);break;case"alpha":u=u.multiply(n.a)}if("number"==typeof e.softness&&e.softness>0){const t=b(c,0,1e3);u=u.multiply(P(0,.2*e.softness,t))}const h=ae(r),d=T(o.multiply(n.rgb).multiplyScalar(e.intensity??1),u);var f=new se({color:d,emissive:d.rgb.multiplyScalar(u),transparent:!0,position:h,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);s instanceof i.ShaderMaterial&&!0===e.lockY&&(s.defines.LOCK_Y_AXIS="");const n=new i.Mesh(new i.PlaneGeometry(1,1),s);return n.name="sprite",n}(e.output,t,I));break;case"stretchedSprite":V=new a(await async function(e,t){const a=null!=e.texture?await t.getTexture(e.texture):ce,s=B(a).sample(j.uv),n=z(new l("color")),r=n.rgb.multiply(s.rgb);let o=n.w;switch(e.opacityChannel??"red"){case"none":break;case"red":o=o.multiply(s.r);break;case"alpha":o=o.multiply(s.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(P(0,.2*e.softness,a))}const c=A(d,{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:T(r.multiplyScalar(e.intensity??1),o),alphaTest:.1,transparent:!0,position:c,uniforms:{color:{value:new i.Color(e.color)}}});null!=u&&!0===e.bloom&&(u.userData.hasBloom=!0);u.blending=Z[e.blendingMode]??i.NormalBlending;const p=new X(new i.PlaneGeometry(1,1),u);return p.scaleFactor=e.scale,p}(e.output,t));break;case"shape":V=new a(await async function(e,t,a){if(null==e.shape)return console.log("Shape is null"),new r;const s=O[e.shape];if(null==s)return console.error(`No shape with type ${e.shape}`),new r;const n=F(e.params??{}),l=s.geometry(n);let u=null;u=null!=e.shader?await ue(e,t,a):null!=e.material?pe(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})}();null!=u&&!0===e.bloom&&(u.userData.hasBloom=!0);return new i.Mesh(l,u)}(e.output,t,I));break;case"mesh":V=new a(await async function(e,t,a){if(null==e.assetId)return console.warn("Can't use mesh as particle without asset id"),new r;const s=await t.getMesh(e.assetId),n=await t.getAsset(e.assetId);if(null!=e.shader||null!=e.material){let n;n=null!=e.shader?await ue(e,t,a):pe(await t.getMaterial(e.material)),null!=n&&!0===e.bloom&&(n.userData.hasBloom=!0),null!=n&&!0===e.bloom&&(n.userData.hasBloom=!0),s.traverse(e=>{e instanceof i.Mesh&&(e.material=n)})}else{const e=[];if(null!=n.materialAssignments)for(const a of n.materialAssignments)s.traverse(s=>{s instanceof i.Mesh&&s.material instanceof i.Material&&s.material.color instanceof i.Color&&(s.material.name!=a.name&&null!=a.name||"#"+s.material.color.getHexString()!==a.color||e.push(t.getMaterial(a.materialId).then(e=>s.material=e)))});await Promise.all(e)}const o=[];if(s.traverse(e=>{e instanceof i.Mesh&&o.push(e)}),1===o.length){const e=o[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 s}(e.output,t,I));break;case"trail":V=new a({type:"trail",taper:e.output.taper,headGeometry:null,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 he;H.parent=v,H.setRate(D),H._space=e.output.space;const U=await Promise.all(e.initializers.filter(e=>!1!==e.enabled).filter(e=>null!=$[e.type]).map(async e=>{const t=$[e.type],a=await F(e.params??{});return oe(t,e.params??{},a,S)}));U.push(V,new N),H.addInitializers(U);const G=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,s]of Object.entries(e.params))t.parameters&&null!=t.parameters[a]&&"curve"===t.parameters[a].type&&s.type!==L.Curve&&(s.type=L.Curve);const a=await F(e.params??{},s,u);return re(t,e.params??{},a,S)}).sort((e,t)=>e instanceof te?1:0));G.push(new me);for(const e of G)e instanceof te&&(e.physics=x);H.addBehaviours(G);for(const a of e.children){const e=await le(a,t,s,u,v,x,I,S),n=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),n.release(t)},t}),i=H.eventDispatcher,r=new Map;H.bindEmitterEvent=!0,i.addEventListener("PARTICLE_DEAD",e=>{const t=r.get(e.id);if(null!=t){const e=H.childEmitters.findIndex(e=>e.id===t.id);null!=e&&(t.stopEmit(),H.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"}i.addEventListener(o,e=>{const t=n.get();t.age=0,t.totalEmitTimes=-1,t.particles.length=0,t.currentEmitTime=0,t.cID=0,t.eventDispatcher.removeAllEventListeners(),H.childEmitters.push(t),r.set(e.id,t),t.parentParticle=e,t.system=H.system,t.emit()})}return H}const ce=(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 ue(e,t,a){const s=a.get(e.shader);if(null==s)return console.error("No shader exists with name "+e.shader),new i.Material;const n=new s.type,r=await V(e.shaderParams,s.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);return Object.assign(n,r),n.build()}function pe(e){const t=k(new h("instanceColor")).rgb;let a,s=k(new o("particleData")).x;if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshBasicMaterial){let n=t.multiply(I(e.color));null!=e.map&&(n=n.multiply(B(e.map).sample(j.uv).rgb)),null!=e.alphaMap&&(s=s.multiply(B(e.alphaMap).sample(j.uv).r)),e instanceof i.MeshStandardMaterial?a=new c({color:S({color:n,emissive:I(e.emissive),emissiveIntensity:v(e.emissiveIntensity),roughness:e.roughness,metalness:e.metalness}).rgb.rgba(s),emissive:I(e.emissive).multiplyScalar(e.emissiveIntensity),transparent:e.transparent,opacity:s,alphaTest:e.alphaTest}):e instanceof i.MeshLambertMaterial?a=new c({color:E({color:n}).rgb.rgba(s),emissive:I(e.emissive).multiplyScalar(e.emissiveIntensity),transparent:e.transparent,opacity:s,alphaTest:e.alphaTest}):e instanceof i.MeshBasicMaterial&&(a=new c({color:n.rgb.rgba(s),emissive:n.rgb,transparent:e.transparent,opacity:s,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 me 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[G])}})}mutate(e,t,a){this.energize(e,t),e.target instanceof r&&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[G]&&(a.uniforms[G].value=e.velocity))}})}}class he extends s{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 he;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 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}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */