@hology/core 0.0.200 → 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.
@@ -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
  */
@@ -1,4 +1,4 @@
1
- import{CustomRenderer as e,MeshRenderer as t,PUID as r}from"@hology/nebula";import*as a from"three";import{InstancedBufferAttribute as o,Object3D as i}from"three";import{NodeShaderMaterial as n}from"three-shader-graph";import{StretchedSprite as s}from"./stretched-sprite.js";import{Trail as l}from"./trail-renderer.js";import{SpriteNodeShaderMaterial as c}from"../../shader/sprite-shader";var d;!function(e){e[e.mesh=0]="mesh",e[e.instanced=1]="instanced",e[e.sprite=2]="sprite",e[e.stretchedBillboard=3]="stretchedBillboard",e[e.trail=4]="trail"}(d||(d={}));export class MultiRenderer extends e{constructor(e,t,r,a){super(),this.worldContainer=e,this.localContainer=t,this.three=r,this.view=a,this.localRenderers=[],this.worldRenderers=[]}onSystemUpdate(){for(const e of this.worldRenderers)e?.onSystemUpdate();for(const e of this.localRenderers)e?.onSystemUpdate()}onParticleCreated(e){e.target=null,this.getRenderer(e)?.onParticleCreated(e)}onParticleUpdate(e){this.getRenderer(e)?.onParticleUpdate(e)}onParticleDead(e){this.getRenderer(e)?.onParticleDead(e),e._renderer=null}getRenderer(e){if(e._renderer)return e._renderer;const t=(null!=e?.parent?e?.parent._space:null)??"world",r="world"===t?this.worldContainer:this.localContainer,o="world"===t?this.worldRenderers:this.localRenderers;return"trail"===e.body.type?(null==o[d.trail]&&(o[d.trail]=new TrailRenderer(r,this.three)),e._renderer=o[d.trail]):e.body instanceof s?(null==o[d.stretchedBillboard]&&(o[d.stretchedBillboard]=new StretchedSpriteInstancedRenderer(r,this.three,this.view)),e._renderer=o[d.stretchedBillboard]):e.body instanceof a.Sprite||e.body instanceof a.Mesh&&"sprite"===e.body.name?(null==o[d.sprite]&&(o[d.sprite]=new CombinedRenderer(r,this.three)),e._renderer=o[d.sprite]):e.body instanceof a.Mesh&&0==e.body.children.length&&e.body.material instanceof n?(null==o[d.instanced]&&(o[d.instanced]=new InstancedRenderer(r,this.three,this.view)),e._renderer=o[d.instanced]):e.body instanceof a.Object3D?(null==o[d.mesh]&&(o[d.mesh]=new CombinedRenderer(r,this.three)),e._renderer=o[d.mesh]):void 0}dispose(){this.localRenderers.forEach(e=>{e instanceof InstancedRenderer&&e.dispose()}),this.worldRenderers.forEach(e=>{e instanceof InstancedRenderer&&e.dispose()})}}export class TrailRenderer extends t{constructor(){super(...arguments),this.trails=[]}dispose(){}onSystemUpdate(){for(const e of this.trails)e.update()}onParticleCreated(e){const t=e.body,r=new l(this.container,!1),o=new i;this.container.add(o),o.updateMatrixWorld(),o.updateWorldMatrix(!0,!0);const n=t.material?.clone()??l.createBaseMaterial(t.texture,t.scrollSpeed,t.opacityChannel,t.billboard??!1);n.uniforms.taper&&(n.uniforms.taper.value=t.taper??!1);const s=new a.Color(t.color??0).multiplyScalar(t.intensity),c=new a.Color(t.colorEnd??0).multiplyScalar(t.intensityEnd??t.intensity??1);n.uniforms.headColor&&n.uniforms.tailColor&&(n.uniforms.headColor.value=new a.Vector4(s.r,s.g,s.b,t.opacityStart??1),n.uniforms.tailColor.value=new a.Vector4(c.r,c.g,c.b,t.opacityEnd??1)),n.uniforms.color&&null==n.uniforms.headColor&&(n.uniforms.color.value=s),n.uniforms.opacity&&null==n.uniforms.headColor&&(n.uniforms.opacity.value=t.opacityStart??1),t.bloom&&(n.userData.hasBloom=!0),r.initialize(n,Math.round(t.length??10),!1,t.width,null,o,t.billboard??!1);const d=e.rotation;o.rotation.set(d.x,d.y,d.z);e.scale;r.activate(),this.trails.push(r),e.target=o}onParticleUpdate(e){const t=e.target;t.position.copy(e.position);const r=e.body;let a=w;e.old&&e.old.position?a.set(e.position.x-e.old.position.x,e.position.y-e.old.position.y,e.position.z-e.old.position.z).normalize():a.copy(e.velocity).normalize();const o=x;o.setFromUnitVectors(a,y),t.rotation.set(0,0,0),t.rotation.set(e.rotation.x,e.rotation.y,e.rotation.z),t.applyQuaternion(o);const i=this.trails.findIndex(e=>e.targetObject.id===t.id);if(-1!=i){const t=this.trails[i];if(e.useAlpha&&t.material.uniforms.headColor&&t.material.uniforms.tailColor){t.material.uniforms.headColor.value.setW(r.opacityStart*e.alpha);t.material.uniforms.tailColor.value.setW(r.opacityEnd*e.alpha)}}}onParticleDead(e){const t=e.target,r=this.trails.findIndex(e=>e.targetObject.id===t.id);if(-1!=r){const e=this.trails[r];e.removeFromParent(),e.mesh.removeFromParent(),e.targetObject.removeFromParent(),t.removeFromParent(),this.trails.splice(r,1)}}}export class CombinedRenderer extends t{dispose(){}scale(e){const t=e.transform.initialScale;e.target instanceof a.Sprite?null!=t?e.target.scale.set(t.x*e.scale*e.radius,t.y*e.scale*e.radius,1):e.target.scale.set(e.scale*e.radius,e.scale*e.radius,1):null!=t?e.target.scale.set(t.x*e.scale,t.y*e.scale,t.z*e.scale):super.scale(e)}rotate(e){e.target.material.rotation=e.rotation.z}onParticleCreated(e){e.target||(e.target=this._targetPool.get(e.body),(e.useAlpha||e.useColor)&&(e.target instanceof a.Mesh||e.target instanceof a.Sprite&&e.target.material instanceof a.Material)&&(e.target.material.__puid=r.id(e.body.material),e.target.material=this._materialPool.get(e.target.material))),e.target&&e.target instanceof i&&(e.target.position.set(e.position.x,e.position.y,e.position.z),this.container.add(e.target))}onParticleUpdate(e){const{target:t,useAlpha:r,useColor:o,rotation:n}=e;if(t){if(t.position.copy(e.position),this.isThreeSprite(e)||(t instanceof a.Mesh&&t.material instanceof c?e.target.material.rotation=e.rotation.z:t.rotation.set(n.x,n.y,n.z)),this.scale(e),e.transform&&e.transform.orientAlongVelocity&&t instanceof i){const r=m.set(e.velocity.x,e.velocity.y,e.velocity.z).normalize(),a=t.getWorldDirection(u);a.applyAxisAngle(p,Math.PI/-2),h.setFromUnitVectors(a,r),t.quaternion.copy(h)}t.material instanceof a.Material&&(r&&(t.material instanceof c&&null!=t.material.uniforms.opacity&&(t.material.uniforms.opacity.value=e.alpha,t.material.uniformsNeedUpdate=!0),t.material.opacity=e.alpha,t.material.transparent=!0),o&&(null!=t.material.color?t.material.color.copy(e.color):t.material instanceof a.ShaderMaterial&&null!=t.material.uniforms.color&&(t.material.uniforms.color.value=e.color,t.material.uniformsNeedUpdate=!0)))}}onParticleDead(e){e.target&&(e.target.material&&(e.useAlpha||e.useColor)&&this._materialPool.expire(e.target.material),this._targetPool.expire(e.target),this.container.remove(e.target),e.target=null)}}export class StretchedSpriteInstancedRenderer extends t{constructor(e,t,r){super(e,t),this.view=r,this.meshes=[]}dispose(){this.meshes.forEach(e=>e.mesh.geometry.dispose())}onSystemUpdate(){for(const e of this.meshes){const t=e.mesh.geometry.getAttribute("offset"),r=e.mesh.geometry.getAttribute("size"),o=e.mesh.geometry.getAttribute("velocity"),i=e.mesh.geometry.getAttribute("rotation"),n=e.mesh.geometry.getAttribute("color");let s=0;for(const l of e.particles){if(null==l||l.dead)continue;if(l.useColor||l.color instanceof a.Color){const e=C.copy(l.color).getRGB(M);n.setXYZW(s,e.r,e.g,e.b,1),n.needsUpdate=!0}l.useAlpha&&(n.setW(s,l.alpha),n.needsUpdate=!0),"number"==typeof l.rotation?i.setX(s,l.rotation):i.setX(s,l.rotation.x);const e=l.position;if(t.setXYZ(s,e.x,e.y,e.z),"number"!=typeof l.scale)throw new Error("Particle scale is not a number");r.setXYZ(s,l.scale,l.scale,l.scale);let c=l.body.scaleFactor;0===c&&(c=.001);const d=1,m=l.velocity;o.setXYZW(s,m.x*c,m.y*c,m.z*c,d),s++}s>0&&(t.clearUpdateRanges(),t.addUpdateRange(0,3*s),t.needsUpdate=!0,r.clearUpdateRanges(),r.addUpdateRange(0,3*s),r.needsUpdate=!0,n.clearUpdateRanges(),n.addUpdateRange(0,4*s),n.needsUpdate=!0,o.clearUpdateRanges(),o.addUpdateRange(0,4*s),o.needsUpdate=!0,i.clearUpdateRanges(),i.addUpdateRange(0,s),i.needsUpdate=!0)}}calcMaxCount(e){if(null==e)return 1;const t=e.parent.rate,r=t.timePan.a;if(!Number.isFinite(r)||r<=0)return t.numPan.b*this.calcMaxCount(e.parent.parentParticle);return Math.min(t.numPan.b*Math.ceil(e.life/Math.min(Math.max(t.timePan.a,.01),1)),1e5)*this.calcMaxCount(e.parent.parentParticle)}onParticleCreated(e){if(e.body instanceof s&&null==e.target){const t=e.body;let r=this.meshes.find(e=>e.mesh.material.uuid===t.material.uuid);if(null==r){const i=this.calcMaxCount(e),n=new a.InstancedBufferGeometry;n.setIndex(t.geometry.getIndex()),n.setAttribute("position",t.geometry.getAttribute("position")),t.geometry.hasAttribute("normal")&&n.setAttribute("normal",t.geometry.getAttribute("normal")),n.setAttribute("uv",t.geometry.getAttribute("uv"));const s=new o(new Float32Array(3*i),3);s.setUsage(a.DynamicDrawUsage),n.setAttribute("offset",s);const l=new o(new Float32Array(4*i),4);if(l.setUsage(a.DynamicDrawUsage),n.setAttribute("color",l),t.material instanceof c){const e=new a.Color(t.material.color);for(let t=0;t<l.count;t++)l.setXYZW(t,e.r,e.g,e.b,1)}const d=new o(new Float32Array(3*i),3);d.setUsage(a.DynamicDrawUsage),n.setAttribute("size",d);const m=new o(new Float32Array(4*i),4);m.setUsage(a.DynamicDrawUsage),n.setAttribute("velocity",m);const u=new o(new Float32Array(4*i),1);u.setUsage(a.DynamicDrawUsage),n.setAttribute("rotation",u),r={mesh:new a.Mesh(n,t.material),indices:new Float32Array(i),particles:[]},this.meshes.push(r),this.container.add(r.mesh)}let i=r.indices.findIndex(e=>0===e);i<0&&(i=function(e){let t=e[0],r=0;for(let a=1;a<e.length;a++)e[a]<t&&(t=e[a],r=a);return r}(r.indices)),r.indices[i]=performance.now(),e.target=i,r.particles[i]=e}}onParticleUpdate(e){}onParticleDead(e){const t=e.body;let r=this.meshes.find(e=>e.mesh.material.uuid===t.material.uuid);if(r){const t=r.mesh.geometry.getAttribute("size");t.setXYZ(e.target,0,0,0),t.needsUpdate=!0,r.particles[e.target]=null,r.indices[e.target]=0}e.target=null}}const m=new a.Vector3,u=new a.Vector3,h=new a.Quaternion,p=new a.Vector3(1,0,0);export class InstancedRenderer extends t{constructor(e,t,r){super(e,t),this.view=r,this.meshes=[]}dispose(){this.meshes.forEach(e=>e.mesh.dispose())}onSystemUpdate(){for(const e of this.meshes);}calcMaxCount(e){if(null==e)return 1;const t=e.parent.rate,r=t.timePan.a;if(!Number.isFinite(r)||r<=0)return t.numPan.b*this.calcMaxCount(e.parent.parentParticle);return Math.min(t.numPan.b*Math.ceil(e.life/Math.min(Math.max(t.timePan.a,.01),1)),1e5)*this.calcMaxCount(e.parent.parentParticle)}onParticleCreated(e){if(e.body instanceof a.Sprite)return;const t=e.body;let r=this.meshes.find(e=>e.mesh.geometry.uuid===t.geometry.uuid&&e.mesh.material.uuid===t.material.uuid);if(null==r){const o=this.calcMaxCount(e);r={mesh:new a.InstancedMesh(t.geometry,t.material,o),indices:new Array(o).fill(null),particles:[]},r.mesh.renderOrder=t.renderOrder,r.mesh.setColorAt(0,C.setScalar(1)),r.mesh.instanceColor.needsUpdate=!0,r.mesh.material.defines.USE_INSTANCING="";const i=new Float32Array(3*o);b.makeScale(0,0,0);for(let e=0;e<o;e++)i[3*e+0]=1,i[3*e+1]=1,r.mesh.setMatrixAt(e,b);r.mesh.instanceMatrix.needsUpdate=!0,r.mesh.geometry.setAttribute("particleData",new a.InstancedBufferAttribute(i,3)),this.meshes.push(r),this.container.add(r.mesh)}let o=r.indices.findIndex(e=>null==e);if(o<0&&(o=r.indices.indexOf(Math.min(...r.indices))),r.indices[o]=performance.now(),e.target=o,r.particles[o]=e,"number"==typeof e.target){e.transform.initialScale;const t=e.body;let r=this.meshes.find(e=>e.mesh.geometry.uuid===t.geometry.uuid&&e.mesh.material.uuid===t.material.uuid);g(e,r.mesh),e.useAlpha&&(r.mesh.material.transparent=!0)}}onParticleUpdate(e){const{target:t,useAlpha:r,useColor:a,rotation:o}=e;if(null==t)return;const i=e.body,n=this.meshes.find(e=>e.mesh.geometry.uuid===i.geometry.uuid&&e.mesh.material.uuid===i.material.uuid);if(null==n)return;n.mesh.frustumCulled=!1,g(e,n.mesh),a&&(n.mesh.setColorAt(e.target,C.copy(e.color)),n.mesh.instanceColor.needsUpdate=!0);const s=n.mesh.geometry.getAttribute("particleData");r&&s.setX(e.target,e.alpha),s.setY(e.target,e.energy),s.needsUpdate=!0}onParticleDead(e){if(null!=e.target){const t=e.body,r=this.meshes.find(e=>e.mesh.geometry.uuid===t.geometry.uuid&&e.mesh.material.uuid===t.material.uuid);if(null==r)return;r.indices[e.target]=null,e.scale=0,g(e,r.mesh),r.mesh.instanceMatrix.needsUpdate=!0,e.target=null}}}const f=new i;function g(e,t){if(w.set(e.position.x,e.position.y,e.position.z),e.transform&&e.transform.orientAlongVelocity){const r=m.set(e.position.x-e.old.position.x,e.position.y-e.old.position.y,e.position.z-e.old.position.z).normalize();t.getMatrixAt(e.target,f.matrix);const a=f.getWorldDirection(A);a.applyAxisAngle(p,Math.PI/-2),x.setFromUnitVectors(a,r)}else U.set(e.rotation.x,e.rotation.y,e.rotation.z),x.setFromEuler(U);const r=e.transform.initialScale;null!=r?A.set(r.x*e.scale,r.y*e.scale,r.z*e.scale):A.set(e.scale,e.scale,e.scale),b.compose(w,x,A),t.setMatrixAt(e.target,b),t.instanceMatrix.needsUpdate=!0}const y=new a.Vector3(0,0,-1),b=new a.Matrix4,x=new a.Quaternion,w=new a.Vector3,A=new a.Vector3,U=new a.Euler,C=new a.Color(0),M={r:0,g:0,b:0};function P(e,t){const r=e.mesh,o=r.count,i=[],n=r.geometry.getAttribute("particleData"),s=new a.Vector3;for(let l=0;l<o;l++){const o=new a.Matrix4,c=new a.Color;r.getMatrixAt(l,o),r.getColorAt(l,c);const d=n.getX(l);s.setFromMatrixPosition(o);const m=s.distanceTo(t.position);i.push({index:l,distance:m,matrix:o,particle:e.particles[l],color:c,pdx:d})}i.sort((e,t)=>t.distance-e.distance);for(let e=0;e<o;e++){const t=i[e].matrix;null==i[e].particle&&t.makeScale(0,0,0),r.setMatrixAt(e,t),r.setColorAt(e,i[e].color),n.setX(e,i[e].pdx)}r.instanceMatrix.needsUpdate=!0}export{P as sortInstancedMeshByDistance};/*
1
+ import{CustomRenderer as e,MeshRenderer as t,PUID as r}from"@hology/nebula";import*as a from"three";import{InstancedBufferAttribute as o,Object3D as i}from"three";import{NodeShaderMaterial as n}from"three-shader-graph";import{StretchedSprite as s}from"./stretched-sprite.js";import{Trail as l}from"./trail-renderer.js";import{SpriteNodeShaderMaterial as c}from"../../shader/sprite-shader";import{particleEnergyUniformName as d}from"../../shader-nodes/particle";var m;!function(e){e[e.mesh=0]="mesh",e[e.instanced=1]="instanced",e[e.sprite=2]="sprite",e[e.stretchedBillboard=3]="stretchedBillboard",e[e.trail=4]="trail"}(m||(m={}));export class MultiRenderer extends e{constructor(e,t,r,a){super(),this.worldContainer=e,this.localContainer=t,this.three=r,this.view=a,this.localRenderers=[],this.worldRenderers=[]}onSystemUpdate(){for(const e of this.worldRenderers)e?.onSystemUpdate();for(const e of this.localRenderers)e?.onSystemUpdate()}onParticleCreated(e){e.target=null,this.getRenderer(e)?.onParticleCreated(e)}onParticleUpdate(e){this.getRenderer(e)?.onParticleUpdate(e)}onParticleDead(e){this.getRenderer(e)?.onParticleDead(e),e._renderer=null}getRenderer(e){if(e._renderer)return e._renderer;const t=(null!=e?.parent?e?.parent._space:null)??"world",r="world"===t?this.worldContainer:this.localContainer,o="world"===t?this.worldRenderers:this.localRenderers;return"trail"===e.body.type?(null==o[m.trail]&&(o[m.trail]=new TrailRenderer(r,this.three)),e._renderer=o[m.trail]):e.body instanceof s?(null==o[m.stretchedBillboard]&&(o[m.stretchedBillboard]=new StretchedSpriteInstancedRenderer(r,this.three,this.view)),e._renderer=o[m.stretchedBillboard]):e.body instanceof a.Sprite||e.body instanceof a.Mesh&&"sprite"===e.body.name?(null==o[m.sprite]&&(o[m.sprite]=new CombinedRenderer(r,this.three)),e._renderer=o[m.sprite]):e.body instanceof a.Mesh&&0==e.body.children.length&&e.body.material instanceof n?(null==o[m.instanced]&&(o[m.instanced]=new InstancedRenderer(r,this.three,this.view)),e._renderer=o[m.instanced]):e.body instanceof a.Object3D?(null==o[m.mesh]&&(o[m.mesh]=new CombinedRenderer(r,this.three)),e._renderer=o[m.mesh]):void 0}dispose(){this.localRenderers.forEach(e=>{e instanceof InstancedRenderer&&e.dispose()}),this.worldRenderers.forEach(e=>{e instanceof InstancedRenderer&&e.dispose()})}}export class TrailRenderer extends t{constructor(){super(...arguments),this.trails=[]}dispose(){}onSystemUpdate(){for(const e of this.trails)e.update()}onParticleCreated(e){const t=e.body,r=new l(this.container,!1),o=new i;this.container.add(o),o.updateMatrixWorld(),o.updateWorldMatrix(!0,!0);const n=t.material?.clone()??l.createBaseMaterial(t.texture,t.scrollSpeed,t.opacityChannel,t.billboard??!1);n.uniforms.taper&&(n.uniforms.taper.value=t.taper??!1);const s=new a.Color(t.color??0).multiplyScalar(t.intensity),c=new a.Color(t.colorEnd??0).multiplyScalar(t.intensityEnd??t.intensity??1);n.uniforms.headColor&&n.uniforms.tailColor&&(n.uniforms.headColor.value=new a.Vector4(s.r,s.g,s.b,t.opacityStart??1),n.uniforms.tailColor.value=new a.Vector4(c.r,c.g,c.b,t.opacityEnd??1)),n.uniforms.color&&null==n.uniforms.headColor&&(n.uniforms.color.value=s),n.uniforms.opacity&&null==n.uniforms.headColor&&(n.uniforms.opacity.value=t.opacityStart??1),t.bloom&&(n.userData.hasBloom=!0),r.initialize(n,Math.round(t.length??10),!1,t.width,null,o,t.billboard??!1);const d=e.rotation;o.rotation.set(d.x,d.y,d.z);e.scale;r.activate(),this.trails.push(r),e.target=o}onParticleUpdate(e){const t=e.target;t.position.copy(e.position);const r=e.body;let a=A;e.old&&e.old.position?a.set(e.position.x-e.old.position.x,e.position.y-e.old.position.y,e.position.z-e.old.position.z).normalize():a.copy(e.velocity).normalize();const o=w;o.setFromUnitVectors(a,b),t.rotation.set(0,0,0),t.rotation.set(e.rotation.x,e.rotation.y,e.rotation.z),t.applyQuaternion(o);const i=this.trails.findIndex(e=>e.targetObject.id===t.id);if(-1!=i){const t=this.trails[i];if(e.useAlpha){if(t.material.uniforms.headColor&&t.material.uniforms.tailColor){t.material.uniforms.headColor.value.setW(r.opacityStart*e.alpha);t.material.uniforms.tailColor.value.setW(r.opacityEnd*e.alpha)}null!=t.material.uniforms.opacity&&(t.material.uniforms.opacity.value=e.alpha)}e.useColor&&null!=t.material.uniforms.color&&t.material.uniforms.color.value.copy(e.color),null!=t.material.uniforms[d]&&(t.material.uniforms[d].value=e.energy)}}onParticleDead(e){const t=e.target,r=this.trails.findIndex(e=>e.targetObject.id===t.id);if(-1!=r){const e=this.trails[r];e.removeFromParent(),e.mesh.removeFromParent(),e.targetObject.removeFromParent(),t.removeFromParent(),this.trails.splice(r,1)}}}export class CombinedRenderer extends t{dispose(){}scale(e){const t=e.transform.initialScale;e.target instanceof a.Sprite?null!=t?e.target.scale.set(t.x*e.scale*e.radius,t.y*e.scale*e.radius,1):e.target.scale.set(e.scale*e.radius,e.scale*e.radius,1):null!=t?e.target.scale.set(t.x*e.scale,t.y*e.scale,t.z*e.scale):super.scale(e)}rotate(e){e.target.material.rotation=e.rotation.z}onParticleCreated(e){e.target||(e.target=this._targetPool.get(e.body),(e.useAlpha||e.useColor)&&(e.target instanceof a.Mesh||e.target instanceof a.Sprite&&e.target.material instanceof a.Material)&&(e.target.material.__puid=r.id(e.body.material),e.target.material=this._materialPool.get(e.target.material))),e.target&&e.target instanceof i&&(e.target.position.set(e.position.x,e.position.y,e.position.z),this.container.add(e.target))}onParticleUpdate(e){const{target:t,useAlpha:r,useColor:o,rotation:n}=e;if(t){if(t.position.copy(e.position),this.isThreeSprite(e)||(t instanceof a.Mesh&&t.material instanceof c?e.target.material.rotation=e.rotation.z:t.rotation.set(n.x,n.y,n.z)),this.scale(e),e.transform&&e.transform.orientAlongVelocity&&t instanceof i){const r=u.set(e.velocity.x,e.velocity.y,e.velocity.z).normalize(),a=t.getWorldDirection(p);a.applyAxisAngle(f,Math.PI/-2),h.setFromUnitVectors(a,r),t.quaternion.copy(h)}t.material instanceof a.Material&&(r&&(t.material instanceof c&&null!=t.material.uniforms.opacity&&(t.material.uniforms.opacity.value=e.alpha,t.material.uniformsNeedUpdate=!0),t.material.opacity=e.alpha,t.material.transparent=!0),o&&(null!=t.material.color?t.material.color.copy(e.color):t.material instanceof a.ShaderMaterial&&null!=t.material.uniforms.color&&(t.material.uniforms.color.value=e.color,t.material.uniformsNeedUpdate=!0)))}}onParticleDead(e){e.target&&(e.target.material&&(e.useAlpha||e.useColor)&&this._materialPool.expire(e.target.material),this._targetPool.expire(e.target),this.container.remove(e.target),e.target=null)}}export class StretchedSpriteInstancedRenderer extends t{constructor(e,t,r){super(e,t),this.view=r,this.meshes=[]}dispose(){this.meshes.forEach(e=>e.mesh.geometry.dispose())}onSystemUpdate(){for(const e of this.meshes){const t=e.mesh.geometry.getAttribute("offset"),r=e.mesh.geometry.getAttribute("size"),o=e.mesh.geometry.getAttribute("velocity"),i=e.mesh.geometry.getAttribute("rotation"),n=e.mesh.geometry.getAttribute("color");let s=0;for(const l of e.particles){if(null==l||l.dead)continue;if(l.useColor||l.color instanceof a.Color){const e=M.copy(l.color).getRGB(P);n.setXYZW(s,e.r,e.g,e.b,1),n.needsUpdate=!0}l.useAlpha&&(n.setW(s,l.alpha),n.needsUpdate=!0),"number"==typeof l.rotation?i.setX(s,l.rotation):i.setX(s,l.rotation.x);const e=l.position;if(t.setXYZ(s,e.x,e.y,e.z),"number"!=typeof l.scale)throw new Error("Particle scale is not a number");r.setXYZ(s,l.scale,l.scale,l.scale);let c=l.body.scaleFactor;0===c&&(c=.001);const d=1,m=l.velocity;o.setXYZW(s,m.x*c,m.y*c,m.z*c,d),s++}s>0&&(t.clearUpdateRanges(),t.addUpdateRange(0,3*s),t.needsUpdate=!0,r.clearUpdateRanges(),r.addUpdateRange(0,3*s),r.needsUpdate=!0,n.clearUpdateRanges(),n.addUpdateRange(0,4*s),n.needsUpdate=!0,o.clearUpdateRanges(),o.addUpdateRange(0,4*s),o.needsUpdate=!0,i.clearUpdateRanges(),i.addUpdateRange(0,s),i.needsUpdate=!0)}}calcMaxCount(e){if(null==e)return 1;const t=e.parent.rate,r=t.timePan.a;if(!Number.isFinite(r)||r<=0)return t.numPan.b*this.calcMaxCount(e.parent.parentParticle);return Math.min(t.numPan.b*Math.ceil(e.life/Math.min(Math.max(t.timePan.a,.01),1)),1e5)*this.calcMaxCount(e.parent.parentParticle)}onParticleCreated(e){if(e.body instanceof s&&null==e.target){const t=e.body;let r=this.meshes.find(e=>e.mesh.material.uuid===t.material.uuid);if(null==r){const i=this.calcMaxCount(e),n=new a.InstancedBufferGeometry;n.setIndex(t.geometry.getIndex()),n.setAttribute("position",t.geometry.getAttribute("position")),t.geometry.hasAttribute("normal")&&n.setAttribute("normal",t.geometry.getAttribute("normal")),n.setAttribute("uv",t.geometry.getAttribute("uv"));const s=new o(new Float32Array(3*i),3);s.setUsage(a.DynamicDrawUsage),n.setAttribute("offset",s);const l=new o(new Float32Array(4*i),4);if(l.setUsage(a.DynamicDrawUsage),n.setAttribute("color",l),t.material instanceof c){const e=new a.Color(t.material.color);for(let t=0;t<l.count;t++)l.setXYZW(t,e.r,e.g,e.b,1)}const d=new o(new Float32Array(3*i),3);d.setUsage(a.DynamicDrawUsage),n.setAttribute("size",d);const m=new o(new Float32Array(4*i),4);m.setUsage(a.DynamicDrawUsage),n.setAttribute("velocity",m);const u=new o(new Float32Array(4*i),1);u.setUsage(a.DynamicDrawUsage),n.setAttribute("rotation",u),r={mesh:new a.Mesh(n,t.material),indices:new Float32Array(i),particles:[]},this.meshes.push(r),this.container.add(r.mesh)}let i=r.indices.findIndex(e=>0===e);i<0&&(i=function(e){let t=e[0],r=0;for(let a=1;a<e.length;a++)e[a]<t&&(t=e[a],r=a);return r}(r.indices)),r.indices[i]=performance.now(),e.target=i,r.particles[i]=e}}onParticleUpdate(e){}onParticleDead(e){const t=e.body;let r=this.meshes.find(e=>e.mesh.material.uuid===t.material.uuid);if(r){const t=r.mesh.geometry.getAttribute("size");t.setXYZ(e.target,0,0,0),t.needsUpdate=!0,r.particles[e.target]=null,r.indices[e.target]=0}e.target=null}}const u=new a.Vector3,p=new a.Vector3,h=new a.Quaternion,f=new a.Vector3(1,0,0);export class InstancedRenderer extends t{constructor(e,t,r){super(e,t),this.view=r,this.meshes=[]}dispose(){this.meshes.forEach(e=>e.mesh.dispose())}onSystemUpdate(){for(const e of this.meshes);}calcMaxCount(e){if(null==e)return 1;const t=e.parent.rate,r=t.timePan.a;if(!Number.isFinite(r)||r<=0)return t.numPan.b*this.calcMaxCount(e.parent.parentParticle);return Math.min(t.numPan.b*Math.ceil(e.life/Math.min(Math.max(t.timePan.a,.01),1)),1e5)*this.calcMaxCount(e.parent.parentParticle)}onParticleCreated(e){if(e.body instanceof a.Sprite)return;const t=e.body;let r=this.meshes.find(e=>e.mesh.geometry.uuid===t.geometry.uuid&&e.mesh.material.uuid===t.material.uuid);if(null==r){const o=this.calcMaxCount(e);r={mesh:new a.InstancedMesh(t.geometry,t.material,o),indices:new Array(o).fill(null),particles:[]},r.mesh.renderOrder=t.renderOrder,r.mesh.setColorAt(0,M.setScalar(1)),r.mesh.instanceColor.needsUpdate=!0,r.mesh.material.defines.USE_INSTANCING="";const i=new Float32Array(3*o);x.makeScale(0,0,0);for(let e=0;e<o;e++)i[3*e+0]=1,i[3*e+1]=1,r.mesh.setMatrixAt(e,x);r.mesh.instanceMatrix.needsUpdate=!0,r.mesh.geometry.setAttribute("particleData",new a.InstancedBufferAttribute(i,3)),this.meshes.push(r),this.container.add(r.mesh)}let o=r.indices.findIndex(e=>null==e);if(o<0&&(o=r.indices.indexOf(Math.min(...r.indices))),r.indices[o]=performance.now(),e.target=o,r.particles[o]=e,"number"==typeof e.target){e.transform.initialScale;const t=e.body;let r=this.meshes.find(e=>e.mesh.geometry.uuid===t.geometry.uuid&&e.mesh.material.uuid===t.material.uuid);y(e,r.mesh),e.useAlpha&&(r.mesh.material.transparent=!0)}}onParticleUpdate(e){const{target:t,useAlpha:r,useColor:a,rotation:o}=e;if(null==t)return;const i=e.body,n=this.meshes.find(e=>e.mesh.geometry.uuid===i.geometry.uuid&&e.mesh.material.uuid===i.material.uuid);if(null==n)return;n.mesh.frustumCulled=!1,y(e,n.mesh),a&&(n.mesh.setColorAt(e.target,M.copy(e.color)),n.mesh.instanceColor.needsUpdate=!0);const s=n.mesh.geometry.getAttribute("particleData");r&&s.setX(e.target,e.alpha),s.setY(e.target,e.energy),s.needsUpdate=!0}onParticleDead(e){if(null!=e.target){const t=e.body,r=this.meshes.find(e=>e.mesh.geometry.uuid===t.geometry.uuid&&e.mesh.material.uuid===t.material.uuid);if(null==r)return;r.indices[e.target]=null,e.scale=0,y(e,r.mesh),r.mesh.instanceMatrix.needsUpdate=!0,e.target=null}}}const g=new i;function y(e,t){if(A.set(e.position.x,e.position.y,e.position.z),e.transform&&e.transform.orientAlongVelocity){const r=u.set(e.position.x-e.old.position.x,e.position.y-e.old.position.y,e.position.z-e.old.position.z).normalize();t.getMatrixAt(e.target,g.matrix);const a=g.getWorldDirection(U);a.applyAxisAngle(f,Math.PI/-2),w.setFromUnitVectors(a,r)}else C.set(e.rotation.x,e.rotation.y,e.rotation.z),w.setFromEuler(C);const r=e.transform.initialScale;null!=r?U.set(r.x*e.scale,r.y*e.scale,r.z*e.scale):U.set(e.scale,e.scale,e.scale),x.compose(A,w,U),t.setMatrixAt(e.target,x),t.instanceMatrix.needsUpdate=!0}const b=new a.Vector3(0,0,-1),x=new a.Matrix4,w=new a.Quaternion,A=new a.Vector3,U=new a.Vector3,C=new a.Euler,M=new a.Color(0),P={r:0,g:0,b:0};function R(e,t){const r=e.mesh,o=r.count,i=[],n=r.geometry.getAttribute("particleData"),s=new a.Vector3;for(let l=0;l<o;l++){const o=new a.Matrix4,c=new a.Color;r.getMatrixAt(l,o),r.getColorAt(l,c);const d=n.getX(l);s.setFromMatrixPosition(o);const m=s.distanceTo(t.position);i.push({index:l,distance:m,matrix:o,particle:e.particles[l],color:c,pdx:d})}i.sort((e,t)=>t.distance-e.distance);for(let e=0;e<o;e++){const t=i[e].matrix;null==i[e].particle&&t.makeScale(0,0,0),r.setMatrixAt(e,t),r.setColorAt(e,i[e].color),n.setX(e,i[e].pdx)}r.instanceMatrix.needsUpdate=!0}export{R as sortInstancedMeshByDistance};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */