@hology/core 0.0.259 → 0.0.260
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/effects/sequence/sequence-actor.d.ts +3 -1
- package/dist/effects/sequence/sequence-actor.js +1 -1
- package/dist/effects/sequence/sequence-player.d.ts +11 -0
- package/dist/effects/sequence/sequence-player.js +1 -1
- package/dist/effects/vfx/gpu-sprite-compiler.js +1 -1
- package/dist/effects/vfx/gpu-sprite-runtime.d.ts +3 -1
- package/dist/effects/vfx/gpu-sprite-runtime.js +1 -1
- package/dist/effects/vfx/trail-renderer.d.ts +2 -0
- package/dist/effects/vfx/trail-renderer.js +1 -1
- package/dist/effects/vfx/vfx-actor.d.ts +11 -0
- package/dist/effects/vfx/vfx-actor.js +1 -1
- package/dist/effects/vfx/vfx-asset.d.ts +4 -0
- package/dist/effects/vfx/vfx-collision-behaviour.d.ts +4 -1
- package/dist/effects/vfx/vfx-collision-behaviour.js +1 -1
- package/dist/effects/vfx/vfx-defs.d.ts +1 -0
- package/dist/effects/vfx/vfx-defs.js +1 -1
- package/dist/effects/vfx/vfx-materializer.d.ts +1 -1
- package/dist/effects/vfx/vfx-materializer.js +1 -1
- package/dist/effects/vfx/vfx-renderers.d.ts +2 -0
- package/dist/effects/vfx/vfx-renderers.js +1 -1
- package/dist/test/gpu-sprite-compiler.test.js +1 -1
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BaseActor } from '../../gameplay/actors/actor.js';
|
|
2
2
|
import { SequenceData, SequenceRole } from './sequence-data.js';
|
|
3
|
-
import { SequencePlaybackState } from './sequence-player.js';
|
|
3
|
+
import { SequencePlaybackState, type SequenceVfxCollisionEvent } from './sequence-player.js';
|
|
4
4
|
import { Asset } from '../../scene/model.js';
|
|
5
5
|
import { Subject } from 'rxjs';
|
|
6
6
|
import { Object3D } from 'three';
|
|
@@ -90,6 +90,8 @@ export declare class SequenceActor extends BaseActor implements SequenceAction {
|
|
|
90
90
|
set inEditor(value: boolean);
|
|
91
91
|
readonly onComplete: Subject<void>;
|
|
92
92
|
readonly onLoop: Subject<number>;
|
|
93
|
+
/** Synchronous impacts from sequence VFX clips. Copy payload values to retain them. */
|
|
94
|
+
onVfxCollision?: (event: SequenceVfxCollisionEvent) => void;
|
|
93
95
|
private player;
|
|
94
96
|
private viewController;
|
|
95
97
|
private assetLoader;
|
|
@@ -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 i}from"../../gameplay/services/render.js";import{AssetLoader as n}from"../../gameplay/services/asset-loader.js";import{World as o}from"../../gameplay/services/world.js";import{ActorFactory as l}from"../../gameplay/actors/factory.js";import{VfxService as p}from"../../effects/vfx/vfx-service.js";import{EventGraphCallable as c}from"../../gameplay/event-graph/decorators.js";import{EVENT_GRAPH_NUMBER_TYPE as h,EVENT_GRAPH_VOID_TYPE as d}from"../../gameplay/event-graph/types.js";import{SEQUENCE_ACTOR_TYPE_ID as m}from"../../gameplay/event-graph/asset-actor-types.js";import{Parameter as y}from"../../shader/parameter.js";import{createSequenceData as u}from"./sequence-data.js";import{SequencePlayer as g,SequencePlaybackState as b}from"./sequence-player.js";import{Subject as f,takeUntil as C}from"rxjs";let v=class extends r{constructor(){super(...arguments),this.sequenceData=u(),this.sequenceAssetId=null,this._cameraControlEnabled=!1,this._cameraControlTrackId=null,this.onComplete=new f,this.onLoop=new f,this.player=new g,this.viewController=a(i),this.assetLoader=a(n),this.world=a(o),this.actorFactory=a(l),this.vfxService=a(p),this.sourceAsset=null,this.missingSceneTargets=new Set}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===b.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(C(this.disposed)).subscribe(e=>this.player.update(e)),this.player.onComplete.pipe(C(this.disposed)).subscribe(()=>this.onComplete.next()),this.player.onLoop.pipe(C(this.disposed)).subscribe(e=>this.onLoop.next(e)),this.sequenceAssetId?await this.loadFromAssetId(this.sequenceAssetId):this.sequenceData&&this.player.load(this.sequenceData),this.refreshSceneBindings()}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),this.missingSceneTargets.clear(),this.refreshSceneBindings())}async loadFromAssetId(e){const t=await this.assetLoader.getAsset(e);t&&await this.loadFromAsset(t)}setSequenceData(e){this.sequenceData=e,this.player.load(e),this.missingSceneTargets.clear(),this.refreshSceneBindings()}applySceneParameters(e,t){const s=new Set(["sequenceData","cameraControlEnabled"]);return![...t].some(e=>!s.has(e))&&(t.has("sequenceData")&&e.sequenceData&&this.setSequenceData(e.sequenceData),t.has("cameraControlEnabled")&&(this.cameraControlEnabled=Boolean(e.cameraControlEnabled)),!0)}bindRole(e,t){this.player.bindRole(e,t)}async prepare(){this.refreshSceneBindings(),await this.player.prepare()}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.refreshSceneBindings(),this.player.getActiveTrackObjects(e)}play(e){this.refreshSceneBindings(),this.player.cameraControlEnabled=e?.cameraControlEnabled??this.cameraControlEnabled,this.player.timescale=this.sequenceData.playbackRate*(e?.timeScale??1),this.player.play()}pause(){this.player.pause()}cancel(){this.player.cancel()}stop(){this.player.stop()}restart(){this.player.restart()}seek(e){this.refreshSceneBindings(),this.player.seek(e)}refreshSceneBindings(){for(const e of S(this.sequenceData?.tracks??[])){if("object"!==e.type||e.role||!e.targetId)continue;const t=this.world.resolveSceneActor(e.targetId);t?(this.player.bindObject(e.targetId,t),this.missingSceneTargets.delete(e.targetId)):(this.player.unbindObject(e.targetId),this.missingSceneTargets.has(e.targetId)||(console.warn(`Sequence "${this.object.name||this.__netSceneId||this.id}" could not resolve scene actor "${e.targetId}"`),this.missingSceneTargets.add(e.targetId)))}}refreshAsset(e){return this.player.refreshAsset(e)}onUpdate(e){}onEndPlay(){this.player.dispose()}dispose(){this.world.removeActor(this)}};e([y({label:"Sequence Data"}),t("design:type",Object)],v.prototype,"sequenceData",void 0),e([y({label:"Camera Control Enabled"}),t("design:type",Boolean),t("design:paramtypes",[Boolean])],v.prototype,"cameraControlEnabled",null),e([c({parameters:[],returns:d}),t("design:type",Function),t("design:paramtypes",[Object]),t("design:returntype",void 0)],v.prototype,"play",null),e([c({parameters:[],returns:d}),t("design:type",Function),t("design:paramtypes",[]),t("design:returntype",void 0)],v.prototype,"pause",null),e([c({parameters:[],returns:d}),t("design:type",Function),t("design:paramtypes",[]),t("design:returntype",void 0)],v.prototype,"cancel",null),e([c({parameters:[],returns:d}),t("design:type",Function),t("design:paramtypes",[]),t("design:returntype",void 0)],v.prototype,"stop",null),e([c({parameters:[],returns:d}),t("design:type",Function),t("design:paramtypes",[]),t("design:returntype",void 0)],v.prototype,"restart",null),e([c({parameters:[{name:"time",type:h}],returns:d}),t("design:type",Function),t("design:paramtypes",[Number]),t("design:returntype",void 0)],v.prototype,"seek",null),v=e([s({typeId:m})],v);export{v as SequenceActor};function S(e){const t=[];for(const s of e)t.push(s),"group"===s.type&&t.push(...S(s.childTracks));return t}/*
|
|
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 i}from"../../gameplay/services/render.js";import{AssetLoader as n}from"../../gameplay/services/asset-loader.js";import{World as o}from"../../gameplay/services/world.js";import{ActorFactory as l}from"../../gameplay/actors/factory.js";import{VfxService as p}from"../../effects/vfx/vfx-service.js";import{EventGraphCallable as c}from"../../gameplay/event-graph/decorators.js";import{EVENT_GRAPH_NUMBER_TYPE as h,EVENT_GRAPH_VOID_TYPE as d}from"../../gameplay/event-graph/types.js";import{SEQUENCE_ACTOR_TYPE_ID as m}from"../../gameplay/event-graph/asset-actor-types.js";import{Parameter as y}from"../../shader/parameter.js";import{createSequenceData as u}from"./sequence-data.js";import{SequencePlayer as g,SequencePlaybackState as b}from"./sequence-player.js";import{Subject as f,takeUntil as C}from"rxjs";let v=class extends r{constructor(){super(...arguments),this.sequenceData=u(),this.sequenceAssetId=null,this._cameraControlEnabled=!1,this._cameraControlTrackId=null,this.onComplete=new f,this.onLoop=new f,this.player=new g,this.viewController=a(i),this.assetLoader=a(n),this.world=a(o),this.actorFactory=a(l),this.vfxService=a(p),this.sourceAsset=null,this.missingSceneTargets=new Set}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===b.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.player.onVfxCollision=e=>this.onVfxCollision?.(e),this.viewController.onUpdate(this).pipe(C(this.disposed)).subscribe(e=>this.player.update(e)),this.player.onComplete.pipe(C(this.disposed)).subscribe(()=>this.onComplete.next()),this.player.onLoop.pipe(C(this.disposed)).subscribe(e=>this.onLoop.next(e)),this.sequenceAssetId?await this.loadFromAssetId(this.sequenceAssetId):this.sequenceData&&this.player.load(this.sequenceData),this.refreshSceneBindings()}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),this.missingSceneTargets.clear(),this.refreshSceneBindings())}async loadFromAssetId(e){const t=await this.assetLoader.getAsset(e);t&&await this.loadFromAsset(t)}setSequenceData(e){this.sequenceData=e,this.player.load(e),this.missingSceneTargets.clear(),this.refreshSceneBindings()}applySceneParameters(e,t){const s=new Set(["sequenceData","cameraControlEnabled"]);return![...t].some(e=>!s.has(e))&&(t.has("sequenceData")&&e.sequenceData&&this.setSequenceData(e.sequenceData),t.has("cameraControlEnabled")&&(this.cameraControlEnabled=Boolean(e.cameraControlEnabled)),!0)}bindRole(e,t){this.player.bindRole(e,t)}async prepare(){this.refreshSceneBindings(),await this.player.prepare()}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.refreshSceneBindings(),this.player.getActiveTrackObjects(e)}play(e){this.refreshSceneBindings(),this.player.cameraControlEnabled=e?.cameraControlEnabled??this.cameraControlEnabled,this.player.timescale=this.sequenceData.playbackRate*(e?.timeScale??1),this.player.play()}pause(){this.player.pause()}cancel(){this.player.cancel()}stop(){this.player.stop()}restart(){this.player.restart()}seek(e){this.refreshSceneBindings(),this.player.seek(e)}refreshSceneBindings(){for(const e of S(this.sequenceData?.tracks??[])){if("object"!==e.type||e.role||!e.targetId)continue;const t=this.world.resolveSceneActor(e.targetId);t?(this.player.bindObject(e.targetId,t),this.missingSceneTargets.delete(e.targetId)):(this.player.unbindObject(e.targetId),this.missingSceneTargets.has(e.targetId)||(console.warn(`Sequence "${this.object.name||this.__netSceneId||this.id}" could not resolve scene actor "${e.targetId}"`),this.missingSceneTargets.add(e.targetId)))}}refreshAsset(e){return this.player.refreshAsset(e)}onUpdate(e){}onEndPlay(){this.player.dispose()}dispose(){this.world.removeActor(this)}};e([y({label:"Sequence Data"}),t("design:type",Object)],v.prototype,"sequenceData",void 0),e([y({label:"Camera Control Enabled"}),t("design:type",Boolean),t("design:paramtypes",[Boolean])],v.prototype,"cameraControlEnabled",null),e([c({parameters:[],returns:d}),t("design:type",Function),t("design:paramtypes",[Object]),t("design:returntype",void 0)],v.prototype,"play",null),e([c({parameters:[],returns:d}),t("design:type",Function),t("design:paramtypes",[]),t("design:returntype",void 0)],v.prototype,"pause",null),e([c({parameters:[],returns:d}),t("design:type",Function),t("design:paramtypes",[]),t("design:returntype",void 0)],v.prototype,"cancel",null),e([c({parameters:[],returns:d}),t("design:type",Function),t("design:paramtypes",[]),t("design:returntype",void 0)],v.prototype,"stop",null),e([c({parameters:[],returns:d}),t("design:type",Function),t("design:paramtypes",[]),t("design:returntype",void 0)],v.prototype,"restart",null),e([c({parameters:[{name:"time",type:h}],returns:d}),t("design:type",Function),t("design:paramtypes",[Number]),t("design:returntype",void 0)],v.prototype,"seek",null),v=e([s({typeId:m})],v);export{v as SequenceActor};function S(e){const t=[];for(const s of e)t.push(s),"group"===s.type&&t.push(...S(s.childTracks));return t}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -2,12 +2,14 @@ import { Subject } from 'rxjs';
|
|
|
2
2
|
import * as THREE from 'three';
|
|
3
3
|
import type { AnimationAction } from 'three';
|
|
4
4
|
import { AnimationMixer, Euler, Object3D, Vector3 } from 'three';
|
|
5
|
+
import type { VfxCollisionEvent } from '../../effects/vfx/vfx-actor.js';
|
|
5
6
|
import type { VfxService } from '../../effects/vfx/vfx-service.js';
|
|
6
7
|
import { BaseActor } from '../../gameplay/actors/actor.js';
|
|
7
8
|
import type { ActorFactory } from '../../gameplay/actors/factory.js';
|
|
8
9
|
import type { AssetLoader } from '../../gameplay/services/asset-loader.js';
|
|
9
10
|
import type { World } from '../../gameplay/services/world.js';
|
|
10
11
|
import type { PrefabInstance } from '../../scene/objects/prefab.js';
|
|
12
|
+
import { type AssetId } from '../../scene/model.js';
|
|
11
13
|
import type { SequenceData, SequenceRole, SequenceTrack } from './sequence-data.js';
|
|
12
14
|
import type { SequenceLocatorReader, SequenceLocatorSnapshot } from './sequence-locator.js';
|
|
13
15
|
import { CharacterAnimationComponent } from '../../gameplay/actors/index.js';
|
|
@@ -84,6 +86,12 @@ export type SpawnedInstance = ({
|
|
|
84
86
|
type: 'proxy';
|
|
85
87
|
target: BaseActor | Object3D;
|
|
86
88
|
}) & Partial<AnimationPlayable>;
|
|
89
|
+
/** Reused during synchronous sequence VFX collision callbacks. */
|
|
90
|
+
export interface SequenceVfxCollisionEvent extends VfxCollisionEvent {
|
|
91
|
+
readonly trackId: string;
|
|
92
|
+
readonly clipId: string;
|
|
93
|
+
readonly vfxAssetId: AssetId;
|
|
94
|
+
}
|
|
87
95
|
/**
|
|
88
96
|
* SequencePlayer is the runtime system that plays a sequence.
|
|
89
97
|
* It manages track bindings, playback state, and updates.
|
|
@@ -101,6 +109,9 @@ export declare class SequencePlayer implements SequenceLocatorReader {
|
|
|
101
109
|
private sequenceData;
|
|
102
110
|
readonly onComplete: Subject<void>;
|
|
103
111
|
readonly onLoop: Subject<number>;
|
|
112
|
+
/** Synchronous impacts from sequence-owned VFX clips. The payload is reused. */
|
|
113
|
+
onVfxCollision?: (event: SequenceVfxCollisionEvent) => void;
|
|
114
|
+
private readonly vfxCollisionEvent;
|
|
104
115
|
readonly onTimeUpdate: import("rxjs").Observable<number>;
|
|
105
116
|
readonly onStateChange: import("rxjs").Observable<SequencePlaybackState>;
|
|
106
117
|
private loopCount;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{BehaviorSubject as e,Subject as t}from"rxjs";import*as s from"three";import{AnimationMixer as a,Color as i,Euler as r,Object3D as n,Quaternion as o,Vector2 as l,Vector3 as c,Vector4 as h}from"three";import{VisualEffect as u}from"../../effects/vfx/vfx-param.js";import{hashVfxPreviewSeed as p}from"../../effects/vfx/seeded-random.js";import{BaseActor as d}from"../../gameplay/actors/actor.js";import f from"../../gameplay/actors/builtin/index.js";import{Prefab as m,PrefabOf as y}from"../../scene/objects/prefab.js";import{SerializedParamType as v}from"../../scene/model.js";import{customParamValueNeedsAsyncResolution as g,deserializeCustomParamValue as C,deserializeCustomParamValueSync as A}from"../../scene/custom-param-deserialize.js";import{getAudioParameterDefinition as S}from"./audio-parameters.js";import{getMaterialSubTrackMatchMode as w,getMaterialSubTrackTarget as b,Sequence as P,isSequenceData as k}from"./sequence-data.js";import{getSequenceSubTrackDefinition as x,getSequenceTrackDefinition as T}from"./sequence-definitions.js";import{applyInterpolation as I,evaluateCustomParamValueKeyframes as M,evaluateNumericKeyframes as q,findKeyframeSpan as B}from"./sequence-value-lane.js";import{evaluateTransformPositionSpan as O}from"./sequence-transform.js";import{applyAnimationClipRootMotionAxisMask as F,buildRetimedAnimationClip as E,getAnimationClipRetimingSignature as V,isAnimationClipUsingRetiming as L}from"./sequence-animation-retiming.js";import*as j from"three/addons/utils/SkeletonUtils.js";import{CharacterAnimationComponent as R,getCharacterMovementLike as _}from"../../gameplay/actors/index.js";import{RootMotionClip as D}from"../../gameplay/animation/root-motion.js";import{markMaterialUniformValuesNeedUpdate as K}from"../../rendering/node-material-webgpu-resolver.js";import{getAnimationClipRigId as $,getAnimationRigIdFromObject as G,setAnimationClipRigId as N}from"../../gameplay/animation/retarget.js";import{hashCameraShakeSeed as U}from"../../gameplay/services/camera-shake.js";import{buildShaderGraphPostProcessMaterial as W,shaderGraphPostProcessWeightUniformName as Q}from"../../shader/graph/index.js";export var SequencePlaybackState;!function(e){e.Stopped="stopped",e.Playing="playing",e.Paused="paused"}(SequencePlaybackState||(SequencePlaybackState={}));export class SequencePlayer{constructor(){this._state=new e(SequencePlaybackState.Stopped),this._time=new e(0),this._duration=0,this._timescale=1,this._loop=!1,this._externalTimeControl=!1,this._inEditor=!1,this.bindings=new Map,this.roleBindings=new Map,this.sequenceData=null,this.onComplete=new t,this.onLoop=new t,this.onTimeUpdate=this._time.asObservable(),this.onStateChange=this._state.asObservable(),this.loopCount=0,this.viewController=null,this._cameraControlEnabled=!1,this._cameraControlTrackId=null,this.sequenceCameras=new Map,this.cameraPlayables=new Map,this.cameraBlendCamera=null,this.cameraBlendSource=null,this.cameraBlendOutSource=null,this.cameraOverrideHandle=null,this.activeCameraClipKey=null,this.cameraBlendOutClipKey=null,this.activeCameraShakeClipKeys=new Set,this.nextCameraShakeClipKeys=new Set,this.activePostProcessClips=new Map,this.nextPostProcessClipKeys=new Set,this.sequenceLights=new Map,this.lightPlayables=new Map,this.audioListener=null,this.audioBuffers=new Map,this.loadingAudioBuffers=new Map,this.animationClips=new Map,this.loadingAnimationClips=new Map,this.retimedAnimationClips=new Map,this.externalRootMotionInterpolants=new WeakMap,this.audioByClip=new Map,this.activeAudioClips=new Set,this.audioGainNodes=new Map,this.audioStartInFlight=new Map,this.lastAudioStartAttemptTime=new Map,this.audioStartRetryIntervalSeconds=.25,this.world=null,this.assetLoader=null,this.actorFactory=null,this.vfxService=null,this.spawnedInstances=new Map,this.activeClips=new Set,this.pendingSpawns=new Set,this.vfxActors=new Map,this.activeVfxClips=new Set,this.locatorMarkers=new Map,this.clearCounter=0,this.propertyPathSegments=new Map,this.propertyResolutionCache=new Map,this.propertySnapshots=new Map,this.materialResolutionCache=new Map,this.materialSnapshots=new Map,this.visibilitySnapshots=new Map,this.audioFilters=new Map,this.audioPannerNodes=new Map,this.firedEvents=new Set,this.sequenceEventSyncResolvers={actor:e=>this.resolveSequenceEventActorReference(e)},this.sequenceEventAsyncResolvers={actor:e=>this.resolveSequenceEventActorReference(e),texture:e=>this.assetLoader?.getTextureByAssetId(e)??null,sampler2DNode:e=>this.assetLoader?.getTextureByAssetId(e)??null,object3D:async e=>{const t=await(this.assetLoader?.getModelByAssetId(e));return t?.scene??null},material:e=>this.assetLoader?.getMaterialByAssetId(e)??null,audioBuffer:e=>this.assetLoader?.getAudioByAssetId(e)??null,visualEffect:async e=>{if(!this.assetLoader||!this.actorFactory)return null;const t=await this.assetLoader.getAsset(e);return t?new u(this.actorFactory,t):null},prefab:async e=>{const t=await(this.assetLoader?.getPrefabById(e));return t?new m(t.asset):null},prefabActor:async e=>{const t=await(this.assetLoader?.getPrefabById(e));return t?new y(new m(t.asset)):null},sequence:e=>this.resolveSequenceEventSequence(e),animationClip:e=>this.resolveSequenceEventAnimationClip(e)},this.trackRuntimeEvaluators={object:(e,t,s)=>{t&&this.evaluateObjectTrack(e,t,s)},locator:(e,t,s)=>{t&&this.evaluateLocatorTrack(e,t,s)},camera:(e,t,s)=>this.evaluateCameraTrack(e,s),cameraShake:(e,t,s)=>this.evaluateCameraShakeTrack(e,s),postProcess:(e,t,s)=>this.evaluatePostProcessTrack(e,s),light:(e,t,s)=>this.evaluateLightTrack(e,s),audio:(e,t,s)=>this.evaluateAudioTrack(e,s),vfx:(e,t,s)=>this.evaluateVfxTrack(e,s),spawn:(e,t,s)=>this.evaluateSpawnTrack(e,t,s),group:(e,t,s)=>{if("group"===e.type)for(const t of e.childTracks)this.evaluateTrack(t,s)}},this.subTrackRuntimeEvaluators={transform:(e,t,s)=>{const a=this.getPlayableObject(t);a&&this.evaluateTransformSubTrack(e,a,s)},animation:(e,t,s)=>this.evaluateAnimationSubTrack(e,t,s),visibility:(e,t,s)=>{const a=this.getPlayableObject(t);a&&this.evaluateVisibilitySubTrack(e,a,s)},parameter:(e,t,s)=>this.evaluateParameterSubTrack(e,t.target||null,s),event:(e,t,s)=>this.evaluateEventSubTrack(e,t.target||null,s)}}get state(){return this._state.value}get time(){return this._time.value}get duration(){return this._duration}get timescale(){return this._timescale}set timescale(e){this._timescale=Math.max(.01,e)}get loop(){return this._loop}set loop(e){this._loop=e}get externalTimeControl(){return this._externalTimeControl}set externalTimeControl(e){this._externalTimeControl=e}get inEditor(){return this._inEditor}set inEditor(e){this._inEditor=e,this.updateLocatorMarkerVisibility()}get cameraControlEnabled(){return this._cameraControlEnabled}set cameraControlEnabled(e){this._cameraControlEnabled=e,e||this.releaseCameraOverride()}get cameraControlTrackId(){return this._cameraControlTrackId}set cameraControlTrackId(e){this._cameraControlTrackId!==e&&(this._cameraControlTrackId=e,this.releaseCameraOverride())}setViewController(e){this.viewController&&this.viewController!==e&&this.viewController.clearCameraShakeContributionsForOwner(this),this.viewController=e}setWorld(e){this.world!==e&&(this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.clearLocatorBindings(),this.clearSequenceCameras(),this.clearSequenceLights(),this.clearCameraShakeContributions(),this.clearPostProcessEffects(),this.world=e,this.clearCounter++,this.vfxActors.clear(),this.spawnedInstances.clear(),this.bindings.clear(),this.activeClips.clear(),this.activeVfxClips.clear(),this.activeAudioClips.clear(),this.audioStartInFlight.clear(),this.lastAudioStartAttemptTime.clear(),this.loadingAudioBuffers.clear(),this.audioFilters.clear(),this.audioPannerNodes.clear(),this.pendingSpawns.clear(),this.propertyResolutionCache.clear(),this.materialResolutionCache.clear(),this.clearRetimedAnimationClipCache(),this._state.next(SequencePlaybackState.Stopped),this.sequenceData&&this.initializeLocatorBindings())}setAudioListener(e){this.audioListener=e}setAssetLoader(e){if(this.assetLoader=e,this.sequenceData){const e=this.clearCounter;this.preloadSequenceResources(this.sequenceData,e)}}setActorFactory(e){this.actorFactory=e}setVfxService(e){this.vfxService=e}load(e){if(this.stop(),this.clearCounter++,this.clearLocatorBindings(),this.clearSequenceCameras(),this.clearSequenceLights(),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 s of e.tracks){if("audio"!==s.type)continue;const e=s;for(const s of e.clips??[])s.audioAssetId&&t.add(s.audioAssetId)}return[...t]}async preloadAudioBuffersForSequence(e,t){if(!this.assetLoader)return;const s=this.getAudioAssetIdsForSequence(e);0!==s.length&&await Promise.all(s.map(async e=>{if(t!==this.clearCounter)return;if(this.audioBuffers.has(e))return;let s=this.loadingAudioBuffers.get(e);s||(s=this.assetLoader.getAudioByAssetId(e),this.loadingAudioBuffers.set(e,s));try{const a=await s;if(t!==this.clearCounter)return;this.audioBuffers.set(e,a)}catch(e){}finally{this.loadingAudioBuffers.get(e)===s&&this.loadingAudioBuffers.delete(e)}}))}async preloadAnimationClipsForSequence(e,t){this.assetLoader&&t===this.clearCounter&&await this.prepareAnimationClipsForBindings(e,t)}async prepare(){if(!this.sequenceData||!this.assetLoader)return;this.resolveBindings();const e=this.clearCounter;await Promise.all([this.prepareAnimationClipsForBindings(this.sequenceData,e),this.prepareVisualEffectsForSequence(this.sequenceData,e)])}async prepareVisualEffectsForSequence(e,t){if(await this.preloadVisualEffectsForSequence(e,t),t!==this.clearCounter||!this.vfxService||!this.world)return;const s=[];for(const t of oe(e.tracks))if("vfx"===t.type&&!t.muted)for(const e of t.clips??[])null!=e.vfxAssetId&&s.push({track:t,clip:e,key:this.getVfxClipKey(t,e)});await Promise.all(s.map(({track:e,clip:t,key:s})=>this.ensureVfxActor(e,t,s)))}async preloadVisualEffectsForSequence(e,t){if(!this.world||!this.actorFactory)return;const s=new Set;for(const t of oe(e.tracks))if("vfx"===t.type)for(const e of t.clips??[])null!=e.vfxAssetId&&s.add(e.vfxAssetId);if(0===s.size)return;const a=await Promise.all([...s].map(e=>this.assetLoader.getAsset(e)));if(t!==this.clearCounter)return;const i=a.filter(e=>null!=e&&null!=e.vfx).map(e=>new u(this.actorFactory,e));await this.world.preloadVisualEffects(i)}async prepareAnimationClipsForBindings(e,t){const s=[];for(const a of oe(e.tracks)){if(!("subTracks"in a))continue;const e=this.bindings.get(a.id),i=null==e?null:this.getPlayableObject(e);if(null==i)continue;const r=G(i);for(const e of a.subTracks)if("animation"===e.type)for(const a of e.clips){if(t!==this.clearCounter)return;if(null!=a.animationClipAssetId){const e=this.animationClipCacheKey(a.animationClipAssetId,r);s.push(this.ensureAnimationClip(a.animationClipAssetId,r).then(s=>{null!=s&&t===this.clearCounter&&L(a)&&(this.getPlayableAnimationClip(e,s,a,!1),a.rootMotion&&this.getPlayableAnimationClip(e,s,a,!0))}))}}}await Promise.all(s)}bindRole(e,t){this.roleBindings.set(e,t),this.sequenceData&&this.resolveBindings()}bindObject(e,t){if(this.sequenceData)for(const s of oe(this.sequenceData.tracks))"object"!==s.type||s.targetId!==e||s.role||this.createBinding(s,t)}unbindObject(e){if(this.sequenceData)for(const t of oe(this.sequenceData.tracks))"object"!==t.type||t.targetId!==e||t.role||this.removeBinding(t.id)}getLocator(e){return this.getLocators(e)[0]??null}getLocators(e){const t=le(e);if(!t||!this.sequenceData)return[];const s=[];for(const e of oe(this.sequenceData.tracks)){if("locator"!==e.type)continue;if(le(e.bindingId)!==t)continue;const a=this.bindings.get(e.id),i=a?this.getPlayableObject(a):null;i&&(i.updateWorldMatrix(!0,!1),s.push({trackId:e.id,name:e.name,bindingId:e.bindingId,position:i.getWorldPosition(new c),rotation:i.getWorldQuaternion(new o),scale:i.getWorldScale(new c)}))}return s}resolveBindings(){if(this.sequenceData)for(const e of this.sequenceData.tracks)this.resolveTrackBinding(e)}initializeLocatorBindings(){if(this.sequenceData)for(const e of oe(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 s=ce(e.name);s.visible=this._inEditor,t.add(s),this.locatorMarkers.set(e.id,s),this.disableLocatorInteraction(t),this.createBinding(e,t)}}clearLocatorBindings(){for(const e of this.locatorMarkers.values())he(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 s=t instanceof d?t.object:t,i=this.bindings.get(e.id),r=null!=i?i.target instanceof d?i.target.object:i.target:null,n=null!=i&&i.target===t&&r===s,o=e.subTracks.some(e=>"animation"===e.type);null==i||n||this.releaseBinding(i);const l=n?i:{track:e,target:t,activeActions:new Map};l.track=e,l.target=t,n||(l.originalTransform={position:s.position.clone(),rotation:s.rotation.clone(),scale:s.scale.clone()},l.originalParent=s.parent),o&&null==l.mixer?l.mixer=new a(s):o||(l.mixer=void 0),this.bindings.set(e.id,l)}removeBinding(e){const t=this.bindings.get(e);t&&(this.releaseBinding(t),this.bindings.delete(e))}releaseBinding(e){this.clearExternalRootMotionPreview(e);for(const[t,s]of e.activeActions.entries())e.charAnimActionKeys?.has(t)||s.stop();e.activeActions.clear(),e.mixer?.stopAllAction(),e.charAnimComponent?.stopSequenceAnimation(),e.charAnimComponent=void 0,e.charAnimActionKeys?.clear()}play(){this._state.value!==SequencePlaybackState.Playing&&this.sequenceData&&(this._state.value===SequencePlaybackState.Stopped&&(this._time.next(0),this.loopCount=0,this.resolveBindings(),this.captureOriginalTransforms()),this._state.next(SequencePlaybackState.Playing),this.evaluate(this._time.value),this.resumeVfx())}pause(){this._state.value===SequencePlaybackState.Playing&&(this._state.next(SequencePlaybackState.Paused),this.pauseAudio(),this.pauseVfx())}pauseAudio(){for(const e of this.audioByClip.values())e.pause()}pauseVfx(){for(const e of this.vfxActors.values())e.pause()}resumeVfx(){for(const[e,t]of this.vfxActors.entries())(this.activeVfxClips.has(e)||t.getParticleCount()>0)&&t.play()}cancel(){this._state.next(SequencePlaybackState.Stopped),this._time.next(0),this.clearCounter++,this.loopCount=0,this.pauseAudio(),this.releaseCameraOverride(),this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.restoreAllVisibilitySnapshots(),this.stopAllAudio(),this.stopAllAnimations(),this.despawnAll(),this.stopAllVfx(),this.firedEvents.clear(),this.clearCameraShakeContributions(),this.clearPostProcessEffects();for(const e of this.sequenceLights.values())e.visible=!1}stop(){this._state.next(SequencePlaybackState.Stopped),this._time.next(0),this.clearCounter++,this.loopCount=0,this.pauseAudio(),this.releaseCameraOverride(),this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.restoreAllVisibilitySnapshots(),this.restoreOriginalTransforms(),this.restoreOriginalParents(),this.stopAllAudio(),this.stopAllAnimations(),this.despawnAll(),this.stopAllVfx(),this.firedEvents.clear(),this.clearCameraShakeContributions(),this.clearPostProcessEffects();for(const e of this.sequenceLights.values())e.visible=!1}restart(){this.stop(),this.play()}seek(e){const t=Math.max(0,Math.min(e,this._duration));t<this._time.value&&this.resetVfxForTimeReset(t),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.charAnimComponent?t.charAnimComponent.evaluateExternalPose(e*this._timescale):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.deactivateCharacterAnimationActions(),this.releaseCameraOverride(),this.clearCameraShakeContributions(),this.clearPostProcessEffects(),this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.restoreAllVisibilitySnapshots(),this._state.next(SequencePlaybackState.Stopped),void this.onComplete.next();{this.loopCount++;const e=t%this._duration;this.resetVfxForTimeReset(e),this._time.next(e),this.firedEvents.clear(),this.onLoop.next(this.loopCount)}}else this._time.next(t);this.evaluate(this._time.value);for(const t of this.bindings.values())t.mixer&&t.mixer.update(e*this._timescale);for(const t of this.spawnedInstances.values())t.mixer&&t.mixer.update(e*this._timescale)}evaluate(e){if(this.sequenceData){this.nextCameraShakeClipKeys.clear(),this.nextPostProcessClipKeys.clear();for(const e of this.sequenceLights.values())e.visible=!1;for(const t of this.sequenceData.tracks){if(!t.muted&&("object"===t.type||"locator"===t.type||"camera"===t.type||"light"===t.type||"spawn"===t.type||"vfx"===t.type)){const e=this.bindings.get(t.id);this.updateTrackParenting(t,e)}this.evaluateTrack(t,e)}this.updateCameraControl(e),this.syncCameraShakeContributions(),this.syncPostProcessEffects()}}evaluateTrack(e,t){if(e.muted)return;const s=this.bindings.get(e.id);(0,this.trackRuntimeEvaluators[T(e.type).runtimeEvaluator])(e,s,t)}evaluateObjectTrack(e,t,s){this.evaluateSubTracks(e.subTracks,t,s)}evaluateLocatorTrack(e,t,s){this.evaluateSubTracks(e.subTracks,t,s)}getActiveTrackObjects(e){if(!this.sequenceData)return[];const t=oe(this.sequenceData.tracks).find(t=>t.id===e);return t?this.getActiveObjectsForTrack(t):[]}evaluateSubTracks(e,t,s){this._externalTimeControl&&this.beginExternalRootMotionPreview(t);for(const a of e){if(a.muted)continue;(0,this.subTrackRuntimeEvaluators[x(a.type).runtimeEvaluator])(a,t,s)}this._externalTimeControl&&this.applyExternalRootMotionPreview(t)}beginExternalRootMotionPreview(e){const t=e.externalRootMotionPreview;if(!t)return;const s=this.getPlayableObject(e);s&&s.position.sub(t.appliedOffset),t.appliedOffset.set(0,0,0),t.sampledOffset.set(0,0,0),t.root=null}sampleExternalRootMotionPreview(e,t,a,i){if(!t.motionTrack)return;let r=this.externalRootMotionInterpolants.get(t);r||(r=t.motionTrack.InterpolantFactoryMethodSmooth([]),this.externalRootMotionInterpolants.set(t,r));const n=e.externalRootMotionPreview??(e.externalRootMotionPreview={appliedOffset:new c,sampledOffset:new c,root:null}),o=Math.max(0,Math.min(i,t.duration)),l=Math.max(o,Math.min(a,t.duration));fe.fromArray(r.evaluate(o)),me.fromArray(r.evaluate(l)),n.sampledOffset.subVectors(me,fe),n.sampledOffset.y=0;const h=this.getPlayableObject(e),u=s.PropertyBinding.parseTrackName(t.motionTrack.name);n.root=h?.getObjectByName(u.nodeName)??h}applyExternalRootMotionPreview(e){const t=e.externalRootMotionPreview,s=this.getPlayableObject(e);t&&s&&t.root&&(t.root.getWorldScale(ye),t.appliedOffset.copy(t.sampledOffset).multiply(ye).applyQuaternion(s.quaternion),s.position.add(t.appliedOffset))}clearExternalRootMotionPreview(e){const t=e.externalRootMotionPreview,s=this.getPlayableObject(e);t&&s&&s.position.sub(t.appliedOffset),e.externalRootMotionPreview=void 0}evaluateTransformSubTrack(e,t,s){const a=e.keyframes;if(0===a.length)return;const{prev:i,next:r,prevIndex:n,nextIndex:o,t:l}=B(a,s);if(i)if(e.components.position&&O(a,n,o,l,t.position),r&&i!==r){const s=I(l,i.interpolation);e.components.rotation&&i.rotation&&r.rotation&&(ve.setFromEuler(Ce.fromArray([...i.rotation,"XYZ"])),ge.setFromEuler(Ae.fromArray([...r.rotation,"XYZ"])),t.quaternion.slerpQuaternions(ve,ge,s)),e.components.scale&&i.scale&&r.scale&&t.scale.lerpVectors(ue.fromArray(i.scale),pe.fromArray(r.scale),s)}else e.components.rotation&&i.rotation&&t.rotation.fromArray([...i.rotation,"XYZ"]),e.components.scale&&i.scale&&t.scale.fromArray(i.scale)}evaluateAnimationSubTrack(e,t,a){if(!t.mixer||!t.activeActions)return;const i=t.target instanceof d?t.target.object:t.target;if(i)for(const r of e.clips){const n=r.startTime+r.duration,o=a>=r.startTime&&a<n,l=`${e.id}-${r.id}`;let c=t.activeActions.get(l),h=!1;if(o){if(!c){h=!0;const e=r.animationClipAssetId;if(null==e)continue;const a=G(i),n=this.animationClipCacheKey(e,a),o=this.animationClips.get(n);if(null==o){this.ensureAnimationClip(e,a);continue}const u=this.prepareAnimationPlayback(n,o,r),p=t;let f=!1;if(t.target instanceof d){p.charAnimComponent||(p.charAnimComponent=t.target.getComponent(R)??void 0);const e=p.charAnimComponent;if(null!=e){const s=r.rootMotion?L(r)?this.getPlayableAnimationClip(n,o,r,!0):D.fromClip(u.clip,!1):u.clip;if(this._externalTimeControl)c=e.beginExternalAnimationControl(s,{timeScale:u.timeScale});else if(e.play(s,{inPlace:!r.rootMotion,loop:!1,priority:20,sequenceControlled:!0,timeScale:u.timeScale,fadeTime:r.fadeInDuration??.2,offset:u.startOffset}),c=e.getFullBodyAction(),r.rootMotion){const e=_(t.target);e&&e.setRootMotionAction(c,{cancelWithJump:e.allowRootMotionJumpCancel,onJumpCancel:()=>this.cancel()})}t.activeActions.set(l,c),p.charAnimActionKeys||(p.charAnimActionKeys=new Set),p.charAnimActionKeys.add(l),f=!0}}f||(c=t.mixer.clipAction(u.clip),c.setLoop(s.LoopOnce,1),c.clampWhenFinished=!0,c.timeScale=u.timeScale,u.startOffset>0&&(c.time=u.startOffset),t.activeActions.set(l,c),c.play())}if(c){const e=t;if(this._externalTimeControl){e.charAnimComponent?.beginExternalControl();const s=this.getAnimationPlaybackLocalTime(r,a),i=Math.min(s,c.getClip().duration);(h||Math.abs(c.time-i)>.001)&&(c.time=i,c.paused=!1,c.play(),e.charAnimComponent?e.charAnimComponent.evaluateExternalPose():t.mixer&&t.mixer.update(0)),r.rootMotion&&c.getClip()instanceof D&&this.sampleExternalRootMotionPreview(t,c.getClip(),i,L(r)?0:r.clipStartOffset)}else e.charAnimComponent?.endExternalControl()}}else c&&this.deactivateAnimationAction(t,l,c)}}deactivateAnimationAction(e,t,s){if(e.activeActions.delete(t),e.charAnimActionKeys?.has(t))return e.charAnimActionKeys.delete(t),void(0===e.charAnimActionKeys.size&&e.charAnimComponent&&(e.charAnimComponent.requestSequenceAnimationRelease(),e.charAnimComponent=void 0));s.stop(),this._externalTimeControl&&e.mixer&&e.mixer.update(0)}deactivateAnimationSubTracks(e,t){for(const s of e)if(!s.muted&&"animation"===s.type)for(const e of s.clips){const a=`${s.id}-${e.id}`,i=t.activeActions.get(a);i&&this.deactivateAnimationAction(t,a,i)}}deactivateCharacterAnimationActions(){for(const e of this.bindings.values())for(const t of[...e.charAnimActionKeys??[]]){const s=e.activeActions.get(t);s?this.deactivateAnimationAction(e,t,s):e.charAnimActionKeys?.delete(t)}}evaluateVisibilitySubTrack(e,t,s){const a=e.keyframes;if(0===a.length)return;let i=a[0];for(const e of a){if(!(e.time<=s))break;i=e}this.visibilitySnapshots.has(t)||this.visibilitySnapshots.set(t,{visible:t.visible}),t.visible=i.visible}evaluatePropertySubTrack(e,t,s){const a=M(e.keyframes,s,{min:e.range?.[0],max:e.range?.[1],stepOnly:X(e)});a&&this.applyResolvedPropertyValue(e,t,a)}evaluateParameterSubTrack(e,t,s){if("audioParameter"===e.type)return;const a=M(e.keyframes,s,"property"===e.type?{min:e.range?.[0],max:e.range?.[1],stepOnly:X(e)}:"material"===e.type?{min:e.range?.[0],max:e.range?.[1],stepOnly:z(e)}:{});a&&("property"!==e.type?this.applyResolvedMaterialValue(e,t,a):this.applyResolvedPropertyValue(e,t,a))}evaluateEventSubTrack(e,t,s){if(t instanceof d&&this._state.value===SequencePlaybackState.Playing)for(const a of e.events){const i=`${e.id}-${a.id}`;if(s>=a.time&&!this.firedEvents.has(i)){if(this.firedEvents.add(i),a.editorOnly&&!this._inEditor)continue;if(!a.functionName)continue;const e=t[a.functionName];"function"==typeof e?this.invokeSequenceEvent(t,a.functionName,e,a.arguments??[]):console.warn(`Sequence event method '${a.functionName}' not found on actor`)}else a.time>s&&this.firedEvents.delete(i)}}evaluateCameraTrack(e,t){const s=this.ensureSequenceCamera(e);this.applyCameraTrackSettings(e,s),this.evaluateSubTracks(e.subTracks,this.getCameraPlayable(e,s),t),s.updateProjectionMatrix()}evaluateCameraShakeTrack(e,t){if(this.viewController)for(const s of e.clips??[]){if(!this.isCameraShakeClipActive(s,t))continue;const e=t-s.startTime,a=s.id;this.nextCameraShakeClipKeys.add(a),this.viewController.setCameraShakeContribution(this,a,s,e,s.seed??U(s.id))}}evaluatePostProcessTrack(e,t){if(this.viewController&&this.assetLoader){for(const s of e.clips??[]){if(!this.isPostProcessClipActive(s,t))continue;const a=this.getPostProcessClipKey(e,s);this.nextPostProcessClipKeys.add(a),this.ensurePostProcessClipEffect(e,s,a);const i=this.activePostProcessClips.get(a);i?.handle&&(i.handle.stage=e.stage,i.handle.priority=e.priority,i.handle.enabled=!0,this.applyPostProcessClipWeight(i.handle,s,t))}this.evaluatePostProcessMaterialSubTracks(e,t)}}evaluatePostProcessMaterialSubTracks(e,t){for(const s of e.subTracks){if(s.muted||"material"!==s.type)continue;const a=M(s.keyframes,t,{min:s.range?.[0],max:s.range?.[1],stepOnly:z(s)});a&&this.applyPostProcessMaterialValue(e.id,s,a)}}evaluateLightTrack(e,t){const s=this.ensureSequenceLight(e);if(this.applyLightTrackSettings(e,s),s.visible=(e.clips??[]).some(e=>t>=e.startTime&&t<e.startTime+e.duration),!s.visible)return;let a=this.lightPlayables.get(e.id);a||(a={target:s},this.lightPlayables.set(e.id,a)),this.evaluateSubTracks(e.subTracks,a,t)}ensureSequenceLight(e){let t=this.sequenceLights.get(e.id);return t?null==t.parent&&this.world?.scene.add(t):(t=new s.PointLight,t.name=e.name||"Sequence Point Light",t.userData.sequenceLightTrackId=e.id,t.visible=!1,this.sequenceLights.set(e.id,t),this.world?.scene.add(t)),t}applyLightTrackSettings(e,t){t.color.set(e.color??"#ffffff"),t.intensity=Math.max(0,e.intensity??10),t.distance=Math.max(0,e.distance??10),t.decay=Math.max(0,e.decay??2),t.castShadow=e.castShadow??!1,t.userData.volumetricIntensity=Math.max(0,e.volumetricIntensity??0)}clearSequenceLights(){for(const e of this.sequenceLights.values())e.removeFromParent(),e.dispose();this.sequenceLights.clear(),this.lightPlayables.clear()}applyPostProcessMaterialValue(e,t,s){if("shaderUniform"===b(t)&&t.uniformName)for(const a of this.activePostProcessClips.values()){if(a.trackId!==e||!a.handle)continue;const i=a.handle.material,r=i.uniforms?.[t.uniformName];if(!r)continue;const n=Z(r.value,s);n.applied&&(r.value=n.value,i.uniformsNeedUpdate=!0,K(i))}}isPostProcessClipActive(e,t){return t>=e.startTime&&t<e.startTime+e.duration}getPostProcessClipKey(e,t){return`${e.id}-${t.id}`}ensurePostProcessClipEffect(e,t,s){const a=t.shaderGraphAssetId;if(!a)return void this.releasePostProcessClipEffect(s);const i=JSON.stringify(t.shaderGraphParams??{}),r=this.activePostProcessClips.get(s);if(r?.assetId===a&&r.paramsSignature===i)return;this.releasePostProcessClipEffect(s);const n={key:s,trackId:e.id,clipId:t.id,assetId:a,paramsSignature:i,version:this.clearCounter};this.activePostProcessClips.set(s,n),this.loadPostProcessClipEffect(e,t,n)}async loadPostProcessClipEffect(e,t,s){if(this.assetLoader&&this.viewController)try{const a=await this.assetLoader.getShaderGraphByAssetId(s.assetId);if(!this.isPostProcessClipEntryCurrent(s))return;if("postProcess"!==a.target)return console.warn(`Sequence post-process clip references shader graph "${s.assetId}" with target "${a.target}"`),void this.releasePostProcessClipEffect(s.key);const i=await this.assetLoader.prepareShaderGraphParameters(a,t.shaderGraphParams??{});if(!this.isPostProcessClipEntryCurrent(s))return;const r=W(a,{parameters:i});if(!this.isPostProcessClipEntryCurrent(s))return void r.dispose();s.handle=this.viewController.addPostProcessEffect(r,{stage:e.stage,priority:e.priority,enabled:!0}),this.applyPostProcessClipWeight(s.handle,t,this._time.value)}catch(e){this.isPostProcessClipEntryCurrent(s)&&this.releasePostProcessClipEffect(s.key),console.error(`Failed to create post-process effect for clip ${t.id}:`,e)}}isPostProcessClipEntryCurrent(e){return this.clearCounter===e.version&&this.activePostProcessClips.get(e.key)===e}applyPostProcessClipWeight(e,t,s){const a=e.material.uniforms?.[Q];null!=a&&(a.value=this.getPostProcessClipWeight(t,s),e.material.uniformsNeedUpdate=!0)}getPostProcessClipWeight(e,t){const s=Math.max(0,t-e.startTime),a=Math.max(0,e.startTime+e.duration-t);let i=1;const r=Math.max(0,e.fadeInDuration??0);r>0&&(i=Math.min(i,s/r));const n=Math.max(0,e.fadeOutDuration??0);return n>0&&(i=Math.min(i,a/n)),Math.max(0,Math.min(1,i))}syncPostProcessEffects(){for(const e of Array.from(this.activePostProcessClips.keys()))this.nextPostProcessClipKeys.has(e)||this.releasePostProcessClipEffect(e);this.nextPostProcessClipKeys.clear()}clearPostProcessEffects(){for(const e of Array.from(this.activePostProcessClips.keys()))this.releasePostProcessClipEffect(e);this.nextPostProcessClipKeys.clear()}releasePostProcessClipEffect(e){const t=this.activePostProcessClips.get(e);if(t&&(this.activePostProcessClips.delete(e),t.handle)){const e=t.handle.material;t.handle.dispose(),e.dispose()}}getCameraPlayable(e,t){let s=this.cameraPlayables.get(e.id);return s?s.target=t:(s={target:t},this.cameraPlayables.set(e.id,s)),s}ensureSequenceCamera(e){let t=this.sequenceCameras.get(e.id);if(t)null==t.parent&&this.world?.scene.add(t);else{const a=e.cameraSettings??{fov:60,near:.1,far:1e3};t=new s.PerspectiveCamera(a.fov??60,this.getCurrentCameraAspect(),a.near??.1,a.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 s=e.cameraSettings??{fov:60,near:.1,far:1e3};t.fov=s.fov??60,t.near=s.near??.1,t.far=s.far??1e3,t.aspect=this.getCurrentCameraAspect()}getCurrentCameraAspect(){const e=this.viewController?.getBaseCamera();if(e instanceof s.PerspectiveCamera&&Number.isFinite(e.aspect)&&e.aspect>0)return e.aspect;const t=this.viewController?.getSourceCamera();return t instanceof s.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 s=this.findBlendOutCameraShot(e);s?this.updateCameraBlendOut(s,e):this.releaseCameraOverride()}findActiveCameraShot(e){if(!this.sequenceData)return null;let t=null;for(const s of oe(this.sequenceData.tracks)){if("camera"!==s.type||s.muted||!this.isCameraControlTrackEligible(s))continue;const a=s.clips??[];for(const i of a)this.isCameraClipActive(i,e)&&(t={track:s,clip:i,camera:this.ensureSequenceCamera(s),key:this.getCameraClipKey(s,i)})}return t}findBlendOutCameraShot(e){if(!this.sequenceData)return null;let t=null;for(const s of oe(this.sequenceData.tracks)){if("camera"!==s.type||s.muted||!this.isCameraControlTrackEligible(s))continue;const a=s.clips??[];for(const i of a){const a=Math.max(0,i.blendOutDuration??0);if(a<=0)continue;const r=this.getCameraClipEnd(i);e>=r&&e<r+a&&(t={track:s,clip:i,camera:this.ensureSequenceCamera(s),key:this.getCameraClipKey(s,i)})}}return t}isCameraControlTrackEligible(e){return null==this._cameraControlTrackId||e.id===this._cameraControlTrackId}updateActiveCameraShot(e,t){if(!this.viewController)return;const s=this.ensureCameraBlendCamera();this.activeCameraClipKey!==e.key&&(this.copyCameraState(this.viewController.getSourceCamera(),this.ensureCameraBlendSource()),this.activeCameraClipKey=e.key,this.cameraBlendOutClipKey=null);const a=Math.max(0,e.clip.blendInDuration??0),i=a<=0?1:this.evaluateCameraBlendAlpha((t-e.clip.startTime)/a,e.clip);i>=1?this.copyCameraState(e.camera,s):this.blendCameraState(this.ensureCameraBlendSource(),e.camera,s,i),s.updateProjectionMatrix(),this.ensureCameraOverride()}updateCameraBlendOut(e,t){if(!this.viewController)return;const s=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 a=this.getCameraClipEnd(e.clip),i=Math.max(0,e.clip.blendOutDuration??0),r=i<=0?1:this.evaluateCameraBlendAlpha((t-a)/i,e.clip);this.blendCameraState(this.ensureCameraBlendOutSource(),this.viewController.getBaseCamera(),s,r),s.updateProjectionMatrix(),this.ensureCameraOverride()}ensureCameraBlendCamera(){return this.cameraBlendCamera||(this.cameraBlendCamera=new s.PerspectiveCamera(60,this.getCurrentCameraAspect(),.1,1e3),this.cameraBlendCamera.name="Sequence Camera Blend"),this.cameraBlendCamera}ensureCameraBlendSource(){return this.cameraBlendSource||(this.cameraBlendSource=new s.PerspectiveCamera),this.cameraBlendSource}ensureCameraBlendOutSource(){return this.cameraBlendOutSource||(this.cameraBlendOutSource=new s.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 I(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(ue)),t.quaternion.copy(e.getWorldQuaternion(ve)),t.scale.copy(e.getWorldScale(pe)),e instanceof s.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,a,i){e.updateWorldMatrix(!0,!1),t.updateWorldMatrix(!0,!1),a.position.lerpVectors(e.getWorldPosition(ue),t.getWorldPosition(pe),i),a.quaternion.slerpQuaternions(e.getWorldQuaternion(ve),t.getWorldQuaternion(ge),i),a.scale.lerpVectors(e.getWorldScale(ue),t.getWorldScale(pe),i),e instanceof s.PerspectiveCamera&&t instanceof s.PerspectiveCamera?(a.fov=e.fov+(t.fov-e.fov)*i,a.near=e.near+(t.near-e.near)*i,a.far=e.far+(t.far-e.far)*i,a.aspect=t.aspect):t instanceof s.PerspectiveCamera?(a.fov=t.fov,a.near=t.near,a.far=t.far,a.aspect=t.aspect):a.aspect=this.getCurrentCameraAspect(),a.layers.mask=t.layers.mask}evaluateAudioTrack(e,t){if(!this.assetLoader||!e.clips||0===e.clips.length)return;const s=this._state.value===SequencePlaybackState.Playing,a=this.evaluateAudioSubTracks(e,t);e.volume;for(const i of e.clips){const r=i.startTime+i.duration,n=t>=i.startTime&&t<r,o=`${e.id}-${i.id}`;if(n){if(this.activeAudioClips.has(o)||this.activeAudioClips.add(o),s){const s=this.audioByClip.get(o);s&&s.isPlaying||this.tryStartAudioClip(e,i,o,t,a)}const r=this.audioByClip.get(o);r&&this.applyAudioParameters(r,e,i,o,t,a)}else this.activeAudioClips.has(o)&&(this.activeAudioClips.delete(o),this.lastAudioStartAttemptTime.delete(o),this.audioStartInFlight.delete(o),this.stopAudioClip(o))}}tryStartAudioClip(e,t,s,a,i){if(this.audioStartInFlight.has(s))return;const r=this.lastAudioStartAttemptTime.get(s);if(void 0!==r&&a-r<this.audioStartRetryIntervalSeconds)return;this.lastAudioStartAttemptTime.set(s,a);const n=this.playAudioClip(e,t,s,a,i).catch(()=>{}).finally(()=>{this.audioStartInFlight.get(s)===n&&this.audioStartInFlight.delete(s)});this.audioStartInFlight.set(s,n)}applyAudioParameters(e,t,a,i,r,n){const o=n.volume??1,l=Math.random(),c=a.volumeRandomization?(2*l-1)*a.volumeRandomization:0;let h=1;const u=r-a.startTime;u<a.fadeInDuration&&a.fadeInDuration>0?h=u/a.fadeInDuration:u>a.duration-a.fadeOutDuration&&a.fadeOutDuration>0&&(h=(a.duration-u)/a.fadeOutDuration);const p=Math.max(0,(t.volume??1)*o*(a.volume+c)*h);e.setVolume(p);let d=n.detune??0;if(a.pitchRandomization){d+=(2*Math.random()-1)*a.pitchRandomization}if(e.setDetune(d),e.hasPlaybackControl&&e.setPlaybackRate(a.playbackRate*this.timescale),this.audioListener&&this.audioListener.context){const a=this.audioListener.context,r=[],o=n.lowpass,l=n.highpass;let c=this.audioFilters.get(i);if(void 0!==o||void 0!==l)c||(c=a.createBiquadFilter(),this.audioFilters.set(i,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(i)}const h=n.pan;if(!t.spatial&&e instanceof s.Audio&&void 0!==h&&"function"==typeof a.createStereoPanner){let e=this.audioPannerNodes.get(i);e||(e=a.createStereoPanner(),this.audioPannerNodes.set(i,e)),e.pan.value=h,r.push(e)}else{const e=this.audioPannerNodes.get(i);if(e){try{e.disconnect()}catch{}this.audioPannerNodes.delete(i)}}e.setFilters(r)}t.spatial&&e instanceof s.PositionalAudio?this.updatePositionalAudioTransform(e,t,a,n.spatialBlend):void 0!==n.pan&&this.audioListener}updatePositionalAudioTransform(e,t,a,i){let r=null,n=null;const o=a.attachedToTrackId||t.parent?.trackId,l=a.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=ue,n=ve,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 i?s.MathUtils.clamp(i,0,1):1;if(t<1&&this.audioListener){const e=de;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,a,i,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(a);const n=this.clearCounter;try{let i=this.audioBuffers.get(t.audioAssetId);if(!i){let e=this.loadingAudioBuffers.get(t.audioAssetId);e||(e=this.assetLoader.getAudioByAssetId(t.audioAssetId),this.loadingAudioBuffers.set(t.audioAssetId,e));try{i=await e,this.audioBuffers.set(t.audioAssetId,i)}finally{this.loadingAudioBuffers.delete(t.audioAssetId)}}if(n!==this.clearCounter)return;const o=this._time.value,l=t.startTime+t.duration;if(!(o>=t.startTime&&o<l))return;const c=Math.max(0,o-t.startTime),h=t.clipStartOffset+c*t.playbackRate;if(h>=i.duration||c>=t.duration)return;let u=this.audioByClip.get(a);const p=!0===e.spatial,d=u&&!0===u.isPositionalAudio;if(u&&p!==d&&(u.isPlaying&&u.stop(),u.disconnect(),this.audioByClip.delete(a),u=void 0),!u){if(p){const e=new s.PositionalAudio(this.audioListener);e.setRefDistance(10),e.setRolloffFactor(1),u=e}else u=new s.Audio(this.audioListener);this.world&&this.world.scene.add(u),this.audioByClip.set(a,u)}Math.min((t.duration-c)/t.playbackRate,(i.duration-h)/t.playbackRate);u.setLoopStart(t.clipStartOffset),u.setLoopEnd(Math.min(t.clipStartOffset+t.duration,i.duration)),u.setLoop(!0),u.setBuffer(i),this.applyAudioParameters(u,e,t,a,o,r),u.isPlaying||u.play()}catch(e){console.error(`Failed to play audio clip ${t.id}:`,e)}}stopAudioClip(e){const t=this.audioByClip.get(e);if(t){try{t.isPlaying&&t.stop()}catch(e){}t.parent&&t.parent.remove(t),this.audioByClip.delete(e)}const s=this.audioGainNodes.get(e);s&&(s.disconnect(),this.audioGainNodes.delete(e));const a=this.audioFilters.get(e);if(a){try{a.disconnect()}catch{}this.audioFilters.delete(e)}const i=this.audioPannerNodes.get(e);if(i){try{i.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;if(this.shouldPreviewVfxAtSeekTime())return void this.previewVfxTrackAtSeekTime(e,t);const s=new Set,a=new Map;for(const i of e.clips){const r=this.getVfxClipKey(e,i);a.set(r,i),this.isVfxClipActiveAtTime(i,t)&&s.add(r)}const i=[];for(const t of this.activeVfxClips)t.startsWith(`${e.id}-`)&&(s.has(t)||i.push(t));for(const e of i)this.activeVfxClips.delete(e);for(const[i,r]of a.entries()){const a=this.vfxActors.get(i);s.has(i)&&!this.activeVfxClips.has(i)?(this.activeVfxClips.add(i),this.ensureVfxActor(e,r,i)):s.has(i)&&a?this.updateVfxTransform(e,a,t):a&&this.applyInactiveVfxClipBehavior(r,a,t)}}getVfxClipKey(e,t){return`${e.id}-${t.id}-${t.vfxAssetId}`}isVfxClipActiveAtTime(e,t){const s=e.startTime+e.duration;return t>=e.startTime&&t<s}shouldPreviewVfxAtSeekTime(){return this._externalTimeControl&&this._inEditor&&this._state.value!==SequencePlaybackState.Playing}previewVfxTrackAtSeekTime(e,t){const s=new Set;for(const a of e.clips){const i=this.getVfxClipKey(e,a),r=this.vfxActors.get(i);this.isVfxClipActiveAtTime(a,t)&&s.add(i),t<a.startTime?r?.clearPreview():r?this.previewVfxActorAtSeekTime(e,a,r,t):this.ensureVfxActor(e,a,i)}for(const t of[...this.activeVfxClips])t.startsWith(`${e.id}-`)&&!s.has(t)&&this.activeVfxClips.delete(t);for(const e of s)this.activeVfxClips.add(e)}previewVfxActorAtSeekTime(e,t,s,a){const i=t.startTime+t.duration;this.updateVfxTransform(e,s,Math.min(a,i)),s.previewAt(a-t.startTime,t.duration,t.endBehavior,t.expireWithinSeconds,p(this.getVfxClipKey(e,t)))}resetVfxForTimeReset(e){const t=new Set;if(this.sequenceData)for(const s of oe(this.sequenceData.tracks))if("vfx"===s.type)for(const a of s.clips??[])this.isVfxClipActiveAtTime(a,e)&&t.add(this.getVfxClipKey(s,a));this.activeVfxClips.clear();for(const[e,s]of this.vfxActors.entries())t.has(e)||(s.restart(),s.stop(),s.pause())}applyInactiveVfxClipBehavior(e,t,s){const a=e.endBehavior??"finish";if("finish"===a)return void t.stop();if("kill"===a)return void t.applyClipEndBehavior(a);const i=e.startTime+e.duration,r=Math.max(s-i,0),n=Math.max(0,e.expireWithinSeconds??.25),o=Math.max(0,n-r);t.applyClipEndBehavior(a,o)}async ensureVfxActor(e,t,s){if(!this.vfxService||!t.vfxAssetId)return;if(this.vfxActors.has(s)){const e=this.vfxActors.get(s);return e.restart(),void e.play()}const a=this.clearCounter;try{const i=this._inEditor&&this._externalTimeControl?{backend:"cpu"}:void 0,r=await this.vfxService.createFromAssetId(t.vfxAssetId,this.world.scene,i);if(a!==this.clearCounter)return void(this.world&&this.world.removeActor(r));const{position:n,rotation:o,scale:l}=this.getVfxTransform(e,t.startTime);r.object.position.copy(n),r.object.rotation.copy(o),r.object.scale.copy(l),this.vfxActors.set(s,r),this.shouldPreviewVfxAtSeekTime()?this.previewVfxActorAtSeekTime(e,t,r,this._time.value):this._state.value===SequencePlaybackState.Playing&&r.play()}catch(e){console.error(`Failed to create VFX actor for clip ${t.id}:`,e)}}getVfxTransform(e,t){const s=new c,a=new r,i=new c(1,1,1),n=e.subTracks.find(e=>"transform"===e.type);if(n&&n.keyframes.length>0){const{prev:e,next:r,prevIndex:l,nextIndex:c,t:h}=B(n.keyframes,t);if(n.components.position&&O(n.keyframes,l,c,h,s),e&&(e.rotation&&a.fromArray([...e.rotation,"XYZ"]),e.scale&&i.fromArray(e.scale)),r&&e!==r&&e.time!==r.time){const t=I(h,e.interpolation);if(e.rotation&&r.rotation){ve.setFromEuler(Ce.fromArray([...e.rotation,"XYZ"])),ge.setFromEuler(Ae.fromArray([...r.rotation,"XYZ"]));const s=new o;s.slerpQuaternions(ve,ge,t),a.setFromQuaternion(s)}e.scale&&r.scale&&i.lerpVectors(ue.fromArray(e.scale),pe.fromArray(r.scale),t)}}else s.fromArray(e.position),a.fromArray([...e.rotation,"XYZ"]),i.fromArray(e.scale);return{position:s,rotation:a,scale:i}}updateVfxTransform(e,t,s){const{position:a,rotation:i,scale:r}=this.getVfxTransform(e,s);t.object.position.copy(a),t.object.rotation.copy(i),t.object.scale.copy(r)}resolveActorType(e){const t=this.actorFactory.classes[e];if(null!=t)return t;const s=f[e];return s||(console.warn(`Could not resolve actor type: ${e}`),null)}async spawnActorForClip(e,t,s,a){if(!this.world||!e.actorType)return null;const i=this.resolveActorType(e.actorType);if(!i)return null;try{return await this.world.spawnActor(i,s,a)}catch(t){return console.error(`Failed to spawn actor ${e.actorType}:`,t),null}}async spawnPrefabForClip(e,t,s,a){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,s,a)}catch(t){return console.error(`Failed to spawn prefab ${e.prefabId}:`,t),null}}async spawnMeshForClip(e,t,s,a){if(!this.world||!this.assetLoader||!e.meshId)return null;try{const t=await this.assetLoader.getAsset(e.meshId),i=await this.assetLoader.getModelByAssetId(e.meshId),r=j.clone(i.scene);if(r.position.copy(s),r.rotation.copy(a),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.restoreVisibilitySnapshotsForInstance(e),this.restorePropertySnapshotsForInstance(e),this.restoreMaterialSnapshotsForInstance(e),this.world)switch(e?.type){case"actor":this.world.removeActor(e.instance);break;case"prefab":this.world.removePrefab(e.instance);break;case"mesh":this.world.scene.remove(e.instance)}}despawnAll(){for(const e of this.spawnedInstances.values())this.despawnInstance(e);this.spawnedInstances.clear(),this.activeClips.clear(),this.pendingSpawns.clear()}getInitialTransform(e,t,s){const a=new c,i=new r,n=e.subTracks.find(e=>"transform"===e.type);if(n&&n.keyframes.length>0){const{prev:e,prevIndex:t,nextIndex:r,t:o}=B(n.keyframes,s);n.components.position&&O(n.keyframes,t,r,o,a),e&&e.rotation&&i.fromArray([...e.rotation,"XYZ"])}else t.initialPosition&&a.fromArray(t.initialPosition),t.initialRotation&&i.fromArray([...t.initialRotation,"XYZ"]);return{position:a,rotation:i}}evaluateSpawnTrack(e,t,s){if(!e.clips||0===e.clips.length)return;const a=t||this.bindings.get(e.id);if(a&&a.target)for(const t of e.clips){const i=t.startTime+t.duration,r=s>=t.startTime&&s<i,n=`${e.id}-${t.id}`;if(r){this.activeClips.has(n)||(this.activeClips.add(n),this.spawnedInstances.set(n,{type:"proxy",target:a.target}));(a.target instanceof d?a.target.object:a.target)&&this.evaluateSubTracks(e.subTracks,a,s)}else if(this.activeClips.has(n)){e.clips.some(e=>e!==t&&s>=e.startTime&&s<e.startTime+e.duration)||this.deactivateAnimationSubTracks(e.subTracks,a),this.clearExternalRootMotionPreview(a),this.restorePropertySnapshotsForTarget(a.target),this.restoreMaterialSnapshotsForTarget(a.target),this.restoreVisibilitySnapshotForObject(this.getPlayableObject(a)),this.activeClips.delete(n),this.spawnedInstances.delete(n)}}else for(const t of e.clips){const a=t.startTime+t.duration,i=s>=t.startTime&&s<a,r=`${e.id}-${t.id}`,n=this.spawnedInstances.has(r),o=this.pendingSpawns.has(r);if(!i||n||o){if(i&&n){const t=this.spawnedInstances.get(r);t&&"proxy"!==t.type&&this.evaluateSubTracks(e.subTracks,t,s)}else if(!i&&n){const e=this.spawnedInstances.get(r);e&&(this.despawnInstance(e),this.spawnedInstances.delete(r),this.activeClips.delete(r))}}else{const{position:s,rotation:a}=this.getInitialTransform(e,t,t.startTime);this.pendingSpawns.add(r),this.spawnForClip(e,t,s,a,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 d?e.target.object:e.target;default:return null}}async spawnForClip(e,t,s,i,r){const n=this.clearCounter;let o=null;try{switch(e.spawnType){case"actor":const a=await this.spawnActorForClip(e,t,s,i);a&&(o={type:"actor",instance:a});break;case"prefab":const r=await this.spawnPrefabForClip(e,t,s,i);r&&(o={type:"prefab",instance:r});break;case"mesh":const n=await this.spawnMeshForClip(e,t,s,i);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 a(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 d?e.target.object:e.target??null}applyResolvedPropertyValue(e,t,s){if(!t||!e.propertyPath)return;const a=this.getPropertyResolution(t,e);if(!a)return;const i=this.getPropertySnapshotKey(e);this.capturePropertySnapshot(t,i,a);const n=function(e,t){switch(t.type){case v.Number:return"number"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case v.Boolean:return"boolean"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case v.String:return"string"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case v.Vector2:return J(e,t.value);case v.Vector3:return ee(e,t.value);case v.Vector4:return te(e,t.value);case v.Euler:return function(e,t){const s=ae(t,3);if(!s)return{applied:!1};const a=Array.isArray(t)&&"string"==typeof t[3]?t[3]:"XYZ";if(e instanceof r)return e.set(s[0],s[1],s[2],a),{applied:!0,value:e};return{applied:!0,value:new r(s[0],s[1],s[2],a)}}(e,t.value);case v.Color:return se(e,t.value);default:return{applied:!1}}}(a.owner[a.key],s);n.applied&&(a.owner[a.key]=n.value)}getPropertyResolution(e,t){const s=e,a=this.getPropertySnapshotKey(t);let i=this.propertyResolutionCache.get(s);if(i||(i=new Map,this.propertyResolutionCache.set(s,i)),i.has(a))return i.get(a)??null;const r=this.getPropertyPathSegments(t.propertyPath);if(0===r.length)return i.set(a,null),null;let n=e;for(let e=0;e<r.length-1;e++){if(!Y(n))return i.set(a,null),null;n=n[r[e]]}if(!Y(n))return i.set(a,null),null;const o={owner:n,key:r[r.length-1]};return i.set(a,o),o}getPropertyPathSegments(e){const t=this.propertyPathSegments.get(e);if(t)return t;const s=e.split(".").map(e=>e.trim()).filter(Boolean);return this.propertyPathSegments.set(e,s),s}getPropertySnapshotKey(e){return`${e.id}:${e.propertyPath}`}capturePropertySnapshot(e,t,s){const a=e;let i=this.propertySnapshots.get(a);if(i||(i=new Map,this.propertySnapshots.set(a,i)),i.has(t))return;const r=s.owner[s.key];i.set(t,{resolution:s,hadOwnProperty:Object.prototype.hasOwnProperty.call(s.owner,s.key),value:r,valueSnapshot:re(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,s=this.propertySnapshots.get(t);if(s){for(const e of s.values())ne(e);this.propertySnapshots.delete(t),this.propertyResolutionCache.delete(t)}}restoreAllPropertySnapshots(){for(const e of Array.from(this.propertySnapshots.keys()))this.restorePropertySnapshotsForTarget(e)}restoreMaterialSnapshotsForInstance(e){switch(e.type){case"actor":case"mesh":this.restoreMaterialSnapshotsForTarget(e.instance);break;case"prefab":this.restoreMaterialSnapshotsForTarget(e.target??null),this.restoreMaterialSnapshotsForTarget(e.instance.mainActor??null),this.restoreMaterialSnapshotsForTarget(e.instance.object);break;case"proxy":this.restoreMaterialSnapshotsForTarget(e.target)}}restoreMaterialSnapshotsForTarget(e){if(!e)return;const t=e;this.materialResolutionCache.delete(t);const s=this.materialSnapshots.get(t);if(s){for(const e of s.values())null==e.materialIndex?e.owner.material=e.originalMaterial:Array.isArray(e.owner.material)&&(e.owner.material[e.materialIndex]=e.originalMaterial),e.controlledMaterial!==e.originalMaterial&&e.controlledMaterial.dispose();this.materialSnapshots.delete(t)}}restoreAllMaterialSnapshots(){for(const e of Array.from(this.materialSnapshots.keys()))this.restoreMaterialSnapshotsForTarget(e)}restoreVisibilitySnapshotForObject(e){if(!e)return;const t=this.visibilitySnapshots.get(e);t&&(e.visible=t.visible,this.visibilitySnapshots.delete(e))}restoreVisibilitySnapshotsForInstance(e){this.restoreVisibilitySnapshotForObject(this.getInstanceObject(e))}restoreAllVisibilitySnapshots(){for(const e of Array.from(this.visibilitySnapshots.keys()))this.restoreVisibilitySnapshotForObject(e)}applyResolvedMaterialValue(e,t,s){if(!t)return;if("asset"===w(e)&&!e.materialAssetId)return;if("outlineVisibility"===b(e))return void this.applyResolvedMaterialOutlineVisibility(e,t,s);if(!e.uniformName)return;const a=this.getMaterialSlotResolutions(t,e);for(const i of a){const a=this.ensureSequenceControlledMaterial(t,i),r=a.uniforms?.[e.uniformName];if(!r)continue;const n=Z(r.value,s);n.applied&&(r.value=n.value,a.uniformsNeedUpdate=!0,K(a))}}applyResolvedMaterialOutlineVisibility(e,t,s){if(s.type!==v.Boolean||"boolean"!=typeof s.value)return;const a=this.getMaterialSlotResolutions(t,e);for(const e of a){const a=this.ensureSequenceControlledMaterial(t,e),i=a.userData?.outlineParameters;null!=i&&(i.visible=s.value)}}getMaterialSlotResolutions(e,t){const s=e,a=w(t),i=b(t),r=`${t.id}:${i}:${a}:${t.materialAssetId??""}:${t.uniformName}`;let n=this.materialResolutionCache.get(s);n||(n=new Map,this.materialResolutionCache.set(s,n));const o=n.get(r);if(o)return o;const l=e instanceof d?e.object:e,c=[];return l.traverse(e=>{const s=e.material;if(Array.isArray(s))for(let a=0;a<s.length;a++){const i=s[a];H(i,t)&&c.push({owner:e,materialIndex:a,material:i,key:`${e.uuid}:${a}`})}else H(s,t)&&c.push({owner:e,materialIndex:null,material:s,key:`${e.uuid}:material`})}),n.set(r,c),c}ensureSequenceControlledMaterial(e,t){const s=e;let a=this.materialSnapshots.get(s);a||(a=new Map,this.materialSnapshots.set(s,a));const i=a.get(t.key);if(i)return i.controlledMaterial;const r=t.material.clone();return r.userData={...t.material.userData??{}},null!=t.material.userData?.outlineParameters&&(r.userData.outlineParameters={...t.material.userData.outlineParameters}),null==t.materialIndex?t.owner.material=r:Array.isArray(t.owner.material)&&(t.owner.material[t.materialIndex]=r),a.set(t.key,{owner:t.owner,materialIndex:t.materialIndex,originalMaterial:t.material,controlledMaterial:r}),r}animationClipCacheKey(e,t){return`${e}|${t??""}`}async ensureAnimationClip(e,t){if(!this.assetLoader)return null;const s=this.animationClipCacheKey(e,t),a=this.animationClips.get(s);if(a)return a;const i=this.loadingAnimationClips.get(s);if(i)return i;const r=(async()=>{try{const a=await this.assetLoader.getAnimationClipForTargetByAssetId(e,t);return a&&this.animationClips.set(s,a),a}catch(s){return console.error(`Failed to load animation clip for asset ${e}`+(null==t?"":` and target rig ${t}`)+":",s),null}finally{this.loadingAnimationClips.get(s)===r&&this.loadingAnimationClips.delete(s)}})();return this.loadingAnimationClips.set(s,r),r}prepareAnimationPlayback(e,t,s){if(!L(s)){let e=t;return s.clipEndOffset>0&&(e=e.clone(),N(e,$(t)),e.duration=Math.max(0,e.duration-s.clipEndOffset)),s.rootMotion&&(e=F(e,s)),{clip:e,timeScale:s.playbackRate*this._timescale,startOffset:s.clipStartOffset}}return{clip:this.getPlayableAnimationClip(e,t,s,!1),timeScale:1*this._timescale,startOffset:0}}getPlayableAnimationClip(e,t,s,a){if(!L(s)){const e=s.rootMotion?F(t,s):t;return a?D.fromClip(e,!1):e}const i=`${s.id}:${a?"root":"base"}`,r=`${V(s)}|${a?"root":"base"}`,n=this.retimedAnimationClips.get(i);if(n&&n.assetId===e&&n.signature===r)return n.clip;const o=E(t,s),l=s.rootMotion?F(o,s):o,c=a?D.fromClip(l,!1):l;return this.retimedAnimationClips.set(i,{assetId:e,signature:r,clip:c}),c}getAnimationPlaybackLocalTime(e,t){const s=Math.max(0,t-e.startTime);return L(e)?s:s*e.playbackRate+e.clipStartOffset}clearRetimedAnimationClipCache(e){if(null!=e)for(const[t,s]of this.retimedAnimationClips.entries())s.assetId===e&&this.retimedAnimationClips.delete(t);else this.retimedAnimationClips.clear()}captureOriginalTransforms(){for(const e of this.bindings.values()){const t=e.target instanceof d?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 d?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,s]of e.activeActions.entries())e.charAnimActionKeys?.has(t)||s.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.clearSequenceLights(),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 s=this.getActiveObjectsForTrack(e);if(0===s.length)return;const a="spawn"===e.type&&null!=t?.target;let i=null;const r=e.parent?.trackId;if(r){const t=this.sequenceData?oe(this.sequenceData.tracks).find(e=>e.id===r):void 0;if(t){const s=this.getActiveObjectsForTrack(t);if(s.length>0&&(i=s[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 d?t.object:t,e.parentRoleSocketName){const t=this.findSocket(i,e.parentRoleSocketName);t&&(i=t)}}for(const r of s)i?r.parent!==i&&(i.add(r),!t||"object"!==e.type&&"locator"!==e.type||(t.currentParent=i)):t?.currentParent&&t.currentParent===r.parent?this.restoreObjectParent(t,r):r.parent&&r.parent!==this.world?.scene&&"object"!==e.type&&"locator"!==e.type&&!a&&this.world?.scene.add(r)}findSocket(e,t){if(e.name===t)return e;if(e instanceof s.SkinnedMesh){const s=e.skeleton.bones.find(e=>e.name===t);if(s)return s}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 d?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("light"===e.type)return[this.ensureSequenceLight(e)];if("spawn"===e.type){const t=[];for(const[s,a]of this.spawnedInstances)if(s.startsWith(e.id+"-")&&this.activeClips.has(s)){const e=this.getInstanceObject(a);e&&t.push(e)}return t}if("vfx"===e.type){const t=[];for(const s of this.activeVfxClips)if(s.startsWith(e.id+"-")){const e=this.vfxActors.get(s);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 d?e.target.object:e.target;t&&this.restoreObjectParent(e,t)}}evaluateAudioSubTracks(e,t){const s={};for(const a of e.subTracks)if("audioParameter"===a.type){const e=a,i=S(e.parameter),r=q(e.keyframes,t,{min:i.min,max:i.max});void 0!==r&&(s[e.parameter]=r)}return s}stringToRandom(e){let t=0;for(let s=0;s<e.length;s++){t=(t<<5)-t+e.charCodeAt(s),t&=t}const s=1e4*Math.sin(t);return s-Math.floor(s)}async refreshAsset(e){let t=!1;this.assetLoader?.clearCacheById(e),this.animationClips.delete(e),this.loadingAnimationClips.delete(e),this.clearRetimedAnimationClipCache(e),this.vfxService?.clearPool(e),t=this.refreshVfxActorsForAssetIds(new Set([e]))||t;for(const[s,a]of this.activePostProcessClips.entries())a.assetId===e&&(this.releasePostProcessClipEffect(s),t=!0);t=this.refreshSpawnedInstancesForClipKeys(this.getSpawnClipKeysForAsset(e))||t;const s=await this.getAssetOrNull(e);return"shaderGraph"===s?.type&&(t=await this.refreshShaderGraphDependentAssets(e)||t),t}refreshVfxActorsForAssetIds(e){let t=!1;for(const[s,a]of this.vfxActors.entries())this.vfxClipKeyUsesAnyAsset(s,e)&&(this.world&&this.world.removeActor(a),this.vfxActors.delete(s),this.activeVfxClips.delete(s),t=!0);return t}vfxClipKeyUsesAnyAsset(e,t){for(const s of t)if(e.endsWith(`-${s}`))return!0;return!1}refreshSpawnedInstancesForClipKeys(e){let t=!1;for(const[s,a]of this.spawnedInstances.entries())e.has(s)&&(this.despawnInstance(a),this.spawnedInstances.delete(s),this.activeClips.delete(s),t=!0);return t}getSpawnClipKeysForAsset(e){const t=new Set;if(!this.sequenceData)return t;for(const s of oe(this.sequenceData.tracks))if("spawn"===s.type&&(s.prefabId===e||s.meshId===e))for(const e of s.clips)t.add(`${s.id}-${e.id}`);return t}async refreshShaderGraphDependentAssets(e){const t=await this.findSequenceVfxAssetIdsUsingShaderGraph(e);for(const e of t)this.vfxService?.clearPool(e);const s=this.refreshVfxActorsForAssetIds(t),a=this.refreshSpawnedInstancesForClipKeys(await this.findSpawnClipKeysUsingShaderGraph(e));return s||a}async findSequenceVfxAssetIdsUsingShaderGraph(e){const t=new Set;if(!this.sequenceData)return t;const s=new Map;for(const a of oe(this.sequenceData.tracks))if("vfx"===a.type)for(const i of a.clips)null==i.vfxAssetId||t.has(i.vfxAssetId)||await this.assetUsesShaderGraph(i.vfxAssetId,e,s)&&t.add(i.vfxAssetId);return t}async findSpawnClipKeysUsingShaderGraph(e){const t=new Set;if(!this.sequenceData)return t;const s=new Map;for(const a of oe(this.sequenceData.tracks))if("spawn"===a.type&&await this.spawnTrackUsesShaderGraph(a,e,s))for(const e of a.clips)t.add(`${a.id}-${e.id}`);return t}async spawnTrackUsesShaderGraph(e,t,s){if(null!=e.meshId&&await this.assetUsesShaderGraph(e.meshId,t,s))return!0;if(null!=e.prefabId&&await this.assetUsesShaderGraph(e.prefabId,t,s))return!0;for(const a of e.subTracks??[])if("material"===a.type&&null!=a.materialAssetId&&await this.assetUsesShaderGraph(a.materialAssetId,t,s))return!0;return!1}assetUsesShaderGraph(e,t,s,a=new Set){if(e===t)return Promise.resolve(!0);if(a.has(e))return Promise.resolve(!1);if(s.has(e))return s.get(e);const i=this.assetUsesShaderGraphUncached(e,t,s,a);return s.set(e,i),i}async assetUsesShaderGraphUncached(e,t,s,a){if(a.has(e))return!1;const i=await this.getAssetOrNull(e);if(null==i)return!1;const r=new Set(a);return r.add(e),!!this.materialAssetUsesShaderGraph(i,t)||("mesh"===i.type?this.materialAssignmentsUseShaderGraph(i.materialAssignments,t,s,r):"prefab"===i.type?this.sceneObjectsUseShaderGraph(i.prefab?.objects,t,s,r):"vfx"===i.type&&this.vfxAssetUsesShaderGraph(i,t,s,r))}materialAssetUsesShaderGraph(e,t){return"shaderGraph"===e.type?e.id===t:"asset"===e.material?.shaderGraph?.source&&e.material.shaderGraph.assetId===t}async materialAssignmentsUseShaderGraph(e,t,s,a){for(const i of e??[])if(null!=i.materialId&&"null"!==i.materialId&&await this.assetUsesShaderGraph(i.materialId,t,s,a))return!0;return!1}async sceneObjectsUseShaderGraph(e,t,s,a){for(const i of e??[]){if(await this.materialAssignmentsUseShaderGraph(i.materialAssignments,t,s,a))return!0;if(null!=i.assetId&&("asset_mesh"===i.type||"prefab"===i.type||"vfx"===i.type)&&await this.assetUsesShaderGraph(i.assetId,t,s,a))return!0;if(await this.sceneObjectsUseShaderGraph(i.children,t,s,a))return!0}return!1}async vfxAssetUsesShaderGraph(e,t,s,a){for(const i of e.vfx?.emitters??[])if(await this.emitterUsesShaderGraph(i,t,s,a))return!0;return!1}async emitterUsesShaderGraph(e,t,s,a){if(await this.emitterOutputUsesShaderGraph(e.output,t,s,a))return!0;for(const i of e.children??[])if(await this.emitterUsesShaderGraph(i,t,s,a))return!0;return!1}async emitterOutputUsesShaderGraph(e,t,s,a){const i=e.materialSource??("asset"===e.shaderGraph?.source?"shaderGraph":void 0);return"shaderGraph"===i&&"asset"===e.shaderGraph?.source&&e.shaderGraph.assetId===t||!("material"!==i||!("material"in e)||null==e.material||!await this.assetUsesShaderGraph(e.material,t,s,a))}async getAssetOrNull(e){if(!this.assetLoader)return null;try{return await this.assetLoader.getAsset(e)??null}catch{return null}}async invokeSequenceEvent(e,t,s,a){let i=!1;for(let e=0;e<a.length;e++)if(g(a[e])){i=!0;break}if(i)try{const t=new Array(a.length);for(let e=0;e<a.length;e++)t[e]=C(a[e],this.sequenceEventAsyncResolvers);const i=await Promise.all(t);await s.call(e,...i)}catch(e){console.error(`Failed to call sequence event ${t}:`,e)}else try{const t=new Array(a.length);for(let e=0;e<a.length;e++)t[e]=A(a[e],this.sequenceEventSyncResolvers);s.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,s="object"==typeof t&&null!=t?.id?t.id:"string"==typeof t?t:null;if(null==s)return null;for(const e of this.world.actors){const t=e.object.userData.src??e.object.userData._src;if(t?.id===s)return e}return null}resolveSequenceEventSequence(e){return k(e)?new P(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 X(e){return e.options?.length>0||e.propertyType===v.Boolean||e.propertyType===v.String}function z(e){return"outlineVisibility"===b(e)||e.valueType===v.Boolean||e.valueType===v.String}function Y(e){return"object"==typeof e&&null!=e||"function"==typeof e}function Z(e,t){switch(t.type){case v.Number:return function(e){if("number"==typeof e)return Number.isFinite(e)?{applied:!0,value:e}:{applied:!1};if("string"==typeof e){const t=parseFloat(e);return Number.isFinite(t)?{applied:!0,value:t}:{applied:!1}}return{applied:!1}}(t.value);case v.Boolean:return"boolean"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case v.Vector2:return J(e,t.value);case v.Vector3:return ee(e,t.value);case v.Vector4:return te(e,t.value);case v.Color:return function(e,t){if(e instanceof c){const s=Se.set(0);return ie(s,t)?(e.set(s.r,s.g,s.b),{applied:!0,value:e}):{applied:!1}}if(e instanceof h){const s=Se.set(0);return ie(s,t)?(e.set(s.r,s.g,s.b,e.w),{applied:!0,value:e}):{applied:!1}}return se(e,t)}(e,t.value);default:return{applied:!1}}}function H(e,t){const a=w(t);return!!function(e){return e instanceof s.Material||!0===e?.isMaterial}(e)&&(("asset"!==a||e.userData?.assetId===t.materialAssetId)&&("outlineVisibility"===b(t)?null!=e.userData?.outlineParameters:null!=e.uniforms?.[t.uniformName]))}function J(e,t){const s=ae(t,2);return s?e instanceof l?(e.fromArray(s),{applied:!0,value:e}):{applied:!0,value:new l(s[0],s[1])}:{applied:!1}}function ee(e,t){const s=ae(t,3);return s?e instanceof c?(e.fromArray(s),{applied:!0,value:e}):{applied:!0,value:new c(s[0],s[1],s[2])}:{applied:!1}}function te(e,t){const s=ae(t,4);return s?e instanceof h?(e.fromArray(s),{applied:!0,value:e}):{applied:!0,value:new h(s[0],s[1],s[2],s[3])}:{applied:!1}}function se(e,t){if(e instanceof i)return ie(e,t)?{applied:!0,value:e}:{applied:!1};const s=new i;return ie(s,t)?{applied:!0,value:s}:{applied:!1}}function ae(e,t){if(!Array.isArray(e)||e.length<t)return null;const s=new Array(t);for(let a=0;a<t;a++){if("number"!=typeof e[a])return null;s[a]=e[a]}return s}function ie(e,t){return t instanceof i||"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 re(e){if(e instanceof l||e instanceof c||e instanceof h||e instanceof i||e instanceof r)return e.clone()}function ne(e){const{owner:t,key:s}=e.resolution;e.hadOwnProperty?(!function(e,t){if(e instanceof l&&t instanceof l)return e.copy(t),!0;if(e instanceof c&&t instanceof c)return e.copy(t),!0;if(e instanceof h&&t instanceof h)return e.copy(t),!0;if(e instanceof i&&t instanceof i)return e.copy(t),!0;if(e instanceof r&&t instanceof r)return e.copy(t),!0}(e.value,e.valueSnapshot),t[s]=e.value):delete t[s]}function oe(e){const t=[];for(const s of e)t.push(s),"group"===s.type&&t.push(...oe(s.childTracks));return t}function le(e){if("string"!=typeof e)return null;const t=e.trim();return t.length>0?t:null}function ce(e){const t=new s.Group;t.name=`SequenceLocatorMarker:${e}`,t.renderOrder=1e3;const a=new s.AxesHelper(.35);a.renderOrder=1e3;const i=Array.isArray(a.material)?a.material:[a.material];for(const e of i)e.depthTest=!1,e.transparent=!0,e.opacity=.9,e.toneMapped=!1;t.add(a);const r=function(e){if("undefined"==typeof document)return null;const t=document.createElement("canvas");t.width=256,t.height=64;const a=t.getContext("2d");if(!a)return null;a.clearRect(0,0,t.width,t.height),a.fillStyle="rgba(16, 18, 24, 0.78)",function(e,t,s,a,i,r){const n=t+a,o=s+i;e.beginPath(),e.moveTo(t+r,s),e.lineTo(n-r,s),e.quadraticCurveTo(n,s,n,s+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,s+r),e.quadraticCurveTo(t,s,t+r,s),e.closePath()}(a,0,8,t.width,48,8),a.fill(),a.font="24px sans-serif",a.textAlign="center",a.textBaseline="middle",a.fillStyle="#f8fafc",a.fillText(e||"Locator",t.width/2,t.height/2);const i=new s.CanvasTexture(t);i.needsUpdate=!0;const r=new s.SpriteMaterial({map:i,transparent:!0,depthTest:!1});r.toneMapped=!1;const n=new s.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 he(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 ue=new c,pe=new c,de=new c,fe=new c,me=new c,ye=new c,ve=new o,ge=new o,Ce=new r,Ae=new r,Se=new i;/*
|
|
1
|
+
import{BehaviorSubject as e,Subject as t}from"rxjs";import*as s from"three";import{AnimationMixer as a,Color as i,Euler as r,Object3D as n,Quaternion as o,Vector2 as l,Vector3 as c,Vector4 as h}from"three";import{VisualEffect as u}from"../../effects/vfx/vfx-param.js";import{hashVfxPreviewSeed as p}from"../../effects/vfx/seeded-random.js";import{BaseActor as d}from"../../gameplay/actors/actor.js";import f from"../../gameplay/actors/builtin/index.js";import{Prefab as m,PrefabOf as y}from"../../scene/objects/prefab.js";import{SerializedParamType as v}from"../../scene/model.js";import{customParamValueNeedsAsyncResolution as g,deserializeCustomParamValue as C,deserializeCustomParamValueSync as A}from"../../scene/custom-param-deserialize.js";import{getAudioParameterDefinition as S}from"./audio-parameters.js";import{getMaterialSubTrackMatchMode as w,getMaterialSubTrackTarget as b,Sequence as P,isSequenceData as k}from"./sequence-data.js";import{getSequenceSubTrackDefinition as x,getSequenceTrackDefinition as T}from"./sequence-definitions.js";import{applyInterpolation as I,evaluateCustomParamValueKeyframes as M,evaluateNumericKeyframes as q,findKeyframeSpan as B}from"./sequence-value-lane.js";import{evaluateTransformPositionSpan as O}from"./sequence-transform.js";import{applyAnimationClipRootMotionAxisMask as F,buildRetimedAnimationClip as E,getAnimationClipRetimingSignature as V,isAnimationClipUsingRetiming as L}from"./sequence-animation-retiming.js";import*as j from"three/addons/utils/SkeletonUtils.js";import{CharacterAnimationComponent as R,getCharacterMovementLike as _}from"../../gameplay/actors/index.js";import{RootMotionClip as D}from"../../gameplay/animation/root-motion.js";import{markMaterialUniformValuesNeedUpdate as K}from"../../rendering/node-material-webgpu-resolver.js";import{getAnimationClipRigId as $,getAnimationRigIdFromObject as G,setAnimationClipRigId as N}from"../../gameplay/animation/retarget.js";import{hashCameraShakeSeed as U}from"../../gameplay/services/camera-shake.js";import{buildShaderGraphPostProcessMaterial as W,shaderGraphPostProcessWeightUniformName as Q}from"../../shader/graph/index.js";export var SequencePlaybackState;!function(e){e.Stopped="stopped",e.Playing="playing",e.Paused="paused"}(SequencePlaybackState||(SequencePlaybackState={}));export class SequencePlayer{constructor(){this._state=new e(SequencePlaybackState.Stopped),this._time=new e(0),this._duration=0,this._timescale=1,this._loop=!1,this._externalTimeControl=!1,this._inEditor=!1,this.bindings=new Map,this.roleBindings=new Map,this.sequenceData=null,this.onComplete=new t,this.onLoop=new t,this.vfxCollisionEvent={trackId:"",clipId:"",vfxAssetId:"",emitterId:"",emitterName:"",position:new s.Vector3,normal:new s.Vector3},this.onTimeUpdate=this._time.asObservable(),this.onStateChange=this._state.asObservable(),this.loopCount=0,this.viewController=null,this._cameraControlEnabled=!1,this._cameraControlTrackId=null,this.sequenceCameras=new Map,this.cameraPlayables=new Map,this.cameraBlendCamera=null,this.cameraBlendSource=null,this.cameraBlendOutSource=null,this.cameraOverrideHandle=null,this.activeCameraClipKey=null,this.cameraBlendOutClipKey=null,this.activeCameraShakeClipKeys=new Set,this.nextCameraShakeClipKeys=new Set,this.activePostProcessClips=new Map,this.nextPostProcessClipKeys=new Set,this.sequenceLights=new Map,this.lightPlayables=new Map,this.audioListener=null,this.audioBuffers=new Map,this.loadingAudioBuffers=new Map,this.animationClips=new Map,this.loadingAnimationClips=new Map,this.retimedAnimationClips=new Map,this.externalRootMotionInterpolants=new WeakMap,this.audioByClip=new Map,this.activeAudioClips=new Set,this.audioGainNodes=new Map,this.audioStartInFlight=new Map,this.lastAudioStartAttemptTime=new Map,this.audioStartRetryIntervalSeconds=.25,this.world=null,this.assetLoader=null,this.actorFactory=null,this.vfxService=null,this.spawnedInstances=new Map,this.activeClips=new Set,this.pendingSpawns=new Set,this.vfxActors=new Map,this.activeVfxClips=new Set,this.locatorMarkers=new Map,this.clearCounter=0,this.propertyPathSegments=new Map,this.propertyResolutionCache=new Map,this.propertySnapshots=new Map,this.materialResolutionCache=new Map,this.materialSnapshots=new Map,this.visibilitySnapshots=new Map,this.audioFilters=new Map,this.audioPannerNodes=new Map,this.firedEvents=new Set,this.sequenceEventSyncResolvers={actor:e=>this.resolveSequenceEventActorReference(e)},this.sequenceEventAsyncResolvers={actor:e=>this.resolveSequenceEventActorReference(e),texture:e=>this.assetLoader?.getTextureByAssetId(e)??null,sampler2DNode:e=>this.assetLoader?.getTextureByAssetId(e)??null,object3D:async e=>{const t=await(this.assetLoader?.getModelByAssetId(e));return t?.scene??null},material:e=>this.assetLoader?.getMaterialByAssetId(e)??null,audioBuffer:e=>this.assetLoader?.getAudioByAssetId(e)??null,visualEffect:async e=>{if(!this.assetLoader||!this.actorFactory)return null;const t=await this.assetLoader.getAsset(e);return t?new u(this.actorFactory,t):null},prefab:async e=>{const t=await(this.assetLoader?.getPrefabById(e));return t?new m(t.asset):null},prefabActor:async e=>{const t=await(this.assetLoader?.getPrefabById(e));return t?new y(new m(t.asset)):null},sequence:e=>this.resolveSequenceEventSequence(e),animationClip:e=>this.resolveSequenceEventAnimationClip(e)},this.trackRuntimeEvaluators={object:(e,t,s)=>{t&&this.evaluateObjectTrack(e,t,s)},locator:(e,t,s)=>{t&&this.evaluateLocatorTrack(e,t,s)},camera:(e,t,s)=>this.evaluateCameraTrack(e,s),cameraShake:(e,t,s)=>this.evaluateCameraShakeTrack(e,s),postProcess:(e,t,s)=>this.evaluatePostProcessTrack(e,s),light:(e,t,s)=>this.evaluateLightTrack(e,s),audio:(e,t,s)=>this.evaluateAudioTrack(e,s),vfx:(e,t,s)=>this.evaluateVfxTrack(e,s),spawn:(e,t,s)=>this.evaluateSpawnTrack(e,t,s),group:(e,t,s)=>{if("group"===e.type)for(const t of e.childTracks)this.evaluateTrack(t,s)}},this.subTrackRuntimeEvaluators={transform:(e,t,s)=>{const a=this.getPlayableObject(t);a&&this.evaluateTransformSubTrack(e,a,s)},animation:(e,t,s)=>this.evaluateAnimationSubTrack(e,t,s),visibility:(e,t,s)=>{const a=this.getPlayableObject(t);a&&this.evaluateVisibilitySubTrack(e,a,s)},parameter:(e,t,s)=>this.evaluateParameterSubTrack(e,t.target||null,s),event:(e,t,s)=>this.evaluateEventSubTrack(e,t.target||null,s)}}get state(){return this._state.value}get time(){return this._time.value}get duration(){return this._duration}get timescale(){return this._timescale}set timescale(e){this._timescale=Math.max(.01,e)}get loop(){return this._loop}set loop(e){this._loop=e}get externalTimeControl(){return this._externalTimeControl}set externalTimeControl(e){this._externalTimeControl=e}get inEditor(){return this._inEditor}set inEditor(e){this._inEditor=e,this.updateLocatorMarkerVisibility()}get cameraControlEnabled(){return this._cameraControlEnabled}set cameraControlEnabled(e){this._cameraControlEnabled=e,e||this.releaseCameraOverride()}get cameraControlTrackId(){return this._cameraControlTrackId}set cameraControlTrackId(e){this._cameraControlTrackId!==e&&(this._cameraControlTrackId=e,this.releaseCameraOverride())}setViewController(e){this.viewController&&this.viewController!==e&&this.viewController.clearCameraShakeContributionsForOwner(this),this.viewController=e}setWorld(e){this.world!==e&&(this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.clearLocatorBindings(),this.clearSequenceCameras(),this.clearSequenceLights(),this.clearCameraShakeContributions(),this.clearPostProcessEffects(),this.world=e,this.clearCounter++,this.vfxActors.clear(),this.spawnedInstances.clear(),this.bindings.clear(),this.activeClips.clear(),this.activeVfxClips.clear(),this.activeAudioClips.clear(),this.audioStartInFlight.clear(),this.lastAudioStartAttemptTime.clear(),this.loadingAudioBuffers.clear(),this.audioFilters.clear(),this.audioPannerNodes.clear(),this.pendingSpawns.clear(),this.propertyResolutionCache.clear(),this.materialResolutionCache.clear(),this.clearRetimedAnimationClipCache(),this._state.next(SequencePlaybackState.Stopped),this.sequenceData&&this.initializeLocatorBindings())}setAudioListener(e){this.audioListener=e}setAssetLoader(e){if(this.assetLoader=e,this.sequenceData){const e=this.clearCounter;this.preloadSequenceResources(this.sequenceData,e)}}setActorFactory(e){this.actorFactory=e}setVfxService(e){this.vfxService=e}load(e){if(this.stop(),this.clearCounter++,this.clearLocatorBindings(),this.clearSequenceCameras(),this.clearSequenceLights(),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 s of e.tracks){if("audio"!==s.type)continue;const e=s;for(const s of e.clips??[])s.audioAssetId&&t.add(s.audioAssetId)}return[...t]}async preloadAudioBuffersForSequence(e,t){if(!this.assetLoader)return;const s=this.getAudioAssetIdsForSequence(e);0!==s.length&&await Promise.all(s.map(async e=>{if(t!==this.clearCounter)return;if(this.audioBuffers.has(e))return;let s=this.loadingAudioBuffers.get(e);s||(s=this.assetLoader.getAudioByAssetId(e),this.loadingAudioBuffers.set(e,s));try{const a=await s;if(t!==this.clearCounter)return;this.audioBuffers.set(e,a)}catch(e){}finally{this.loadingAudioBuffers.get(e)===s&&this.loadingAudioBuffers.delete(e)}}))}async preloadAnimationClipsForSequence(e,t){this.assetLoader&&t===this.clearCounter&&await this.prepareAnimationClipsForBindings(e,t)}async prepare(){if(!this.sequenceData||!this.assetLoader)return;this.resolveBindings();const e=this.clearCounter;await Promise.all([this.prepareAnimationClipsForBindings(this.sequenceData,e),this.prepareVisualEffectsForSequence(this.sequenceData,e)])}async prepareVisualEffectsForSequence(e,t){if(await this.preloadVisualEffectsForSequence(e,t),t!==this.clearCounter||!this.vfxService||!this.world)return;const s=[];for(const t of oe(e.tracks))if("vfx"===t.type&&!t.muted)for(const e of t.clips??[])null!=e.vfxAssetId&&s.push({track:t,clip:e,key:this.getVfxClipKey(t,e)});await Promise.all(s.map(({track:e,clip:t,key:s})=>this.ensureVfxActor(e,t,s)))}async preloadVisualEffectsForSequence(e,t){if(!this.world||!this.actorFactory)return;const s=new Set;for(const t of oe(e.tracks))if("vfx"===t.type)for(const e of t.clips??[])null!=e.vfxAssetId&&s.add(e.vfxAssetId);if(0===s.size)return;const a=await Promise.all([...s].map(e=>this.assetLoader.getAsset(e)));if(t!==this.clearCounter)return;const i=a.filter(e=>null!=e&&null!=e.vfx).map(e=>new u(this.actorFactory,e));await this.world.preloadVisualEffects(i)}async prepareAnimationClipsForBindings(e,t){const s=[];for(const a of oe(e.tracks)){if(!("subTracks"in a))continue;const e=this.bindings.get(a.id),i=null==e?null:this.getPlayableObject(e);if(null==i)continue;const r=G(i);for(const e of a.subTracks)if("animation"===e.type)for(const a of e.clips){if(t!==this.clearCounter)return;if(null!=a.animationClipAssetId){const e=this.animationClipCacheKey(a.animationClipAssetId,r);s.push(this.ensureAnimationClip(a.animationClipAssetId,r).then(s=>{null!=s&&t===this.clearCounter&&L(a)&&(this.getPlayableAnimationClip(e,s,a,!1),a.rootMotion&&this.getPlayableAnimationClip(e,s,a,!0))}))}}}await Promise.all(s)}bindRole(e,t){this.roleBindings.set(e,t),this.sequenceData&&this.resolveBindings()}bindObject(e,t){if(this.sequenceData)for(const s of oe(this.sequenceData.tracks))"object"!==s.type||s.targetId!==e||s.role||this.createBinding(s,t)}unbindObject(e){if(this.sequenceData)for(const t of oe(this.sequenceData.tracks))"object"!==t.type||t.targetId!==e||t.role||this.removeBinding(t.id)}getLocator(e){return this.getLocators(e)[0]??null}getLocators(e){const t=le(e);if(!t||!this.sequenceData)return[];const s=[];for(const e of oe(this.sequenceData.tracks)){if("locator"!==e.type)continue;if(le(e.bindingId)!==t)continue;const a=this.bindings.get(e.id),i=a?this.getPlayableObject(a):null;i&&(i.updateWorldMatrix(!0,!1),s.push({trackId:e.id,name:e.name,bindingId:e.bindingId,position:i.getWorldPosition(new c),rotation:i.getWorldQuaternion(new o),scale:i.getWorldScale(new c)}))}return s}resolveBindings(){if(this.sequenceData)for(const e of this.sequenceData.tracks)this.resolveTrackBinding(e)}initializeLocatorBindings(){if(this.sequenceData)for(const e of oe(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 s=ce(e.name);s.visible=this._inEditor,t.add(s),this.locatorMarkers.set(e.id,s),this.disableLocatorInteraction(t),this.createBinding(e,t)}}clearLocatorBindings(){for(const e of this.locatorMarkers.values())he(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 s=t instanceof d?t.object:t,i=this.bindings.get(e.id),r=null!=i?i.target instanceof d?i.target.object:i.target:null,n=null!=i&&i.target===t&&r===s,o=e.subTracks.some(e=>"animation"===e.type);null==i||n||this.releaseBinding(i);const l=n?i:{track:e,target:t,activeActions:new Map};l.track=e,l.target=t,n||(l.originalTransform={position:s.position.clone(),rotation:s.rotation.clone(),scale:s.scale.clone()},l.originalParent=s.parent),o&&null==l.mixer?l.mixer=new a(s):o||(l.mixer=void 0),this.bindings.set(e.id,l)}removeBinding(e){const t=this.bindings.get(e);t&&(this.releaseBinding(t),this.bindings.delete(e))}releaseBinding(e){this.clearExternalRootMotionPreview(e);for(const[t,s]of e.activeActions.entries())e.charAnimActionKeys?.has(t)||s.stop();e.activeActions.clear(),e.mixer?.stopAllAction(),e.charAnimComponent?.stopSequenceAnimation(),e.charAnimComponent=void 0,e.charAnimActionKeys?.clear()}play(){this._state.value!==SequencePlaybackState.Playing&&this.sequenceData&&(this._state.value===SequencePlaybackState.Stopped&&(this._time.next(0),this.loopCount=0,this.resolveBindings(),this.captureOriginalTransforms()),this._state.next(SequencePlaybackState.Playing),this.evaluate(this._time.value),this.resumeVfx())}pause(){this._state.value===SequencePlaybackState.Playing&&(this._state.next(SequencePlaybackState.Paused),this.pauseAudio(),this.pauseVfx())}pauseAudio(){for(const e of this.audioByClip.values())e.pause()}pauseVfx(){for(const e of this.vfxActors.values())e.pause()}resumeVfx(){for(const[e,t]of this.vfxActors.entries())(this.activeVfxClips.has(e)||t.getParticleCount()>0)&&t.play()}cancel(){this._state.next(SequencePlaybackState.Stopped),this._time.next(0),this.clearCounter++,this.loopCount=0,this.pauseAudio(),this.releaseCameraOverride(),this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.restoreAllVisibilitySnapshots(),this.stopAllAudio(),this.stopAllAnimations(),this.despawnAll(),this.stopAllVfx(),this.firedEvents.clear(),this.clearCameraShakeContributions(),this.clearPostProcessEffects();for(const e of this.sequenceLights.values())e.visible=!1}stop(){this._state.next(SequencePlaybackState.Stopped),this._time.next(0),this.clearCounter++,this.loopCount=0,this.pauseAudio(),this.releaseCameraOverride(),this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.restoreAllVisibilitySnapshots(),this.restoreOriginalTransforms(),this.restoreOriginalParents(),this.stopAllAudio(),this.stopAllAnimations(),this.despawnAll(),this.stopAllVfx(),this.firedEvents.clear(),this.clearCameraShakeContributions(),this.clearPostProcessEffects();for(const e of this.sequenceLights.values())e.visible=!1}restart(){this.stop(),this.play()}seek(e){const t=Math.max(0,Math.min(e,this._duration));t<this._time.value&&this.resetVfxForTimeReset(t),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.charAnimComponent?t.charAnimComponent.evaluateExternalPose(e*this._timescale):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.deactivateCharacterAnimationActions(),this.releaseCameraOverride(),this.clearCameraShakeContributions(),this.clearPostProcessEffects(),this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.restoreAllVisibilitySnapshots(),this._state.next(SequencePlaybackState.Stopped),void this.onComplete.next();{this.loopCount++;const e=t%this._duration;this.resetVfxForTimeReset(e),this._time.next(e),this.firedEvents.clear(),this.onLoop.next(this.loopCount)}}else this._time.next(t);this.evaluate(this._time.value);for(const t of this.bindings.values())t.mixer&&t.mixer.update(e*this._timescale);for(const t of this.spawnedInstances.values())t.mixer&&t.mixer.update(e*this._timescale)}evaluate(e){if(this.sequenceData){this.nextCameraShakeClipKeys.clear(),this.nextPostProcessClipKeys.clear();for(const e of this.sequenceLights.values())e.visible=!1;for(const t of this.sequenceData.tracks){if(!t.muted&&("object"===t.type||"locator"===t.type||"camera"===t.type||"light"===t.type||"spawn"===t.type||"vfx"===t.type)){const e=this.bindings.get(t.id);this.updateTrackParenting(t,e)}this.evaluateTrack(t,e)}this.updateCameraControl(e),this.syncCameraShakeContributions(),this.syncPostProcessEffects()}}evaluateTrack(e,t){if(e.muted)return;const s=this.bindings.get(e.id);(0,this.trackRuntimeEvaluators[T(e.type).runtimeEvaluator])(e,s,t)}evaluateObjectTrack(e,t,s){this.evaluateSubTracks(e.subTracks,t,s)}evaluateLocatorTrack(e,t,s){this.evaluateSubTracks(e.subTracks,t,s)}getActiveTrackObjects(e){if(!this.sequenceData)return[];const t=oe(this.sequenceData.tracks).find(t=>t.id===e);return t?this.getActiveObjectsForTrack(t):[]}evaluateSubTracks(e,t,s){this._externalTimeControl&&this.beginExternalRootMotionPreview(t);for(const a of e){if(a.muted)continue;(0,this.subTrackRuntimeEvaluators[x(a.type).runtimeEvaluator])(a,t,s)}this._externalTimeControl&&this.applyExternalRootMotionPreview(t)}beginExternalRootMotionPreview(e){const t=e.externalRootMotionPreview;if(!t)return;const s=this.getPlayableObject(e);s&&s.position.sub(t.appliedOffset),t.appliedOffset.set(0,0,0),t.sampledOffset.set(0,0,0),t.root=null}sampleExternalRootMotionPreview(e,t,a,i){if(!t.motionTrack)return;let r=this.externalRootMotionInterpolants.get(t);r||(r=t.motionTrack.InterpolantFactoryMethodSmooth([]),this.externalRootMotionInterpolants.set(t,r));const n=e.externalRootMotionPreview??(e.externalRootMotionPreview={appliedOffset:new c,sampledOffset:new c,root:null}),o=Math.max(0,Math.min(i,t.duration)),l=Math.max(o,Math.min(a,t.duration));fe.fromArray(r.evaluate(o)),me.fromArray(r.evaluate(l)),n.sampledOffset.subVectors(me,fe),n.sampledOffset.y=0;const h=this.getPlayableObject(e),u=s.PropertyBinding.parseTrackName(t.motionTrack.name);n.root=h?.getObjectByName(u.nodeName)??h}applyExternalRootMotionPreview(e){const t=e.externalRootMotionPreview,s=this.getPlayableObject(e);t&&s&&t.root&&(t.root.getWorldScale(ye),t.appliedOffset.copy(t.sampledOffset).multiply(ye).applyQuaternion(s.quaternion),s.position.add(t.appliedOffset))}clearExternalRootMotionPreview(e){const t=e.externalRootMotionPreview,s=this.getPlayableObject(e);t&&s&&s.position.sub(t.appliedOffset),e.externalRootMotionPreview=void 0}evaluateTransformSubTrack(e,t,s){const a=e.keyframes;if(0===a.length)return;const{prev:i,next:r,prevIndex:n,nextIndex:o,t:l}=B(a,s);if(i)if(e.components.position&&O(a,n,o,l,t.position),r&&i!==r){const s=I(l,i.interpolation);e.components.rotation&&i.rotation&&r.rotation&&(ve.setFromEuler(Ce.fromArray([...i.rotation,"XYZ"])),ge.setFromEuler(Ae.fromArray([...r.rotation,"XYZ"])),t.quaternion.slerpQuaternions(ve,ge,s)),e.components.scale&&i.scale&&r.scale&&t.scale.lerpVectors(ue.fromArray(i.scale),pe.fromArray(r.scale),s)}else e.components.rotation&&i.rotation&&t.rotation.fromArray([...i.rotation,"XYZ"]),e.components.scale&&i.scale&&t.scale.fromArray(i.scale)}evaluateAnimationSubTrack(e,t,a){if(!t.mixer||!t.activeActions)return;const i=t.target instanceof d?t.target.object:t.target;if(i)for(const r of e.clips){const n=r.startTime+r.duration,o=a>=r.startTime&&a<n,l=`${e.id}-${r.id}`;let c=t.activeActions.get(l),h=!1;if(o){if(!c){h=!0;const e=r.animationClipAssetId;if(null==e)continue;const a=G(i),n=this.animationClipCacheKey(e,a),o=this.animationClips.get(n);if(null==o){this.ensureAnimationClip(e,a);continue}const u=this.prepareAnimationPlayback(n,o,r),p=t;let f=!1;if(t.target instanceof d){p.charAnimComponent||(p.charAnimComponent=t.target.getComponent(R)??void 0);const e=p.charAnimComponent;if(null!=e){const s=r.rootMotion?L(r)?this.getPlayableAnimationClip(n,o,r,!0):D.fromClip(u.clip,!1):u.clip;if(this._externalTimeControl)c=e.beginExternalAnimationControl(s,{timeScale:u.timeScale});else if(e.play(s,{inPlace:!r.rootMotion,loop:!1,priority:20,sequenceControlled:!0,timeScale:u.timeScale,fadeTime:r.fadeInDuration??.2,offset:u.startOffset}),c=e.getFullBodyAction(),r.rootMotion){const e=_(t.target);e&&e.setRootMotionAction(c,{cancelWithJump:e.allowRootMotionJumpCancel,onJumpCancel:()=>this.cancel()})}t.activeActions.set(l,c),p.charAnimActionKeys||(p.charAnimActionKeys=new Set),p.charAnimActionKeys.add(l),f=!0}}f||(c=t.mixer.clipAction(u.clip),c.setLoop(s.LoopOnce,1),c.clampWhenFinished=!0,c.timeScale=u.timeScale,u.startOffset>0&&(c.time=u.startOffset),t.activeActions.set(l,c),c.play())}if(c){const e=t;if(this._externalTimeControl){e.charAnimComponent?.beginExternalControl();const s=this.getAnimationPlaybackLocalTime(r,a),i=Math.min(s,c.getClip().duration);(h||Math.abs(c.time-i)>.001)&&(c.time=i,c.paused=!1,c.play(),e.charAnimComponent?e.charAnimComponent.evaluateExternalPose():t.mixer&&t.mixer.update(0)),r.rootMotion&&c.getClip()instanceof D&&this.sampleExternalRootMotionPreview(t,c.getClip(),i,L(r)?0:r.clipStartOffset)}else e.charAnimComponent?.endExternalControl()}}else c&&this.deactivateAnimationAction(t,l,c)}}deactivateAnimationAction(e,t,s){if(e.activeActions.delete(t),e.charAnimActionKeys?.has(t))return e.charAnimActionKeys.delete(t),void(0===e.charAnimActionKeys.size&&e.charAnimComponent&&(e.charAnimComponent.requestSequenceAnimationRelease(),e.charAnimComponent=void 0));s.stop(),this._externalTimeControl&&e.mixer&&e.mixer.update(0)}deactivateAnimationSubTracks(e,t){for(const s of e)if(!s.muted&&"animation"===s.type)for(const e of s.clips){const a=`${s.id}-${e.id}`,i=t.activeActions.get(a);i&&this.deactivateAnimationAction(t,a,i)}}deactivateCharacterAnimationActions(){for(const e of this.bindings.values())for(const t of[...e.charAnimActionKeys??[]]){const s=e.activeActions.get(t);s?this.deactivateAnimationAction(e,t,s):e.charAnimActionKeys?.delete(t)}}evaluateVisibilitySubTrack(e,t,s){const a=e.keyframes;if(0===a.length)return;let i=a[0];for(const e of a){if(!(e.time<=s))break;i=e}this.visibilitySnapshots.has(t)||this.visibilitySnapshots.set(t,{visible:t.visible}),t.visible=i.visible}evaluatePropertySubTrack(e,t,s){const a=M(e.keyframes,s,{min:e.range?.[0],max:e.range?.[1],stepOnly:X(e)});a&&this.applyResolvedPropertyValue(e,t,a)}evaluateParameterSubTrack(e,t,s){if("audioParameter"===e.type)return;const a=M(e.keyframes,s,"property"===e.type?{min:e.range?.[0],max:e.range?.[1],stepOnly:X(e)}:"material"===e.type?{min:e.range?.[0],max:e.range?.[1],stepOnly:z(e)}:{});a&&("property"!==e.type?this.applyResolvedMaterialValue(e,t,a):this.applyResolvedPropertyValue(e,t,a))}evaluateEventSubTrack(e,t,s){if(t instanceof d&&this._state.value===SequencePlaybackState.Playing)for(const a of e.events){const i=`${e.id}-${a.id}`;if(s>=a.time&&!this.firedEvents.has(i)){if(this.firedEvents.add(i),a.editorOnly&&!this._inEditor)continue;if(!a.functionName)continue;const e=t[a.functionName];"function"==typeof e?this.invokeSequenceEvent(t,a.functionName,e,a.arguments??[]):console.warn(`Sequence event method '${a.functionName}' not found on actor`)}else a.time>s&&this.firedEvents.delete(i)}}evaluateCameraTrack(e,t){const s=this.ensureSequenceCamera(e);this.applyCameraTrackSettings(e,s),this.evaluateSubTracks(e.subTracks,this.getCameraPlayable(e,s),t),s.updateProjectionMatrix()}evaluateCameraShakeTrack(e,t){if(this.viewController)for(const s of e.clips??[]){if(!this.isCameraShakeClipActive(s,t))continue;const e=t-s.startTime,a=s.id;this.nextCameraShakeClipKeys.add(a),this.viewController.setCameraShakeContribution(this,a,s,e,s.seed??U(s.id))}}evaluatePostProcessTrack(e,t){if(this.viewController&&this.assetLoader){for(const s of e.clips??[]){if(!this.isPostProcessClipActive(s,t))continue;const a=this.getPostProcessClipKey(e,s);this.nextPostProcessClipKeys.add(a),this.ensurePostProcessClipEffect(e,s,a);const i=this.activePostProcessClips.get(a);i?.handle&&(i.handle.stage=e.stage,i.handle.priority=e.priority,i.handle.enabled=!0,this.applyPostProcessClipWeight(i.handle,s,t))}this.evaluatePostProcessMaterialSubTracks(e,t)}}evaluatePostProcessMaterialSubTracks(e,t){for(const s of e.subTracks){if(s.muted||"material"!==s.type)continue;const a=M(s.keyframes,t,{min:s.range?.[0],max:s.range?.[1],stepOnly:z(s)});a&&this.applyPostProcessMaterialValue(e.id,s,a)}}evaluateLightTrack(e,t){const s=this.ensureSequenceLight(e);if(this.applyLightTrackSettings(e,s),s.visible=(e.clips??[]).some(e=>t>=e.startTime&&t<e.startTime+e.duration),!s.visible)return;let a=this.lightPlayables.get(e.id);a||(a={target:s},this.lightPlayables.set(e.id,a)),this.evaluateSubTracks(e.subTracks,a,t)}ensureSequenceLight(e){let t=this.sequenceLights.get(e.id);return t?null==t.parent&&this.world?.scene.add(t):(t=new s.PointLight,t.name=e.name||"Sequence Point Light",t.userData.sequenceLightTrackId=e.id,t.visible=!1,this.sequenceLights.set(e.id,t),this.world?.scene.add(t)),t}applyLightTrackSettings(e,t){t.color.set(e.color??"#ffffff"),t.intensity=Math.max(0,e.intensity??10),t.distance=Math.max(0,e.distance??10),t.decay=Math.max(0,e.decay??2),t.castShadow=e.castShadow??!1,t.userData.volumetricIntensity=Math.max(0,e.volumetricIntensity??0)}clearSequenceLights(){for(const e of this.sequenceLights.values())e.removeFromParent(),e.dispose();this.sequenceLights.clear(),this.lightPlayables.clear()}applyPostProcessMaterialValue(e,t,s){if("shaderUniform"===b(t)&&t.uniformName)for(const a of this.activePostProcessClips.values()){if(a.trackId!==e||!a.handle)continue;const i=a.handle.material,r=i.uniforms?.[t.uniformName];if(!r)continue;const n=Z(r.value,s);n.applied&&(r.value=n.value,i.uniformsNeedUpdate=!0,K(i))}}isPostProcessClipActive(e,t){return t>=e.startTime&&t<e.startTime+e.duration}getPostProcessClipKey(e,t){return`${e.id}-${t.id}`}ensurePostProcessClipEffect(e,t,s){const a=t.shaderGraphAssetId;if(!a)return void this.releasePostProcessClipEffect(s);const i=JSON.stringify(t.shaderGraphParams??{}),r=this.activePostProcessClips.get(s);if(r?.assetId===a&&r.paramsSignature===i)return;this.releasePostProcessClipEffect(s);const n={key:s,trackId:e.id,clipId:t.id,assetId:a,paramsSignature:i,version:this.clearCounter};this.activePostProcessClips.set(s,n),this.loadPostProcessClipEffect(e,t,n)}async loadPostProcessClipEffect(e,t,s){if(this.assetLoader&&this.viewController)try{const a=await this.assetLoader.getShaderGraphByAssetId(s.assetId);if(!this.isPostProcessClipEntryCurrent(s))return;if("postProcess"!==a.target)return console.warn(`Sequence post-process clip references shader graph "${s.assetId}" with target "${a.target}"`),void this.releasePostProcessClipEffect(s.key);const i=await this.assetLoader.prepareShaderGraphParameters(a,t.shaderGraphParams??{});if(!this.isPostProcessClipEntryCurrent(s))return;const r=W(a,{parameters:i});if(!this.isPostProcessClipEntryCurrent(s))return void r.dispose();s.handle=this.viewController.addPostProcessEffect(r,{stage:e.stage,priority:e.priority,enabled:!0}),this.applyPostProcessClipWeight(s.handle,t,this._time.value)}catch(e){this.isPostProcessClipEntryCurrent(s)&&this.releasePostProcessClipEffect(s.key),console.error(`Failed to create post-process effect for clip ${t.id}:`,e)}}isPostProcessClipEntryCurrent(e){return this.clearCounter===e.version&&this.activePostProcessClips.get(e.key)===e}applyPostProcessClipWeight(e,t,s){const a=e.material.uniforms?.[Q];null!=a&&(a.value=this.getPostProcessClipWeight(t,s),e.material.uniformsNeedUpdate=!0)}getPostProcessClipWeight(e,t){const s=Math.max(0,t-e.startTime),a=Math.max(0,e.startTime+e.duration-t);let i=1;const r=Math.max(0,e.fadeInDuration??0);r>0&&(i=Math.min(i,s/r));const n=Math.max(0,e.fadeOutDuration??0);return n>0&&(i=Math.min(i,a/n)),Math.max(0,Math.min(1,i))}syncPostProcessEffects(){for(const e of Array.from(this.activePostProcessClips.keys()))this.nextPostProcessClipKeys.has(e)||this.releasePostProcessClipEffect(e);this.nextPostProcessClipKeys.clear()}clearPostProcessEffects(){for(const e of Array.from(this.activePostProcessClips.keys()))this.releasePostProcessClipEffect(e);this.nextPostProcessClipKeys.clear()}releasePostProcessClipEffect(e){const t=this.activePostProcessClips.get(e);if(t&&(this.activePostProcessClips.delete(e),t.handle)){const e=t.handle.material;t.handle.dispose(),e.dispose()}}getCameraPlayable(e,t){let s=this.cameraPlayables.get(e.id);return s?s.target=t:(s={target:t},this.cameraPlayables.set(e.id,s)),s}ensureSequenceCamera(e){let t=this.sequenceCameras.get(e.id);if(t)null==t.parent&&this.world?.scene.add(t);else{const a=e.cameraSettings??{fov:60,near:.1,far:1e3};t=new s.PerspectiveCamera(a.fov??60,this.getCurrentCameraAspect(),a.near??.1,a.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 s=e.cameraSettings??{fov:60,near:.1,far:1e3};t.fov=s.fov??60,t.near=s.near??.1,t.far=s.far??1e3,t.aspect=this.getCurrentCameraAspect()}getCurrentCameraAspect(){const e=this.viewController?.getBaseCamera();if(e instanceof s.PerspectiveCamera&&Number.isFinite(e.aspect)&&e.aspect>0)return e.aspect;const t=this.viewController?.getSourceCamera();return t instanceof s.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 s=this.findBlendOutCameraShot(e);s?this.updateCameraBlendOut(s,e):this.releaseCameraOverride()}findActiveCameraShot(e){if(!this.sequenceData)return null;let t=null;for(const s of oe(this.sequenceData.tracks)){if("camera"!==s.type||s.muted||!this.isCameraControlTrackEligible(s))continue;const a=s.clips??[];for(const i of a)this.isCameraClipActive(i,e)&&(t={track:s,clip:i,camera:this.ensureSequenceCamera(s),key:this.getCameraClipKey(s,i)})}return t}findBlendOutCameraShot(e){if(!this.sequenceData)return null;let t=null;for(const s of oe(this.sequenceData.tracks)){if("camera"!==s.type||s.muted||!this.isCameraControlTrackEligible(s))continue;const a=s.clips??[];for(const i of a){const a=Math.max(0,i.blendOutDuration??0);if(a<=0)continue;const r=this.getCameraClipEnd(i);e>=r&&e<r+a&&(t={track:s,clip:i,camera:this.ensureSequenceCamera(s),key:this.getCameraClipKey(s,i)})}}return t}isCameraControlTrackEligible(e){return null==this._cameraControlTrackId||e.id===this._cameraControlTrackId}updateActiveCameraShot(e,t){if(!this.viewController)return;const s=this.ensureCameraBlendCamera();this.activeCameraClipKey!==e.key&&(this.copyCameraState(this.viewController.getSourceCamera(),this.ensureCameraBlendSource()),this.activeCameraClipKey=e.key,this.cameraBlendOutClipKey=null);const a=Math.max(0,e.clip.blendInDuration??0),i=a<=0?1:this.evaluateCameraBlendAlpha((t-e.clip.startTime)/a,e.clip);i>=1?this.copyCameraState(e.camera,s):this.blendCameraState(this.ensureCameraBlendSource(),e.camera,s,i),s.updateProjectionMatrix(),this.ensureCameraOverride()}updateCameraBlendOut(e,t){if(!this.viewController)return;const s=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 a=this.getCameraClipEnd(e.clip),i=Math.max(0,e.clip.blendOutDuration??0),r=i<=0?1:this.evaluateCameraBlendAlpha((t-a)/i,e.clip);this.blendCameraState(this.ensureCameraBlendOutSource(),this.viewController.getBaseCamera(),s,r),s.updateProjectionMatrix(),this.ensureCameraOverride()}ensureCameraBlendCamera(){return this.cameraBlendCamera||(this.cameraBlendCamera=new s.PerspectiveCamera(60,this.getCurrentCameraAspect(),.1,1e3),this.cameraBlendCamera.name="Sequence Camera Blend"),this.cameraBlendCamera}ensureCameraBlendSource(){return this.cameraBlendSource||(this.cameraBlendSource=new s.PerspectiveCamera),this.cameraBlendSource}ensureCameraBlendOutSource(){return this.cameraBlendOutSource||(this.cameraBlendOutSource=new s.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 I(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(ue)),t.quaternion.copy(e.getWorldQuaternion(ve)),t.scale.copy(e.getWorldScale(pe)),e instanceof s.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,a,i){e.updateWorldMatrix(!0,!1),t.updateWorldMatrix(!0,!1),a.position.lerpVectors(e.getWorldPosition(ue),t.getWorldPosition(pe),i),a.quaternion.slerpQuaternions(e.getWorldQuaternion(ve),t.getWorldQuaternion(ge),i),a.scale.lerpVectors(e.getWorldScale(ue),t.getWorldScale(pe),i),e instanceof s.PerspectiveCamera&&t instanceof s.PerspectiveCamera?(a.fov=e.fov+(t.fov-e.fov)*i,a.near=e.near+(t.near-e.near)*i,a.far=e.far+(t.far-e.far)*i,a.aspect=t.aspect):t instanceof s.PerspectiveCamera?(a.fov=t.fov,a.near=t.near,a.far=t.far,a.aspect=t.aspect):a.aspect=this.getCurrentCameraAspect(),a.layers.mask=t.layers.mask}evaluateAudioTrack(e,t){if(!this.assetLoader||!e.clips||0===e.clips.length)return;const s=this._state.value===SequencePlaybackState.Playing,a=this.evaluateAudioSubTracks(e,t);e.volume;for(const i of e.clips){const r=i.startTime+i.duration,n=t>=i.startTime&&t<r,o=`${e.id}-${i.id}`;if(n){if(this.activeAudioClips.has(o)||this.activeAudioClips.add(o),s){const s=this.audioByClip.get(o);s&&s.isPlaying||this.tryStartAudioClip(e,i,o,t,a)}const r=this.audioByClip.get(o);r&&this.applyAudioParameters(r,e,i,o,t,a)}else this.activeAudioClips.has(o)&&(this.activeAudioClips.delete(o),this.lastAudioStartAttemptTime.delete(o),this.audioStartInFlight.delete(o),this.stopAudioClip(o))}}tryStartAudioClip(e,t,s,a,i){if(this.audioStartInFlight.has(s))return;const r=this.lastAudioStartAttemptTime.get(s);if(void 0!==r&&a-r<this.audioStartRetryIntervalSeconds)return;this.lastAudioStartAttemptTime.set(s,a);const n=this.playAudioClip(e,t,s,a,i).catch(()=>{}).finally(()=>{this.audioStartInFlight.get(s)===n&&this.audioStartInFlight.delete(s)});this.audioStartInFlight.set(s,n)}applyAudioParameters(e,t,a,i,r,n){const o=n.volume??1,l=Math.random(),c=a.volumeRandomization?(2*l-1)*a.volumeRandomization:0;let h=1;const u=r-a.startTime;u<a.fadeInDuration&&a.fadeInDuration>0?h=u/a.fadeInDuration:u>a.duration-a.fadeOutDuration&&a.fadeOutDuration>0&&(h=(a.duration-u)/a.fadeOutDuration);const p=Math.max(0,(t.volume??1)*o*(a.volume+c)*h);e.setVolume(p);let d=n.detune??0;if(a.pitchRandomization){d+=(2*Math.random()-1)*a.pitchRandomization}if(e.setDetune(d),e.hasPlaybackControl&&e.setPlaybackRate(a.playbackRate*this.timescale),this.audioListener&&this.audioListener.context){const a=this.audioListener.context,r=[],o=n.lowpass,l=n.highpass;let c=this.audioFilters.get(i);if(void 0!==o||void 0!==l)c||(c=a.createBiquadFilter(),this.audioFilters.set(i,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(i)}const h=n.pan;if(!t.spatial&&e instanceof s.Audio&&void 0!==h&&"function"==typeof a.createStereoPanner){let e=this.audioPannerNodes.get(i);e||(e=a.createStereoPanner(),this.audioPannerNodes.set(i,e)),e.pan.value=h,r.push(e)}else{const e=this.audioPannerNodes.get(i);if(e){try{e.disconnect()}catch{}this.audioPannerNodes.delete(i)}}e.setFilters(r)}t.spatial&&e instanceof s.PositionalAudio?this.updatePositionalAudioTransform(e,t,a,n.spatialBlend):void 0!==n.pan&&this.audioListener}updatePositionalAudioTransform(e,t,a,i){let r=null,n=null;const o=a.attachedToTrackId||t.parent?.trackId,l=a.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=ue,n=ve,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 i?s.MathUtils.clamp(i,0,1):1;if(t<1&&this.audioListener){const e=de;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,a,i,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(a);const n=this.clearCounter;try{let i=this.audioBuffers.get(t.audioAssetId);if(!i){let e=this.loadingAudioBuffers.get(t.audioAssetId);e||(e=this.assetLoader.getAudioByAssetId(t.audioAssetId),this.loadingAudioBuffers.set(t.audioAssetId,e));try{i=await e,this.audioBuffers.set(t.audioAssetId,i)}finally{this.loadingAudioBuffers.delete(t.audioAssetId)}}if(n!==this.clearCounter)return;const o=this._time.value,l=t.startTime+t.duration;if(!(o>=t.startTime&&o<l))return;const c=Math.max(0,o-t.startTime),h=t.clipStartOffset+c*t.playbackRate;if(h>=i.duration||c>=t.duration)return;let u=this.audioByClip.get(a);const p=!0===e.spatial,d=u&&!0===u.isPositionalAudio;if(u&&p!==d&&(u.isPlaying&&u.stop(),u.disconnect(),this.audioByClip.delete(a),u=void 0),!u){if(p){const e=new s.PositionalAudio(this.audioListener);e.setRefDistance(10),e.setRolloffFactor(1),u=e}else u=new s.Audio(this.audioListener);this.world&&this.world.scene.add(u),this.audioByClip.set(a,u)}Math.min((t.duration-c)/t.playbackRate,(i.duration-h)/t.playbackRate);u.setLoopStart(t.clipStartOffset),u.setLoopEnd(Math.min(t.clipStartOffset+t.duration,i.duration)),u.setLoop(!0),u.setBuffer(i),this.applyAudioParameters(u,e,t,a,o,r),u.isPlaying||u.play()}catch(e){console.error(`Failed to play audio clip ${t.id}:`,e)}}stopAudioClip(e){const t=this.audioByClip.get(e);if(t){try{t.isPlaying&&t.stop()}catch(e){}t.parent&&t.parent.remove(t),this.audioByClip.delete(e)}const s=this.audioGainNodes.get(e);s&&(s.disconnect(),this.audioGainNodes.delete(e));const a=this.audioFilters.get(e);if(a){try{a.disconnect()}catch{}this.audioFilters.delete(e)}const i=this.audioPannerNodes.get(e);if(i){try{i.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;if(this.shouldPreviewVfxAtSeekTime())return void this.previewVfxTrackAtSeekTime(e,t);const s=new Set,a=new Map;for(const i of e.clips){const r=this.getVfxClipKey(e,i);a.set(r,i),this.isVfxClipActiveAtTime(i,t)&&s.add(r)}const i=[];for(const t of this.activeVfxClips)t.startsWith(`${e.id}-`)&&(s.has(t)||i.push(t));for(const e of i)this.activeVfxClips.delete(e);for(const[i,r]of a.entries()){const a=this.vfxActors.get(i);s.has(i)&&!this.activeVfxClips.has(i)?(this.activeVfxClips.add(i),this.ensureVfxActor(e,r,i)):s.has(i)&&a?this.updateVfxTransform(e,a,t):a&&this.applyInactiveVfxClipBehavior(r,a,t)}}getVfxClipKey(e,t){return`${e.id}-${t.id}-${t.vfxAssetId}`}isVfxClipActiveAtTime(e,t){const s=e.startTime+e.duration;return t>=e.startTime&&t<s}shouldPreviewVfxAtSeekTime(){return this._externalTimeControl&&this._inEditor&&this._state.value!==SequencePlaybackState.Playing}previewVfxTrackAtSeekTime(e,t){const s=new Set;for(const a of e.clips){const i=this.getVfxClipKey(e,a),r=this.vfxActors.get(i);this.isVfxClipActiveAtTime(a,t)&&s.add(i),t<a.startTime?r?.clearPreview():r?this.previewVfxActorAtSeekTime(e,a,r,t):this.ensureVfxActor(e,a,i)}for(const t of[...this.activeVfxClips])t.startsWith(`${e.id}-`)&&!s.has(t)&&this.activeVfxClips.delete(t);for(const e of s)this.activeVfxClips.add(e)}previewVfxActorAtSeekTime(e,t,s,a){const i=t.startTime+t.duration;this.updateVfxTransform(e,s,Math.min(a,i)),s.previewAt(a-t.startTime,t.duration,t.endBehavior,t.expireWithinSeconds,p(this.getVfxClipKey(e,t)))}resetVfxForTimeReset(e){const t=new Set;if(this.sequenceData)for(const s of oe(this.sequenceData.tracks))if("vfx"===s.type)for(const a of s.clips??[])this.isVfxClipActiveAtTime(a,e)&&t.add(this.getVfxClipKey(s,a));this.activeVfxClips.clear();for(const[e,s]of this.vfxActors.entries())t.has(e)||(s.restart(),s.stop(),s.pause())}applyInactiveVfxClipBehavior(e,t,s){const a=e.endBehavior??"finish";if("finish"===a)return void t.stop();if("kill"===a)return void t.applyClipEndBehavior(a);const i=e.startTime+e.duration,r=Math.max(s-i,0),n=Math.max(0,e.expireWithinSeconds??.25),o=Math.max(0,n-r);t.applyClipEndBehavior(a,o)}async ensureVfxActor(e,t,s){if(!this.vfxService||!t.vfxAssetId)return;if(this.vfxActors.has(s)){const e=this.vfxActors.get(s);return e.restart(),void e.play()}const a=this.clearCounter;try{const i=this._inEditor&&this._externalTimeControl?{backend:"cpu"}:void 0,r=await this.vfxService.createFromAssetId(t.vfxAssetId,this.world.scene,i);if(a!==this.clearCounter)return void(this.world&&this.world.removeActor(r));const{position:n,rotation:o,scale:l}=this.getVfxTransform(e,t.startTime);r.object.position.copy(n),r.object.rotation.copy(o),r.object.scale.copy(l),r.onCollision=s=>{if(this._state.value!==SequencePlaybackState.Playing||null==this.onVfxCollision)return;const a=this.vfxCollisionEvent;a.trackId=e.id,a.clipId=t.id,a.vfxAssetId=t.vfxAssetId,a.emitterId=s.emitterId,a.emitterName=s.emitterName,a.position.copy(s.position),a.normal.copy(s.normal),this.onVfxCollision(a)},this.vfxActors.set(s,r),this.shouldPreviewVfxAtSeekTime()?this.previewVfxActorAtSeekTime(e,t,r,this._time.value):this._state.value===SequencePlaybackState.Playing&&r.play()}catch(e){console.error(`Failed to create VFX actor for clip ${t.id}:`,e)}}getVfxTransform(e,t){const s=new c,a=new r,i=new c(1,1,1),n=e.subTracks.find(e=>"transform"===e.type);if(n&&n.keyframes.length>0){const{prev:e,next:r,prevIndex:l,nextIndex:c,t:h}=B(n.keyframes,t);if(n.components.position&&O(n.keyframes,l,c,h,s),e&&(e.rotation&&a.fromArray([...e.rotation,"XYZ"]),e.scale&&i.fromArray(e.scale)),r&&e!==r&&e.time!==r.time){const t=I(h,e.interpolation);if(e.rotation&&r.rotation){ve.setFromEuler(Ce.fromArray([...e.rotation,"XYZ"])),ge.setFromEuler(Ae.fromArray([...r.rotation,"XYZ"]));const s=new o;s.slerpQuaternions(ve,ge,t),a.setFromQuaternion(s)}e.scale&&r.scale&&i.lerpVectors(ue.fromArray(e.scale),pe.fromArray(r.scale),t)}}else s.fromArray(e.position),a.fromArray([...e.rotation,"XYZ"]),i.fromArray(e.scale);return{position:s,rotation:a,scale:i}}updateVfxTransform(e,t,s){const{position:a,rotation:i,scale:r}=this.getVfxTransform(e,s);t.object.position.copy(a),t.object.rotation.copy(i),t.object.scale.copy(r)}resolveActorType(e){const t=this.actorFactory.classes[e];if(null!=t)return t;const s=f[e];return s||(console.warn(`Could not resolve actor type: ${e}`),null)}async spawnActorForClip(e,t,s,a){if(!this.world||!e.actorType)return null;const i=this.resolveActorType(e.actorType);if(!i)return null;try{return await this.world.spawnActor(i,s,a)}catch(t){return console.error(`Failed to spawn actor ${e.actorType}:`,t),null}}async spawnPrefabForClip(e,t,s,a){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,s,a)}catch(t){return console.error(`Failed to spawn prefab ${e.prefabId}:`,t),null}}async spawnMeshForClip(e,t,s,a){if(!this.world||!this.assetLoader||!e.meshId)return null;try{const t=await this.assetLoader.getAsset(e.meshId),i=await this.assetLoader.getModelByAssetId(e.meshId),r=j.clone(i.scene);if(r.position.copy(s),r.rotation.copy(a),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.restoreVisibilitySnapshotsForInstance(e),this.restorePropertySnapshotsForInstance(e),this.restoreMaterialSnapshotsForInstance(e),this.world)switch(e?.type){case"actor":this.world.removeActor(e.instance);break;case"prefab":this.world.removePrefab(e.instance);break;case"mesh":this.world.scene.remove(e.instance)}}despawnAll(){for(const e of this.spawnedInstances.values())this.despawnInstance(e);this.spawnedInstances.clear(),this.activeClips.clear(),this.pendingSpawns.clear()}getInitialTransform(e,t,s){const a=new c,i=new r,n=e.subTracks.find(e=>"transform"===e.type);if(n&&n.keyframes.length>0){const{prev:e,prevIndex:t,nextIndex:r,t:o}=B(n.keyframes,s);n.components.position&&O(n.keyframes,t,r,o,a),e&&e.rotation&&i.fromArray([...e.rotation,"XYZ"])}else t.initialPosition&&a.fromArray(t.initialPosition),t.initialRotation&&i.fromArray([...t.initialRotation,"XYZ"]);return{position:a,rotation:i}}evaluateSpawnTrack(e,t,s){if(!e.clips||0===e.clips.length)return;const a=t||this.bindings.get(e.id);if(a&&a.target)for(const t of e.clips){const i=t.startTime+t.duration,r=s>=t.startTime&&s<i,n=`${e.id}-${t.id}`;if(r){this.activeClips.has(n)||(this.activeClips.add(n),this.spawnedInstances.set(n,{type:"proxy",target:a.target}));(a.target instanceof d?a.target.object:a.target)&&this.evaluateSubTracks(e.subTracks,a,s)}else if(this.activeClips.has(n)){e.clips.some(e=>e!==t&&s>=e.startTime&&s<e.startTime+e.duration)||this.deactivateAnimationSubTracks(e.subTracks,a),this.clearExternalRootMotionPreview(a),this.restorePropertySnapshotsForTarget(a.target),this.restoreMaterialSnapshotsForTarget(a.target),this.restoreVisibilitySnapshotForObject(this.getPlayableObject(a)),this.activeClips.delete(n),this.spawnedInstances.delete(n)}}else for(const t of e.clips){const a=t.startTime+t.duration,i=s>=t.startTime&&s<a,r=`${e.id}-${t.id}`,n=this.spawnedInstances.has(r),o=this.pendingSpawns.has(r);if(!i||n||o){if(i&&n){const t=this.spawnedInstances.get(r);t&&"proxy"!==t.type&&this.evaluateSubTracks(e.subTracks,t,s)}else if(!i&&n){const e=this.spawnedInstances.get(r);e&&(this.despawnInstance(e),this.spawnedInstances.delete(r),this.activeClips.delete(r))}}else{const{position:s,rotation:a}=this.getInitialTransform(e,t,t.startTime);this.pendingSpawns.add(r),this.spawnForClip(e,t,s,a,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 d?e.target.object:e.target;default:return null}}async spawnForClip(e,t,s,i,r){const n=this.clearCounter;let o=null;try{switch(e.spawnType){case"actor":const a=await this.spawnActorForClip(e,t,s,i);a&&(o={type:"actor",instance:a});break;case"prefab":const r=await this.spawnPrefabForClip(e,t,s,i);r&&(o={type:"prefab",instance:r});break;case"mesh":const n=await this.spawnMeshForClip(e,t,s,i);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 a(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 d?e.target.object:e.target??null}applyResolvedPropertyValue(e,t,s){if(!t||!e.propertyPath)return;const a=this.getPropertyResolution(t,e);if(!a)return;const i=this.getPropertySnapshotKey(e);this.capturePropertySnapshot(t,i,a);const n=function(e,t){switch(t.type){case v.Number:return"number"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case v.Boolean:return"boolean"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case v.String:return"string"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case v.Vector2:return J(e,t.value);case v.Vector3:return ee(e,t.value);case v.Vector4:return te(e,t.value);case v.Euler:return function(e,t){const s=ae(t,3);if(!s)return{applied:!1};const a=Array.isArray(t)&&"string"==typeof t[3]?t[3]:"XYZ";if(e instanceof r)return e.set(s[0],s[1],s[2],a),{applied:!0,value:e};return{applied:!0,value:new r(s[0],s[1],s[2],a)}}(e,t.value);case v.Color:return se(e,t.value);default:return{applied:!1}}}(a.owner[a.key],s);n.applied&&(a.owner[a.key]=n.value)}getPropertyResolution(e,t){const s=e,a=this.getPropertySnapshotKey(t);let i=this.propertyResolutionCache.get(s);if(i||(i=new Map,this.propertyResolutionCache.set(s,i)),i.has(a))return i.get(a)??null;const r=this.getPropertyPathSegments(t.propertyPath);if(0===r.length)return i.set(a,null),null;let n=e;for(let e=0;e<r.length-1;e++){if(!Y(n))return i.set(a,null),null;n=n[r[e]]}if(!Y(n))return i.set(a,null),null;const o={owner:n,key:r[r.length-1]};return i.set(a,o),o}getPropertyPathSegments(e){const t=this.propertyPathSegments.get(e);if(t)return t;const s=e.split(".").map(e=>e.trim()).filter(Boolean);return this.propertyPathSegments.set(e,s),s}getPropertySnapshotKey(e){return`${e.id}:${e.propertyPath}`}capturePropertySnapshot(e,t,s){const a=e;let i=this.propertySnapshots.get(a);if(i||(i=new Map,this.propertySnapshots.set(a,i)),i.has(t))return;const r=s.owner[s.key];i.set(t,{resolution:s,hadOwnProperty:Object.prototype.hasOwnProperty.call(s.owner,s.key),value:r,valueSnapshot:re(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,s=this.propertySnapshots.get(t);if(s){for(const e of s.values())ne(e);this.propertySnapshots.delete(t),this.propertyResolutionCache.delete(t)}}restoreAllPropertySnapshots(){for(const e of Array.from(this.propertySnapshots.keys()))this.restorePropertySnapshotsForTarget(e)}restoreMaterialSnapshotsForInstance(e){switch(e.type){case"actor":case"mesh":this.restoreMaterialSnapshotsForTarget(e.instance);break;case"prefab":this.restoreMaterialSnapshotsForTarget(e.target??null),this.restoreMaterialSnapshotsForTarget(e.instance.mainActor??null),this.restoreMaterialSnapshotsForTarget(e.instance.object);break;case"proxy":this.restoreMaterialSnapshotsForTarget(e.target)}}restoreMaterialSnapshotsForTarget(e){if(!e)return;const t=e;this.materialResolutionCache.delete(t);const s=this.materialSnapshots.get(t);if(s){for(const e of s.values())null==e.materialIndex?e.owner.material=e.originalMaterial:Array.isArray(e.owner.material)&&(e.owner.material[e.materialIndex]=e.originalMaterial),e.controlledMaterial!==e.originalMaterial&&e.controlledMaterial.dispose();this.materialSnapshots.delete(t)}}restoreAllMaterialSnapshots(){for(const e of Array.from(this.materialSnapshots.keys()))this.restoreMaterialSnapshotsForTarget(e)}restoreVisibilitySnapshotForObject(e){if(!e)return;const t=this.visibilitySnapshots.get(e);t&&(e.visible=t.visible,this.visibilitySnapshots.delete(e))}restoreVisibilitySnapshotsForInstance(e){this.restoreVisibilitySnapshotForObject(this.getInstanceObject(e))}restoreAllVisibilitySnapshots(){for(const e of Array.from(this.visibilitySnapshots.keys()))this.restoreVisibilitySnapshotForObject(e)}applyResolvedMaterialValue(e,t,s){if(!t)return;if("asset"===w(e)&&!e.materialAssetId)return;if("outlineVisibility"===b(e))return void this.applyResolvedMaterialOutlineVisibility(e,t,s);if(!e.uniformName)return;const a=this.getMaterialSlotResolutions(t,e);for(const i of a){const a=this.ensureSequenceControlledMaterial(t,i),r=a.uniforms?.[e.uniformName];if(!r)continue;const n=Z(r.value,s);n.applied&&(r.value=n.value,a.uniformsNeedUpdate=!0,K(a))}}applyResolvedMaterialOutlineVisibility(e,t,s){if(s.type!==v.Boolean||"boolean"!=typeof s.value)return;const a=this.getMaterialSlotResolutions(t,e);for(const e of a){const a=this.ensureSequenceControlledMaterial(t,e),i=a.userData?.outlineParameters;null!=i&&(i.visible=s.value)}}getMaterialSlotResolutions(e,t){const s=e,a=w(t),i=b(t),r=`${t.id}:${i}:${a}:${t.materialAssetId??""}:${t.uniformName}`;let n=this.materialResolutionCache.get(s);n||(n=new Map,this.materialResolutionCache.set(s,n));const o=n.get(r);if(o)return o;const l=e instanceof d?e.object:e,c=[];return l.traverse(e=>{const s=e.material;if(Array.isArray(s))for(let a=0;a<s.length;a++){const i=s[a];H(i,t)&&c.push({owner:e,materialIndex:a,material:i,key:`${e.uuid}:${a}`})}else H(s,t)&&c.push({owner:e,materialIndex:null,material:s,key:`${e.uuid}:material`})}),n.set(r,c),c}ensureSequenceControlledMaterial(e,t){const s=e;let a=this.materialSnapshots.get(s);a||(a=new Map,this.materialSnapshots.set(s,a));const i=a.get(t.key);if(i)return i.controlledMaterial;const r=t.material.clone();return r.userData={...t.material.userData??{}},null!=t.material.userData?.outlineParameters&&(r.userData.outlineParameters={...t.material.userData.outlineParameters}),null==t.materialIndex?t.owner.material=r:Array.isArray(t.owner.material)&&(t.owner.material[t.materialIndex]=r),a.set(t.key,{owner:t.owner,materialIndex:t.materialIndex,originalMaterial:t.material,controlledMaterial:r}),r}animationClipCacheKey(e,t){return`${e}|${t??""}`}async ensureAnimationClip(e,t){if(!this.assetLoader)return null;const s=this.animationClipCacheKey(e,t),a=this.animationClips.get(s);if(a)return a;const i=this.loadingAnimationClips.get(s);if(i)return i;const r=(async()=>{try{const a=await this.assetLoader.getAnimationClipForTargetByAssetId(e,t);return a&&this.animationClips.set(s,a),a}catch(s){return console.error(`Failed to load animation clip for asset ${e}`+(null==t?"":` and target rig ${t}`)+":",s),null}finally{this.loadingAnimationClips.get(s)===r&&this.loadingAnimationClips.delete(s)}})();return this.loadingAnimationClips.set(s,r),r}prepareAnimationPlayback(e,t,s){if(!L(s)){let e=t;return s.clipEndOffset>0&&(e=e.clone(),N(e,$(t)),e.duration=Math.max(0,e.duration-s.clipEndOffset)),s.rootMotion&&(e=F(e,s)),{clip:e,timeScale:s.playbackRate*this._timescale,startOffset:s.clipStartOffset}}return{clip:this.getPlayableAnimationClip(e,t,s,!1),timeScale:1*this._timescale,startOffset:0}}getPlayableAnimationClip(e,t,s,a){if(!L(s)){const e=s.rootMotion?F(t,s):t;return a?D.fromClip(e,!1):e}const i=`${s.id}:${a?"root":"base"}`,r=`${V(s)}|${a?"root":"base"}`,n=this.retimedAnimationClips.get(i);if(n&&n.assetId===e&&n.signature===r)return n.clip;const o=E(t,s),l=s.rootMotion?F(o,s):o,c=a?D.fromClip(l,!1):l;return this.retimedAnimationClips.set(i,{assetId:e,signature:r,clip:c}),c}getAnimationPlaybackLocalTime(e,t){const s=Math.max(0,t-e.startTime);return L(e)?s:s*e.playbackRate+e.clipStartOffset}clearRetimedAnimationClipCache(e){if(null!=e)for(const[t,s]of this.retimedAnimationClips.entries())s.assetId===e&&this.retimedAnimationClips.delete(t);else this.retimedAnimationClips.clear()}captureOriginalTransforms(){for(const e of this.bindings.values()){const t=e.target instanceof d?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 d?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,s]of e.activeActions.entries())e.charAnimActionKeys?.has(t)||s.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.clearSequenceLights(),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 s=this.getActiveObjectsForTrack(e);if(0===s.length)return;const a="spawn"===e.type&&null!=t?.target;let i=null;const r=e.parent?.trackId;if(r){const t=this.sequenceData?oe(this.sequenceData.tracks).find(e=>e.id===r):void 0;if(t){const s=this.getActiveObjectsForTrack(t);if(s.length>0&&(i=s[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 d?t.object:t,e.parentRoleSocketName){const t=this.findSocket(i,e.parentRoleSocketName);t&&(i=t)}}for(const r of s)i?r.parent!==i&&(i.add(r),!t||"object"!==e.type&&"locator"!==e.type||(t.currentParent=i)):t?.currentParent&&t.currentParent===r.parent?this.restoreObjectParent(t,r):r.parent&&r.parent!==this.world?.scene&&"object"!==e.type&&"locator"!==e.type&&!a&&this.world?.scene.add(r)}findSocket(e,t){if(e.name===t)return e;if(e instanceof s.SkinnedMesh){const s=e.skeleton.bones.find(e=>e.name===t);if(s)return s}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 d?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("light"===e.type)return[this.ensureSequenceLight(e)];if("spawn"===e.type){const t=[];for(const[s,a]of this.spawnedInstances)if(s.startsWith(e.id+"-")&&this.activeClips.has(s)){const e=this.getInstanceObject(a);e&&t.push(e)}return t}if("vfx"===e.type){const t=[];for(const s of this.activeVfxClips)if(s.startsWith(e.id+"-")){const e=this.vfxActors.get(s);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 d?e.target.object:e.target;t&&this.restoreObjectParent(e,t)}}evaluateAudioSubTracks(e,t){const s={};for(const a of e.subTracks)if("audioParameter"===a.type){const e=a,i=S(e.parameter),r=q(e.keyframes,t,{min:i.min,max:i.max});void 0!==r&&(s[e.parameter]=r)}return s}stringToRandom(e){let t=0;for(let s=0;s<e.length;s++){t=(t<<5)-t+e.charCodeAt(s),t&=t}const s=1e4*Math.sin(t);return s-Math.floor(s)}async refreshAsset(e){let t=!1;this.assetLoader?.clearCacheById(e),this.animationClips.delete(e),this.loadingAnimationClips.delete(e),this.clearRetimedAnimationClipCache(e),this.vfxService?.clearPool(e),t=this.refreshVfxActorsForAssetIds(new Set([e]))||t;for(const[s,a]of this.activePostProcessClips.entries())a.assetId===e&&(this.releasePostProcessClipEffect(s),t=!0);t=this.refreshSpawnedInstancesForClipKeys(this.getSpawnClipKeysForAsset(e))||t;const s=await this.getAssetOrNull(e);return"shaderGraph"===s?.type&&(t=await this.refreshShaderGraphDependentAssets(e)||t),t}refreshVfxActorsForAssetIds(e){let t=!1;for(const[s,a]of this.vfxActors.entries())this.vfxClipKeyUsesAnyAsset(s,e)&&(this.world&&this.world.removeActor(a),this.vfxActors.delete(s),this.activeVfxClips.delete(s),t=!0);return t}vfxClipKeyUsesAnyAsset(e,t){for(const s of t)if(e.endsWith(`-${s}`))return!0;return!1}refreshSpawnedInstancesForClipKeys(e){let t=!1;for(const[s,a]of this.spawnedInstances.entries())e.has(s)&&(this.despawnInstance(a),this.spawnedInstances.delete(s),this.activeClips.delete(s),t=!0);return t}getSpawnClipKeysForAsset(e){const t=new Set;if(!this.sequenceData)return t;for(const s of oe(this.sequenceData.tracks))if("spawn"===s.type&&(s.prefabId===e||s.meshId===e))for(const e of s.clips)t.add(`${s.id}-${e.id}`);return t}async refreshShaderGraphDependentAssets(e){const t=await this.findSequenceVfxAssetIdsUsingShaderGraph(e);for(const e of t)this.vfxService?.clearPool(e);const s=this.refreshVfxActorsForAssetIds(t),a=this.refreshSpawnedInstancesForClipKeys(await this.findSpawnClipKeysUsingShaderGraph(e));return s||a}async findSequenceVfxAssetIdsUsingShaderGraph(e){const t=new Set;if(!this.sequenceData)return t;const s=new Map;for(const a of oe(this.sequenceData.tracks))if("vfx"===a.type)for(const i of a.clips)null==i.vfxAssetId||t.has(i.vfxAssetId)||await this.assetUsesShaderGraph(i.vfxAssetId,e,s)&&t.add(i.vfxAssetId);return t}async findSpawnClipKeysUsingShaderGraph(e){const t=new Set;if(!this.sequenceData)return t;const s=new Map;for(const a of oe(this.sequenceData.tracks))if("spawn"===a.type&&await this.spawnTrackUsesShaderGraph(a,e,s))for(const e of a.clips)t.add(`${a.id}-${e.id}`);return t}async spawnTrackUsesShaderGraph(e,t,s){if(null!=e.meshId&&await this.assetUsesShaderGraph(e.meshId,t,s))return!0;if(null!=e.prefabId&&await this.assetUsesShaderGraph(e.prefabId,t,s))return!0;for(const a of e.subTracks??[])if("material"===a.type&&null!=a.materialAssetId&&await this.assetUsesShaderGraph(a.materialAssetId,t,s))return!0;return!1}assetUsesShaderGraph(e,t,s,a=new Set){if(e===t)return Promise.resolve(!0);if(a.has(e))return Promise.resolve(!1);if(s.has(e))return s.get(e);const i=this.assetUsesShaderGraphUncached(e,t,s,a);return s.set(e,i),i}async assetUsesShaderGraphUncached(e,t,s,a){if(a.has(e))return!1;const i=await this.getAssetOrNull(e);if(null==i)return!1;const r=new Set(a);return r.add(e),!!this.materialAssetUsesShaderGraph(i,t)||("mesh"===i.type?this.materialAssignmentsUseShaderGraph(i.materialAssignments,t,s,r):"prefab"===i.type?this.sceneObjectsUseShaderGraph(i.prefab?.objects,t,s,r):"vfx"===i.type&&this.vfxAssetUsesShaderGraph(i,t,s,r))}materialAssetUsesShaderGraph(e,t){return"shaderGraph"===e.type?e.id===t:"asset"===e.material?.shaderGraph?.source&&e.material.shaderGraph.assetId===t}async materialAssignmentsUseShaderGraph(e,t,s,a){for(const i of e??[])if(null!=i.materialId&&"null"!==i.materialId&&await this.assetUsesShaderGraph(i.materialId,t,s,a))return!0;return!1}async sceneObjectsUseShaderGraph(e,t,s,a){for(const i of e??[]){if(await this.materialAssignmentsUseShaderGraph(i.materialAssignments,t,s,a))return!0;if(null!=i.assetId&&("asset_mesh"===i.type||"prefab"===i.type||"vfx"===i.type)&&await this.assetUsesShaderGraph(i.assetId,t,s,a))return!0;if(await this.sceneObjectsUseShaderGraph(i.children,t,s,a))return!0}return!1}async vfxAssetUsesShaderGraph(e,t,s,a){for(const i of e.vfx?.emitters??[])if(await this.emitterUsesShaderGraph(i,t,s,a))return!0;return!1}async emitterUsesShaderGraph(e,t,s,a){if(await this.emitterOutputUsesShaderGraph(e.output,t,s,a))return!0;for(const i of e.children??[])if(await this.emitterUsesShaderGraph(i,t,s,a))return!0;return!1}async emitterOutputUsesShaderGraph(e,t,s,a){const i=e.materialSource??("asset"===e.shaderGraph?.source?"shaderGraph":void 0);return"shaderGraph"===i&&"asset"===e.shaderGraph?.source&&e.shaderGraph.assetId===t||!("material"!==i||!("material"in e)||null==e.material||!await this.assetUsesShaderGraph(e.material,t,s,a))}async getAssetOrNull(e){if(!this.assetLoader)return null;try{return await this.assetLoader.getAsset(e)??null}catch{return null}}async invokeSequenceEvent(e,t,s,a){let i=!1;for(let e=0;e<a.length;e++)if(g(a[e])){i=!0;break}if(i)try{const t=new Array(a.length);for(let e=0;e<a.length;e++)t[e]=C(a[e],this.sequenceEventAsyncResolvers);const i=await Promise.all(t);await s.call(e,...i)}catch(e){console.error(`Failed to call sequence event ${t}:`,e)}else try{const t=new Array(a.length);for(let e=0;e<a.length;e++)t[e]=A(a[e],this.sequenceEventSyncResolvers);s.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,s="object"==typeof t&&null!=t?.id?t.id:"string"==typeof t?t:null;if(null==s)return null;for(const e of this.world.actors){const t=e.object.userData.src??e.object.userData._src;if(t?.id===s)return e}return null}resolveSequenceEventSequence(e){return k(e)?new P(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 X(e){return e.options?.length>0||e.propertyType===v.Boolean||e.propertyType===v.String}function z(e){return"outlineVisibility"===b(e)||e.valueType===v.Boolean||e.valueType===v.String}function Y(e){return"object"==typeof e&&null!=e||"function"==typeof e}function Z(e,t){switch(t.type){case v.Number:return function(e){if("number"==typeof e)return Number.isFinite(e)?{applied:!0,value:e}:{applied:!1};if("string"==typeof e){const t=parseFloat(e);return Number.isFinite(t)?{applied:!0,value:t}:{applied:!1}}return{applied:!1}}(t.value);case v.Boolean:return"boolean"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case v.Vector2:return J(e,t.value);case v.Vector3:return ee(e,t.value);case v.Vector4:return te(e,t.value);case v.Color:return function(e,t){if(e instanceof c){const s=Se.set(0);return ie(s,t)?(e.set(s.r,s.g,s.b),{applied:!0,value:e}):{applied:!1}}if(e instanceof h){const s=Se.set(0);return ie(s,t)?(e.set(s.r,s.g,s.b,e.w),{applied:!0,value:e}):{applied:!1}}return se(e,t)}(e,t.value);default:return{applied:!1}}}function H(e,t){const a=w(t);return!!function(e){return e instanceof s.Material||!0===e?.isMaterial}(e)&&(("asset"!==a||e.userData?.assetId===t.materialAssetId)&&("outlineVisibility"===b(t)?null!=e.userData?.outlineParameters:null!=e.uniforms?.[t.uniformName]))}function J(e,t){const s=ae(t,2);return s?e instanceof l?(e.fromArray(s),{applied:!0,value:e}):{applied:!0,value:new l(s[0],s[1])}:{applied:!1}}function ee(e,t){const s=ae(t,3);return s?e instanceof c?(e.fromArray(s),{applied:!0,value:e}):{applied:!0,value:new c(s[0],s[1],s[2])}:{applied:!1}}function te(e,t){const s=ae(t,4);return s?e instanceof h?(e.fromArray(s),{applied:!0,value:e}):{applied:!0,value:new h(s[0],s[1],s[2],s[3])}:{applied:!1}}function se(e,t){if(e instanceof i)return ie(e,t)?{applied:!0,value:e}:{applied:!1};const s=new i;return ie(s,t)?{applied:!0,value:s}:{applied:!1}}function ae(e,t){if(!Array.isArray(e)||e.length<t)return null;const s=new Array(t);for(let a=0;a<t;a++){if("number"!=typeof e[a])return null;s[a]=e[a]}return s}function ie(e,t){return t instanceof i||"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 re(e){if(e instanceof l||e instanceof c||e instanceof h||e instanceof i||e instanceof r)return e.clone()}function ne(e){const{owner:t,key:s}=e.resolution;e.hadOwnProperty?(!function(e,t){if(e instanceof l&&t instanceof l)return e.copy(t),!0;if(e instanceof c&&t instanceof c)return e.copy(t),!0;if(e instanceof h&&t instanceof h)return e.copy(t),!0;if(e instanceof i&&t instanceof i)return e.copy(t),!0;if(e instanceof r&&t instanceof r)return e.copy(t),!0}(e.value,e.valueSnapshot),t[s]=e.value):delete t[s]}function oe(e){const t=[];for(const s of e)t.push(s),"group"===s.type&&t.push(...oe(s.childTracks));return t}function le(e){if("string"!=typeof e)return null;const t=e.trim();return t.length>0?t:null}function ce(e){const t=new s.Group;t.name=`SequenceLocatorMarker:${e}`,t.renderOrder=1e3;const a=new s.AxesHelper(.35);a.renderOrder=1e3;const i=Array.isArray(a.material)?a.material:[a.material];for(const e of i)e.depthTest=!1,e.transparent=!0,e.opacity=.9,e.toneMapped=!1;t.add(a);const r=function(e){if("undefined"==typeof document)return null;const t=document.createElement("canvas");t.width=256,t.height=64;const a=t.getContext("2d");if(!a)return null;a.clearRect(0,0,t.width,t.height),a.fillStyle="rgba(16, 18, 24, 0.78)",function(e,t,s,a,i,r){const n=t+a,o=s+i;e.beginPath(),e.moveTo(t+r,s),e.lineTo(n-r,s),e.quadraticCurveTo(n,s,n,s+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,s+r),e.quadraticCurveTo(t,s,t+r,s),e.closePath()}(a,0,8,t.width,48,8),a.fill(),a.font="24px sans-serif",a.textAlign="center",a.textBaseline="middle",a.fillStyle="#f8fafc",a.fillText(e||"Locator",t.width/2,t.height/2);const i=new s.CanvasTexture(t);i.needsUpdate=!0;const r=new s.SpriteMaterial({map:i,transparent:!0,depthTest:!1});r.toneMapped=!1;const n=new s.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 he(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 ue=new c,pe=new c,de=new c,fe=new c,me=new c,ye=new c,ve=new o,ge=new o,Ce=new r,Ae=new r,Se=new i;/*
|
|
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*as e from"three";import{applyMeshWorldTransformToGeometry as t}from"./vfx-mesh-transform.js";import{attributes as a,clamp as r,lambertMaterial as s,NodeShaderMaterial as o,rgba as n,smoothstep as i,textureSampler2d as l,varyingAttributes as c}from"three-shader-graph";import{SerializedParamType as p}from"../../scene/model.js";import{particleUniforms as u}from"../../shader-nodes/particle.js";import{sampleFlipbook as m}from"../../shader-nodes/texture-sequence.js";import{fragmentLinearEyeDepth as d,linearEyeDepth as h}from"../../shader-nodes/depth.js";import{ThreeBlendingMode as y,WorldCollisionMethod as f}from"./vfx-asset.js";import{getDefaultVfxSpriteTexture as b}from"./vfx-default-sprite-texture.js";import{ShapeLibrary as g}from"../../scene/objects/shapes.js";export class GpuSpriteRenderClassCache{constructor(){this.entries=new Map}resolve(e,t){let a=this.entries.get(e);return null==a&&(a=t().catch(t=>{throw this.entries.delete(e),t}),this.entries.set(e,a)),a}clear(){this.entries.clear()}}export function hasGpuUnsupportedVfxInputBindings(e){const t=new Map((e.vfx.inputs??[]).map(e=>[e.id,e.type])),a=e=>{for(const a of[...e.initializers,...e.behaviours])if(!1!==a.enabled)for(const[r,s]of Object.entries(a.params)){if("vfxInput"!==s?.binding?.type)continue;const o=s.type===p.Number?"number":s.type===p.Vector3?"vec3":s.type===p.Color?"color":s.type===p.Object3D?"mesh":void 0;if(null==o||t.get(s.binding.inputId)!==o)return!0;if("lifetime"===a.type&&"duration"===r&&"continuous"===e.rate.type)return!0}return(e.children??[]).some(a)};return e.vfx.emitters.some(a)}export function selectVfxBackend(e,t="auto"){if("cpu"===t)return{backend:"cpu",reasons:["CPU backend explicitly requested"]};const a=e.issues.filter(e=>"requirement"===e.severity).map(e=>e.message);if(a.length>0)return{backend:"cpu",reasons:a};const r=e.issues.filter(e=>"error"===e.severity).map(e=>e.message);return r.length>0&&"gpu"!==t?{backend:"cpu",reasons:r}:r.length>0?{backend:"gpu",reasons:["GPU backend explicitly forced despite incompatibilities",...r]}:{backend:"gpu",reasons:e.issues.filter(e=>"warning"===e.severity).map(e=>e.message)}}export function compileGpuSpriteEmitters(t,a,r="emitter-major"){const s=[],o=[],n=new Map,i=[],l=[],c=new Map((t.vfx.inputs??[]).map(e=>[e.id,e.type])),u=new Map((t.vfx.inputs??[]).filter(e=>"number"===e.type).map(e=>[e.id,"number"==typeof e.defaultValue?e.defaultValue:0]));hasGpuUnsupportedVfxInputBindings(t)&&i.push({severity:"error",code:"vfx-input-binding",emitter:"effect",message:"this VFX input binding target is not supported on GPU yet"});const m=t.vfx.emitters.slice().sort((e,t)=>(e.output.renderOrder??0)-(t.output.renderOrder??0)),d=(t,r,m)=>{const h="vfxInput"===t.rate.delayBinding?.type?u.get(t.rate.delayBinding.inputId):void 0,y=null==h?t:{...t,rate:{...t.rate,delay:Math.max(0,h)}};if("sprite"!==t.output.type&&"mesh"!==t.output.type&&"stretchedSprite"!==t.output.type&&"decal"!==t.output.type&&"shape"!==t.output.type&&"trail"!==t.output.type)return void v(i,t,"error","output-type","this output type is not supported by the GPU sprite backend");if("mesh"===t.output.type&&null==t.output.assetId)return;if(t.rate.count<=0)return;const f="trail"===(b=t.output).type?JSON.stringify(b):"mesh"===b.type?JSON.stringify({type:b.type,assetId:b.assetId,renderOrder:b.renderOrder??0,useLegacyTransform:!0===b.useLegacyTransform,materialSource:b.materialSource??null,material:b.material??null,shader:b.shader??null,shaderParams:b.shaderParams??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space}):"decal"===b.type?JSON.stringify({type:b.type,colorMap:b.colorMap,alphaMap:b.alphaMap,color:b.color,unlit:b.unlit,intensity:b.intensity,opacityChannel:b.opacityChannel??"red",blendingMode:b.blendingMode,renderOrder:b.renderOrder??0,materialSource:b.materialSource??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space}):"shape"===b.type?JSON.stringify({type:b.type,shape:b.shape,params:b.params,material:b.material,renderOrder:b.renderOrder??0,materialSource:b.materialSource??null,shader:b.shader??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space}):JSON.stringify({type:b.type,texture:b.texture,opacityChannel:b.opacityChannel??"red",blendingMode:b.blendingMode,softness:b.softness,renderOrder:b.renderOrder??0,bloom:b.bloom,materialSource:b.materialSource??null,shader:b.shader??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space,lockY:"sprite"===b.type&&!0===b.lockY,stretchScale:"stretchedSprite"===b.type?b.scale:null});var b;let g=n.get(f);null==g&&(g=o.length,n.set(f,g),o.push({key:f,output:t.output}));const x=[];for(let o=0;o<a.length;o++){const n=w(y,null==r?a[o]:new e.Vector3,g,i);if(null!=n){if(null!=r){const e=s[r]?.instances[o];if(null==e)continue;const a=n.capacity,l=e.capacity*a;if(l>25e4){v(i,t,"error","child-particle-capacity",`child emitter expansion requires ${l} particles, exceeding the GPU per-emitter limit`);continue}n.capacity=l,n.parentEmitter=r,n.childParticlesPerParent=a,n.childSpawnEvent="collision"===t.spawnEvent?2:1,n.childLevel=m,!0===n.localSpace&&!0!==e.localSpace&&v(i,t,"error","child-emitter-local-space","GPU child emitters do not yet support a world-space parent with local-space child output"),"trail"===t.output.type&&v(i,t,"error","child-emitter-trail","GPU child emitters do not yet support trail output")}x.push(n)}}if(x.length>0){const e=s.length;s.push({instances:x,parentSource:r});for(const a of[...t.initializers,...t.behaviours])if(!1!==a.enabled)for(const[r,s]of Object.entries(a.params)){const o=s?.binding;if("vfxInput"!==o?.type)continue;const n=s.type===p.Number?"number":s.type===p.Vector3?"vec3":s.type===p.Color?"color":s.type===p.Object3D?"mesh":void 0;null!=n&&c.get(o.inputId)===n&&("mesh"!==n&&("lifetime"===a.type&&"duration"===r&&"continuous"===t.rate.type||l.push({inputId:o.inputId,emitterIndex:e,target:`${t.initializers.includes(a)?"initializer":"behaviour"}:${a.type}:${r}`,authoredScalar:"number"==typeof s.value?s.value:void 0,baseScaleStart:[...x[0].scaleStart],baseScaleEnd:[...x[0].scaleEnd]})))}for(const a of t.children??[])d(a,e,m+1)}};for(const e of m)d(e,null,0);const h="instance-major"===r?a.flatMap((e,t)=>s.flatMap(e=>null==e.instances[t]?[]:[e.instances[t]])):s.flatMap(e=>e.instances);for(let e=0;e<s.length;e++){const t=s[e];if(null!=t.parentSource)for(let e=0;e<t.instances.length;e++)t.instances[e].parentEmitter="instance-major"===r?e*s.length+t.parentSource:t.parentSource*a.length+e}const y=o.map((e,t)=>({renderClass:e,oldIndex:t})).sort((e,t)=>(e.renderClass.output.renderOrder??0)-(t.renderClass.output.renderOrder??0)),f=new Array(o.length);for(let e=0;e<y.length;e++)f[y[e].oldIndex]=e;for(const e of h)e.renderClass=f[e.renderClass??0]??0;const b={compatible:!i.some(e=>"warning"!==e.severity),issues:i};return{emitters:h,inputBindings:l,renderClasses:y.map(e=>e.renderClass),compatibility:b,unsupported:[...new Set(i.map(e=>`${e.emitter}: ${e.message}`))]}}export async function materializeGpuSpriteRenderClasses(p,f,w,v){const x=async p=>{const v=p.output;if("trail"===v.type){const t=v.materialSource??("asset"===v.shaderGraph?.source?"shaderGraph":"default"),a="default"===t?null:await(w?.(v))??null;if(null==a&&"default"!==t)throw new Error(`${t} trail material requires a compatible GPU material resolver`);return{texture:null!=v.texture?await f.getTexture(v.texture):b(),material:a??void 0,localSpace:"local"===v.space,trail:{historyLength:Math.max(2,Math.round(v.length)+1),width:v.width??1,taper:v.taper,colorStart:new e.Color(v.color).multiplyScalar(v.intensity),colorEnd:new e.Color(v.colorEnd).multiplyScalar(v.intensityEnd),opacityStart:v.opacityStart,opacityEnd:v.opacityEnd,scrollSpeed:v.scrollSpeed??0,opacityChannel:v.opacityChannel??"red",blendingMode:v.blendingMode??"normal",billboard:v.billboard??!1}}}if("mesh"===v.type){if(null==f.getMesh)throw new Error("GPU mesh particles require a mesh asset provider");const a=await f.getMesh(v.assetId);a.updateWorldMatrix(!0,!0);const r=[];if(a.traverse(t=>{t instanceof e.Mesh&&r.push(t)}),1!==r.length)throw new Error(`GPU mesh particles require exactly one mesh geometry; asset ${v.assetId} resolved to ${r.length}`);const s=null==r[0].geometry.index?r[0].geometry.clone():r[0].geometry.toNonIndexed();!0!==v.useLegacyTransform&&t(r[0],s);const n=s.getAttribute("position");if(null==n)throw new Error(`GPU mesh particle asset ${v.assetId} has no position attribute`);const i=s.getAttribute("normal"),l=s.getAttribute("uv"),c=new Float32Array(8*n.count);for(let e=0;e<n.count;e++){const t=8*e;c[t]=n.getX(e),c[t+1]=n.getY(e),c[t+2]=n.getZ(e),c[t+3]=i?.getX(e)??0,c[t+4]=i?.getY(e)??1,c[t+5]=i?.getZ(e)??0,c[t+6]=l?.getX(e)??0,c[t+7]=l?.getY(e)??0}s.dispose();const p=Array.isArray(r[0].material)?r[0].material[0]:r[0].material,m="material"===v.materialSource&&null==v.material||"shaderGraph"===v.materialSource&&("asset"!==v.shaderGraph?.source||null==v.shaderGraph.assetId)||"shader"===v.materialSource&&null==v.shader?"default":v.materialSource??("asset"===v.shaderGraph?.source?"shaderGraph":null!=v.shader?"shader":null!=v.material?"material":"default"),d="default"===m?await(w?.(v))??function(){const e=u.opacity;return new o({color:u.color.rgb.rgba(e),opacity:e,transparent:!0})}():await(w?.(v))??null;if(null==d&&"default"!==m)throw new Error(`${m} mesh material requires a compatible GPU material resolver`);const h=null!=p&&"color"in p&&p.color instanceof e.Color?p.color.clone():new e.Color(16777215);return{texture:b(),meshVertices:c,meshColor:h,meshOpacity:p?.opacity??1,localSpace:"local"===v.space,material:d??void 0}}if("decal"===v.type){const t=await(w?.(v))??null;if(null==t)throw new Error("GPU decal output requires a compatible GPU decal material resolver");const a=new e.BoxGeometry(1,1,1).toNonIndexed(),r=a.getAttribute("position"),s=a.getAttribute("normal"),o=a.getAttribute("uv"),n=new Float32Array(8*r.count);for(let e=0;e<r.count;e++){const t=8*e;n[t]=r.getX(e),n[t+1]=r.getY(e),n[t+2]=r.getZ(e),n[t+3]=s.getX(e),n[t+4]=s.getY(e),n[t+5]=s.getZ(e),n[t+6]=o.getX(e),n[t+7]=o.getY(e)}return a.dispose(),{texture:b(),meshVertices:n,meshColor:new e.Color(16777215),meshOpacity:1,localSpace:"local"===v.space,material:t}}if("shape"===v.type){const t=g[v.shape];if(null==t)throw new Error(`GPU shape output has unknown shape ${v.shape}`);const a=v.materialSource??("asset"===v.shaderGraph?.source?"shaderGraph":null!=v.shader?"shader":null!=v.material?"material":"default"),r="default"===a?function(){const e=u.opacity;return new o({color:s({color:u.color.rgb}).rgb.rgba(e),opacity:e,transparent:!0})}():await(w?.(v))??null;if(null==r&&"default"!==a)throw new Error(`${a} shape material requires a compatible GPU material resolver`);const n=Object.fromEntries(Object.entries(v.params??{}).map(([e,t])=>[e,t.value])),i=t.geometry(n),l=null==i.index?i:i.toNonIndexed(),c=l.getAttribute("position"),p=l.getAttribute("normal"),m=l.getAttribute("uv"),d=new Float32Array(8*c.count);for(let e=0;e<c.count;e++){const t=8*e;d[t]=c.getX(e),d[t+1]=c.getY(e),d[t+2]=c.getZ(e),d[t+3]=p?.getX(e)??0,d[t+4]=p?.getY(e)??1,d[t+5]=p?.getZ(e)??0,d[t+6]=m?.getX(e)??0,d[t+7]=m?.getY(e)??0}return l!==i&&l.dispose(),i.dispose(),{texture:b(),meshVertices:d,meshColor:new e.Color(16777215),meshOpacity:1,localSpace:"local"===v.space,material:r??void 0}}const x=null!=v.texture?await f.getTexture(v.texture):b(),S="stretchedSprite"===v.type?"default":v.materialSource??("asset"===v.shaderGraph?.source?"shaderGraph":"default");let M="default"===S?null:await(w?.(v))??null;if(null==M&&"default"!==S)throw new Error(`${S} material requires a compatible GPU material resolver`);return M??(M=function(t,s){const p=l(s),f="sprite"===t.type&&!0===t.flipbook?.enabled?m(p,a.uv,t.flipbook.columns,t.flipbook.rows,u.time,t.flipbook.fps,t.flipbook.mode):p.sample(c.uv);let b=u.opacity;"red"===(t.opacityChannel??"red")?b=b.multiply(f.r):"alpha"===t.opacityChannel&&(b=b.multiply(f.a));if(t.softness>0){const e=h.subtract(d).divide(h);b=b.multiply(i(0,.2*t.softness,r(e,0,1e3)))}const g=new o({color:n(u.color.multiply(f.rgb),b),transparent:!0,lights:!1,fog:!1,alphaTest:1e-4});return g.blending=y[t.blendingMode]??e.NormalBlending,g.depthWrite=!1,g}(v,x)),M.transparent&&(M.depthWrite=!1),{texture:x,material:M,lockY:"sprite"===v.type&&!0===v.lockY,localSpace:"local"===v.space,stretchScale:"stretchedSprite"===v.type?0===v.scale?.001:v.scale:void 0}};return{renderClasses:await Promise.all(p.map(e=>v?.resolve(e.key,()=>x(e))??x(e))),unsupported:[]}}function w(t,a,r,s){if("sprite"!==t.output.type&&"mesh"!==t.output.type&&"decal"!==t.output.type&&"shape"!==t.output.type&&"trail"!==t.output.type&&"stretchedSprite"!==t.output.type)return null;const o="mesh"===t.output.type||"decal"===t.output.type||"shape"===t.output.type;let n=99999,i=99999,l=0,c=0;const p=new e.Vector4,u=new e.Vector4,m=new e.Vector3,d=new e.Vector3,h=new e.Vector3;let y=0,b=1;const g=new e.Vector3;let w=0,G=0,V=!1,C=0,P=!1;const I=new e.Vector3;let O,E=0,U=!1,A=!1,R=0,N=0,B=0,T=!1,z=[1,1],$=1,j=1,F=new e.Color("sprite"===t.output.type||"stretchedSprite"===t.output.type?t.output.color:"#ffffff"),Y=F.clone(),X=!1,Z=1,q=1,D=0,L=0;const Q=new e.Quaternion,J=new e.Vector3,W=new e.Vector3;let H=0;const K=new e.Vector3(0,1,0);let _=0,ee=0,te=!1;const ae=new e.Vector3;let re=0,se=0,oe=!1;const ne=new e.Vector3(0,1,0);let ie=0;const le=new e.Vector3,ce=new e.Vector3,pe=new e.Vector3(0,1,0);let ue=0,me=!1,de=0,he=0,ye=0,fe=!1;const be=new e.Vector4(0,0,0,0),ge=new e.Vector3(1,1,1),we=new e.Vector3(1,1,1),ve=new e.Vector3(1,1,1);let xe,Se,Me,ke,Ge,Ve="surface";for(const a of t.initializers.filter(e=>!1!==e.enabled))switch(a.type){case"lifetime":i=n=x(a.params.duration,1);break;case"randomLifetime":{const e=x(a.params.minDuration,1),t=x(a.params.maxDuration,2);i=Math.min(e,t),n=Math.max(e,t);break}case"velocity":{const e=M(a.params.velocity);m.copy(e),d.copy(e);break}case"randomVelocity":m.copy(M(a.params.min)),d.copy(M(a.params.max));break;case"randomDirection":{const e=x(a.params.speed,1);m.setScalar(-e),d.setScalar(e);break}case"radialVelocity":K.copy(M(a.params.direction)).normalize(),_=x(a.params.speed,1),ee=e.MathUtils.degToRad(x(a.params.spread,0)),te=!0;break;case"mass":b=Math.max(1e-6,x(a.params.min,1));break;case"positionPoint":p.copy(new e.Vector4(...M(a.params.position).toArray(),0));break;case"positionSphere":{l=x(a.params.radius,1);const e=M(a.params.position);c=1,p.set(e.x,e.y,e.z,!0===a.params.surface?.value?1:0);break}case"positionBox":{const e=M(a.params.position),t=M(a.params.dimensions);c=2,p.set(e.x,e.y,e.z,0),u.set(t.x,t.y,t.z,0);break}case"positionLine":{const e=M(a.params.a),t=M(a.params.b);c=3,p.set(e.x,e.y,e.z,0),u.set(t.x,t.y,t.z,0);break}case"positionCircle":case"positionRing":{const t=M(a.params.position),r=M(a.params.rotation).multiplyScalar(Math.PI/180);l=x(a.params.radius,1);const s="positionRing"===a.type?Math.max(x(a.params.thickness,.2),1e-4):0;c=4,p.set(t.x,t.y,t.z,s),u.set(r.x,r.y,r.z,e.MathUtils.degToRad(Math.max(0,Math.min(360,x(a.params.angle,360)))));break}case"positionMesh":{const r=a.params.mesh?.value,o=a.params.mesh?.binding;if("vfxInput"===o?.type&&(Se=o.inputId),("string"!=typeof r||0===r.length)&&null==Se){v(s,t,"error","mesh-sampler-source","GPU mesh sampling requires a selected fallback mesh asset");break}if(xe="string"==typeof r&&r.length>0?r:void 0,Ve="vertices"===a.params.sampling?.value?"vertices":"surface",Me=(new e.Matrix4).compose(M(a.params.position),(new e.Quaternion).setFromEuler((new e.Euler).setFromVector3(M(a.params.rotation).multiplyScalar(Math.PI/180))),null==a.params.scale?new e.Vector3(1,1,1):M(a.params.scale)),!0===a.params.alignNormal?.value){const t=a.params.alignmentAxis?.value;ke="+X"===t?new e.Vector3(1,0,0):"-X"===t?new e.Vector3(-1,0,0):"-Y"===t?new e.Vector3(0,-1,0):"+Z"===t?new e.Vector3(0,0,1):"-Z"===t?new e.Vector3(0,0,-1):new e.Vector3(0,1,0)}!0===a.params.normalVelocity?.value&&(Ge=new e.Vector4(x(a.params.normalVelocityMin,1),x(a.params.normalVelocityMax,1),e.MathUtils.degToRad(e.MathUtils.clamp(x(a.params.normalVelocitySpread,0),0,180)),1)),c=5;break}case"scale":{const e=x(a.params.scale,1);z=[e,e];break}case"scaleComponents":ge.copy(M(a.params.scale));break;case"randomScale":z=[x(a.params.min,1),x(a.params.max,1)];break;case"randomColor":F=k(a.params.a,F),Y=k(a.params.b,F),X=!0;break;case"rotation":{const t=M(a.params.rotation);D=L=e.MathUtils.degToRad(t.z),J.set(e.MathUtils.degToRad(t.x),e.MathUtils.degToRad(t.y),e.MathUtils.degToRad(t.z)),Q.setFromEuler(new e.Euler(J.x,J.y,J.z));break}case"randomRotation":{if(o){const e=a.params.axis?.value;H="X"===e?2:"Y"===e?3:"Z"===e?4:1;break}const e=a.params.axis?.value;"XYZ"!==e&&"Z"!==e&&null!=e||(L=2*Math.PI);break}case"alignRotation":{if(!o)break;const e=a.params.axis?.value;"+X"===e?ne.set(1,0,0):"-X"===e?ne.set(-1,0,0):"-Y"===e?ne.set(0,-1,0):"+Z"===e?ne.set(0,0,1):"-Z"===e?ne.set(0,0,-1):ne.set(0,1,0);const t=a.params.mode?.value;ie="TowardsCenter"===t?2:"AlongVelocity"===t?3:1,le.copy(M(a.params.center)),ce.copy(M(a.params.offset)).multiplyScalar(Math.PI/180);break}default:v(s,t,"error",`initializer:${a.type}`,`initializer ${a.type} is not supported on GPU`)}for(const e of t.behaviours.filter(e=>!1!==e.enabled))switch(e.type){case"force":h.add(M(e.params.force));break;case"gravity":h.y-=x(e.params.gravity,8);break;case"linearDamping":y+=x(e.params.factor,.1);break;case"randomDrift":g.copy(M(e.params.drift)),w=Math.max(0,x(e.params.delay,0)),G=S(e.params.ease?.value),V=!0;break;case"followParent":C=x(e.params.speed,0),P=!0;break;case"moveTo":I.copy(M(e.params.target)),E=S(e.params.ease?.value),U=!0;break;case"attraction":case"repulsion":if(oe){v(s,t,"error","multiple-attraction-behaviours","multiple attraction or repulsion behaviours are not supported in one GPU emitter");break}ae.copy(M(e.params.target)),re=x(e.params.force,1)*("repulsion"===e.type?-1:1),se=Math.max(0,x(e.params.radius,1)),oe=!0;break;case"vortex":if(me){v(s,t,"error","multiple-vortex-behaviours","multiple vortex behaviours are not supported in one GPU emitter");break}pe.copy(M(e.params.axis)),ue=x(e.params.amount,1),me=!0;break;case"disperse":{if(fe){v(s,t,"error","multiple-disperse-behaviours","multiple disperse behaviours are not supported in one GPU emitter");break}de=x(e.params.distance,1);const a=e.params.axis?.value;he="XY"===a?1:"XZ"===a?2:"YZ"===a?3:0,ye=S(e.params.ease?.value),fe=!0;break}case"worldCollision":if(e.params.method?.value===f.PhysicsRaycast){v(s,t,"requirement","physics-raycast-collision","Physics raycast world collision requests CPU particle simulation");break}A=!0,R=Math.max(0,x(e.params.bounce,0)),N=Math.max(0,Math.min(1,x(e.params.friction,0))),B=Math.max(0,x(e.params.lifeLoss,0)),T=!0===e.params.debug?.value;break;case"scale":$=x(e.params.a,1),j=x(e.params.b,1),be.x=S(e.params.ease?.value);break;case"scaleComponents":we.copy(ge).multiply(M(e.params.a)),ve.copy(ge).multiply(M(e.params.b)),be.w=S(e.params.ease?.value);break;case"changeColor":F=k(e.params.a,F),Y=k(e.params.b,Y),be.y=S(e.params.ease?.value),X=!1;break;case"changeOpacity":Z=x(e.params.a,1),q=x(e.params.b,0),be.z=S(e.params.ease?.value);break;case"rotate":case"rotateAdd":{const t=M(e.params.rotation);t.multiplyScalar(Math.PI/180*Math.PI/180),o?W.add(t):O=(O??0)+t.z;break}default:v(s,t,"error",`behaviour:${e.type}`,`behaviour ${e.type} is not supported on GPU`)}const Ce=Math.max(0,Math.floor(t.rate.count)),Pe="sprite"!==t.output.type&&"stretchedSprite"!==t.output.type||!Number.isFinite(t.output.intensity)?1:t.output.intensity;F.multiplyScalar(Pe),Y.multiplyScalar(Pe);const Ie="once"===t.rate.type?Ce:Math.max(Ce,Math.ceil(n/Math.max(t.rate.time,1e-4))*Ce),Oe=Math.min(25e4,Ie);return Oe!==Ie&&v(s,t,"warning","particle-capacity-clamped",`particle capacity ${Ie} exceeds the current GPU per-emitter limit of ${Oe}`),t.behaviours.some(e=>!1!==e.enabled&&"scaleComponents"===e.type)||(we.copy(ge),ve.copy(ge)),A&&"local"===t.output.space&&v(s,t,"error","world-collision-local-space","GPU screen-space world collision currently requires world-space output"),{position:(new e.Vector3).fromArray(t.position).add("local"===t.output.space?new e.Vector3:a),localSpace:"local"===t.output.space,capacity:Oe,rate:"once"===t.rate.type?{type:"once",count:Ce,delay:Math.max(0,t.rate.delay??0)}:{type:"continuous",count:Ce,interval:Math.max(t.rate.time,1e-4),delay:Math.max(0,t.rate.delay??0),duration:(t.rate.duration??0)>0?t.rate.duration:-1},life:n,lifeMin:i,positionRadius:l,spawnZoneType:c,spawnZoneA:p,spawnZoneB:u,meshSamplerAssetId:xe,meshSamplerInputId:Se,meshSamplerMode:Ve,meshSamplerTransform:Me,meshSamplerAlignAxis:ke,meshNormalVelocity:Ge,velocityMin:m,velocityMax:d,force:h,damping:y,mass:b,randomDrift:g,randomDriftDelay:w,randomDriftEasing:G,hasRandomDrift:V,followParentSpeed:C,hasFollowParent:P,moveToTarget:I,moveToEasing:E,hasMoveTo:U,hasWorldCollision:A,collisionBounce:R,collisionFriction:N,collisionLifeLoss:B,collisionDebug:T,orientAlongVelocity:!1,scaleStart:[z[0]*$,z[1]*$],scaleEnd:[z[0]*j,z[1]*j],colorStart:F,colorEnd:Y,randomColor:X,alphaStart:Z,alphaEnd:q,rotationMin:D,rotationMax:L,spriteRotationStep:O,meshRotation:Q,meshRotationEuler:J,meshRotationStep:W,randomMeshRotationAxis:H,radialVelocityDirection:K,radialVelocitySpeed:_,radialVelocitySpread:ee,hasRadialVelocity:te,attractionTarget:ae,attractionForce:re,attractionRadius:se,hasAttraction:oe,alignRotationAxis:ne,alignRotationMode:ie,alignRotationCenter:le,alignRotationOffset:ce,vortexAxis:pe,vortexAmount:ue,hasVortex:me,disperseDistance:de,dispersePlane:he,disperseEasing:ye,hasDisperse:fe,curveEasing:be,meshScaleStart:we,meshScaleEnd:ve,renderClass:r}}export function requiresCpuVfxBackend(e){const t=e=>e.behaviours.some(e=>!1!==e.enabled&&"worldCollision"===e.type&&e.params.method?.value===f.PhysicsRaycast)||(e.children??[]).some(t);return e.vfx.emitters.some(t)}function v(e,t,a,r,s){e.some(e=>e.emitter===t.name&&e.code===r)||e.push({severity:a,code:r,emitter:t.name||t.id,message:s})}function x(e,t){const a=e?.value;if("number"==typeof a)return Number.isFinite(a)?a:t;if("string"==typeof a&&""!==a.trim()){const e=Number(a);if(Number.isFinite(e))return e}return t}function S(e){switch(e){case"InQuad":return 1;case"OutQuad":return 2;case"InOutQuad":return 3;case"InCubic":return 4;case"OutCubic":return 5;case"InOutCubic":return 6;case"InQuart":return 7;case"OutQuart":return 8;case"InOutQuart":return 9;case"InSine":return 10;case"OutSine":return 11;case"InOutSine":return 12;case"InExpo":return 13;case"OutExpo":return 14;case"InOutExpo":return 15;case"InCirc":return 16;case"InBack":return 17;case"OutBack":return 18;case"Bump":return 19;case"BumpSharp":return 20;case"BumpFlat":return 21;case"SpikeFade":return 22;case"OutCirc":return 23;case"InOutCirc":return 24;case"InOutBack":return 25;case"BumpFade":return 26;case"BumpFall":return 27;default:return 0}}function M(t){const a=t?.value;return Array.isArray(a)?new e.Vector3(Number(a[0]),Number(a[1]),Number(a[2])):new e.Vector3}function k(t,a){const r=t?.value;if("string"==typeof r){if(null!=/^#([A-Fa-f0-9]{6})$/.exec(r))return new e.Color(r);const t=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(r);if(null!=t)return(new e.Color).setRGB(Math.min(255,Number.parseInt(t[1],10))/255,Math.min(255,Number.parseInt(t[2],10))/255,Math.min(255,Number.parseInt(t[3],10))/255,e.SRGBColorSpace)}if("number"==typeof r&&Number.isFinite(r))return new e.Color(Math.floor(r));if(null!=r&&"object"==typeof r&&"r"in r&&"g"in r&&"b"in r){const t=r;return(new e.Color).setRGB(t.r,t.g,t.b)}return a.clone()}/*
|
|
1
|
+
import*as e from"three";import{applyMeshWorldTransformToGeometry as t}from"./vfx-mesh-transform.js";import{attributes as a,clamp as r,lambertMaterial as s,NodeShaderMaterial as o,rgba as n,smoothstep as i,textureSampler2d as l,varyingAttributes as p}from"three-shader-graph";import{SerializedParamType as c}from"../../scene/model.js";import{particleUniforms as u}from"../../shader-nodes/particle.js";import{sampleFlipbook as m}from"../../shader-nodes/texture-sequence.js";import{fragmentLinearEyeDepth as d,linearEyeDepth as h}from"../../shader-nodes/depth.js";import{ThreeBlendingMode as y,WorldCollisionMethod as f}from"./vfx-asset.js";import{getDefaultVfxSpriteTexture as b}from"./vfx-default-sprite-texture.js";import{ShapeLibrary as g}from"../../scene/objects/shapes.js";export class GpuSpriteRenderClassCache{constructor(){this.entries=new Map}resolve(e,t){let a=this.entries.get(e);return null==a&&(a=t().catch(t=>{throw this.entries.delete(e),t}),this.entries.set(e,a)),a}clear(){this.entries.clear()}}export function hasGpuUnsupportedVfxInputBindings(e){const t=new Map((e.vfx.inputs??[]).map(e=>[e.id,e.type])),a=e=>{for(const a of[...e.initializers,...e.behaviours])if(!1!==a.enabled)for(const[r,s]of Object.entries(a.params)){if("vfxInput"!==s?.binding?.type)continue;const o=s.type===c.Number?"number":s.type===c.Vector3?"vec3":s.type===c.Color?"color":s.type===c.Object3D?"mesh":void 0;if(null==o||t.get(s.binding.inputId)!==o)return!0;if("lifetime"===a.type&&"duration"===r&&"continuous"===e.rate.type)return!0}return(e.children??[]).some(a)};return e.vfx.emitters.some(a)}export function selectVfxBackend(e,t="auto"){if("cpu"===t)return{backend:"cpu",reasons:["CPU backend explicitly requested"]};const a=e.issues.filter(e=>"requirement"===e.severity).map(e=>e.message);if(a.length>0)return{backend:"cpu",reasons:a};const r=e.issues.filter(e=>"error"===e.severity).map(e=>e.message);return r.length>0&&"gpu"!==t?{backend:"cpu",reasons:r}:r.length>0?{backend:"gpu",reasons:["GPU backend explicitly forced despite incompatibilities",...r]}:{backend:"gpu",reasons:e.issues.filter(e=>"warning"===e.severity).map(e=>e.message)}}export function compileGpuSpriteEmitters(t,a,r="emitter-major"){const s=[],o=[],n=new Map,i=[],l=[],p=new Map((t.vfx.inputs??[]).map(e=>[e.id,e.type])),u=new Map((t.vfx.inputs??[]).filter(e=>"number"===e.type).map(e=>[e.id,"number"==typeof e.defaultValue?e.defaultValue:0]));hasGpuUnsupportedVfxInputBindings(t)&&i.push({severity:"error",code:"vfx-input-binding",emitter:"effect",message:"this VFX input binding target is not supported on GPU yet"});const m=t.vfx.emitters.slice().sort((e,t)=>(e.output.renderOrder??0)-(t.output.renderOrder??0)),d=(t,r,m)=>{const h="vfxInput"===t.rate.delayBinding?.type?u.get(t.rate.delayBinding.inputId):void 0,y=null==h?t:{...t,rate:{...t.rate,delay:Math.max(0,h)}};if("sprite"!==t.output.type&&"mesh"!==t.output.type&&"stretchedSprite"!==t.output.type&&"decal"!==t.output.type&&"shape"!==t.output.type&&"trail"!==t.output.type)return void v(i,t,"error","output-type","this output type is not supported by the GPU sprite backend");if("mesh"===t.output.type&&null==t.output.assetId)return;if(t.rate.count<=0)return;const f="trail"===(b=t.output).type?JSON.stringify(b):"mesh"===b.type?JSON.stringify({type:b.type,assetId:b.assetId,renderOrder:b.renderOrder??0,useLegacyTransform:!0===b.useLegacyTransform,materialSource:b.materialSource??null,material:b.material??null,shader:b.shader??null,shaderParams:b.shaderParams??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space}):"decal"===b.type?JSON.stringify({type:b.type,colorMap:b.colorMap,alphaMap:b.alphaMap,color:b.color,unlit:b.unlit,intensity:b.intensity,opacityChannel:b.opacityChannel??"red",blendingMode:b.blendingMode,renderOrder:b.renderOrder??0,materialSource:b.materialSource??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space}):"shape"===b.type?JSON.stringify({type:b.type,shape:b.shape,params:b.params,material:b.material,renderOrder:b.renderOrder??0,materialSource:b.materialSource??null,shader:b.shader??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space}):JSON.stringify({type:b.type,texture:b.texture,opacityChannel:b.opacityChannel??"red",blendingMode:b.blendingMode,softness:b.softness,renderOrder:b.renderOrder??0,bloom:b.bloom,materialSource:b.materialSource??null,shader:b.shader??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space,lockY:"sprite"===b.type&&!0===b.lockY,stretchScale:"stretchedSprite"===b.type?b.scale:null});var b;let g=n.get(f);null==g&&(g=o.length,n.set(f,g),o.push({key:f,output:t.output}));const x=[];for(let o=0;o<a.length;o++){const n=w(y,null==r?a[o]:new e.Vector3,g,i);if(null!=n){if(null!=r){const e=s[r]?.instances[o];if(null==e)continue;const a=n.capacity,l=e.capacity*a;if(l>25e4){v(i,t,"error","child-particle-capacity",`child emitter expansion requires ${l} particles, exceeding the GPU per-emitter limit`);continue}n.capacity=l,n.parentEmitter=r,n.childParticlesPerParent=a,n.childSpawnEvent="collision"===t.spawnEvent?2:1,n.childLevel=m,!0===n.localSpace&&!0!==e.localSpace&&v(i,t,"error","child-emitter-local-space","GPU child emitters do not yet support a world-space parent with local-space child output"),"trail"===t.output.type&&v(i,t,"error","child-emitter-trail","GPU child emitters do not yet support trail output")}x.push(n)}}if(x.length>0){const e=s.length;s.push({instances:x,parentSource:r});for(const a of[...t.initializers,...t.behaviours])if(!1!==a.enabled)for(const[r,s]of Object.entries(a.params)){const o=s?.binding;if("vfxInput"!==o?.type)continue;const n=s.type===c.Number?"number":s.type===c.Vector3?"vec3":s.type===c.Color?"color":s.type===c.Object3D?"mesh":void 0;null!=n&&p.get(o.inputId)===n&&("mesh"!==n&&("lifetime"===a.type&&"duration"===r&&"continuous"===t.rate.type||l.push({inputId:o.inputId,emitterIndex:e,target:`${t.initializers.includes(a)?"initializer":"behaviour"}:${a.type}:${r}`,authoredScalar:"number"==typeof s.value?s.value:void 0,baseScaleStart:[...x[0].scaleStart],baseScaleEnd:[...x[0].scaleEnd]})))}for(const a of t.children??[])d(a,e,m+1)}};for(const e of m)d(e,null,0);const h="instance-major"===r?a.flatMap((e,t)=>s.flatMap(e=>null==e.instances[t]?[]:[e.instances[t]])):s.flatMap(e=>e.instances);for(let e=0;e<s.length;e++){const t=s[e];if(null!=t.parentSource)for(let e=0;e<t.instances.length;e++)t.instances[e].parentEmitter="instance-major"===r?e*s.length+t.parentSource:t.parentSource*a.length+e}const y=o.map((e,t)=>({renderClass:e,oldIndex:t})).sort((e,t)=>(e.renderClass.output.renderOrder??0)-(t.renderClass.output.renderOrder??0)),f=new Array(o.length);for(let e=0;e<y.length;e++)f[y[e].oldIndex]=e;for(const e of h)e.renderClass=f[e.renderClass??0]??0;const b={compatible:!i.some(e=>"warning"!==e.severity),issues:i};return{emitters:h,inputBindings:l,renderClasses:y.map(e=>e.renderClass),compatibility:b,unsupported:[...new Set(i.map(e=>`${e.emitter}: ${e.message}`))]}}export async function materializeGpuSpriteRenderClasses(c,f,w,v){const x=async c=>{const v=c.output;if("trail"===v.type){const t=v.materialSource??("asset"===v.shaderGraph?.source?"shaderGraph":"default"),a="default"===t?null:await(w?.(v))??null;if(null==a&&"default"!==t)throw new Error(`${t} trail material requires a compatible GPU material resolver`);const r=null!=v.texture?await f.getTexture(v.texture):b(),s="repeat"===v.uvMode?r.clone():r;return"repeat"===v.uvMode&&(s.wrapS=e.RepeatWrapping,s.needsUpdate=!0),{texture:s,material:a??void 0,localSpace:"local"===v.space,trail:{historyLength:Math.max(2,Math.round(v.length)+1),width:v.width??1,taper:v.taper,colorStart:new e.Color(v.color).multiplyScalar(v.intensity),colorEnd:new e.Color(v.colorEnd).multiplyScalar(v.intensityEnd),opacityStart:v.opacityStart,opacityEnd:v.opacityEnd,scrollSpeed:v.scrollSpeed??0,uvMode:v.uvMode??"stretch",unitsPerRepeat:Math.max(.001,v.unitsPerRepeat??1),opacityChannel:v.opacityChannel??"red",blendingMode:v.blendingMode??"normal",billboard:v.billboard??!1}}}if("mesh"===v.type){if(null==f.getMesh)throw new Error("GPU mesh particles require a mesh asset provider");const a=await f.getMesh(v.assetId);a.updateWorldMatrix(!0,!0);const r=[];if(a.traverse(t=>{t instanceof e.Mesh&&r.push(t)}),1!==r.length)throw new Error(`GPU mesh particles require exactly one mesh geometry; asset ${v.assetId} resolved to ${r.length}`);const s=null==r[0].geometry.index?r[0].geometry.clone():r[0].geometry.toNonIndexed();!0!==v.useLegacyTransform&&t(r[0],s);const n=s.getAttribute("position");if(null==n)throw new Error(`GPU mesh particle asset ${v.assetId} has no position attribute`);const i=s.getAttribute("normal"),l=s.getAttribute("uv"),p=new Float32Array(8*n.count);for(let e=0;e<n.count;e++){const t=8*e;p[t]=n.getX(e),p[t+1]=n.getY(e),p[t+2]=n.getZ(e),p[t+3]=i?.getX(e)??0,p[t+4]=i?.getY(e)??1,p[t+5]=i?.getZ(e)??0,p[t+6]=l?.getX(e)??0,p[t+7]=l?.getY(e)??0}s.dispose();const c=Array.isArray(r[0].material)?r[0].material[0]:r[0].material,m="material"===v.materialSource&&null==v.material||"shaderGraph"===v.materialSource&&("asset"!==v.shaderGraph?.source||null==v.shaderGraph.assetId)||"shader"===v.materialSource&&null==v.shader?"default":v.materialSource??("asset"===v.shaderGraph?.source?"shaderGraph":null!=v.shader?"shader":null!=v.material?"material":"default"),d="default"===m?await(w?.(v))??function(){const e=u.opacity;return new o({color:u.color.rgb.rgba(e),opacity:e,transparent:!0})}():await(w?.(v))??null;if(null==d&&"default"!==m)throw new Error(`${m} mesh material requires a compatible GPU material resolver`);const h=null!=c&&"color"in c&&c.color instanceof e.Color?c.color.clone():new e.Color(16777215);return{texture:b(),meshVertices:p,meshColor:h,meshOpacity:c?.opacity??1,localSpace:"local"===v.space,material:d??void 0}}if("decal"===v.type){const t=await(w?.(v))??null;if(null==t)throw new Error("GPU decal output requires a compatible GPU decal material resolver");const a=new e.BoxGeometry(1,1,1).toNonIndexed(),r=a.getAttribute("position"),s=a.getAttribute("normal"),o=a.getAttribute("uv"),n=new Float32Array(8*r.count);for(let e=0;e<r.count;e++){const t=8*e;n[t]=r.getX(e),n[t+1]=r.getY(e),n[t+2]=r.getZ(e),n[t+3]=s.getX(e),n[t+4]=s.getY(e),n[t+5]=s.getZ(e),n[t+6]=o.getX(e),n[t+7]=o.getY(e)}return a.dispose(),{texture:b(),meshVertices:n,meshColor:new e.Color(16777215),meshOpacity:1,localSpace:"local"===v.space,material:t}}if("shape"===v.type){const t=g[v.shape];if(null==t)throw new Error(`GPU shape output has unknown shape ${v.shape}`);const a=v.materialSource??("asset"===v.shaderGraph?.source?"shaderGraph":null!=v.shader?"shader":null!=v.material?"material":"default"),r="default"===a?function(){const e=u.opacity;return new o({color:s({color:u.color.rgb}).rgb.rgba(e),opacity:e,transparent:!0})}():await(w?.(v))??null;if(null==r&&"default"!==a)throw new Error(`${a} shape material requires a compatible GPU material resolver`);const n=Object.fromEntries(Object.entries(v.params??{}).map(([e,t])=>[e,t.value])),i=t.geometry(n),l=null==i.index?i:i.toNonIndexed(),p=l.getAttribute("position"),c=l.getAttribute("normal"),m=l.getAttribute("uv"),d=new Float32Array(8*p.count);for(let e=0;e<p.count;e++){const t=8*e;d[t]=p.getX(e),d[t+1]=p.getY(e),d[t+2]=p.getZ(e),d[t+3]=c?.getX(e)??0,d[t+4]=c?.getY(e)??1,d[t+5]=c?.getZ(e)??0,d[t+6]=m?.getX(e)??0,d[t+7]=m?.getY(e)??0}return l!==i&&l.dispose(),i.dispose(),{texture:b(),meshVertices:d,meshColor:new e.Color(16777215),meshOpacity:1,localSpace:"local"===v.space,material:r??void 0}}const x=null!=v.texture?await f.getTexture(v.texture):b(),S="stretchedSprite"===v.type?"default":v.materialSource??("asset"===v.shaderGraph?.source?"shaderGraph":"default");let M="default"===S?null:await(w?.(v))??null;if(null==M&&"default"!==S)throw new Error(`${S} material requires a compatible GPU material resolver`);return M??(M=function(t,s){const c=l(s),f="sprite"===t.type&&!0===t.flipbook?.enabled?m(c,a.uv,t.flipbook.columns,t.flipbook.rows,u.time,t.flipbook.fps,t.flipbook.mode):c.sample(p.uv);let b=u.opacity;"red"===(t.opacityChannel??"red")?b=b.multiply(f.r):"alpha"===t.opacityChannel&&(b=b.multiply(f.a));if(t.softness>0){const e=h.subtract(d).divide(h);b=b.multiply(i(0,.2*t.softness,r(e,0,1e3)))}const g=new o({color:n(u.color.multiply(f.rgb),b),transparent:!0,lights:!1,fog:!1,alphaTest:1e-4});return g.blending=y[t.blendingMode]??e.NormalBlending,g.depthWrite=!1,g}(v,x)),M.transparent&&(M.depthWrite=!1),{texture:x,material:M,lockY:"sprite"===v.type&&!0===v.lockY,localSpace:"local"===v.space,stretchScale:"stretchedSprite"===v.type?0===v.scale?.001:v.scale:void 0}};return{renderClasses:await Promise.all(c.map(e=>v?.resolve(e.key,()=>x(e))??x(e))),unsupported:[]}}function w(t,a,r,s){if("sprite"!==t.output.type&&"mesh"!==t.output.type&&"decal"!==t.output.type&&"shape"!==t.output.type&&"trail"!==t.output.type&&"stretchedSprite"!==t.output.type)return null;const o="mesh"===t.output.type||"decal"===t.output.type||"shape"===t.output.type;let n=99999,i=99999,l=0,p=0;const c=new e.Vector4,u=new e.Vector4,m=new e.Vector3,d=new e.Vector3,h=new e.Vector3;let y=0,b=1;const g=new e.Vector3;let w=0,G=0,V=!1,C=0,P=!1;const I=new e.Vector3;let O,E=0,U=!1,R=!1,A=0,N=0,B=0,T=!1,z=[1,1],$=1,j=1,F=new e.Color("sprite"===t.output.type||"stretchedSprite"===t.output.type?t.output.color:"#ffffff"),Y=F.clone(),X=!1,Z=1,q=1,D=0,L=0;const Q=new e.Quaternion,J=new e.Vector3,W=new e.Vector3;let H=0;const K=new e.Vector3(0,1,0);let _=0,ee=0,te=!1;const ae=new e.Vector3;let re=0,se=0,oe=!1;const ne=new e.Vector3(0,1,0);let ie=0;const le=new e.Vector3,pe=new e.Vector3,ce=new e.Vector3(0,1,0);let ue=0,me=!1,de=0,he=0,ye=0,fe=!1;const be=new e.Vector4(0,0,0,0),ge=new e.Vector3(1,1,1),we=new e.Vector3(1,1,1),ve=new e.Vector3(1,1,1);let xe,Se,Me,ke,Ge,Ve="surface";for(const a of t.initializers.filter(e=>!1!==e.enabled))switch(a.type){case"lifetime":i=n=x(a.params.duration,1);break;case"randomLifetime":{const e=x(a.params.minDuration,1),t=x(a.params.maxDuration,2);i=Math.min(e,t),n=Math.max(e,t);break}case"velocity":{const e=M(a.params.velocity);m.copy(e),d.copy(e);break}case"randomVelocity":m.copy(M(a.params.min)),d.copy(M(a.params.max));break;case"randomDirection":{const e=x(a.params.speed,1);m.setScalar(-e),d.setScalar(e);break}case"radialVelocity":K.copy(M(a.params.direction)).normalize(),_=x(a.params.speed,1),ee=e.MathUtils.degToRad(x(a.params.spread,0)),te=!0;break;case"mass":b=Math.max(1e-6,x(a.params.min,1));break;case"positionPoint":c.copy(new e.Vector4(...M(a.params.position).toArray(),0));break;case"positionSphere":{l=x(a.params.radius,1);const e=M(a.params.position);p=1,c.set(e.x,e.y,e.z,!0===a.params.surface?.value?1:0);break}case"positionBox":{const e=M(a.params.position),t=M(a.params.dimensions);p=2,c.set(e.x,e.y,e.z,0),u.set(t.x,t.y,t.z,0);break}case"positionLine":{const e=M(a.params.a),t=M(a.params.b);p=3,c.set(e.x,e.y,e.z,0),u.set(t.x,t.y,t.z,0);break}case"positionCircle":case"positionRing":{const t=M(a.params.position),r=M(a.params.rotation).multiplyScalar(Math.PI/180);l=x(a.params.radius,1);const s="positionRing"===a.type?Math.max(x(a.params.thickness,.2),1e-4):0;p=4,c.set(t.x,t.y,t.z,s),u.set(r.x,r.y,r.z,e.MathUtils.degToRad(Math.max(0,Math.min(360,x(a.params.angle,360)))));break}case"positionMesh":{const r=a.params.mesh?.value,o=a.params.mesh?.binding;if("vfxInput"===o?.type&&(Se=o.inputId),("string"!=typeof r||0===r.length)&&null==Se){v(s,t,"error","mesh-sampler-source","GPU mesh sampling requires a selected fallback mesh asset");break}if(xe="string"==typeof r&&r.length>0?r:void 0,Ve="vertices"===a.params.sampling?.value?"vertices":"surface",Me=(new e.Matrix4).compose(M(a.params.position),(new e.Quaternion).setFromEuler((new e.Euler).setFromVector3(M(a.params.rotation).multiplyScalar(Math.PI/180))),null==a.params.scale?new e.Vector3(1,1,1):M(a.params.scale)),!0===a.params.alignNormal?.value){const t=a.params.alignmentAxis?.value;ke="+X"===t?new e.Vector3(1,0,0):"-X"===t?new e.Vector3(-1,0,0):"-Y"===t?new e.Vector3(0,-1,0):"+Z"===t?new e.Vector3(0,0,1):"-Z"===t?new e.Vector3(0,0,-1):new e.Vector3(0,1,0)}!0===a.params.normalVelocity?.value&&(Ge=new e.Vector4(x(a.params.normalVelocityMin,1),x(a.params.normalVelocityMax,1),e.MathUtils.degToRad(e.MathUtils.clamp(x(a.params.normalVelocitySpread,0),0,180)),1)),p=5;break}case"scale":{const e=x(a.params.scale,1);z=[e,e];break}case"scaleComponents":ge.copy(M(a.params.scale));break;case"randomScale":z=[x(a.params.min,1),x(a.params.max,1)];break;case"randomColor":F=k(a.params.a,F),Y=k(a.params.b,F),X=!0;break;case"rotation":{const t=M(a.params.rotation);D=L=e.MathUtils.degToRad(t.z),J.set(e.MathUtils.degToRad(t.x),e.MathUtils.degToRad(t.y),e.MathUtils.degToRad(t.z)),Q.setFromEuler(new e.Euler(J.x,J.y,J.z));break}case"randomRotation":{if(o){const e=a.params.axis?.value;H="X"===e?2:"Y"===e?3:"Z"===e?4:1;break}const e=a.params.axis?.value;"XYZ"!==e&&"Z"!==e&&null!=e||(L=2*Math.PI);break}case"alignRotation":{if(!o)break;const e=a.params.axis?.value;"+X"===e?ne.set(1,0,0):"-X"===e?ne.set(-1,0,0):"-Y"===e?ne.set(0,-1,0):"+Z"===e?ne.set(0,0,1):"-Z"===e?ne.set(0,0,-1):ne.set(0,1,0);const t=a.params.mode?.value;ie="TowardsCenter"===t?2:"AlongVelocity"===t?3:1,le.copy(M(a.params.center)),pe.copy(M(a.params.offset)).multiplyScalar(Math.PI/180);break}default:v(s,t,"error",`initializer:${a.type}`,`initializer ${a.type} is not supported on GPU`)}for(const e of t.behaviours.filter(e=>!1!==e.enabled))switch(e.type){case"force":h.add(M(e.params.force));break;case"gravity":h.y-=x(e.params.gravity,8);break;case"linearDamping":y+=x(e.params.factor,.1);break;case"randomDrift":g.copy(M(e.params.drift)),w=Math.max(0,x(e.params.delay,0)),G=S(e.params.ease?.value),V=!0;break;case"followParent":C=x(e.params.speed,0),P=!0;break;case"moveTo":I.copy(M(e.params.target)),E=S(e.params.ease?.value),U=!0;break;case"attraction":case"repulsion":if(oe){v(s,t,"error","multiple-attraction-behaviours","multiple attraction or repulsion behaviours are not supported in one GPU emitter");break}ae.copy(M(e.params.target)),re=x(e.params.force,1)*("repulsion"===e.type?-1:1),se=Math.max(0,x(e.params.radius,1)),oe=!0;break;case"vortex":if(me){v(s,t,"error","multiple-vortex-behaviours","multiple vortex behaviours are not supported in one GPU emitter");break}ce.copy(M(e.params.axis)),ue=x(e.params.amount,1),me=!0;break;case"disperse":{if(fe){v(s,t,"error","multiple-disperse-behaviours","multiple disperse behaviours are not supported in one GPU emitter");break}de=x(e.params.distance,1);const a=e.params.axis?.value;he="XY"===a?1:"XZ"===a?2:"YZ"===a?3:0,ye=S(e.params.ease?.value),fe=!0;break}case"worldCollision":if(e.params.method?.value===f.PhysicsRaycast){v(s,t,"requirement","physics-raycast-collision","Physics raycast world collision requests CPU particle simulation");break}R=!0,A=Math.max(0,x(e.params.bounce,0)),N=Math.max(0,Math.min(1,x(e.params.friction,0))),B=Math.max(0,x(e.params.lifeLoss,0)),T=!0===e.params.debug?.value;break;case"scale":$=x(e.params.a,1),j=x(e.params.b,1),be.x=S(e.params.ease?.value);break;case"scaleComponents":we.copy(ge).multiply(M(e.params.a)),ve.copy(ge).multiply(M(e.params.b)),be.w=S(e.params.ease?.value);break;case"changeColor":F=k(e.params.a,F),Y=k(e.params.b,Y),be.y=S(e.params.ease?.value),X=!1;break;case"changeOpacity":Z=x(e.params.a,1),q=x(e.params.b,0),be.z=S(e.params.ease?.value);break;case"rotate":case"rotateAdd":{const t=M(e.params.rotation);t.multiplyScalar(Math.PI/180*Math.PI/180),o?W.add(t):O=(O??0)+t.z;break}default:v(s,t,"error",`behaviour:${e.type}`,`behaviour ${e.type} is not supported on GPU`)}const Ce=Math.max(0,Math.floor(t.rate.count)),Pe="sprite"!==t.output.type&&"stretchedSprite"!==t.output.type||!Number.isFinite(t.output.intensity)?1:t.output.intensity;F.multiplyScalar(Pe),Y.multiplyScalar(Pe);const Ie="once"===t.rate.type?Ce:Math.max(Ce,Math.ceil(n/Math.max(t.rate.time,1e-4))*Ce),Oe=Math.min(25e4,Ie);return Oe!==Ie&&v(s,t,"warning","particle-capacity-clamped",`particle capacity ${Ie} exceeds the current GPU per-emitter limit of ${Oe}`),t.behaviours.some(e=>!1!==e.enabled&&"scaleComponents"===e.type)||(we.copy(ge),ve.copy(ge)),R&&"local"===t.output.space&&v(s,t,"error","world-collision-local-space","GPU screen-space world collision currently requires world-space output"),{position:(new e.Vector3).fromArray(t.position).add("local"===t.output.space?new e.Vector3:a),localSpace:"local"===t.output.space,capacity:Oe,rate:"once"===t.rate.type?{type:"once",count:Ce,delay:Math.max(0,t.rate.delay??0)}:{type:"continuous",count:Ce,interval:Math.max(t.rate.time,1e-4),delay:Math.max(0,t.rate.delay??0),duration:(t.rate.duration??0)>0?t.rate.duration:-1},life:n,lifeMin:i,positionRadius:l,spawnZoneType:p,spawnZoneA:c,spawnZoneB:u,meshSamplerAssetId:xe,meshSamplerInputId:Se,meshSamplerMode:Ve,meshSamplerTransform:Me,meshSamplerAlignAxis:ke,meshNormalVelocity:Ge,velocityMin:m,velocityMax:d,force:h,damping:y,mass:b,randomDrift:g,randomDriftDelay:w,randomDriftEasing:G,hasRandomDrift:V,followParentSpeed:C,hasFollowParent:P,moveToTarget:I,moveToEasing:E,hasMoveTo:U,hasWorldCollision:R,collisionBounce:A,collisionFriction:N,collisionLifeLoss:B,collisionDebug:T,orientAlongVelocity:!1,scaleStart:[z[0]*$,z[1]*$],scaleEnd:[z[0]*j,z[1]*j],colorStart:F,colorEnd:Y,randomColor:X,alphaStart:Z,alphaEnd:q,rotationMin:D,rotationMax:L,spriteRotationStep:O,meshRotation:Q,meshRotationEuler:J,meshRotationStep:W,randomMeshRotationAxis:H,radialVelocityDirection:K,radialVelocitySpeed:_,radialVelocitySpread:ee,hasRadialVelocity:te,attractionTarget:ae,attractionForce:re,attractionRadius:se,hasAttraction:oe,alignRotationAxis:ne,alignRotationMode:ie,alignRotationCenter:le,alignRotationOffset:pe,vortexAxis:ce,vortexAmount:ue,hasVortex:me,disperseDistance:de,dispersePlane:he,disperseEasing:ye,hasDisperse:fe,curveEasing:be,meshScaleStart:we,meshScaleEnd:ve,renderClass:r}}export function requiresCpuVfxBackend(e){const t=e=>e.behaviours.some(e=>!1!==e.enabled&&"worldCollision"===e.type&&e.params.method?.value===f.PhysicsRaycast)||(e.children??[]).some(t);return e.vfx.emitters.some(t)}function v(e,t,a,r,s){e.some(e=>e.emitter===t.name&&e.code===r)||e.push({severity:a,code:r,emitter:t.name||t.id,message:s})}function x(e,t){const a=e?.value;if("number"==typeof a)return Number.isFinite(a)?a:t;if("string"==typeof a&&""!==a.trim()){const e=Number(a);if(Number.isFinite(e))return e}return t}function S(e){switch(e){case"InQuad":return 1;case"OutQuad":return 2;case"InOutQuad":return 3;case"InCubic":return 4;case"OutCubic":return 5;case"InOutCubic":return 6;case"InQuart":return 7;case"OutQuart":return 8;case"InOutQuart":return 9;case"InSine":return 10;case"OutSine":return 11;case"InOutSine":return 12;case"InExpo":return 13;case"OutExpo":return 14;case"InOutExpo":return 15;case"InCirc":return 16;case"InBack":return 17;case"OutBack":return 18;case"Bump":return 19;case"BumpSharp":return 20;case"BumpFlat":return 21;case"SpikeFade":return 22;case"OutCirc":return 23;case"InOutCirc":return 24;case"InOutBack":return 25;case"BumpFade":return 26;case"BumpFall":return 27;default:return 0}}function M(t){const a=t?.value;return Array.isArray(a)?new e.Vector3(Number(a[0]),Number(a[1]),Number(a[2])):new e.Vector3}function k(t,a){const r=t?.value;if("string"==typeof r){if(null!=/^#([A-Fa-f0-9]{6})$/.exec(r))return new e.Color(r);const t=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(r);if(null!=t)return(new e.Color).setRGB(Math.min(255,Number.parseInt(t[1],10))/255,Math.min(255,Number.parseInt(t[2],10))/255,Math.min(255,Number.parseInt(t[3],10))/255,e.SRGBColorSpace)}if("number"==typeof r&&Number.isFinite(r))return new e.Color(Math.floor(r));if(null!=r&&"object"==typeof r&&"r"in r&&"g"in r&&"b"in r){const t=r;return(new e.Color).setRGB(t.r,t.g,t.b)}return a.clone()}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|