@hology/core 0.0.236 → 0.0.238

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/effects/sequence/sequence-player.d.ts +3 -0
  2. package/dist/effects/sequence/sequence-player.js +1 -1
  3. package/dist/effects/vfx/gpu-particle-arena.d.ts +57 -0
  4. package/dist/effects/vfx/gpu-particle-arena.js +4 -0
  5. package/dist/effects/vfx/gpu-sprite-backend.d.ts +33 -0
  6. package/dist/effects/vfx/gpu-sprite-backend.js +4 -0
  7. package/dist/effects/vfx/gpu-sprite-compiler.d.ts +58 -0
  8. package/dist/effects/vfx/gpu-sprite-compiler.js +4 -0
  9. package/dist/effects/vfx/gpu-sprite-render-graph.d.ts +10 -0
  10. package/dist/effects/vfx/gpu-sprite-render-graph.js +4 -0
  11. package/dist/effects/vfx/gpu-sprite-runtime.d.ts +304 -0
  12. package/dist/effects/vfx/gpu-sprite-runtime.js +4 -0
  13. package/dist/effects/vfx/gpu-sprite-scheduler-runtime.d.ts +71 -0
  14. package/dist/effects/vfx/gpu-sprite-scheduler-runtime.js +4 -0
  15. package/dist/effects/vfx/gpu-sprite-template.d.ts +47 -0
  16. package/dist/effects/vfx/gpu-sprite-template.js +4 -0
  17. package/dist/effects/vfx/gpu-sprite-world-runtime.d.ts +61 -0
  18. package/dist/effects/vfx/gpu-sprite-world-runtime.js +4 -0
  19. package/dist/effects/vfx/gpu-vfx-capacity.d.ts +3 -0
  20. package/dist/effects/vfx/gpu-vfx-capacity.js +4 -0
  21. package/dist/effects/vfx/gpu-vfx-scheduler.d.ts +52 -0
  22. package/dist/effects/vfx/gpu-vfx-scheduler.js +4 -0
  23. package/dist/effects/vfx/gpu-vfx-world-service.d.ts +103 -0
  24. package/dist/effects/vfx/gpu-vfx-world-service.js +4 -0
  25. package/dist/effects/vfx/index.d.ts +11 -0
  26. package/dist/effects/vfx/index.js +1 -1
  27. package/dist/effects/vfx/trail-renderer.js +1 -1
  28. package/dist/effects/vfx/vfx-actor.d.ts +19 -2
  29. package/dist/effects/vfx/vfx-actor.js +1 -1
  30. package/dist/effects/vfx/vfx-asset.d.ts +2 -0
  31. package/dist/effects/vfx/vfx-default-sprite-texture.d.ts +3 -0
  32. package/dist/effects/vfx/vfx-default-sprite-texture.js +4 -0
  33. package/dist/effects/vfx/vfx-input-runtime.d.ts +3 -1
  34. package/dist/effects/vfx/vfx-materializer.d.ts +10 -0
  35. package/dist/effects/vfx/vfx-materializer.js +1 -1
  36. package/dist/effects/vfx/vfx-mesh-transform.d.ts +4 -0
  37. package/dist/effects/vfx/vfx-mesh-transform.js +4 -0
  38. package/dist/effects/vfx/vfx-param.d.ts +2 -0
  39. package/dist/effects/vfx/vfx-param.js +1 -1
  40. package/dist/effects/vfx/vfx-renderers.js +1 -1
  41. package/dist/effects/vfx/vfx-runtime.d.ts +35 -0
  42. package/dist/effects/vfx/vfx-runtime.js +4 -0
  43. package/dist/effects/vfx/vfx-service.d.ts +3 -0
  44. package/dist/effects/vfx/vfx-service.js +1 -1
  45. package/dist/gameplay/actors/builtin/components/character/character-animation.d.ts +19 -0
  46. package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
  47. package/dist/gameplay/actors/builtin/components/character/character-movement-like.d.ts +1 -1
  48. package/dist/gameplay/actors/builtin/components/character/character-movement.d.ts +8 -3
  49. package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
  50. package/dist/gameplay/actors/builtin/components/character/root-motion-constraint.d.ts +10 -0
  51. package/dist/gameplay/actors/builtin/components/character/root-motion-constraint.js +1 -1
  52. package/dist/gameplay/ai/behavior-tree/move.d.ts +14 -0
  53. package/dist/gameplay/ai/behavior-tree/move.js +1 -1
  54. package/dist/gameplay/initiate.d.ts +3 -0
  55. package/dist/gameplay/initiate.js +1 -1
  56. package/dist/gameplay/services/physics/physics-system.js +1 -1
  57. package/dist/gameplay/services/render.d.ts +14 -1
  58. package/dist/gameplay/services/render.js +1 -1
  59. package/dist/rendering/webgpu-experimental-backend.d.ts +8 -2
  60. package/dist/rendering/webgpu-experimental-backend.js +1 -1
  61. package/dist/rendering.d.ts +32 -3
  62. package/dist/rendering.js +1 -1
  63. package/dist/scene/asset-resource-loader.js +1 -1
  64. package/dist/scene/materializer.js +1 -1
  65. package/dist/scene/objects/shapes.js +1 -1
  66. package/dist/shader/builtin/decal-standard-shader.d.ts +1 -0
  67. package/dist/shader/builtin/decal-standard-shader.js +1 -1
  68. package/dist/shader/decal-shader.js +1 -1
  69. package/dist/shader-nodes/effects.js +1 -1
  70. package/dist/shader-nodes/material-flags.js +1 -1
  71. package/dist/shader-nodes/particle.d.ts +5 -2
  72. package/dist/shader-nodes/particle.js +1 -1
  73. package/dist/test/asset-resource-loader-skinned-merge.test.d.ts +2 -0
  74. package/dist/test/asset-resource-loader-skinned-merge.test.js +4 -0
  75. package/dist/test/character-animation-transition.test.js +1 -1
  76. package/dist/test/character-root-motion-constraint.test.js +1 -1
  77. package/dist/test/gpu-particle-arena.test.d.ts +2 -0
  78. package/dist/test/gpu-particle-arena.test.js +4 -0
  79. package/dist/test/gpu-sprite-compiler.test.d.ts +2 -0
  80. package/dist/test/gpu-sprite-compiler.test.js +4 -0
  81. package/dist/test/gpu-vfx-scheduler.test.d.ts +2 -0
  82. package/dist/test/gpu-vfx-scheduler.test.js +4 -0
  83. package/dist/test/mesh-clone.test.d.ts +2 -0
  84. package/dist/test/mesh-clone.test.js +4 -0
  85. package/dist/test/sequence-animation-retiming.test.js +1 -1
  86. package/dist/test/sequence-scene-binding.test.js +1 -1
  87. package/dist/test/sequence-vfx.test.js +1 -1
  88. package/dist/test/vfx-mesh-transform.test.d.ts +2 -0
  89. package/dist/test/vfx-mesh-transform.test.js +4 -0
  90. package/dist/utils/mesh.d.ts +7 -1
  91. package/dist/utils/mesh.js +1 -1
  92. package/package.json +15 -3
  93. package/tsconfig.tsbuildinfo +1 -1
@@ -315,6 +315,9 @@ export declare class SequencePlayer implements SequenceLocatorReader {
315
315
  private clearExternalRootMotionPreview;
316
316
  private evaluateTransformSubTrack;
317
317
  private evaluateAnimationSubTrack;
318
+ private deactivateAnimationAction;
319
+ private deactivateAnimationSubTracks;
320
+ private deactivateCharacterAnimationActions;
318
321
  private evaluateVisibilitySubTrack;
319
322
  private evaluatePropertySubTrack;
320
323
  private evaluateParameterSubTrack;
@@ -1,4 +1,4 @@
1
- import{BehaviorSubject as e,Subject as t}from"rxjs";import*as a from"three";import{AnimationMixer as s,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{BaseActor as p}from"../../gameplay/actors/actor.js";import d from"../../gameplay/actors/builtin/index.js";import{Prefab as f,PrefabOf as m}from"../../scene/objects/prefab.js";import{SerializedParamType as y}from"../../scene/model.js";import{customParamValueNeedsAsyncResolution as v,deserializeCustomParamValue as C,deserializeCustomParamValueSync as g}from"../../scene/custom-param-deserialize.js";import{getAudioParameterDefinition as A}from"./audio-parameters.js";import{getMaterialSubTrackMatchMode as S,getMaterialSubTrackTarget as w,Sequence as P,isSequenceData as b}from"./sequence-data.js";import{getSequenceSubTrackDefinition as k,getSequenceTrackDefinition as x}from"./sequence-definitions.js";import{applyInterpolation as T,evaluateCustomParamValueKeyframes as I,evaluateNumericKeyframes as M,findKeyframeSpan as B}from"./sequence-value-lane.js";import{evaluateTransformPositionSpan as q}from"./sequence-transform.js";import{applyAnimationClipRootMotionAxisMask as O,buildRetimedAnimationClip as F,getAnimationClipRetimingSignature as E,isAnimationClipUsingRetiming as j}from"./sequence-animation-retiming.js";import*as V from"three/addons/utils/SkeletonUtils.js";import{CharacterAnimationComponent as R,getCharacterMovementLike as _}from"../../gameplay/actors/index.js";import{RootMotionClip as L}from"../../gameplay/animation/root-motion.js";import{markMaterialUniformValuesNeedUpdate as D}from"../../rendering/node-material-webgpu-resolver.js";import{getAnimationClipRigId as K,getAnimationRigIdFromObject as $,setAnimationClipRigId as G}from"../../gameplay/animation/retarget.js";import{hashCameraShakeSeed as N}from"../../gameplay/services/camera-shake.js";import{buildShaderGraphPostProcessMaterial as U,shaderGraphPostProcessWeightUniformName as W}from"../../shader/graph/index.js";export var SequencePlaybackState;!function(e){e.Stopped="stopped",e.Playing="playing",e.Paused="paused"}(SequencePlaybackState||(SequencePlaybackState={}));export class SequencePlayer{constructor(){this._state=new e(SequencePlaybackState.Stopped),this._time=new e(0),this._duration=0,this._timescale=1,this._loop=!1,this._externalTimeControl=!1,this._inEditor=!1,this.bindings=new Map,this.roleBindings=new Map,this.sequenceData=null,this.onComplete=new t,this.onLoop=new t,this.onTimeUpdate=this._time.asObservable(),this.onStateChange=this._state.asObservable(),this.loopCount=0,this.viewController=null,this._cameraControlEnabled=!1,this._cameraControlTrackId=null,this.sequenceCameras=new Map,this.cameraPlayables=new Map,this.cameraBlendCamera=null,this.cameraBlendSource=null,this.cameraBlendOutSource=null,this.cameraOverrideHandle=null,this.activeCameraClipKey=null,this.cameraBlendOutClipKey=null,this.activeCameraShakeClipKeys=new Set,this.nextCameraShakeClipKeys=new Set,this.activePostProcessClips=new Map,this.nextPostProcessClipKeys=new Set,this.audioListener=null,this.audioBuffers=new Map,this.loadingAudioBuffers=new Map,this.animationClips=new Map,this.loadingAnimationClips=new Map,this.retimedAnimationClips=new Map,this.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.audioFilters=new Map,this.audioPannerNodes=new Map,this.firedEvents=new Set,this.sequenceEventSyncResolvers={actor:e=>this.resolveSequenceEventActorReference(e)},this.sequenceEventAsyncResolvers={actor:e=>this.resolveSequenceEventActorReference(e),texture:e=>this.assetLoader?.getTextureByAssetId(e)??null,sampler2DNode:e=>this.assetLoader?.getTextureByAssetId(e)??null,object3D:async e=>{const t=await(this.assetLoader?.getModelByAssetId(e));return t?.scene??null},material:e=>this.assetLoader?.getMaterialByAssetId(e)??null,audioBuffer:e=>this.assetLoader?.getAudioByAssetId(e)??null,visualEffect:async e=>{if(!this.assetLoader||!this.actorFactory)return null;const t=await this.assetLoader.getAsset(e);return t?new u(this.actorFactory,t):null},prefab:async e=>{const t=await(this.assetLoader?.getPrefabById(e));return t?new f(t.asset):null},prefabActor:async e=>{const t=await(this.assetLoader?.getPrefabById(e));return t?new m(new f(t.asset)):null},sequence:e=>this.resolveSequenceEventSequence(e),animationClip:e=>this.resolveSequenceEventAnimationClip(e)},this.trackRuntimeEvaluators={object:(e,t,a)=>{t&&this.evaluateObjectTrack(e,t,a)},locator:(e,t,a)=>{t&&this.evaluateLocatorTrack(e,t,a)},camera:(e,t,a)=>this.evaluateCameraTrack(e,a),cameraShake:(e,t,a)=>this.evaluateCameraShakeTrack(e,a),postProcess:(e,t,a)=>this.evaluatePostProcessTrack(e,a),audio:(e,t,a)=>this.evaluateAudioTrack(e,a),vfx:(e,t,a)=>this.evaluateVfxTrack(e,a),spawn:(e,t,a)=>this.evaluateSpawnTrack(e,t,a),group:(e,t,a)=>{if("group"===e.type)for(const t of e.childTracks)this.evaluateTrack(t,a)}},this.subTrackRuntimeEvaluators={transform:(e,t,a)=>{const s=this.getPlayableObject(t);s&&this.evaluateTransformSubTrack(e,s,a)},animation:(e,t,a)=>this.evaluateAnimationSubTrack(e,t,a),visibility:(e,t,a)=>{const s=this.getPlayableObject(t);s&&this.evaluateVisibilitySubTrack(e,s,a)},parameter:(e,t,a)=>this.evaluateParameterSubTrack(e,t.target||null,a),event:(e,t,a)=>this.evaluateEventSubTrack(e,t.target||null,a)}}get state(){return this._state.value}get time(){return this._time.value}get duration(){return this._duration}get timescale(){return this._timescale}set timescale(e){this._timescale=Math.max(.01,e)}get loop(){return this._loop}set loop(e){this._loop=e}get externalTimeControl(){return this._externalTimeControl}set externalTimeControl(e){this._externalTimeControl=e}get inEditor(){return this._inEditor}set inEditor(e){this._inEditor=e,this.updateLocatorMarkerVisibility()}get cameraControlEnabled(){return this._cameraControlEnabled}set cameraControlEnabled(e){this._cameraControlEnabled=e,e||this.releaseCameraOverride()}get cameraControlTrackId(){return this._cameraControlTrackId}set cameraControlTrackId(e){this._cameraControlTrackId!==e&&(this._cameraControlTrackId=e,this.releaseCameraOverride())}setViewController(e){this.viewController&&this.viewController!==e&&this.viewController.clearCameraShakeContributionsForOwner(this),this.viewController=e}setWorld(e){this.world!==e&&(this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.clearLocatorBindings(),this.clearSequenceCameras(),this.clearCameraShakeContributions(),this.clearPostProcessEffects(),this.world=e,this.clearCounter++,this.vfxActors.clear(),this.spawnedInstances.clear(),this.bindings.clear(),this.activeClips.clear(),this.activeVfxClips.clear(),this.activeAudioClips.clear(),this.audioStartInFlight.clear(),this.lastAudioStartAttemptTime.clear(),this.loadingAudioBuffers.clear(),this.audioFilters.clear(),this.audioPannerNodes.clear(),this.pendingSpawns.clear(),this.propertyResolutionCache.clear(),this.materialResolutionCache.clear(),this.clearRetimedAnimationClipCache(),this._state.next(SequencePlaybackState.Stopped),this.sequenceData&&this.initializeLocatorBindings())}setAudioListener(e){this.audioListener=e}setAssetLoader(e){if(this.assetLoader=e,this.sequenceData){const e=this.clearCounter;this.preloadSequenceResources(this.sequenceData,e)}}setActorFactory(e){this.actorFactory=e}setVfxService(e){this.vfxService=e}load(e){if(this.stop(),this.clearCounter++,this.clearLocatorBindings(),this.clearSequenceCameras(),this.sequenceData=e,this._duration=e.duration,this._loop=e.loop,this._timescale=e.playbackRate,this.clearRetimedAnimationClipCache(),this.bindings.clear(),this.initializeLocatorBindings(),this.loopCount=0,this.assetLoader){const t=this.clearCounter;this.preloadSequenceResources(e,t)}}preloadSequenceResources(e,t){return Promise.all([this.preloadAudioBuffersForSequence(e,t),this.preloadAnimationClipsForSequence(e,t)]).then(()=>{})}getAudioAssetIdsForSequence(e){const t=new Set;for(const a of e.tracks){if("audio"!==a.type)continue;const e=a;for(const a of e.clips??[])a.audioAssetId&&t.add(a.audioAssetId)}return[...t]}async preloadAudioBuffersForSequence(e,t){if(!this.assetLoader)return;const a=this.getAudioAssetIdsForSequence(e);0!==a.length&&await Promise.all(a.map(async e=>{if(t!==this.clearCounter)return;if(this.audioBuffers.has(e))return;let a=this.loadingAudioBuffers.get(e);a||(a=this.assetLoader.getAudioByAssetId(e),this.loadingAudioBuffers.set(e,a));try{const s=await a;if(t!==this.clearCounter)return;this.audioBuffers.set(e,s)}catch(e){}finally{this.loadingAudioBuffers.get(e)===a&&this.loadingAudioBuffers.delete(e)}}))}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.preloadVisualEffectsForSequence(this.sequenceData,e)])}async preloadVisualEffectsForSequence(e,t){if(!this.world||!this.actorFactory)return;const a=new Set;for(const t of ne(e.tracks))if("vfx"===t.type)for(const e of t.clips??[])null!=e.vfxAssetId&&a.add(e.vfxAssetId);if(0===a.size)return;const s=await Promise.all([...a].map(e=>this.assetLoader.getAsset(e)));if(t!==this.clearCounter)return;const i=s.filter(e=>null!=e&&null!=e.vfx).map(e=>new u(this.actorFactory,e));await this.world.preloadVisualEffects(i)}async prepareAnimationClipsForBindings(e,t){const a=[];for(const s of ne(e.tracks)){if(!("subTracks"in s))continue;const e=this.bindings.get(s.id),i=null==e?null:this.getPlayableObject(e);if(null==i)continue;const r=$(i);for(const e of s.subTracks)if("animation"===e.type)for(const s of e.clips){if(t!==this.clearCounter)return;if(null!=s.animationClipAssetId){const e=this.animationClipCacheKey(s.animationClipAssetId,r);a.push(this.ensureAnimationClip(s.animationClipAssetId,r).then(a=>{null!=a&&t===this.clearCounter&&j(s)&&(this.getPlayableAnimationClip(e,a,s,!1),s.rootMotion&&this.getPlayableAnimationClip(e,a,s,!0))}))}}}await Promise.all(a)}bindRole(e,t){this.roleBindings.set(e,t),this.sequenceData&&this.resolveBindings()}bindObject(e,t){if(this.sequenceData)for(const a of ne(this.sequenceData.tracks))"object"!==a.type||a.targetId!==e||a.role||this.createBinding(a,t)}unbindObject(e){if(this.sequenceData)for(const t of ne(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=oe(e);if(!t||!this.sequenceData)return[];const a=[];for(const e of ne(this.sequenceData.tracks)){if("locator"!==e.type)continue;if(oe(e.bindingId)!==t)continue;const s=this.bindings.get(e.id),i=s?this.getPlayableObject(s):null;i&&(i.updateWorldMatrix(!0,!1),a.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 a}resolveBindings(){if(this.sequenceData)for(const e of this.sequenceData.tracks)this.resolveTrackBinding(e)}initializeLocatorBindings(){if(this.sequenceData)for(const e of ne(this.sequenceData.tracks)){if("locator"!==e.type||this.bindings.has(e.id))continue;const t=new n;t.name=e.name||"Locator",t.userData.sequenceLocatorTrackId=e.id,this.world?.scene&&null==t.parent&&this.world.scene.add(t);const a=le(e.name);a.visible=this._inEditor,t.add(a),this.locatorMarkers.set(e.id,a),this.disableLocatorInteraction(t),this.createBinding(e,t)}}clearLocatorBindings(){for(const e of this.locatorMarkers.values())ce(e);for(const e of this.bindings.values()){if("locator"!==e.track.type)continue;const t=this.getPlayableObject(e);t?.parent&&t.removeFromParent()}this.locatorMarkers.clear()}updateLocatorMarkerVisibility(){for(const e of this.locatorMarkers.values())e.visible=this._inEditor}disableLocatorInteraction(e){e.traverse(e=>{e.raycast=()=>{}})}resolveTrackBinding(e){if("object"===e.type){const t=e;t.role&&this.roleBindings.has(t.role)&&this.createBinding(e,this.roleBindings.get(t.role))}else if("spawn"===e.type){const t=e;t.role&&this.roleBindings.has(t.role)&&this.createBinding(e,this.roleBindings.get(t.role))}else if("group"===e.type)for(const t of e.childTracks)this.resolveTrackBinding(t)}createBinding(e,t){const a=t instanceof p?t.object:t,i=this.bindings.get(e.id),r=null!=i?i.target instanceof p?i.target.object:i.target:null,n=null!=i&&i.target===t&&r===a,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:a.position.clone(),rotation:a.rotation.clone(),scale:a.scale.clone()},l.originalParent=a.parent),o&&null==l.mixer?l.mixer=new s(a):o||(l.mixer=void 0),this.bindings.set(e.id,l)}removeBinding(e){const t=this.bindings.get(e);t&&(this.releaseBinding(t),this.bindings.delete(e))}releaseBinding(e){this.clearExternalRootMotionPreview(e);for(const t of e.activeActions.values())t.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.stopAllAudio(),this.stopAllAnimations(),this.despawnAll(),this.stopAllVfx(),this.firedEvents.clear(),this.clearCameraShakeContributions(),this.clearPostProcessEffects()}stop(){this._state.next(SequencePlaybackState.Stopped),this._time.next(0),this.clearCounter++,this.loopCount=0,this.pauseAudio(),this.releaseCameraOverride(),this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.restoreOriginalTransforms(),this.restoreOriginalParents(),this.stopAllAudio(),this.stopAllAnimations(),this.despawnAll(),this.stopAllVfx(),this.firedEvents.clear(),this.clearCameraShakeContributions(),this.clearPostProcessEffects()}restart(){this.stop(),this.play()}seek(e){const t=Math.max(0,Math.min(e,this._duration));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.mixer&&t.mixer.update(e*this._timescale);for(const t of this.spawnedInstances.values())t.mixer&&t.mixer.update(e*this._timescale);return}const t=this._time.value+e*this._timescale;if(t>=this._duration){if(!this._loop)return this._time.next(this._duration),this.evaluate(this._duration),this.releaseCameraOverride(),this.clearCameraShakeContributions(),this.clearPostProcessEffects(),this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this._state.next(SequencePlaybackState.Stopped),void this.onComplete.next();{this.loopCount++;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 t of this.sequenceData.tracks){if(!t.muted&&("object"===t.type||"locator"===t.type||"camera"===t.type||"spawn"===t.type||"vfx"===t.type)){const e=this.bindings.get(t.id);this.updateTrackParenting(t,e)}this.evaluateTrack(t,e)}this.updateCameraControl(e),this.syncCameraShakeContributions(),this.syncPostProcessEffects()}}evaluateTrack(e,t){if(e.muted)return;const a=this.bindings.get(e.id);(0,this.trackRuntimeEvaluators[x(e.type).runtimeEvaluator])(e,a,t)}evaluateObjectTrack(e,t,a){this.evaluateSubTracks(e.subTracks,t,a)}evaluateLocatorTrack(e,t,a){this.evaluateSubTracks(e.subTracks,t,a)}getActiveTrackObjects(e){if(!this.sequenceData)return[];const t=ne(this.sequenceData.tracks).find(t=>t.id===e);return t?this.getActiveObjectsForTrack(t):[]}evaluateSubTracks(e,t,a){this._externalTimeControl&&this.beginExternalRootMotionPreview(t);for(const s of e){if(s.muted)continue;(0,this.subTrackRuntimeEvaluators[k(s.type).runtimeEvaluator])(s,t,a)}this._externalTimeControl&&this.applyExternalRootMotionPreview(t)}beginExternalRootMotionPreview(e){const t=e.externalRootMotionPreview;if(!t)return;const a=this.getPlayableObject(e);a&&a.position.sub(t.appliedOffset),t.appliedOffset.set(0,0,0),t.sampledOffset.set(0,0,0),t.root=null}sampleExternalRootMotionPreview(e,t,s,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(s,t.duration));de.fromArray(r.evaluate(o)),fe.fromArray(r.evaluate(l)),n.sampledOffset.subVectors(fe,de),n.sampledOffset.y=0;const h=this.getPlayableObject(e),u=a.PropertyBinding.parseTrackName(t.motionTrack.name);n.root=h?.getObjectByName(u.nodeName)??h}applyExternalRootMotionPreview(e){const t=e.externalRootMotionPreview,a=this.getPlayableObject(e);t&&a&&t.root&&(t.root.getWorldScale(me),t.appliedOffset.copy(t.sampledOffset).multiply(me).applyQuaternion(a.quaternion),a.position.add(t.appliedOffset))}clearExternalRootMotionPreview(e){const t=e.externalRootMotionPreview,a=this.getPlayableObject(e);t&&a&&a.position.sub(t.appliedOffset),e.externalRootMotionPreview=void 0}evaluateTransformSubTrack(e,t,a){const s=e.keyframes;if(0===s.length)return;const{prev:i,next:r,prevIndex:n,nextIndex:o,t:l}=B(s,a);if(i)if(e.components.position&&q(s,n,o,l,t.position),r&&i!==r){const a=T(l,i.interpolation);e.components.rotation&&i.rotation&&r.rotation&&(ye.setFromEuler(Ce.fromArray([...i.rotation,"XYZ"])),ve.setFromEuler(ge.fromArray([...r.rotation,"XYZ"])),t.quaternion.slerpQuaternions(ye,ve,a)),e.components.scale&&i.scale&&r.scale&&t.scale.lerpVectors(he.fromArray(i.scale),ue.fromArray(r.scale),a)}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,s){if(!t.mixer||!t.activeActions)return;const i=t.target instanceof p?t.target.object:t.target;if(i)for(const r of e.clips){const n=r.startTime+r.duration,o=s>=r.startTime&&s<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 s=$(i),n=this.animationClipCacheKey(e,s),o=this.animationClips.get(n);if(null==o){this.ensureAnimationClip(e,s);continue}const u=this.prepareAnimationPlayback(n,o,r),d=t;let f=!1;if(t.target instanceof p){d.charAnimComponent||(d.charAnimComponent=t.target.getComponent(R)??void 0);const e=d.charAnimComponent;if(null!=e){const a=r.rootMotion?j(r)?this.getPlayableAnimationClip(n,o,r,!0):L.fromClip(u.clip,!1):u.clip;if(this._externalTimeControl)c=e.beginExternalAnimationControl(a,{timeScale:u.timeScale});else if(e.play(a,{inPlace:!r.rootMotion,loop:!1,priority:20,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),d.charAnimActionKeys||(d.charAnimActionKeys=new Set),d.charAnimActionKeys.add(l),f=!0}}f||(c=t.mixer.clipAction(u.clip),c.setLoop(a.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 a=this.getAnimationPlaybackLocalTime(r,s),i=Math.min(a,c.getClip().duration);(h||Math.abs(c.time-i)>.001)&&(c.time=i,c.paused=!1,c.play(),e.charAnimComponent?e.charAnimComponent.getMixer()?.update(0):t.mixer&&t.mixer.update(0)),r.rootMotion&&c.getClip()instanceof L&&this.sampleExternalRootMotionPreview(t,c.getClip(),i,j(r)?0:r.clipStartOffset)}else e.charAnimComponent?.endExternalControl()}}else if(c){t.activeActions.delete(l);const e=t;e.charAnimActionKeys?.has(l)?(e.charAnimActionKeys.delete(l),c.stop(),0===e.charAnimActionKeys.size&&e.charAnimComponent&&(e.charAnimComponent.stopSequenceAnimation(),e.charAnimComponent=void 0)):(c.stop(),this._externalTimeControl&&t.mixer&&t.mixer.update(0))}}}evaluateVisibilitySubTrack(e,t,a){const s=e.keyframes;if(0===s.length)return;let i=s[0];for(const e of s){if(!(e.time<=a))break;i=e}t.visible=i.visible}evaluatePropertySubTrack(e,t,a){const s=I(e.keyframes,a,{min:e.range?.[0],max:e.range?.[1],stepOnly:Q(e)});s&&this.applyResolvedPropertyValue(e,t,s)}evaluateParameterSubTrack(e,t,a){if("audioParameter"===e.type)return;const s=I(e.keyframes,a,"property"===e.type?{min:e.range?.[0],max:e.range?.[1],stepOnly:Q(e)}:"material"===e.type?{min:e.range?.[0],max:e.range?.[1],stepOnly:X(e)}:{});s&&("property"!==e.type?this.applyResolvedMaterialValue(e,t,s):this.applyResolvedPropertyValue(e,t,s))}evaluateEventSubTrack(e,t,a){if(t instanceof p&&this._state.value===SequencePlaybackState.Playing)for(const s of e.events){const i=`${e.id}-${s.id}`;if(a>=s.time&&!this.firedEvents.has(i)){if(this.firedEvents.add(i),s.editorOnly&&!this._inEditor)continue;if(!s.functionName)continue;const e=t[s.functionName];"function"==typeof e?this.invokeSequenceEvent(t,s.functionName,e,s.arguments??[]):console.warn(`Sequence event method '${s.functionName}' not found on actor`)}else s.time>a&&this.firedEvents.delete(i)}}evaluateCameraTrack(e,t){const a=this.ensureSequenceCamera(e);this.applyCameraTrackSettings(e,a),this.evaluateSubTracks(e.subTracks,this.getCameraPlayable(e,a),t),a.updateProjectionMatrix()}evaluateCameraShakeTrack(e,t){if(this.viewController)for(const a of e.clips??[]){if(!this.isCameraShakeClipActive(a,t))continue;const e=t-a.startTime,s=a.id;this.nextCameraShakeClipKeys.add(s),this.viewController.setCameraShakeContribution(this,s,a,e,a.seed??N(a.id))}}evaluatePostProcessTrack(e,t){if(this.viewController&&this.assetLoader){for(const a of e.clips??[]){if(!this.isPostProcessClipActive(a,t))continue;const s=this.getPostProcessClipKey(e,a);this.nextPostProcessClipKeys.add(s),this.ensurePostProcessClipEffect(e,a,s);const i=this.activePostProcessClips.get(s);i?.handle&&(i.handle.stage=e.stage,i.handle.priority=e.priority,i.handle.enabled=!0,this.applyPostProcessClipWeight(i.handle,a,t))}this.evaluatePostProcessMaterialSubTracks(e,t)}}evaluatePostProcessMaterialSubTracks(e,t){for(const a of e.subTracks){if(a.muted||"material"!==a.type)continue;const s=I(a.keyframes,t,{min:a.range?.[0],max:a.range?.[1],stepOnly:X(a)});s&&this.applyPostProcessMaterialValue(e.id,a,s)}}applyPostProcessMaterialValue(e,t,a){if("shaderUniform"===w(t)&&t.uniformName)for(const s of this.activePostProcessClips.values()){if(s.trackId!==e||!s.handle)continue;const i=s.handle.material,r=i.uniforms?.[t.uniformName];if(!r)continue;const n=Y(r.value,a);n.applied&&(r.value=n.value,i.uniformsNeedUpdate=!0,D(i))}}isPostProcessClipActive(e,t){return t>=e.startTime&&t<e.startTime+e.duration}getPostProcessClipKey(e,t){return`${e.id}-${t.id}`}ensurePostProcessClipEffect(e,t,a){const s=t.shaderGraphAssetId;if(!s)return void this.releasePostProcessClipEffect(a);const i=JSON.stringify(t.shaderGraphParams??{}),r=this.activePostProcessClips.get(a);if(r?.assetId===s&&r.paramsSignature===i)return;this.releasePostProcessClipEffect(a);const n={key:a,trackId:e.id,clipId:t.id,assetId:s,paramsSignature:i,version:this.clearCounter};this.activePostProcessClips.set(a,n),this.loadPostProcessClipEffect(e,t,n)}async loadPostProcessClipEffect(e,t,a){if(this.assetLoader&&this.viewController)try{const s=await this.assetLoader.getShaderGraphByAssetId(a.assetId);if(!this.isPostProcessClipEntryCurrent(a))return;if("postProcess"!==s.target)return console.warn(`Sequence post-process clip references shader graph "${a.assetId}" with target "${s.target}"`),void this.releasePostProcessClipEffect(a.key);const i=await this.assetLoader.prepareShaderGraphParameters(s,t.shaderGraphParams??{});if(!this.isPostProcessClipEntryCurrent(a))return;const r=U(s,{parameters:i});if(!this.isPostProcessClipEntryCurrent(a))return void r.dispose();a.handle=this.viewController.addPostProcessEffect(r,{stage:e.stage,priority:e.priority,enabled:!0}),this.applyPostProcessClipWeight(a.handle,t,this._time.value)}catch(e){this.isPostProcessClipEntryCurrent(a)&&this.releasePostProcessClipEffect(a.key),console.error(`Failed to create post-process effect for clip ${t.id}:`,e)}}isPostProcessClipEntryCurrent(e){return this.clearCounter===e.version&&this.activePostProcessClips.get(e.key)===e}applyPostProcessClipWeight(e,t,a){const s=e.material.uniforms?.[W];null!=s&&(s.value=this.getPostProcessClipWeight(t,a),e.material.uniformsNeedUpdate=!0)}getPostProcessClipWeight(e,t){const a=Math.max(0,t-e.startTime),s=Math.max(0,e.startTime+e.duration-t);let i=1;const r=Math.max(0,e.fadeInDuration??0);r>0&&(i=Math.min(i,a/r));const n=Math.max(0,e.fadeOutDuration??0);return n>0&&(i=Math.min(i,s/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 a=this.cameraPlayables.get(e.id);return a?a.target=t:(a={target:t},this.cameraPlayables.set(e.id,a)),a}ensureSequenceCamera(e){let t=this.sequenceCameras.get(e.id);if(t)null==t.parent&&this.world?.scene.add(t);else{const s=e.cameraSettings??{fov:60,near:.1,far:1e3};t=new a.PerspectiveCamera(s.fov??60,this.getCurrentCameraAspect(),s.near??.1,s.far??1e3),t.name=e.name||"Sequence Camera",t.userData.sequenceCameraTrackId=e.id,t.layers.mask=this.viewController?.getBaseCamera().layers.mask??t.layers.mask,this.sequenceCameras.set(e.id,t),this.world?.scene.add(t)}return t}clearSequenceCameras(){this.releaseCameraOverride();for(const e of this.sequenceCameras.values())e.removeFromParent();this.sequenceCameras.clear(),this.cameraPlayables.clear()}applyCameraTrackSettings(e,t){const a=e.cameraSettings??{fov:60,near:.1,far:1e3};t.fov=a.fov??60,t.near=a.near??.1,t.far=a.far??1e3,t.aspect=this.getCurrentCameraAspect()}getCurrentCameraAspect(){const e=this.viewController?.getBaseCamera();if(e instanceof a.PerspectiveCamera&&Number.isFinite(e.aspect)&&e.aspect>0)return e.aspect;const t=this.viewController?.getSourceCamera();return t instanceof a.PerspectiveCamera&&Number.isFinite(t.aspect)&&t.aspect>0?t.aspect:1}updateCameraControl(e){if(!this._cameraControlEnabled||!this.viewController||!this.sequenceData)return void this.releaseCameraOverride();const t=this.findActiveCameraShot(e);if(t)return void this.updateActiveCameraShot(t,e);const a=this.findBlendOutCameraShot(e);a?this.updateCameraBlendOut(a,e):this.releaseCameraOverride()}findActiveCameraShot(e){if(!this.sequenceData)return null;let t=null;for(const a of ne(this.sequenceData.tracks)){if("camera"!==a.type||a.muted||!this.isCameraControlTrackEligible(a))continue;const s=a.clips??[];for(const i of s)this.isCameraClipActive(i,e)&&(t={track:a,clip:i,camera:this.ensureSequenceCamera(a),key:this.getCameraClipKey(a,i)})}return t}findBlendOutCameraShot(e){if(!this.sequenceData)return null;let t=null;for(const a of ne(this.sequenceData.tracks)){if("camera"!==a.type||a.muted||!this.isCameraControlTrackEligible(a))continue;const s=a.clips??[];for(const i of s){const s=Math.max(0,i.blendOutDuration??0);if(s<=0)continue;const r=this.getCameraClipEnd(i);e>=r&&e<r+s&&(t={track:a,clip:i,camera:this.ensureSequenceCamera(a),key:this.getCameraClipKey(a,i)})}}return t}isCameraControlTrackEligible(e){return null==this._cameraControlTrackId||e.id===this._cameraControlTrackId}updateActiveCameraShot(e,t){if(!this.viewController)return;const a=this.ensureCameraBlendCamera();this.activeCameraClipKey!==e.key&&(this.copyCameraState(this.viewController.getSourceCamera(),this.ensureCameraBlendSource()),this.activeCameraClipKey=e.key,this.cameraBlendOutClipKey=null);const s=Math.max(0,e.clip.blendInDuration??0),i=s<=0?1:this.evaluateCameraBlendAlpha((t-e.clip.startTime)/s,e.clip);i>=1?this.copyCameraState(e.camera,a):this.blendCameraState(this.ensureCameraBlendSource(),e.camera,a,i),a.updateProjectionMatrix(),this.ensureCameraOverride()}updateCameraBlendOut(e,t){if(!this.viewController)return;const a=this.ensureCameraBlendCamera();if(this.cameraBlendOutClipKey!==e.key){const t=this.activeCameraClipKey===e.key?this.viewController.getSourceCamera():e.camera;this.copyCameraState(t,this.ensureCameraBlendOutSource()),this.activeCameraClipKey=null,this.cameraBlendOutClipKey=e.key}const s=this.getCameraClipEnd(e.clip),i=Math.max(0,e.clip.blendOutDuration??0),r=i<=0?1:this.evaluateCameraBlendAlpha((t-s)/i,e.clip);this.blendCameraState(this.ensureCameraBlendOutSource(),this.viewController.getBaseCamera(),a,r),a.updateProjectionMatrix(),this.ensureCameraOverride()}ensureCameraBlendCamera(){return this.cameraBlendCamera||(this.cameraBlendCamera=new a.PerspectiveCamera(60,this.getCurrentCameraAspect(),.1,1e3),this.cameraBlendCamera.name="Sequence Camera Blend"),this.cameraBlendCamera}ensureCameraBlendSource(){return this.cameraBlendSource||(this.cameraBlendSource=new a.PerspectiveCamera),this.cameraBlendSource}ensureCameraBlendOutSource(){return this.cameraBlendOutSource||(this.cameraBlendOutSource=new a.PerspectiveCamera),this.cameraBlendOutSource}ensureCameraOverride(){this.viewController&&!this.cameraOverrideHandle&&(this.cameraOverrideHandle=this.viewController.pushCameraOverride(this.ensureCameraBlendCamera(),this))}releaseCameraOverride(){this.cameraOverrideHandle?.release(),this.cameraOverrideHandle=null,this.viewController?.releaseCameraOverridesForOwner(this),this.activeCameraClipKey=null,this.cameraBlendOutClipKey=null}isCameraClipActive(e,t){return t>=e.startTime&&t<this.getCameraClipEnd(e)}getCameraClipEnd(e){return e.startTime+Math.max(0,e.duration)}isCameraShakeClipActive(e,t){return t>=e.startTime&&t<this.getCameraShakeClipEnd(e)}getCameraShakeClipEnd(e){return e.startTime+Math.max(0,e.duration)}getCameraClipKey(e,t){return`${e.id}-${t.id}`}evaluateCameraBlendAlpha(e,t){return T(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(he)),t.quaternion.copy(e.getWorldQuaternion(ye)),t.scale.copy(e.getWorldScale(ue)),e instanceof a.PerspectiveCamera?(t.fov=e.fov,t.near=e.near,t.far=e.far,t.aspect=e.aspect):t.aspect=this.getCurrentCameraAspect(),t.layers.mask=e.layers.mask}blendCameraState(e,t,s,i){e.updateWorldMatrix(!0,!1),t.updateWorldMatrix(!0,!1),s.position.lerpVectors(e.getWorldPosition(he),t.getWorldPosition(ue),i),s.quaternion.slerpQuaternions(e.getWorldQuaternion(ye),t.getWorldQuaternion(ve),i),s.scale.lerpVectors(e.getWorldScale(he),t.getWorldScale(ue),i),e instanceof a.PerspectiveCamera&&t instanceof a.PerspectiveCamera?(s.fov=e.fov+(t.fov-e.fov)*i,s.near=e.near+(t.near-e.near)*i,s.far=e.far+(t.far-e.far)*i,s.aspect=t.aspect):t instanceof a.PerspectiveCamera?(s.fov=t.fov,s.near=t.near,s.far=t.far,s.aspect=t.aspect):s.aspect=this.getCurrentCameraAspect(),s.layers.mask=t.layers.mask}evaluateAudioTrack(e,t){if(!this.assetLoader||!e.clips||0===e.clips.length)return;const a=this._state.value===SequencePlaybackState.Playing,s=this.evaluateAudioSubTracks(e,t);e.volume;for(const 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),a){const a=this.audioByClip.get(o);a&&a.isPlaying||this.tryStartAudioClip(e,i,o,t,s)}const r=this.audioByClip.get(o);r&&this.applyAudioParameters(r,e,i,o,t,s)}else this.activeAudioClips.has(o)&&(this.activeAudioClips.delete(o),this.lastAudioStartAttemptTime.delete(o),this.audioStartInFlight.delete(o),this.stopAudioClip(o))}}tryStartAudioClip(e,t,a,s,i){if(this.audioStartInFlight.has(a))return;const r=this.lastAudioStartAttemptTime.get(a);if(void 0!==r&&s-r<this.audioStartRetryIntervalSeconds)return;this.lastAudioStartAttemptTime.set(a,s);const n=this.playAudioClip(e,t,a,s,i).catch(()=>{}).finally(()=>{this.audioStartInFlight.get(a)===n&&this.audioStartInFlight.delete(a)});this.audioStartInFlight.set(a,n)}applyAudioParameters(e,t,s,i,r,n){const o=n.volume??1,l=Math.random(),c=s.volumeRandomization?(2*l-1)*s.volumeRandomization:0;let h=1;const u=r-s.startTime;u<s.fadeInDuration&&s.fadeInDuration>0?h=u/s.fadeInDuration:u>s.duration-s.fadeOutDuration&&s.fadeOutDuration>0&&(h=(s.duration-u)/s.fadeOutDuration);const p=Math.max(0,(t.volume??1)*o*(s.volume+c)*h);e.setVolume(p);let d=n.detune??0;if(s.pitchRandomization){d+=(2*Math.random()-1)*s.pitchRandomization}if(e.setDetune(d),e.hasPlaybackControl&&e.setPlaybackRate(s.playbackRate*this.timescale),this.audioListener&&this.audioListener.context){const s=this.audioListener.context,r=[],o=n.lowpass,l=n.highpass;let c=this.audioFilters.get(i);if(void 0!==o||void 0!==l)c||(c=s.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 a.Audio&&void 0!==h&&"function"==typeof s.createStereoPanner){let e=this.audioPannerNodes.get(i);e||(e=s.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 a.PositionalAudio?this.updatePositionalAudioTransform(e,t,s,n.spatialBlend):void 0!==n.pan&&this.audioListener}updatePositionalAudioTransform(e,t,s,i){let r=null,n=null;const o=s.attachedToTrackId||t.parent?.trackId,l=s.attachmentSocketName||t.parent?.socketName;if(o){const e=this.sequenceData?.tracks.find(e=>e.id===o);if(e){const t=this.getActiveObjectsForTrack(e);if(t.length>0){const e=t[0];if(r=he,n=ye,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?a.MathUtils.clamp(i,0,1):1;if(t<1&&this.audioListener){const e=pe;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,s,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(s);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(s);const p=!0===e.spatial,d=u&&!0===u.isPositionalAudio;if(u&&p!==d&&(u.isPlaying&&u.stop(),u.disconnect(),this.audioByClip.delete(s),u=void 0),!u){if(p){const e=new a.PositionalAudio(this.audioListener);e.setRefDistance(10),e.setRolloffFactor(1),u=e}else u=new a.Audio(this.audioListener);this.world&&this.world.scene.add(u),this.audioByClip.set(s,u)}Math.min((t.duration-c)/t.playbackRate,(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,s,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 a=this.audioGainNodes.get(e);a&&(a.disconnect(),this.audioGainNodes.delete(e));const s=this.audioFilters.get(e);if(s){try{s.disconnect()}catch{}this.audioFilters.delete(e)}const 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 a=new Set,s=new Map;for(const i of e.clips){const r=this.getVfxClipKey(e,i);s.set(r,i),this.isVfxClipActiveAtTime(i,t)&&a.add(r)}const i=[];for(const t of this.activeVfxClips)t.startsWith(`${e.id}-`)&&(a.has(t)||i.push(t));for(const e of i)this.activeVfxClips.delete(e);for(const[i,r]of s.entries()){const s=this.vfxActors.get(i);a.has(i)&&!this.activeVfxClips.has(i)?(this.activeVfxClips.add(i),this.ensureVfxActor(e,r,i)):a.has(i)&&s?(this.updateVfxTransform(e,s,t),this._state.value===SequencePlaybackState.Playing&&s.play()):s&&this.applyInactiveVfxClipBehavior(r,s,t)}}getVfxClipKey(e,t){return`${e.id}-${t.id}-${t.vfxAssetId}`}isVfxClipActiveAtTime(e,t){const a=e.startTime+e.duration;return t>=e.startTime&&t<a}shouldPreviewVfxAtSeekTime(){return this._externalTimeControl&&this._inEditor&&this._state.value!==SequencePlaybackState.Playing}previewVfxTrackAtSeekTime(e,t){const a=new Set;for(const s of e.clips){const i=this.getVfxClipKey(e,s),r=this.vfxActors.get(i);this.isVfxClipActiveAtTime(s,t)&&a.add(i),t<s.startTime?r?.clearPreview():r?this.previewVfxActorAtSeekTime(e,s,r,t):this.ensureVfxActor(e,s,i)}for(const t of[...this.activeVfxClips])t.startsWith(`${e.id}-`)&&!a.has(t)&&this.activeVfxClips.delete(t);for(const e of a)this.activeVfxClips.add(e)}previewVfxActorAtSeekTime(e,t,a,s){const i=t.startTime+t.duration;this.updateVfxTransform(e,a,Math.min(s,i)),a.previewAt(s-t.startTime,t.duration,t.endBehavior,t.expireWithinSeconds)}resetVfxForTimeReset(e){const t=new Set;if(this.sequenceData)for(const a of ne(this.sequenceData.tracks))if("vfx"===a.type)for(const s of a.clips??[])this.isVfxClipActiveAtTime(s,e)&&t.add(this.getVfxClipKey(a,s));this.activeVfxClips.clear();for(const[e,a]of this.vfxActors.entries())t.has(e)||(a.restart(),a.stop(),a.pause())}applyInactiveVfxClipBehavior(e,t,a){const s=e.endBehavior??"finish";if("finish"===s)return void t.stop();if("kill"===s)return void t.applyClipEndBehavior(s);const i=e.startTime+e.duration,r=Math.max(a-i,0),n=Math.max(0,e.expireWithinSeconds??.25),o=Math.max(0,n-r);t.applyClipEndBehavior(s,o)}async ensureVfxActor(e,t,a){if(!this.vfxService||!t.vfxAssetId)return;if(this.vfxActors.has(a)){const e=this.vfxActors.get(a);return e.restart(),void e.play()}const s=this.clearCounter;try{const i=await this.vfxService.createFromAssetId(t.vfxAssetId,this.world.scene);if(s!==this.clearCounter)return void(this.world&&this.world.removeActor(i));const{position:r,rotation:n,scale:o}=this.getVfxTransform(e,t.startTime);i.object.position.copy(r),i.object.rotation.copy(n),i.object.scale.copy(o),this.vfxActors.set(a,i),this.shouldPreviewVfxAtSeekTime()?this.previewVfxActorAtSeekTime(e,t,i,this._time.value):this._state.value===SequencePlaybackState.Playing&&i.play()}catch(e){console.error(`Failed to create VFX actor for clip ${t.id}:`,e)}}getVfxTransform(e,t){const a=new c,s=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&&q(n.keyframes,l,c,h,a),e&&(e.rotation&&s.fromArray([...e.rotation,"XYZ"]),e.scale&&i.fromArray(e.scale)),r&&e!==r&&e.time!==r.time){const t=T(h,e.interpolation);if(e.rotation&&r.rotation){ye.setFromEuler(Ce.fromArray([...e.rotation,"XYZ"])),ve.setFromEuler(ge.fromArray([...r.rotation,"XYZ"]));const a=new o;a.slerpQuaternions(ye,ve,t),s.setFromQuaternion(a)}e.scale&&r.scale&&i.lerpVectors(he.fromArray(e.scale),ue.fromArray(r.scale),t)}}else a.fromArray(e.position),s.fromArray([...e.rotation,"XYZ"]),i.fromArray(e.scale);return{position:a,rotation:s,scale:i}}updateVfxTransform(e,t,a){const{position:s,rotation:i,scale:r}=this.getVfxTransform(e,a);t.object.position.copy(s),t.object.rotation.copy(i),t.object.scale.copy(r)}resolveActorType(e){const t=this.actorFactory.classes[e];if(null!=t)return t;const a=d[e];return a||(console.warn(`Could not resolve actor type: ${e}`),null)}async spawnActorForClip(e,t,a,s){if(!this.world||!e.actorType)return null;const i=this.resolveActorType(e.actorType);if(!i)return null;try{return await this.world.spawnActor(i,a,s)}catch(t){return console.error(`Failed to spawn actor ${e.actorType}:`,t),null}}async spawnPrefabForClip(e,t,a,s){if(!this.world||!this.assetLoader||!e.prefabId)return null;try{const t=await this.assetLoader.getPrefabById(e.prefabId);if(!t)return null;return await this.world.spawnPrefab(t,a,s)}catch(t){return console.error(`Failed to spawn prefab ${e.prefabId}:`,t),null}}async spawnMeshForClip(e,t,a,s){if(!this.world||!this.assetLoader||!e.meshId)return null;try{const t=await this.assetLoader.getAsset(e.meshId),i=await this.assetLoader.getModelByAssetId(e.meshId),r=V.clone(i.scene);if(r.position.copy(a),r.rotation.copy(s),t){await this.assetLoader.applyMaterials(t,r);const e=t.mesh?.rescale;null!=e&&1!==e&&r.scale.multiplyScalar(e)}return this.world.scene.add(r),r}catch(t){return console.error(`Failed to spawn mesh ${e.meshId}:`,t),null}}despawnInstance(e){if(this.restorePropertySnapshotsForInstance(e),this.restoreMaterialSnapshotsForInstance(e),this.world)switch(e?.type){case"actor":this.world.removeActor(e.instance);break;case"prefab":this.world.removePrefab(e.instance);break;case"mesh":this.world.scene.remove(e.instance)}}despawnAll(){for(const e of this.spawnedInstances.values())this.despawnInstance(e);this.spawnedInstances.clear(),this.activeClips.clear(),this.pendingSpawns.clear()}getInitialTransform(e,t,a){const s=new c,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,a);n.components.position&&q(n.keyframes,t,r,o,s),e&&e.rotation&&i.fromArray([...e.rotation,"XYZ"])}else t.initialPosition&&s.fromArray(t.initialPosition),t.initialRotation&&i.fromArray([...t.initialRotation,"XYZ"]);return{position:s,rotation:i}}evaluateSpawnTrack(e,t,a){if(!e.clips||0===e.clips.length)return;const s=t||this.bindings.get(e.id);if(s&&s.target)for(const t of e.clips){const i=t.startTime+t.duration,r=a>=t.startTime&&a<i,n=`${e.id}-${t.id}`;if(r){this.activeClips.has(n)||(this.activeClips.add(n),this.spawnedInstances.set(n,{type:"proxy",target:s.target}));(s.target instanceof p?s.target.object:s.target)&&this.evaluateSubTracks(e.subTracks,s,a)}else this.activeClips.has(n)&&(this.clearExternalRootMotionPreview(s),this.restorePropertySnapshotsForTarget(s.target),this.restoreMaterialSnapshotsForTarget(s.target),this.activeClips.delete(n),this.spawnedInstances.delete(n))}else for(const t of e.clips){const s=t.startTime+t.duration,i=a>=t.startTime&&a<s,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,a)}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:a,rotation:s}=this.getInitialTransform(e,t,t.startTime);this.pendingSpawns.add(r),this.spawnForClip(e,t,a,s,r)}}}getInstanceObject(e){switch(e.type){case"actor":return e.instance.object;case"prefab":return e.instance.mainActor?.object||e.instance.object;case"mesh":return e.instance;case"proxy":return e.target instanceof p?e.target.object:e.target;default:return null}}async spawnForClip(e,t,a,i,r){const n=this.clearCounter;let o=null;try{switch(e.spawnType){case"actor":const s=await this.spawnActorForClip(e,t,a,i);s&&(o={type:"actor",instance:s});break;case"prefab":const r=await this.spawnPrefabForClip(e,t,a,i);r&&(o={type:"prefab",instance:r});break;case"mesh":const n=await this.spawnMeshForClip(e,t,a,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 s(t),o.activeActions=new Map),this.spawnedInstances.set(r,o),this.activeClips.add(r)}else o&&this.despawnInstance(o)}finally{this.pendingSpawns.delete(r)}}getPlayableObject(e){return e.target instanceof p?e.target.object:e.target??null}applyResolvedPropertyValue(e,t,a){if(!t||!e.propertyPath)return;const s=this.getPropertyResolution(t,e);if(!s)return;const i=this.getPropertySnapshotKey(e);this.capturePropertySnapshot(t,i,s);const n=function(e,t){switch(t.type){case y.Number:return"number"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.Boolean:return"boolean"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.String:return"string"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.Vector2:return H(e,t.value);case y.Vector3:return J(e,t.value);case y.Vector4:return ee(e,t.value);case y.Euler:return function(e,t){const a=ae(t,3);if(!a)return{applied:!1};const s=Array.isArray(t)&&"string"==typeof t[3]?t[3]:"XYZ";if(e instanceof r)return e.set(a[0],a[1],a[2],s),{applied:!0,value:e};return{applied:!0,value:new r(a[0],a[1],a[2],s)}}(e,t.value);case y.Color:return te(e,t.value);default:return{applied:!1}}}(s.owner[s.key],a);n.applied&&(s.owner[s.key]=n.value)}getPropertyResolution(e,t){const a=e,s=this.getPropertySnapshotKey(t);let i=this.propertyResolutionCache.get(a);if(i||(i=new Map,this.propertyResolutionCache.set(a,i)),i.has(s))return i.get(s)??null;const r=this.getPropertyPathSegments(t.propertyPath);if(0===r.length)return i.set(s,null),null;let n=e;for(let e=0;e<r.length-1;e++){if(!z(n))return i.set(s,null),null;n=n[r[e]]}if(!z(n))return i.set(s,null),null;const o={owner:n,key:r[r.length-1]};return i.set(s,o),o}getPropertyPathSegments(e){const t=this.propertyPathSegments.get(e);if(t)return t;const a=e.split(".").map(e=>e.trim()).filter(Boolean);return this.propertyPathSegments.set(e,a),a}getPropertySnapshotKey(e){return`${e.id}:${e.propertyPath}`}capturePropertySnapshot(e,t,a){const s=e;let i=this.propertySnapshots.get(s);if(i||(i=new Map,this.propertySnapshots.set(s,i)),i.has(t))return;const r=a.owner[a.key];i.set(t,{resolution:a,hadOwnProperty:Object.prototype.hasOwnProperty.call(a.owner,a.key),value:r,valueSnapshot:ie(r)})}restorePropertySnapshotsForInstance(e){switch(e.type){case"actor":case"mesh":this.restorePropertySnapshotsForTarget(e.instance);break;case"prefab":this.restorePropertySnapshotsForTarget(e.target??null),this.restorePropertySnapshotsForTarget(e.instance.mainActor??null),this.restorePropertySnapshotsForTarget(e.instance.object);break;case"proxy":this.restorePropertySnapshotsForTarget(e.target)}}restorePropertySnapshotsForTarget(e){if(!e)return;const t=e,a=this.propertySnapshots.get(t);if(a){for(const e of a.values())re(e);this.propertySnapshots.delete(t),this.propertyResolutionCache.delete(t)}}restoreAllPropertySnapshots(){for(const e of Array.from(this.propertySnapshots.keys()))this.restorePropertySnapshotsForTarget(e)}restoreMaterialSnapshotsForInstance(e){switch(e.type){case"actor":case"mesh":this.restoreMaterialSnapshotsForTarget(e.instance);break;case"prefab":this.restoreMaterialSnapshotsForTarget(e.target??null),this.restoreMaterialSnapshotsForTarget(e.instance.mainActor??null),this.restoreMaterialSnapshotsForTarget(e.instance.object);break;case"proxy":this.restoreMaterialSnapshotsForTarget(e.target)}}restoreMaterialSnapshotsForTarget(e){if(!e)return;const t=e;this.materialResolutionCache.delete(t);const a=this.materialSnapshots.get(t);if(a){for(const e of a.values())null==e.materialIndex?e.owner.material=e.originalMaterial:Array.isArray(e.owner.material)&&(e.owner.material[e.materialIndex]=e.originalMaterial),e.controlledMaterial!==e.originalMaterial&&e.controlledMaterial.dispose();this.materialSnapshots.delete(t)}}restoreAllMaterialSnapshots(){for(const e of Array.from(this.materialSnapshots.keys()))this.restoreMaterialSnapshotsForTarget(e)}applyResolvedMaterialValue(e,t,a){if(!t)return;if("asset"===S(e)&&!e.materialAssetId)return;if("outlineVisibility"===w(e))return void this.applyResolvedMaterialOutlineVisibility(e,t,a);if(!e.uniformName)return;const s=this.getMaterialSlotResolutions(t,e);for(const i of s){const s=this.ensureSequenceControlledMaterial(t,i),r=s.uniforms?.[e.uniformName];if(!r)continue;const n=Y(r.value,a);n.applied&&(r.value=n.value,s.uniformsNeedUpdate=!0,D(s))}}applyResolvedMaterialOutlineVisibility(e,t,a){if(a.type!==y.Boolean||"boolean"!=typeof a.value)return;const s=this.getMaterialSlotResolutions(t,e);for(const e of s){const s=this.ensureSequenceControlledMaterial(t,e),i=s.userData?.outlineParameters;null!=i&&(i.visible=a.value)}}getMaterialSlotResolutions(e,t){const a=e,s=S(t),i=w(t),r=`${t.id}:${i}:${s}:${t.materialAssetId??""}:${t.uniformName}`;let n=this.materialResolutionCache.get(a);n||(n=new Map,this.materialResolutionCache.set(a,n));const o=n.get(r);if(o)return o;const l=e instanceof p?e.object:e,c=[];return l.traverse(e=>{const a=e.material;if(Array.isArray(a))for(let s=0;s<a.length;s++){const i=a[s];Z(i,t)&&c.push({owner:e,materialIndex:s,material:i,key:`${e.uuid}:${s}`})}else Z(a,t)&&c.push({owner:e,materialIndex:null,material:a,key:`${e.uuid}:material`})}),n.set(r,c),c}ensureSequenceControlledMaterial(e,t){const a=e;let s=this.materialSnapshots.get(a);s||(s=new Map,this.materialSnapshots.set(a,s));const i=s.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),s.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 a=this.animationClipCacheKey(e,t),s=this.animationClips.get(a);if(s)return s;const i=this.loadingAnimationClips.get(a);if(i)return i;const r=(async()=>{try{const s=await this.assetLoader.getAnimationClipForTargetByAssetId(e,t);return s&&this.animationClips.set(a,s),s}catch(a){return console.error(`Failed to load animation clip for asset ${e}`+(null==t?"":` and target rig ${t}`)+":",a),null}finally{this.loadingAnimationClips.get(a)===r&&this.loadingAnimationClips.delete(a)}})();return this.loadingAnimationClips.set(a,r),r}prepareAnimationPlayback(e,t,a){if(!j(a)){let e=t;return a.clipEndOffset>0&&(e=e.clone(),G(e,K(t)),e.duration=Math.max(0,e.duration-a.clipEndOffset)),a.rootMotion&&(e=O(e,a)),{clip:e,timeScale:a.playbackRate*this._timescale,startOffset:a.clipStartOffset}}return{clip:this.getPlayableAnimationClip(e,t,a,!1),timeScale:1*this._timescale,startOffset:0}}getPlayableAnimationClip(e,t,a,s){if(!j(a)){const e=a.rootMotion?O(t,a):t;return s?L.fromClip(e,!1):e}const i=`${a.id}:${s?"root":"base"}`,r=`${E(a)}|${s?"root":"base"}`,n=this.retimedAnimationClips.get(i);if(n&&n.assetId===e&&n.signature===r)return n.clip;const o=F(t,a),l=a.rootMotion?O(o,a):o,c=s?L.fromClip(l,!1):l;return this.retimedAnimationClips.set(i,{assetId:e,signature:r,clip:c}),c}getAnimationPlaybackLocalTime(e,t){const a=Math.max(0,t-e.startTime);return j(e)?a:a*e.playbackRate+e.clipStartOffset}clearRetimedAnimationClipCache(e){if(null!=e)for(const[t,a]of this.retimedAnimationClips.entries())a.assetId===e&&this.retimedAnimationClips.delete(t);else this.retimedAnimationClips.clear()}captureOriginalTransforms(){for(const e of this.bindings.values()){const t=e.target instanceof p?e.target.object:e.target;t&&(e.originalTransform={position:t.position.clone(),rotation:t.rotation.clone(),scale:t.scale.clone()})}}restoreOriginalTransforms(){for(const e of this.bindings.values())if(e.originalTransform){const t=e.target instanceof p?e.target.object:e.target;t&&(t.position.copy(e.originalTransform.position),t.rotation.copy(e.originalTransform.rotation),t.scale.copy(e.originalTransform.scale))}}stopAllAnimations(){for(const e of this.bindings.values()){for(const t of e.activeActions.values())t.stop();e.activeActions.clear(),e.mixer&&e.mixer.stopAllAction(),e.charAnimComponent&&(e.charAnimComponent.stopSequenceAnimation(),e.charAnimComponent=void 0),e.charAnimActionKeys?.clear()}}stopAllVfx(){for(const e of this.vfxActors.values())e.paused||e.stop();this.activeVfxClips.clear()}dispose(){if(this.stop(),this.clearLocatorBindings(),this.clearSequenceCameras(),this.bindings.clear(),this.roleBindings.clear(),this.sequenceData=null,this.world)for(const e of this.vfxActors.values())this.world.removeActor(e);this.vfxActors.clear(),this.stopAllAudio(),this.audioBuffers.clear(),this.loadingAudioBuffers.clear(),this.animationClips.clear(),this.loadingAnimationClips.clear(),this.clearRetimedAnimationClipCache(),this.audioByClip.clear()}updateTrackParenting(e,t){const a=this.getActiveObjectsForTrack(e);if(0===a.length)return;let s=null;const i=e.parent?.trackId;if(i){const t=this.sequenceData?ne(this.sequenceData.tracks).find(e=>e.id===i):void 0;if(t){const a=this.getActiveObjectsForTrack(t);if(a.length>0&&(s=a[0],e.parent?.socketName)){const t=this.findSocket(s,e.parent.socketName);t&&(s=t)}}}if(!s&&"camera"===e.type&&e.parentRole&&this.roleBindings.has(e.parentRole)){const t=this.roleBindings.get(e.parentRole);if(s=t instanceof p?t.object:t,e.parentRoleSocketName){const t=this.findSocket(s,e.parentRoleSocketName);t&&(s=t)}}for(const i of a)s?i.parent!==s&&(s.add(i),!t||"object"!==e.type&&"locator"!==e.type||(t.currentParent=s)):t?.currentParent&&t.currentParent===i.parent?this.restoreObjectParent(t,i):i.parent&&i.parent!==this.world?.scene&&"object"!==e.type&&"locator"!==e.type&&this.world?.scene.add(i)}findSocket(e,t){if(e.name===t)return e;if(e instanceof a.SkinnedMesh){const a=e.skeleton.bones.find(e=>e.name===t);if(a)return a}return e.getObjectByName(t)||null}getActiveObjectsForTrack(e){if("object"===e.type){const t=this.bindings.get(e.id);if(t&&t.target)return[t.target instanceof p?t.target.object:t.target]}else if("locator"===e.type){const t=this.bindings.get(e.id);if(t&&t.target instanceof n)return[t.target]}else{if("camera"===e.type)return[this.ensureSequenceCamera(e)];if("spawn"===e.type){const t=[];for(const[a,s]of this.spawnedInstances)if(a.startsWith(e.id+"-")&&this.activeClips.has(a)){const e=this.getInstanceObject(s);e&&t.push(e)}return t}if("vfx"===e.type){const t=[];for(const a of this.activeVfxClips)if(a.startsWith(e.id+"-")){const e=this.vfxActors.get(a);e&&t.push(e.object)}return t}}return[]}restoreObjectParent(e,t){e.originalParent?e.originalParent.add(t):this.world&&this.world.scene.add(t),e.currentParent=void 0}restoreOriginalParents(){for(const e of this.bindings.values())if(e.currentParent){const t=e.target instanceof p?e.target.object:e.target;t&&this.restoreObjectParent(e,t)}}evaluateAudioSubTracks(e,t){const a={};for(const s of e.subTracks)if("audioParameter"===s.type){const e=s,i=A(e.parameter),r=M(e.keyframes,t,{min:i.min,max:i.max});void 0!==r&&(a[e.parameter]=r)}return a}stringToRandom(e){let t=0;for(let a=0;a<e.length;a++){t=(t<<5)-t+e.charCodeAt(a),t&=t}const a=1e4*Math.sin(t);return a-Math.floor(a)}async refreshAsset(e){let t=!1;this.assetLoader?.clearCacheById(e),this.animationClips.delete(e),this.loadingAnimationClips.delete(e),this.clearRetimedAnimationClipCache(e),this.vfxService?.clearPool(e),t=this.refreshVfxActorsForAssetIds(new Set([e]))||t;for(const[a,s]of this.activePostProcessClips.entries())s.assetId===e&&(this.releasePostProcessClipEffect(a),t=!0);t=this.refreshSpawnedInstancesForClipKeys(this.getSpawnClipKeysForAsset(e))||t;const a=await this.getAssetOrNull(e);return"shaderGraph"===a?.type&&(t=await this.refreshShaderGraphDependentAssets(e)||t),t}refreshVfxActorsForAssetIds(e){let t=!1;for(const[a,s]of this.vfxActors.entries())this.vfxClipKeyUsesAnyAsset(a,e)&&(this.world&&this.world.removeActor(s),this.vfxActors.delete(a),this.activeVfxClips.delete(a),t=!0);return t}vfxClipKeyUsesAnyAsset(e,t){for(const a of t)if(e.endsWith(`-${a}`))return!0;return!1}refreshSpawnedInstancesForClipKeys(e){let t=!1;for(const[a,s]of this.spawnedInstances.entries())e.has(a)&&(this.despawnInstance(s),this.spawnedInstances.delete(a),this.activeClips.delete(a),t=!0);return t}getSpawnClipKeysForAsset(e){const t=new Set;if(!this.sequenceData)return t;for(const a of ne(this.sequenceData.tracks))if("spawn"===a.type&&(a.prefabId===e||a.meshId===e))for(const e of a.clips)t.add(`${a.id}-${e.id}`);return t}async refreshShaderGraphDependentAssets(e){const t=await this.findSequenceVfxAssetIdsUsingShaderGraph(e);for(const e of t)this.vfxService?.clearPool(e);const a=this.refreshVfxActorsForAssetIds(t),s=this.refreshSpawnedInstancesForClipKeys(await this.findSpawnClipKeysUsingShaderGraph(e));return a||s}async findSequenceVfxAssetIdsUsingShaderGraph(e){const t=new Set;if(!this.sequenceData)return t;const a=new Map;for(const s of ne(this.sequenceData.tracks))if("vfx"===s.type)for(const i of s.clips)null==i.vfxAssetId||t.has(i.vfxAssetId)||await this.assetUsesShaderGraph(i.vfxAssetId,e,a)&&t.add(i.vfxAssetId);return t}async findSpawnClipKeysUsingShaderGraph(e){const t=new Set;if(!this.sequenceData)return t;const a=new Map;for(const s of ne(this.sequenceData.tracks))if("spawn"===s.type&&await this.spawnTrackUsesShaderGraph(s,e,a))for(const e of s.clips)t.add(`${s.id}-${e.id}`);return t}async spawnTrackUsesShaderGraph(e,t,a){if(null!=e.meshId&&await this.assetUsesShaderGraph(e.meshId,t,a))return!0;if(null!=e.prefabId&&await this.assetUsesShaderGraph(e.prefabId,t,a))return!0;for(const s of e.subTracks??[])if("material"===s.type&&null!=s.materialAssetId&&await this.assetUsesShaderGraph(s.materialAssetId,t,a))return!0;return!1}assetUsesShaderGraph(e,t,a,s=new Set){if(e===t)return Promise.resolve(!0);if(s.has(e))return Promise.resolve(!1);if(a.has(e))return a.get(e);const i=this.assetUsesShaderGraphUncached(e,t,a,s);return a.set(e,i),i}async assetUsesShaderGraphUncached(e,t,a,s){if(s.has(e))return!1;const i=await this.getAssetOrNull(e);if(null==i)return!1;const r=new Set(s);return r.add(e),!!this.materialAssetUsesShaderGraph(i,t)||("mesh"===i.type?this.materialAssignmentsUseShaderGraph(i.materialAssignments,t,a,r):"prefab"===i.type?this.sceneObjectsUseShaderGraph(i.prefab?.objects,t,a,r):"vfx"===i.type&&this.vfxAssetUsesShaderGraph(i,t,a,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,a,s){for(const i of e??[])if(null!=i.materialId&&"null"!==i.materialId&&await this.assetUsesShaderGraph(i.materialId,t,a,s))return!0;return!1}async sceneObjectsUseShaderGraph(e,t,a,s){for(const i of e??[]){if(await this.materialAssignmentsUseShaderGraph(i.materialAssignments,t,a,s))return!0;if(null!=i.assetId&&("asset_mesh"===i.type||"prefab"===i.type||"vfx"===i.type)&&await this.assetUsesShaderGraph(i.assetId,t,a,s))return!0;if(await this.sceneObjectsUseShaderGraph(i.children,t,a,s))return!0}return!1}async vfxAssetUsesShaderGraph(e,t,a,s){for(const i of e.vfx?.emitters??[])if(await this.emitterUsesShaderGraph(i,t,a,s))return!0;return!1}async emitterUsesShaderGraph(e,t,a,s){if(await this.emitterOutputUsesShaderGraph(e.output,t,a,s))return!0;for(const i of e.children??[])if(await this.emitterUsesShaderGraph(i,t,a,s))return!0;return!1}async emitterOutputUsesShaderGraph(e,t,a,s){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,a,s))}async getAssetOrNull(e){if(!this.assetLoader)return null;try{return await this.assetLoader.getAsset(e)??null}catch{return null}}async invokeSequenceEvent(e,t,a,s){let i=!1;for(let e=0;e<s.length;e++)if(v(s[e])){i=!0;break}if(i)try{const t=new Array(s.length);for(let e=0;e<s.length;e++)t[e]=C(s[e],this.sequenceEventAsyncResolvers);const i=await Promise.all(t);await a.call(e,...i)}catch(e){console.error(`Failed to call sequence event ${t}:`,e)}else try{const t=new Array(s.length);for(let e=0;e<s.length;e++)t[e]=g(s[e],this.sequenceEventSyncResolvers);a.call(e,...t)}catch(e){console.error(`Failed to call sequence event ${t}:`,e)}}resolveSequenceEventActorReference(e){if(!this.world||null==e)return null;const t=e,a="object"==typeof t&&null!=t?.id?t.id:"string"==typeof t?t:null;if(null==a)return null;for(const e of this.world.actors){const t=e.object.userData.src??e.object.userData._src;if(t?.id===a)return e}return null}resolveSequenceEventSequence(e){return b(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 Q(e){return e.options?.length>0||e.propertyType===y.Boolean||e.propertyType===y.String}function X(e){return"outlineVisibility"===w(e)||e.valueType===y.Boolean||e.valueType===y.String}function z(e){return"object"==typeof e&&null!=e||"function"==typeof e}function Y(e,t){switch(t.type){case y.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 y.Boolean:return"boolean"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.Vector2:return H(e,t.value);case y.Vector3:return J(e,t.value);case y.Vector4:return ee(e,t.value);case y.Color:return function(e,t){if(e instanceof c){const a=Ae.set(0);return se(a,t)?(e.set(a.r,a.g,a.b),{applied:!0,value:e}):{applied:!1}}if(e instanceof h){const a=Ae.set(0);return se(a,t)?(e.set(a.r,a.g,a.b,e.w),{applied:!0,value:e}):{applied:!1}}return te(e,t)}(e,t.value);default:return{applied:!1}}}function Z(e,t){const s=S(t);return!!function(e){return e instanceof a.Material||!0===e?.isMaterial}(e)&&(("asset"!==s||e.userData?.assetId===t.materialAssetId)&&("outlineVisibility"===w(t)?null!=e.userData?.outlineParameters:null!=e.uniforms?.[t.uniformName]))}function H(e,t){const a=ae(t,2);return a?e instanceof l?(e.fromArray(a),{applied:!0,value:e}):{applied:!0,value:new l(a[0],a[1])}:{applied:!1}}function J(e,t){const a=ae(t,3);return a?e instanceof c?(e.fromArray(a),{applied:!0,value:e}):{applied:!0,value:new c(a[0],a[1],a[2])}:{applied:!1}}function ee(e,t){const a=ae(t,4);return a?e instanceof h?(e.fromArray(a),{applied:!0,value:e}):{applied:!0,value:new h(a[0],a[1],a[2],a[3])}:{applied:!1}}function te(e,t){if(e instanceof i)return se(e,t)?{applied:!0,value:e}:{applied:!1};const a=new i;return se(a,t)?{applied:!0,value:a}:{applied:!1}}function ae(e,t){if(!Array.isArray(e)||e.length<t)return null;const a=new Array(t);for(let s=0;s<t;s++){if("number"!=typeof e[s])return null;a[s]=e[s]}return a}function se(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 ie(e){if(e instanceof l||e instanceof c||e instanceof h||e instanceof i||e instanceof r)return e.clone()}function re(e){const{owner:t,key:a}=e.resolution;e.hadOwnProperty?(!function(e,t){if(e instanceof l&&t instanceof l)return e.copy(t),!0;if(e instanceof c&&t instanceof c)return e.copy(t),!0;if(e instanceof h&&t instanceof h)return e.copy(t),!0;if(e instanceof 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[a]=e.value):delete t[a]}function ne(e){const t=[];for(const a of e)t.push(a),"group"===a.type&&t.push(...ne(a.childTracks));return t}function oe(e){if("string"!=typeof e)return null;const t=e.trim();return t.length>0?t:null}function le(e){const t=new a.Group;t.name=`SequenceLocatorMarker:${e}`,t.renderOrder=1e3;const s=new a.AxesHelper(.35);s.renderOrder=1e3;const i=Array.isArray(s.material)?s.material:[s.material];for(const e of i)e.depthTest=!1,e.transparent=!0,e.opacity=.9,e.toneMapped=!1;t.add(s);const r=function(e){if("undefined"==typeof document)return null;const t=document.createElement("canvas");t.width=256,t.height=64;const s=t.getContext("2d");if(!s)return null;s.clearRect(0,0,t.width,t.height),s.fillStyle="rgba(16, 18, 24, 0.78)",function(e,t,a,s,i,r){const n=t+s,o=a+i;e.beginPath(),e.moveTo(t+r,a),e.lineTo(n-r,a),e.quadraticCurveTo(n,a,n,a+r),e.lineTo(n,o-r),e.quadraticCurveTo(n,o,n-r,o),e.lineTo(t+r,o),e.quadraticCurveTo(t,o,t,o-r),e.lineTo(t,a+r),e.quadraticCurveTo(t,a,t+r,a),e.closePath()}(s,0,8,t.width,48,8),s.fill(),s.font="24px sans-serif",s.textAlign="center",s.textBaseline="middle",s.fillStyle="#f8fafc",s.fillText(e||"Locator",t.width/2,t.height/2);const i=new a.CanvasTexture(t);i.needsUpdate=!0;const r=new a.SpriteMaterial({map:i,transparent:!0,depthTest:!1});r.toneMapped=!1;const n=new a.Sprite(r);return n.scale.set(.9,.225,1),n}(e);return r&&(r.position.set(0,.45,0),r.renderOrder=1001,t.add(r)),t.traverse(e=>{e.raycast=()=>{}}),t}function ce(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 he=new c,ue=new c,pe=new c,de=new c,fe=new c,me=new c,ye=new o,ve=new o,Ce=new r,ge=new r,Ae=new i;/*
1
+ import{BehaviorSubject as e,Subject as t}from"rxjs";import*as a from"three";import{AnimationMixer as s,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{BaseActor as p}from"../../gameplay/actors/actor.js";import d from"../../gameplay/actors/builtin/index.js";import{Prefab as f,PrefabOf as m}from"../../scene/objects/prefab.js";import{SerializedParamType as y}from"../../scene/model.js";import{customParamValueNeedsAsyncResolution as v,deserializeCustomParamValue as C,deserializeCustomParamValueSync as g}from"../../scene/custom-param-deserialize.js";import{getAudioParameterDefinition as A}from"./audio-parameters.js";import{getMaterialSubTrackMatchMode as S,getMaterialSubTrackTarget as w,Sequence as P,isSequenceData as b}from"./sequence-data.js";import{getSequenceSubTrackDefinition as k,getSequenceTrackDefinition as x}from"./sequence-definitions.js";import{applyInterpolation as T,evaluateCustomParamValueKeyframes as I,evaluateNumericKeyframes as M,findKeyframeSpan as B}from"./sequence-value-lane.js";import{evaluateTransformPositionSpan as q}from"./sequence-transform.js";import{applyAnimationClipRootMotionAxisMask as O,buildRetimedAnimationClip as F,getAnimationClipRetimingSignature as E,isAnimationClipUsingRetiming as j}from"./sequence-animation-retiming.js";import*as R from"three/addons/utils/SkeletonUtils.js";import{CharacterAnimationComponent as V,getCharacterMovementLike as _}from"../../gameplay/actors/index.js";import{RootMotionClip as L}from"../../gameplay/animation/root-motion.js";import{markMaterialUniformValuesNeedUpdate as D}from"../../rendering/node-material-webgpu-resolver.js";import{getAnimationClipRigId as K,getAnimationRigIdFromObject as $,setAnimationClipRigId as G}from"../../gameplay/animation/retarget.js";import{hashCameraShakeSeed as N}from"../../gameplay/services/camera-shake.js";import{buildShaderGraphPostProcessMaterial as U,shaderGraphPostProcessWeightUniformName as W}from"../../shader/graph/index.js";export var SequencePlaybackState;!function(e){e.Stopped="stopped",e.Playing="playing",e.Paused="paused"}(SequencePlaybackState||(SequencePlaybackState={}));export class SequencePlayer{constructor(){this._state=new e(SequencePlaybackState.Stopped),this._time=new e(0),this._duration=0,this._timescale=1,this._loop=!1,this._externalTimeControl=!1,this._inEditor=!1,this.bindings=new Map,this.roleBindings=new Map,this.sequenceData=null,this.onComplete=new t,this.onLoop=new t,this.onTimeUpdate=this._time.asObservable(),this.onStateChange=this._state.asObservable(),this.loopCount=0,this.viewController=null,this._cameraControlEnabled=!1,this._cameraControlTrackId=null,this.sequenceCameras=new Map,this.cameraPlayables=new Map,this.cameraBlendCamera=null,this.cameraBlendSource=null,this.cameraBlendOutSource=null,this.cameraOverrideHandle=null,this.activeCameraClipKey=null,this.cameraBlendOutClipKey=null,this.activeCameraShakeClipKeys=new Set,this.nextCameraShakeClipKeys=new Set,this.activePostProcessClips=new Map,this.nextPostProcessClipKeys=new Set,this.audioListener=null,this.audioBuffers=new Map,this.loadingAudioBuffers=new Map,this.animationClips=new Map,this.loadingAnimationClips=new Map,this.retimedAnimationClips=new Map,this.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.audioFilters=new Map,this.audioPannerNodes=new Map,this.firedEvents=new Set,this.sequenceEventSyncResolvers={actor:e=>this.resolveSequenceEventActorReference(e)},this.sequenceEventAsyncResolvers={actor:e=>this.resolveSequenceEventActorReference(e),texture:e=>this.assetLoader?.getTextureByAssetId(e)??null,sampler2DNode:e=>this.assetLoader?.getTextureByAssetId(e)??null,object3D:async e=>{const t=await(this.assetLoader?.getModelByAssetId(e));return t?.scene??null},material:e=>this.assetLoader?.getMaterialByAssetId(e)??null,audioBuffer:e=>this.assetLoader?.getAudioByAssetId(e)??null,visualEffect:async e=>{if(!this.assetLoader||!this.actorFactory)return null;const t=await this.assetLoader.getAsset(e);return t?new u(this.actorFactory,t):null},prefab:async e=>{const t=await(this.assetLoader?.getPrefabById(e));return t?new f(t.asset):null},prefabActor:async e=>{const t=await(this.assetLoader?.getPrefabById(e));return t?new m(new f(t.asset)):null},sequence:e=>this.resolveSequenceEventSequence(e),animationClip:e=>this.resolveSequenceEventAnimationClip(e)},this.trackRuntimeEvaluators={object:(e,t,a)=>{t&&this.evaluateObjectTrack(e,t,a)},locator:(e,t,a)=>{t&&this.evaluateLocatorTrack(e,t,a)},camera:(e,t,a)=>this.evaluateCameraTrack(e,a),cameraShake:(e,t,a)=>this.evaluateCameraShakeTrack(e,a),postProcess:(e,t,a)=>this.evaluatePostProcessTrack(e,a),audio:(e,t,a)=>this.evaluateAudioTrack(e,a),vfx:(e,t,a)=>this.evaluateVfxTrack(e,a),spawn:(e,t,a)=>this.evaluateSpawnTrack(e,t,a),group:(e,t,a)=>{if("group"===e.type)for(const t of e.childTracks)this.evaluateTrack(t,a)}},this.subTrackRuntimeEvaluators={transform:(e,t,a)=>{const s=this.getPlayableObject(t);s&&this.evaluateTransformSubTrack(e,s,a)},animation:(e,t,a)=>this.evaluateAnimationSubTrack(e,t,a),visibility:(e,t,a)=>{const s=this.getPlayableObject(t);s&&this.evaluateVisibilitySubTrack(e,s,a)},parameter:(e,t,a)=>this.evaluateParameterSubTrack(e,t.target||null,a),event:(e,t,a)=>this.evaluateEventSubTrack(e,t.target||null,a)}}get state(){return this._state.value}get time(){return this._time.value}get duration(){return this._duration}get timescale(){return this._timescale}set timescale(e){this._timescale=Math.max(.01,e)}get loop(){return this._loop}set loop(e){this._loop=e}get externalTimeControl(){return this._externalTimeControl}set externalTimeControl(e){this._externalTimeControl=e}get inEditor(){return this._inEditor}set inEditor(e){this._inEditor=e,this.updateLocatorMarkerVisibility()}get cameraControlEnabled(){return this._cameraControlEnabled}set cameraControlEnabled(e){this._cameraControlEnabled=e,e||this.releaseCameraOverride()}get cameraControlTrackId(){return this._cameraControlTrackId}set cameraControlTrackId(e){this._cameraControlTrackId!==e&&(this._cameraControlTrackId=e,this.releaseCameraOverride())}setViewController(e){this.viewController&&this.viewController!==e&&this.viewController.clearCameraShakeContributionsForOwner(this),this.viewController=e}setWorld(e){this.world!==e&&(this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.clearLocatorBindings(),this.clearSequenceCameras(),this.clearCameraShakeContributions(),this.clearPostProcessEffects(),this.world=e,this.clearCounter++,this.vfxActors.clear(),this.spawnedInstances.clear(),this.bindings.clear(),this.activeClips.clear(),this.activeVfxClips.clear(),this.activeAudioClips.clear(),this.audioStartInFlight.clear(),this.lastAudioStartAttemptTime.clear(),this.loadingAudioBuffers.clear(),this.audioFilters.clear(),this.audioPannerNodes.clear(),this.pendingSpawns.clear(),this.propertyResolutionCache.clear(),this.materialResolutionCache.clear(),this.clearRetimedAnimationClipCache(),this._state.next(SequencePlaybackState.Stopped),this.sequenceData&&this.initializeLocatorBindings())}setAudioListener(e){this.audioListener=e}setAssetLoader(e){if(this.assetLoader=e,this.sequenceData){const e=this.clearCounter;this.preloadSequenceResources(this.sequenceData,e)}}setActorFactory(e){this.actorFactory=e}setVfxService(e){this.vfxService=e}load(e){if(this.stop(),this.clearCounter++,this.clearLocatorBindings(),this.clearSequenceCameras(),this.sequenceData=e,this._duration=e.duration,this._loop=e.loop,this._timescale=e.playbackRate,this.clearRetimedAnimationClipCache(),this.bindings.clear(),this.initializeLocatorBindings(),this.loopCount=0,this.assetLoader){const t=this.clearCounter;this.preloadSequenceResources(e,t)}}preloadSequenceResources(e,t){return Promise.all([this.preloadAudioBuffersForSequence(e,t),this.preloadAnimationClipsForSequence(e,t)]).then(()=>{})}getAudioAssetIdsForSequence(e){const t=new Set;for(const a of e.tracks){if("audio"!==a.type)continue;const e=a;for(const a of e.clips??[])a.audioAssetId&&t.add(a.audioAssetId)}return[...t]}async preloadAudioBuffersForSequence(e,t){if(!this.assetLoader)return;const a=this.getAudioAssetIdsForSequence(e);0!==a.length&&await Promise.all(a.map(async e=>{if(t!==this.clearCounter)return;if(this.audioBuffers.has(e))return;let a=this.loadingAudioBuffers.get(e);a||(a=this.assetLoader.getAudioByAssetId(e),this.loadingAudioBuffers.set(e,a));try{const s=await a;if(t!==this.clearCounter)return;this.audioBuffers.set(e,s)}catch(e){}finally{this.loadingAudioBuffers.get(e)===a&&this.loadingAudioBuffers.delete(e)}}))}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.preloadVisualEffectsForSequence(this.sequenceData,e)])}async preloadVisualEffectsForSequence(e,t){if(!this.world||!this.actorFactory)return;const a=new Set;for(const t of ne(e.tracks))if("vfx"===t.type)for(const e of t.clips??[])null!=e.vfxAssetId&&a.add(e.vfxAssetId);if(0===a.size)return;const s=await Promise.all([...a].map(e=>this.assetLoader.getAsset(e)));if(t!==this.clearCounter)return;const i=s.filter(e=>null!=e&&null!=e.vfx).map(e=>new u(this.actorFactory,e));await this.world.preloadVisualEffects(i)}async prepareAnimationClipsForBindings(e,t){const a=[];for(const s of ne(e.tracks)){if(!("subTracks"in s))continue;const e=this.bindings.get(s.id),i=null==e?null:this.getPlayableObject(e);if(null==i)continue;const r=$(i);for(const e of s.subTracks)if("animation"===e.type)for(const s of e.clips){if(t!==this.clearCounter)return;if(null!=s.animationClipAssetId){const e=this.animationClipCacheKey(s.animationClipAssetId,r);a.push(this.ensureAnimationClip(s.animationClipAssetId,r).then(a=>{null!=a&&t===this.clearCounter&&j(s)&&(this.getPlayableAnimationClip(e,a,s,!1),s.rootMotion&&this.getPlayableAnimationClip(e,a,s,!0))}))}}}await Promise.all(a)}bindRole(e,t){this.roleBindings.set(e,t),this.sequenceData&&this.resolveBindings()}bindObject(e,t){if(this.sequenceData)for(const a of ne(this.sequenceData.tracks))"object"!==a.type||a.targetId!==e||a.role||this.createBinding(a,t)}unbindObject(e){if(this.sequenceData)for(const t of ne(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=oe(e);if(!t||!this.sequenceData)return[];const a=[];for(const e of ne(this.sequenceData.tracks)){if("locator"!==e.type)continue;if(oe(e.bindingId)!==t)continue;const s=this.bindings.get(e.id),i=s?this.getPlayableObject(s):null;i&&(i.updateWorldMatrix(!0,!1),a.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 a}resolveBindings(){if(this.sequenceData)for(const e of this.sequenceData.tracks)this.resolveTrackBinding(e)}initializeLocatorBindings(){if(this.sequenceData)for(const e of ne(this.sequenceData.tracks)){if("locator"!==e.type||this.bindings.has(e.id))continue;const t=new n;t.name=e.name||"Locator",t.userData.sequenceLocatorTrackId=e.id,this.world?.scene&&null==t.parent&&this.world.scene.add(t);const a=le(e.name);a.visible=this._inEditor,t.add(a),this.locatorMarkers.set(e.id,a),this.disableLocatorInteraction(t),this.createBinding(e,t)}}clearLocatorBindings(){for(const e of this.locatorMarkers.values())ce(e);for(const e of this.bindings.values()){if("locator"!==e.track.type)continue;const t=this.getPlayableObject(e);t?.parent&&t.removeFromParent()}this.locatorMarkers.clear()}updateLocatorMarkerVisibility(){for(const e of this.locatorMarkers.values())e.visible=this._inEditor}disableLocatorInteraction(e){e.traverse(e=>{e.raycast=()=>{}})}resolveTrackBinding(e){if("object"===e.type){const t=e;t.role&&this.roleBindings.has(t.role)&&this.createBinding(e,this.roleBindings.get(t.role))}else if("spawn"===e.type){const t=e;t.role&&this.roleBindings.has(t.role)&&this.createBinding(e,this.roleBindings.get(t.role))}else if("group"===e.type)for(const t of e.childTracks)this.resolveTrackBinding(t)}createBinding(e,t){const a=t instanceof p?t.object:t,i=this.bindings.get(e.id),r=null!=i?i.target instanceof p?i.target.object:i.target:null,n=null!=i&&i.target===t&&r===a,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:a.position.clone(),rotation:a.rotation.clone(),scale:a.scale.clone()},l.originalParent=a.parent),o&&null==l.mixer?l.mixer=new s(a):o||(l.mixer=void 0),this.bindings.set(e.id,l)}removeBinding(e){const t=this.bindings.get(e);t&&(this.releaseBinding(t),this.bindings.delete(e))}releaseBinding(e){this.clearExternalRootMotionPreview(e);for(const[t,a]of e.activeActions.entries())e.charAnimActionKeys?.has(t)||a.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.stopAllAudio(),this.stopAllAnimations(),this.despawnAll(),this.stopAllVfx(),this.firedEvents.clear(),this.clearCameraShakeContributions(),this.clearPostProcessEffects()}stop(){this._state.next(SequencePlaybackState.Stopped),this._time.next(0),this.clearCounter++,this.loopCount=0,this.pauseAudio(),this.releaseCameraOverride(),this.restoreAllPropertySnapshots(),this.restoreAllMaterialSnapshots(),this.restoreOriginalTransforms(),this.restoreOriginalParents(),this.stopAllAudio(),this.stopAllAnimations(),this.despawnAll(),this.stopAllVfx(),this.firedEvents.clear(),this.clearCameraShakeContributions(),this.clearPostProcessEffects()}restart(){this.stop(),this.play()}seek(e){const t=Math.max(0,Math.min(e,this._duration));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.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._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 t of this.sequenceData.tracks){if(!t.muted&&("object"===t.type||"locator"===t.type||"camera"===t.type||"spawn"===t.type||"vfx"===t.type)){const e=this.bindings.get(t.id);this.updateTrackParenting(t,e)}this.evaluateTrack(t,e)}this.updateCameraControl(e),this.syncCameraShakeContributions(),this.syncPostProcessEffects()}}evaluateTrack(e,t){if(e.muted)return;const a=this.bindings.get(e.id);(0,this.trackRuntimeEvaluators[x(e.type).runtimeEvaluator])(e,a,t)}evaluateObjectTrack(e,t,a){this.evaluateSubTracks(e.subTracks,t,a)}evaluateLocatorTrack(e,t,a){this.evaluateSubTracks(e.subTracks,t,a)}getActiveTrackObjects(e){if(!this.sequenceData)return[];const t=ne(this.sequenceData.tracks).find(t=>t.id===e);return t?this.getActiveObjectsForTrack(t):[]}evaluateSubTracks(e,t,a){this._externalTimeControl&&this.beginExternalRootMotionPreview(t);for(const s of e){if(s.muted)continue;(0,this.subTrackRuntimeEvaluators[k(s.type).runtimeEvaluator])(s,t,a)}this._externalTimeControl&&this.applyExternalRootMotionPreview(t)}beginExternalRootMotionPreview(e){const t=e.externalRootMotionPreview;if(!t)return;const a=this.getPlayableObject(e);a&&a.position.sub(t.appliedOffset),t.appliedOffset.set(0,0,0),t.sampledOffset.set(0,0,0),t.root=null}sampleExternalRootMotionPreview(e,t,s,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(s,t.duration));de.fromArray(r.evaluate(o)),fe.fromArray(r.evaluate(l)),n.sampledOffset.subVectors(fe,de),n.sampledOffset.y=0;const h=this.getPlayableObject(e),u=a.PropertyBinding.parseTrackName(t.motionTrack.name);n.root=h?.getObjectByName(u.nodeName)??h}applyExternalRootMotionPreview(e){const t=e.externalRootMotionPreview,a=this.getPlayableObject(e);t&&a&&t.root&&(t.root.getWorldScale(me),t.appliedOffset.copy(t.sampledOffset).multiply(me).applyQuaternion(a.quaternion),a.position.add(t.appliedOffset))}clearExternalRootMotionPreview(e){const t=e.externalRootMotionPreview,a=this.getPlayableObject(e);t&&a&&a.position.sub(t.appliedOffset),e.externalRootMotionPreview=void 0}evaluateTransformSubTrack(e,t,a){const s=e.keyframes;if(0===s.length)return;const{prev:i,next:r,prevIndex:n,nextIndex:o,t:l}=B(s,a);if(i)if(e.components.position&&q(s,n,o,l,t.position),r&&i!==r){const a=T(l,i.interpolation);e.components.rotation&&i.rotation&&r.rotation&&(ye.setFromEuler(Ce.fromArray([...i.rotation,"XYZ"])),ve.setFromEuler(ge.fromArray([...r.rotation,"XYZ"])),t.quaternion.slerpQuaternions(ye,ve,a)),e.components.scale&&i.scale&&r.scale&&t.scale.lerpVectors(he.fromArray(i.scale),ue.fromArray(r.scale),a)}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,s){if(!t.mixer||!t.activeActions)return;const i=t.target instanceof p?t.target.object:t.target;if(i)for(const r of e.clips){const n=r.startTime+r.duration,o=s>=r.startTime&&s<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 s=$(i),n=this.animationClipCacheKey(e,s),o=this.animationClips.get(n);if(null==o){this.ensureAnimationClip(e,s);continue}const u=this.prepareAnimationPlayback(n,o,r),d=t;let f=!1;if(t.target instanceof p){d.charAnimComponent||(d.charAnimComponent=t.target.getComponent(V)??void 0);const e=d.charAnimComponent;if(null!=e){const a=r.rootMotion?j(r)?this.getPlayableAnimationClip(n,o,r,!0):L.fromClip(u.clip,!1):u.clip;if(this._externalTimeControl)c=e.beginExternalAnimationControl(a,{timeScale:u.timeScale});else if(e.play(a,{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),d.charAnimActionKeys||(d.charAnimActionKeys=new Set),d.charAnimActionKeys.add(l),f=!0}}f||(c=t.mixer.clipAction(u.clip),c.setLoop(a.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 a=this.getAnimationPlaybackLocalTime(r,s),i=Math.min(a,c.getClip().duration);(h||Math.abs(c.time-i)>.001)&&(c.time=i,c.paused=!1,c.play(),e.charAnimComponent?e.charAnimComponent.getMixer()?.update(0):t.mixer&&t.mixer.update(0)),r.rootMotion&&c.getClip()instanceof L&&this.sampleExternalRootMotionPreview(t,c.getClip(),i,j(r)?0:r.clipStartOffset)}else e.charAnimComponent?.endExternalControl()}}else c&&this.deactivateAnimationAction(t,l,c)}}deactivateAnimationAction(e,t,a){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));a.stop(),this._externalTimeControl&&e.mixer&&e.mixer.update(0)}deactivateAnimationSubTracks(e,t){for(const a of e)if(!a.muted&&"animation"===a.type)for(const e of a.clips){const s=`${a.id}-${e.id}`,i=t.activeActions.get(s);i&&this.deactivateAnimationAction(t,s,i)}}deactivateCharacterAnimationActions(){for(const e of this.bindings.values())for(const t of[...e.charAnimActionKeys??[]]){const a=e.activeActions.get(t);a?this.deactivateAnimationAction(e,t,a):e.charAnimActionKeys?.delete(t)}}evaluateVisibilitySubTrack(e,t,a){const s=e.keyframes;if(0===s.length)return;let i=s[0];for(const e of s){if(!(e.time<=a))break;i=e}t.visible=i.visible}evaluatePropertySubTrack(e,t,a){const s=I(e.keyframes,a,{min:e.range?.[0],max:e.range?.[1],stepOnly:Q(e)});s&&this.applyResolvedPropertyValue(e,t,s)}evaluateParameterSubTrack(e,t,a){if("audioParameter"===e.type)return;const s=I(e.keyframes,a,"property"===e.type?{min:e.range?.[0],max:e.range?.[1],stepOnly:Q(e)}:"material"===e.type?{min:e.range?.[0],max:e.range?.[1],stepOnly:X(e)}:{});s&&("property"!==e.type?this.applyResolvedMaterialValue(e,t,s):this.applyResolvedPropertyValue(e,t,s))}evaluateEventSubTrack(e,t,a){if(t instanceof p&&this._state.value===SequencePlaybackState.Playing)for(const s of e.events){const i=`${e.id}-${s.id}`;if(a>=s.time&&!this.firedEvents.has(i)){if(this.firedEvents.add(i),s.editorOnly&&!this._inEditor)continue;if(!s.functionName)continue;const e=t[s.functionName];"function"==typeof e?this.invokeSequenceEvent(t,s.functionName,e,s.arguments??[]):console.warn(`Sequence event method '${s.functionName}' not found on actor`)}else s.time>a&&this.firedEvents.delete(i)}}evaluateCameraTrack(e,t){const a=this.ensureSequenceCamera(e);this.applyCameraTrackSettings(e,a),this.evaluateSubTracks(e.subTracks,this.getCameraPlayable(e,a),t),a.updateProjectionMatrix()}evaluateCameraShakeTrack(e,t){if(this.viewController)for(const a of e.clips??[]){if(!this.isCameraShakeClipActive(a,t))continue;const e=t-a.startTime,s=a.id;this.nextCameraShakeClipKeys.add(s),this.viewController.setCameraShakeContribution(this,s,a,e,a.seed??N(a.id))}}evaluatePostProcessTrack(e,t){if(this.viewController&&this.assetLoader){for(const a of e.clips??[]){if(!this.isPostProcessClipActive(a,t))continue;const s=this.getPostProcessClipKey(e,a);this.nextPostProcessClipKeys.add(s),this.ensurePostProcessClipEffect(e,a,s);const i=this.activePostProcessClips.get(s);i?.handle&&(i.handle.stage=e.stage,i.handle.priority=e.priority,i.handle.enabled=!0,this.applyPostProcessClipWeight(i.handle,a,t))}this.evaluatePostProcessMaterialSubTracks(e,t)}}evaluatePostProcessMaterialSubTracks(e,t){for(const a of e.subTracks){if(a.muted||"material"!==a.type)continue;const s=I(a.keyframes,t,{min:a.range?.[0],max:a.range?.[1],stepOnly:X(a)});s&&this.applyPostProcessMaterialValue(e.id,a,s)}}applyPostProcessMaterialValue(e,t,a){if("shaderUniform"===w(t)&&t.uniformName)for(const s of this.activePostProcessClips.values()){if(s.trackId!==e||!s.handle)continue;const i=s.handle.material,r=i.uniforms?.[t.uniformName];if(!r)continue;const n=Y(r.value,a);n.applied&&(r.value=n.value,i.uniformsNeedUpdate=!0,D(i))}}isPostProcessClipActive(e,t){return t>=e.startTime&&t<e.startTime+e.duration}getPostProcessClipKey(e,t){return`${e.id}-${t.id}`}ensurePostProcessClipEffect(e,t,a){const s=t.shaderGraphAssetId;if(!s)return void this.releasePostProcessClipEffect(a);const i=JSON.stringify(t.shaderGraphParams??{}),r=this.activePostProcessClips.get(a);if(r?.assetId===s&&r.paramsSignature===i)return;this.releasePostProcessClipEffect(a);const n={key:a,trackId:e.id,clipId:t.id,assetId:s,paramsSignature:i,version:this.clearCounter};this.activePostProcessClips.set(a,n),this.loadPostProcessClipEffect(e,t,n)}async loadPostProcessClipEffect(e,t,a){if(this.assetLoader&&this.viewController)try{const s=await this.assetLoader.getShaderGraphByAssetId(a.assetId);if(!this.isPostProcessClipEntryCurrent(a))return;if("postProcess"!==s.target)return console.warn(`Sequence post-process clip references shader graph "${a.assetId}" with target "${s.target}"`),void this.releasePostProcessClipEffect(a.key);const i=await this.assetLoader.prepareShaderGraphParameters(s,t.shaderGraphParams??{});if(!this.isPostProcessClipEntryCurrent(a))return;const r=U(s,{parameters:i});if(!this.isPostProcessClipEntryCurrent(a))return void r.dispose();a.handle=this.viewController.addPostProcessEffect(r,{stage:e.stage,priority:e.priority,enabled:!0}),this.applyPostProcessClipWeight(a.handle,t,this._time.value)}catch(e){this.isPostProcessClipEntryCurrent(a)&&this.releasePostProcessClipEffect(a.key),console.error(`Failed to create post-process effect for clip ${t.id}:`,e)}}isPostProcessClipEntryCurrent(e){return this.clearCounter===e.version&&this.activePostProcessClips.get(e.key)===e}applyPostProcessClipWeight(e,t,a){const s=e.material.uniforms?.[W];null!=s&&(s.value=this.getPostProcessClipWeight(t,a),e.material.uniformsNeedUpdate=!0)}getPostProcessClipWeight(e,t){const a=Math.max(0,t-e.startTime),s=Math.max(0,e.startTime+e.duration-t);let i=1;const r=Math.max(0,e.fadeInDuration??0);r>0&&(i=Math.min(i,a/r));const n=Math.max(0,e.fadeOutDuration??0);return n>0&&(i=Math.min(i,s/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 a=this.cameraPlayables.get(e.id);return a?a.target=t:(a={target:t},this.cameraPlayables.set(e.id,a)),a}ensureSequenceCamera(e){let t=this.sequenceCameras.get(e.id);if(t)null==t.parent&&this.world?.scene.add(t);else{const s=e.cameraSettings??{fov:60,near:.1,far:1e3};t=new a.PerspectiveCamera(s.fov??60,this.getCurrentCameraAspect(),s.near??.1,s.far??1e3),t.name=e.name||"Sequence Camera",t.userData.sequenceCameraTrackId=e.id,t.layers.mask=this.viewController?.getBaseCamera().layers.mask??t.layers.mask,this.sequenceCameras.set(e.id,t),this.world?.scene.add(t)}return t}clearSequenceCameras(){this.releaseCameraOverride();for(const e of this.sequenceCameras.values())e.removeFromParent();this.sequenceCameras.clear(),this.cameraPlayables.clear()}applyCameraTrackSettings(e,t){const a=e.cameraSettings??{fov:60,near:.1,far:1e3};t.fov=a.fov??60,t.near=a.near??.1,t.far=a.far??1e3,t.aspect=this.getCurrentCameraAspect()}getCurrentCameraAspect(){const e=this.viewController?.getBaseCamera();if(e instanceof a.PerspectiveCamera&&Number.isFinite(e.aspect)&&e.aspect>0)return e.aspect;const t=this.viewController?.getSourceCamera();return t instanceof a.PerspectiveCamera&&Number.isFinite(t.aspect)&&t.aspect>0?t.aspect:1}updateCameraControl(e){if(!this._cameraControlEnabled||!this.viewController||!this.sequenceData)return void this.releaseCameraOverride();const t=this.findActiveCameraShot(e);if(t)return void this.updateActiveCameraShot(t,e);const a=this.findBlendOutCameraShot(e);a?this.updateCameraBlendOut(a,e):this.releaseCameraOverride()}findActiveCameraShot(e){if(!this.sequenceData)return null;let t=null;for(const a of ne(this.sequenceData.tracks)){if("camera"!==a.type||a.muted||!this.isCameraControlTrackEligible(a))continue;const s=a.clips??[];for(const i of s)this.isCameraClipActive(i,e)&&(t={track:a,clip:i,camera:this.ensureSequenceCamera(a),key:this.getCameraClipKey(a,i)})}return t}findBlendOutCameraShot(e){if(!this.sequenceData)return null;let t=null;for(const a of ne(this.sequenceData.tracks)){if("camera"!==a.type||a.muted||!this.isCameraControlTrackEligible(a))continue;const s=a.clips??[];for(const i of s){const s=Math.max(0,i.blendOutDuration??0);if(s<=0)continue;const r=this.getCameraClipEnd(i);e>=r&&e<r+s&&(t={track:a,clip:i,camera:this.ensureSequenceCamera(a),key:this.getCameraClipKey(a,i)})}}return t}isCameraControlTrackEligible(e){return null==this._cameraControlTrackId||e.id===this._cameraControlTrackId}updateActiveCameraShot(e,t){if(!this.viewController)return;const a=this.ensureCameraBlendCamera();this.activeCameraClipKey!==e.key&&(this.copyCameraState(this.viewController.getSourceCamera(),this.ensureCameraBlendSource()),this.activeCameraClipKey=e.key,this.cameraBlendOutClipKey=null);const s=Math.max(0,e.clip.blendInDuration??0),i=s<=0?1:this.evaluateCameraBlendAlpha((t-e.clip.startTime)/s,e.clip);i>=1?this.copyCameraState(e.camera,a):this.blendCameraState(this.ensureCameraBlendSource(),e.camera,a,i),a.updateProjectionMatrix(),this.ensureCameraOverride()}updateCameraBlendOut(e,t){if(!this.viewController)return;const a=this.ensureCameraBlendCamera();if(this.cameraBlendOutClipKey!==e.key){const t=this.activeCameraClipKey===e.key?this.viewController.getSourceCamera():e.camera;this.copyCameraState(t,this.ensureCameraBlendOutSource()),this.activeCameraClipKey=null,this.cameraBlendOutClipKey=e.key}const s=this.getCameraClipEnd(e.clip),i=Math.max(0,e.clip.blendOutDuration??0),r=i<=0?1:this.evaluateCameraBlendAlpha((t-s)/i,e.clip);this.blendCameraState(this.ensureCameraBlendOutSource(),this.viewController.getBaseCamera(),a,r),a.updateProjectionMatrix(),this.ensureCameraOverride()}ensureCameraBlendCamera(){return this.cameraBlendCamera||(this.cameraBlendCamera=new a.PerspectiveCamera(60,this.getCurrentCameraAspect(),.1,1e3),this.cameraBlendCamera.name="Sequence Camera Blend"),this.cameraBlendCamera}ensureCameraBlendSource(){return this.cameraBlendSource||(this.cameraBlendSource=new a.PerspectiveCamera),this.cameraBlendSource}ensureCameraBlendOutSource(){return this.cameraBlendOutSource||(this.cameraBlendOutSource=new a.PerspectiveCamera),this.cameraBlendOutSource}ensureCameraOverride(){this.viewController&&!this.cameraOverrideHandle&&(this.cameraOverrideHandle=this.viewController.pushCameraOverride(this.ensureCameraBlendCamera(),this))}releaseCameraOverride(){this.cameraOverrideHandle?.release(),this.cameraOverrideHandle=null,this.viewController?.releaseCameraOverridesForOwner(this),this.activeCameraClipKey=null,this.cameraBlendOutClipKey=null}isCameraClipActive(e,t){return t>=e.startTime&&t<this.getCameraClipEnd(e)}getCameraClipEnd(e){return e.startTime+Math.max(0,e.duration)}isCameraShakeClipActive(e,t){return t>=e.startTime&&t<this.getCameraShakeClipEnd(e)}getCameraShakeClipEnd(e){return e.startTime+Math.max(0,e.duration)}getCameraClipKey(e,t){return`${e.id}-${t.id}`}evaluateCameraBlendAlpha(e,t){return T(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(he)),t.quaternion.copy(e.getWorldQuaternion(ye)),t.scale.copy(e.getWorldScale(ue)),e instanceof a.PerspectiveCamera?(t.fov=e.fov,t.near=e.near,t.far=e.far,t.aspect=e.aspect):t.aspect=this.getCurrentCameraAspect(),t.layers.mask=e.layers.mask}blendCameraState(e,t,s,i){e.updateWorldMatrix(!0,!1),t.updateWorldMatrix(!0,!1),s.position.lerpVectors(e.getWorldPosition(he),t.getWorldPosition(ue),i),s.quaternion.slerpQuaternions(e.getWorldQuaternion(ye),t.getWorldQuaternion(ve),i),s.scale.lerpVectors(e.getWorldScale(he),t.getWorldScale(ue),i),e instanceof a.PerspectiveCamera&&t instanceof a.PerspectiveCamera?(s.fov=e.fov+(t.fov-e.fov)*i,s.near=e.near+(t.near-e.near)*i,s.far=e.far+(t.far-e.far)*i,s.aspect=t.aspect):t instanceof a.PerspectiveCamera?(s.fov=t.fov,s.near=t.near,s.far=t.far,s.aspect=t.aspect):s.aspect=this.getCurrentCameraAspect(),s.layers.mask=t.layers.mask}evaluateAudioTrack(e,t){if(!this.assetLoader||!e.clips||0===e.clips.length)return;const a=this._state.value===SequencePlaybackState.Playing,s=this.evaluateAudioSubTracks(e,t);e.volume;for(const 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),a){const a=this.audioByClip.get(o);a&&a.isPlaying||this.tryStartAudioClip(e,i,o,t,s)}const r=this.audioByClip.get(o);r&&this.applyAudioParameters(r,e,i,o,t,s)}else this.activeAudioClips.has(o)&&(this.activeAudioClips.delete(o),this.lastAudioStartAttemptTime.delete(o),this.audioStartInFlight.delete(o),this.stopAudioClip(o))}}tryStartAudioClip(e,t,a,s,i){if(this.audioStartInFlight.has(a))return;const r=this.lastAudioStartAttemptTime.get(a);if(void 0!==r&&s-r<this.audioStartRetryIntervalSeconds)return;this.lastAudioStartAttemptTime.set(a,s);const n=this.playAudioClip(e,t,a,s,i).catch(()=>{}).finally(()=>{this.audioStartInFlight.get(a)===n&&this.audioStartInFlight.delete(a)});this.audioStartInFlight.set(a,n)}applyAudioParameters(e,t,s,i,r,n){const o=n.volume??1,l=Math.random(),c=s.volumeRandomization?(2*l-1)*s.volumeRandomization:0;let h=1;const u=r-s.startTime;u<s.fadeInDuration&&s.fadeInDuration>0?h=u/s.fadeInDuration:u>s.duration-s.fadeOutDuration&&s.fadeOutDuration>0&&(h=(s.duration-u)/s.fadeOutDuration);const p=Math.max(0,(t.volume??1)*o*(s.volume+c)*h);e.setVolume(p);let d=n.detune??0;if(s.pitchRandomization){d+=(2*Math.random()-1)*s.pitchRandomization}if(e.setDetune(d),e.hasPlaybackControl&&e.setPlaybackRate(s.playbackRate*this.timescale),this.audioListener&&this.audioListener.context){const s=this.audioListener.context,r=[],o=n.lowpass,l=n.highpass;let c=this.audioFilters.get(i);if(void 0!==o||void 0!==l)c||(c=s.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 a.Audio&&void 0!==h&&"function"==typeof s.createStereoPanner){let e=this.audioPannerNodes.get(i);e||(e=s.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 a.PositionalAudio?this.updatePositionalAudioTransform(e,t,s,n.spatialBlend):void 0!==n.pan&&this.audioListener}updatePositionalAudioTransform(e,t,s,i){let r=null,n=null;const o=s.attachedToTrackId||t.parent?.trackId,l=s.attachmentSocketName||t.parent?.socketName;if(o){const e=this.sequenceData?.tracks.find(e=>e.id===o);if(e){const t=this.getActiveObjectsForTrack(e);if(t.length>0){const e=t[0];if(r=he,n=ye,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?a.MathUtils.clamp(i,0,1):1;if(t<1&&this.audioListener){const e=pe;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,s,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(s);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(s);const p=!0===e.spatial,d=u&&!0===u.isPositionalAudio;if(u&&p!==d&&(u.isPlaying&&u.stop(),u.disconnect(),this.audioByClip.delete(s),u=void 0),!u){if(p){const e=new a.PositionalAudio(this.audioListener);e.setRefDistance(10),e.setRolloffFactor(1),u=e}else u=new a.Audio(this.audioListener);this.world&&this.world.scene.add(u),this.audioByClip.set(s,u)}Math.min((t.duration-c)/t.playbackRate,(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,s,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 a=this.audioGainNodes.get(e);a&&(a.disconnect(),this.audioGainNodes.delete(e));const s=this.audioFilters.get(e);if(s){try{s.disconnect()}catch{}this.audioFilters.delete(e)}const 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 a=new Set,s=new Map;for(const i of e.clips){const r=this.getVfxClipKey(e,i);s.set(r,i),this.isVfxClipActiveAtTime(i,t)&&a.add(r)}const i=[];for(const t of this.activeVfxClips)t.startsWith(`${e.id}-`)&&(a.has(t)||i.push(t));for(const e of i)this.activeVfxClips.delete(e);for(const[i,r]of s.entries()){const s=this.vfxActors.get(i);a.has(i)&&!this.activeVfxClips.has(i)?(this.activeVfxClips.add(i),this.ensureVfxActor(e,r,i)):a.has(i)&&s?this.updateVfxTransform(e,s,t):s&&this.applyInactiveVfxClipBehavior(r,s,t)}}getVfxClipKey(e,t){return`${e.id}-${t.id}-${t.vfxAssetId}`}isVfxClipActiveAtTime(e,t){const a=e.startTime+e.duration;return t>=e.startTime&&t<a}shouldPreviewVfxAtSeekTime(){return this._externalTimeControl&&this._inEditor&&this._state.value!==SequencePlaybackState.Playing}previewVfxTrackAtSeekTime(e,t){const a=new Set;for(const s of e.clips){const i=this.getVfxClipKey(e,s),r=this.vfxActors.get(i);this.isVfxClipActiveAtTime(s,t)&&a.add(i),t<s.startTime?r?.clearPreview():r?this.previewVfxActorAtSeekTime(e,s,r,t):this.ensureVfxActor(e,s,i)}for(const t of[...this.activeVfxClips])t.startsWith(`${e.id}-`)&&!a.has(t)&&this.activeVfxClips.delete(t);for(const e of a)this.activeVfxClips.add(e)}previewVfxActorAtSeekTime(e,t,a,s){const i=t.startTime+t.duration;this.updateVfxTransform(e,a,Math.min(s,i)),a.previewAt(s-t.startTime,t.duration,t.endBehavior,t.expireWithinSeconds)}resetVfxForTimeReset(e){const t=new Set;if(this.sequenceData)for(const a of ne(this.sequenceData.tracks))if("vfx"===a.type)for(const s of a.clips??[])this.isVfxClipActiveAtTime(s,e)&&t.add(this.getVfxClipKey(a,s));this.activeVfxClips.clear();for(const[e,a]of this.vfxActors.entries())t.has(e)||(a.restart(),a.stop(),a.pause())}applyInactiveVfxClipBehavior(e,t,a){const s=e.endBehavior??"finish";if("finish"===s)return void t.stop();if("kill"===s)return void t.applyClipEndBehavior(s);const i=e.startTime+e.duration,r=Math.max(a-i,0),n=Math.max(0,e.expireWithinSeconds??.25),o=Math.max(0,n-r);t.applyClipEndBehavior(s,o)}async ensureVfxActor(e,t,a){if(!this.vfxService||!t.vfxAssetId)return;if(this.vfxActors.has(a)){const e=this.vfxActors.get(a);return e.restart(),void e.play()}const s=this.clearCounter;try{const i=this._inEditor&&this._externalTimeControl?{backend:"cpu"}:void 0,r=await this.vfxService.createFromAssetId(t.vfxAssetId,this.world.scene,i);if(s!==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(a,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 a=new c,s=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&&q(n.keyframes,l,c,h,a),e&&(e.rotation&&s.fromArray([...e.rotation,"XYZ"]),e.scale&&i.fromArray(e.scale)),r&&e!==r&&e.time!==r.time){const t=T(h,e.interpolation);if(e.rotation&&r.rotation){ye.setFromEuler(Ce.fromArray([...e.rotation,"XYZ"])),ve.setFromEuler(ge.fromArray([...r.rotation,"XYZ"]));const a=new o;a.slerpQuaternions(ye,ve,t),s.setFromQuaternion(a)}e.scale&&r.scale&&i.lerpVectors(he.fromArray(e.scale),ue.fromArray(r.scale),t)}}else a.fromArray(e.position),s.fromArray([...e.rotation,"XYZ"]),i.fromArray(e.scale);return{position:a,rotation:s,scale:i}}updateVfxTransform(e,t,a){const{position:s,rotation:i,scale:r}=this.getVfxTransform(e,a);t.object.position.copy(s),t.object.rotation.copy(i),t.object.scale.copy(r)}resolveActorType(e){const t=this.actorFactory.classes[e];if(null!=t)return t;const a=d[e];return a||(console.warn(`Could not resolve actor type: ${e}`),null)}async spawnActorForClip(e,t,a,s){if(!this.world||!e.actorType)return null;const i=this.resolveActorType(e.actorType);if(!i)return null;try{return await this.world.spawnActor(i,a,s)}catch(t){return console.error(`Failed to spawn actor ${e.actorType}:`,t),null}}async spawnPrefabForClip(e,t,a,s){if(!this.world||!this.assetLoader||!e.prefabId)return null;try{const t=await this.assetLoader.getPrefabById(e.prefabId);if(!t)return null;return await this.world.spawnPrefab(t,a,s)}catch(t){return console.error(`Failed to spawn prefab ${e.prefabId}:`,t),null}}async spawnMeshForClip(e,t,a,s){if(!this.world||!this.assetLoader||!e.meshId)return null;try{const t=await this.assetLoader.getAsset(e.meshId),i=await this.assetLoader.getModelByAssetId(e.meshId),r=R.clone(i.scene);if(r.position.copy(a),r.rotation.copy(s),t){await this.assetLoader.applyMaterials(t,r);const e=t.mesh?.rescale;null!=e&&1!==e&&r.scale.multiplyScalar(e)}return this.world.scene.add(r),r}catch(t){return console.error(`Failed to spawn mesh ${e.meshId}:`,t),null}}despawnInstance(e){if(this.restorePropertySnapshotsForInstance(e),this.restoreMaterialSnapshotsForInstance(e),this.world)switch(e?.type){case"actor":this.world.removeActor(e.instance);break;case"prefab":this.world.removePrefab(e.instance);break;case"mesh":this.world.scene.remove(e.instance)}}despawnAll(){for(const e of this.spawnedInstances.values())this.despawnInstance(e);this.spawnedInstances.clear(),this.activeClips.clear(),this.pendingSpawns.clear()}getInitialTransform(e,t,a){const s=new c,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,a);n.components.position&&q(n.keyframes,t,r,o,s),e&&e.rotation&&i.fromArray([...e.rotation,"XYZ"])}else t.initialPosition&&s.fromArray(t.initialPosition),t.initialRotation&&i.fromArray([...t.initialRotation,"XYZ"]);return{position:s,rotation:i}}evaluateSpawnTrack(e,t,a){if(!e.clips||0===e.clips.length)return;const s=t||this.bindings.get(e.id);if(s&&s.target)for(const t of e.clips){const i=t.startTime+t.duration,r=a>=t.startTime&&a<i,n=`${e.id}-${t.id}`;if(r){this.activeClips.has(n)||(this.activeClips.add(n),this.spawnedInstances.set(n,{type:"proxy",target:s.target}));(s.target instanceof p?s.target.object:s.target)&&this.evaluateSubTracks(e.subTracks,s,a)}else if(this.activeClips.has(n)){e.clips.some(e=>e!==t&&a>=e.startTime&&a<e.startTime+e.duration)||this.deactivateAnimationSubTracks(e.subTracks,s),this.clearExternalRootMotionPreview(s),this.restorePropertySnapshotsForTarget(s.target),this.restoreMaterialSnapshotsForTarget(s.target),this.activeClips.delete(n),this.spawnedInstances.delete(n)}}else for(const t of e.clips){const s=t.startTime+t.duration,i=a>=t.startTime&&a<s,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,a)}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:a,rotation:s}=this.getInitialTransform(e,t,t.startTime);this.pendingSpawns.add(r),this.spawnForClip(e,t,a,s,r)}}}getInstanceObject(e){switch(e.type){case"actor":return e.instance.object;case"prefab":return e.instance.mainActor?.object||e.instance.object;case"mesh":return e.instance;case"proxy":return e.target instanceof p?e.target.object:e.target;default:return null}}async spawnForClip(e,t,a,i,r){const n=this.clearCounter;let o=null;try{switch(e.spawnType){case"actor":const s=await this.spawnActorForClip(e,t,a,i);s&&(o={type:"actor",instance:s});break;case"prefab":const r=await this.spawnPrefabForClip(e,t,a,i);r&&(o={type:"prefab",instance:r});break;case"mesh":const n=await this.spawnMeshForClip(e,t,a,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 s(t),o.activeActions=new Map),this.spawnedInstances.set(r,o),this.activeClips.add(r)}else o&&this.despawnInstance(o)}finally{this.pendingSpawns.delete(r)}}getPlayableObject(e){return e.target instanceof p?e.target.object:e.target??null}applyResolvedPropertyValue(e,t,a){if(!t||!e.propertyPath)return;const s=this.getPropertyResolution(t,e);if(!s)return;const i=this.getPropertySnapshotKey(e);this.capturePropertySnapshot(t,i,s);const n=function(e,t){switch(t.type){case y.Number:return"number"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.Boolean:return"boolean"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.String:return"string"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.Vector2:return H(e,t.value);case y.Vector3:return J(e,t.value);case y.Vector4:return ee(e,t.value);case y.Euler:return function(e,t){const a=ae(t,3);if(!a)return{applied:!1};const s=Array.isArray(t)&&"string"==typeof t[3]?t[3]:"XYZ";if(e instanceof r)return e.set(a[0],a[1],a[2],s),{applied:!0,value:e};return{applied:!0,value:new r(a[0],a[1],a[2],s)}}(e,t.value);case y.Color:return te(e,t.value);default:return{applied:!1}}}(s.owner[s.key],a);n.applied&&(s.owner[s.key]=n.value)}getPropertyResolution(e,t){const a=e,s=this.getPropertySnapshotKey(t);let i=this.propertyResolutionCache.get(a);if(i||(i=new Map,this.propertyResolutionCache.set(a,i)),i.has(s))return i.get(s)??null;const r=this.getPropertyPathSegments(t.propertyPath);if(0===r.length)return i.set(s,null),null;let n=e;for(let e=0;e<r.length-1;e++){if(!z(n))return i.set(s,null),null;n=n[r[e]]}if(!z(n))return i.set(s,null),null;const o={owner:n,key:r[r.length-1]};return i.set(s,o),o}getPropertyPathSegments(e){const t=this.propertyPathSegments.get(e);if(t)return t;const a=e.split(".").map(e=>e.trim()).filter(Boolean);return this.propertyPathSegments.set(e,a),a}getPropertySnapshotKey(e){return`${e.id}:${e.propertyPath}`}capturePropertySnapshot(e,t,a){const s=e;let i=this.propertySnapshots.get(s);if(i||(i=new Map,this.propertySnapshots.set(s,i)),i.has(t))return;const r=a.owner[a.key];i.set(t,{resolution:a,hadOwnProperty:Object.prototype.hasOwnProperty.call(a.owner,a.key),value:r,valueSnapshot:ie(r)})}restorePropertySnapshotsForInstance(e){switch(e.type){case"actor":case"mesh":this.restorePropertySnapshotsForTarget(e.instance);break;case"prefab":this.restorePropertySnapshotsForTarget(e.target??null),this.restorePropertySnapshotsForTarget(e.instance.mainActor??null),this.restorePropertySnapshotsForTarget(e.instance.object);break;case"proxy":this.restorePropertySnapshotsForTarget(e.target)}}restorePropertySnapshotsForTarget(e){if(!e)return;const t=e,a=this.propertySnapshots.get(t);if(a){for(const e of a.values())re(e);this.propertySnapshots.delete(t),this.propertyResolutionCache.delete(t)}}restoreAllPropertySnapshots(){for(const e of Array.from(this.propertySnapshots.keys()))this.restorePropertySnapshotsForTarget(e)}restoreMaterialSnapshotsForInstance(e){switch(e.type){case"actor":case"mesh":this.restoreMaterialSnapshotsForTarget(e.instance);break;case"prefab":this.restoreMaterialSnapshotsForTarget(e.target??null),this.restoreMaterialSnapshotsForTarget(e.instance.mainActor??null),this.restoreMaterialSnapshotsForTarget(e.instance.object);break;case"proxy":this.restoreMaterialSnapshotsForTarget(e.target)}}restoreMaterialSnapshotsForTarget(e){if(!e)return;const t=e;this.materialResolutionCache.delete(t);const a=this.materialSnapshots.get(t);if(a){for(const e of a.values())null==e.materialIndex?e.owner.material=e.originalMaterial:Array.isArray(e.owner.material)&&(e.owner.material[e.materialIndex]=e.originalMaterial),e.controlledMaterial!==e.originalMaterial&&e.controlledMaterial.dispose();this.materialSnapshots.delete(t)}}restoreAllMaterialSnapshots(){for(const e of Array.from(this.materialSnapshots.keys()))this.restoreMaterialSnapshotsForTarget(e)}applyResolvedMaterialValue(e,t,a){if(!t)return;if("asset"===S(e)&&!e.materialAssetId)return;if("outlineVisibility"===w(e))return void this.applyResolvedMaterialOutlineVisibility(e,t,a);if(!e.uniformName)return;const s=this.getMaterialSlotResolutions(t,e);for(const i of s){const s=this.ensureSequenceControlledMaterial(t,i),r=s.uniforms?.[e.uniformName];if(!r)continue;const n=Y(r.value,a);n.applied&&(r.value=n.value,s.uniformsNeedUpdate=!0,D(s))}}applyResolvedMaterialOutlineVisibility(e,t,a){if(a.type!==y.Boolean||"boolean"!=typeof a.value)return;const s=this.getMaterialSlotResolutions(t,e);for(const e of s){const s=this.ensureSequenceControlledMaterial(t,e),i=s.userData?.outlineParameters;null!=i&&(i.visible=a.value)}}getMaterialSlotResolutions(e,t){const a=e,s=S(t),i=w(t),r=`${t.id}:${i}:${s}:${t.materialAssetId??""}:${t.uniformName}`;let n=this.materialResolutionCache.get(a);n||(n=new Map,this.materialResolutionCache.set(a,n));const o=n.get(r);if(o)return o;const l=e instanceof p?e.object:e,c=[];return l.traverse(e=>{const a=e.material;if(Array.isArray(a))for(let s=0;s<a.length;s++){const i=a[s];Z(i,t)&&c.push({owner:e,materialIndex:s,material:i,key:`${e.uuid}:${s}`})}else Z(a,t)&&c.push({owner:e,materialIndex:null,material:a,key:`${e.uuid}:material`})}),n.set(r,c),c}ensureSequenceControlledMaterial(e,t){const a=e;let s=this.materialSnapshots.get(a);s||(s=new Map,this.materialSnapshots.set(a,s));const i=s.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),s.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 a=this.animationClipCacheKey(e,t),s=this.animationClips.get(a);if(s)return s;const i=this.loadingAnimationClips.get(a);if(i)return i;const r=(async()=>{try{const s=await this.assetLoader.getAnimationClipForTargetByAssetId(e,t);return s&&this.animationClips.set(a,s),s}catch(a){return console.error(`Failed to load animation clip for asset ${e}`+(null==t?"":` and target rig ${t}`)+":",a),null}finally{this.loadingAnimationClips.get(a)===r&&this.loadingAnimationClips.delete(a)}})();return this.loadingAnimationClips.set(a,r),r}prepareAnimationPlayback(e,t,a){if(!j(a)){let e=t;return a.clipEndOffset>0&&(e=e.clone(),G(e,K(t)),e.duration=Math.max(0,e.duration-a.clipEndOffset)),a.rootMotion&&(e=O(e,a)),{clip:e,timeScale:a.playbackRate*this._timescale,startOffset:a.clipStartOffset}}return{clip:this.getPlayableAnimationClip(e,t,a,!1),timeScale:1*this._timescale,startOffset:0}}getPlayableAnimationClip(e,t,a,s){if(!j(a)){const e=a.rootMotion?O(t,a):t;return s?L.fromClip(e,!1):e}const i=`${a.id}:${s?"root":"base"}`,r=`${E(a)}|${s?"root":"base"}`,n=this.retimedAnimationClips.get(i);if(n&&n.assetId===e&&n.signature===r)return n.clip;const o=F(t,a),l=a.rootMotion?O(o,a):o,c=s?L.fromClip(l,!1):l;return this.retimedAnimationClips.set(i,{assetId:e,signature:r,clip:c}),c}getAnimationPlaybackLocalTime(e,t){const a=Math.max(0,t-e.startTime);return j(e)?a:a*e.playbackRate+e.clipStartOffset}clearRetimedAnimationClipCache(e){if(null!=e)for(const[t,a]of this.retimedAnimationClips.entries())a.assetId===e&&this.retimedAnimationClips.delete(t);else this.retimedAnimationClips.clear()}captureOriginalTransforms(){for(const e of this.bindings.values()){const t=e.target instanceof p?e.target.object:e.target;t&&(e.originalTransform={position:t.position.clone(),rotation:t.rotation.clone(),scale:t.scale.clone()})}}restoreOriginalTransforms(){for(const e of this.bindings.values())if(e.originalTransform){const t=e.target instanceof p?e.target.object:e.target;t&&(t.position.copy(e.originalTransform.position),t.rotation.copy(e.originalTransform.rotation),t.scale.copy(e.originalTransform.scale))}}stopAllAnimations(){for(const e of this.bindings.values()){for(const[t,a]of e.activeActions.entries())e.charAnimActionKeys?.has(t)||a.stop();e.activeActions.clear(),e.mixer&&e.mixer.stopAllAction(),e.charAnimComponent&&(e.charAnimComponent.stopSequenceAnimation(),e.charAnimComponent=void 0),e.charAnimActionKeys?.clear()}}stopAllVfx(){for(const e of this.vfxActors.values())e.paused||e.stop();this.activeVfxClips.clear()}dispose(){if(this.stop(),this.clearLocatorBindings(),this.clearSequenceCameras(),this.bindings.clear(),this.roleBindings.clear(),this.sequenceData=null,this.world)for(const e of this.vfxActors.values())this.world.removeActor(e);this.vfxActors.clear(),this.stopAllAudio(),this.audioBuffers.clear(),this.loadingAudioBuffers.clear(),this.animationClips.clear(),this.loadingAnimationClips.clear(),this.clearRetimedAnimationClipCache(),this.audioByClip.clear()}updateTrackParenting(e,t){const a=this.getActiveObjectsForTrack(e);if(0===a.length)return;const s="spawn"===e.type&&null!=t?.target;let i=null;const r=e.parent?.trackId;if(r){const t=this.sequenceData?ne(this.sequenceData.tracks).find(e=>e.id===r):void 0;if(t){const a=this.getActiveObjectsForTrack(t);if(a.length>0&&(i=a[0],e.parent?.socketName)){const t=this.findSocket(i,e.parent.socketName);t&&(i=t)}}}if(!i&&"camera"===e.type&&e.parentRole&&this.roleBindings.has(e.parentRole)){const t=this.roleBindings.get(e.parentRole);if(i=t instanceof p?t.object:t,e.parentRoleSocketName){const t=this.findSocket(i,e.parentRoleSocketName);t&&(i=t)}}for(const r of a)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&&!s&&this.world?.scene.add(r)}findSocket(e,t){if(e.name===t)return e;if(e instanceof a.SkinnedMesh){const a=e.skeleton.bones.find(e=>e.name===t);if(a)return a}return e.getObjectByName(t)||null}getActiveObjectsForTrack(e){if("object"===e.type){const t=this.bindings.get(e.id);if(t&&t.target)return[t.target instanceof p?t.target.object:t.target]}else if("locator"===e.type){const t=this.bindings.get(e.id);if(t&&t.target instanceof n)return[t.target]}else{if("camera"===e.type)return[this.ensureSequenceCamera(e)];if("spawn"===e.type){const t=[];for(const[a,s]of this.spawnedInstances)if(a.startsWith(e.id+"-")&&this.activeClips.has(a)){const e=this.getInstanceObject(s);e&&t.push(e)}return t}if("vfx"===e.type){const t=[];for(const a of this.activeVfxClips)if(a.startsWith(e.id+"-")){const e=this.vfxActors.get(a);e&&t.push(e.object)}return t}}return[]}restoreObjectParent(e,t){e.originalParent?e.originalParent.add(t):this.world&&this.world.scene.add(t),e.currentParent=void 0}restoreOriginalParents(){for(const e of this.bindings.values())if(e.currentParent){const t=e.target instanceof p?e.target.object:e.target;t&&this.restoreObjectParent(e,t)}}evaluateAudioSubTracks(e,t){const a={};for(const s of e.subTracks)if("audioParameter"===s.type){const e=s,i=A(e.parameter),r=M(e.keyframes,t,{min:i.min,max:i.max});void 0!==r&&(a[e.parameter]=r)}return a}stringToRandom(e){let t=0;for(let a=0;a<e.length;a++){t=(t<<5)-t+e.charCodeAt(a),t&=t}const a=1e4*Math.sin(t);return a-Math.floor(a)}async refreshAsset(e){let t=!1;this.assetLoader?.clearCacheById(e),this.animationClips.delete(e),this.loadingAnimationClips.delete(e),this.clearRetimedAnimationClipCache(e),this.vfxService?.clearPool(e),t=this.refreshVfxActorsForAssetIds(new Set([e]))||t;for(const[a,s]of this.activePostProcessClips.entries())s.assetId===e&&(this.releasePostProcessClipEffect(a),t=!0);t=this.refreshSpawnedInstancesForClipKeys(this.getSpawnClipKeysForAsset(e))||t;const a=await this.getAssetOrNull(e);return"shaderGraph"===a?.type&&(t=await this.refreshShaderGraphDependentAssets(e)||t),t}refreshVfxActorsForAssetIds(e){let t=!1;for(const[a,s]of this.vfxActors.entries())this.vfxClipKeyUsesAnyAsset(a,e)&&(this.world&&this.world.removeActor(s),this.vfxActors.delete(a),this.activeVfxClips.delete(a),t=!0);return t}vfxClipKeyUsesAnyAsset(e,t){for(const a of t)if(e.endsWith(`-${a}`))return!0;return!1}refreshSpawnedInstancesForClipKeys(e){let t=!1;for(const[a,s]of this.spawnedInstances.entries())e.has(a)&&(this.despawnInstance(s),this.spawnedInstances.delete(a),this.activeClips.delete(a),t=!0);return t}getSpawnClipKeysForAsset(e){const t=new Set;if(!this.sequenceData)return t;for(const a of ne(this.sequenceData.tracks))if("spawn"===a.type&&(a.prefabId===e||a.meshId===e))for(const e of a.clips)t.add(`${a.id}-${e.id}`);return t}async refreshShaderGraphDependentAssets(e){const t=await this.findSequenceVfxAssetIdsUsingShaderGraph(e);for(const e of t)this.vfxService?.clearPool(e);const a=this.refreshVfxActorsForAssetIds(t),s=this.refreshSpawnedInstancesForClipKeys(await this.findSpawnClipKeysUsingShaderGraph(e));return a||s}async findSequenceVfxAssetIdsUsingShaderGraph(e){const t=new Set;if(!this.sequenceData)return t;const a=new Map;for(const s of ne(this.sequenceData.tracks))if("vfx"===s.type)for(const i of s.clips)null==i.vfxAssetId||t.has(i.vfxAssetId)||await this.assetUsesShaderGraph(i.vfxAssetId,e,a)&&t.add(i.vfxAssetId);return t}async findSpawnClipKeysUsingShaderGraph(e){const t=new Set;if(!this.sequenceData)return t;const a=new Map;for(const s of ne(this.sequenceData.tracks))if("spawn"===s.type&&await this.spawnTrackUsesShaderGraph(s,e,a))for(const e of s.clips)t.add(`${s.id}-${e.id}`);return t}async spawnTrackUsesShaderGraph(e,t,a){if(null!=e.meshId&&await this.assetUsesShaderGraph(e.meshId,t,a))return!0;if(null!=e.prefabId&&await this.assetUsesShaderGraph(e.prefabId,t,a))return!0;for(const s of e.subTracks??[])if("material"===s.type&&null!=s.materialAssetId&&await this.assetUsesShaderGraph(s.materialAssetId,t,a))return!0;return!1}assetUsesShaderGraph(e,t,a,s=new Set){if(e===t)return Promise.resolve(!0);if(s.has(e))return Promise.resolve(!1);if(a.has(e))return a.get(e);const i=this.assetUsesShaderGraphUncached(e,t,a,s);return a.set(e,i),i}async assetUsesShaderGraphUncached(e,t,a,s){if(s.has(e))return!1;const i=await this.getAssetOrNull(e);if(null==i)return!1;const r=new Set(s);return r.add(e),!!this.materialAssetUsesShaderGraph(i,t)||("mesh"===i.type?this.materialAssignmentsUseShaderGraph(i.materialAssignments,t,a,r):"prefab"===i.type?this.sceneObjectsUseShaderGraph(i.prefab?.objects,t,a,r):"vfx"===i.type&&this.vfxAssetUsesShaderGraph(i,t,a,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,a,s){for(const i of e??[])if(null!=i.materialId&&"null"!==i.materialId&&await this.assetUsesShaderGraph(i.materialId,t,a,s))return!0;return!1}async sceneObjectsUseShaderGraph(e,t,a,s){for(const i of e??[]){if(await this.materialAssignmentsUseShaderGraph(i.materialAssignments,t,a,s))return!0;if(null!=i.assetId&&("asset_mesh"===i.type||"prefab"===i.type||"vfx"===i.type)&&await this.assetUsesShaderGraph(i.assetId,t,a,s))return!0;if(await this.sceneObjectsUseShaderGraph(i.children,t,a,s))return!0}return!1}async vfxAssetUsesShaderGraph(e,t,a,s){for(const i of e.vfx?.emitters??[])if(await this.emitterUsesShaderGraph(i,t,a,s))return!0;return!1}async emitterUsesShaderGraph(e,t,a,s){if(await this.emitterOutputUsesShaderGraph(e.output,t,a,s))return!0;for(const i of e.children??[])if(await this.emitterUsesShaderGraph(i,t,a,s))return!0;return!1}async emitterOutputUsesShaderGraph(e,t,a,s){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,a,s))}async getAssetOrNull(e){if(!this.assetLoader)return null;try{return await this.assetLoader.getAsset(e)??null}catch{return null}}async invokeSequenceEvent(e,t,a,s){let i=!1;for(let e=0;e<s.length;e++)if(v(s[e])){i=!0;break}if(i)try{const t=new Array(s.length);for(let e=0;e<s.length;e++)t[e]=C(s[e],this.sequenceEventAsyncResolvers);const i=await Promise.all(t);await a.call(e,...i)}catch(e){console.error(`Failed to call sequence event ${t}:`,e)}else try{const t=new Array(s.length);for(let e=0;e<s.length;e++)t[e]=g(s[e],this.sequenceEventSyncResolvers);a.call(e,...t)}catch(e){console.error(`Failed to call sequence event ${t}:`,e)}}resolveSequenceEventActorReference(e){if(!this.world||null==e)return null;const t=e,a="object"==typeof t&&null!=t?.id?t.id:"string"==typeof t?t:null;if(null==a)return null;for(const e of this.world.actors){const t=e.object.userData.src??e.object.userData._src;if(t?.id===a)return e}return null}resolveSequenceEventSequence(e){return b(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 Q(e){return e.options?.length>0||e.propertyType===y.Boolean||e.propertyType===y.String}function X(e){return"outlineVisibility"===w(e)||e.valueType===y.Boolean||e.valueType===y.String}function z(e){return"object"==typeof e&&null!=e||"function"==typeof e}function Y(e,t){switch(t.type){case y.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 y.Boolean:return"boolean"==typeof t.value?{applied:!0,value:t.value}:{applied:!1};case y.Vector2:return H(e,t.value);case y.Vector3:return J(e,t.value);case y.Vector4:return ee(e,t.value);case y.Color:return function(e,t){if(e instanceof c){const a=Ae.set(0);return se(a,t)?(e.set(a.r,a.g,a.b),{applied:!0,value:e}):{applied:!1}}if(e instanceof h){const a=Ae.set(0);return se(a,t)?(e.set(a.r,a.g,a.b,e.w),{applied:!0,value:e}):{applied:!1}}return te(e,t)}(e,t.value);default:return{applied:!1}}}function Z(e,t){const s=S(t);return!!function(e){return e instanceof a.Material||!0===e?.isMaterial}(e)&&(("asset"!==s||e.userData?.assetId===t.materialAssetId)&&("outlineVisibility"===w(t)?null!=e.userData?.outlineParameters:null!=e.uniforms?.[t.uniformName]))}function H(e,t){const a=ae(t,2);return a?e instanceof l?(e.fromArray(a),{applied:!0,value:e}):{applied:!0,value:new l(a[0],a[1])}:{applied:!1}}function J(e,t){const a=ae(t,3);return a?e instanceof c?(e.fromArray(a),{applied:!0,value:e}):{applied:!0,value:new c(a[0],a[1],a[2])}:{applied:!1}}function ee(e,t){const a=ae(t,4);return a?e instanceof h?(e.fromArray(a),{applied:!0,value:e}):{applied:!0,value:new h(a[0],a[1],a[2],a[3])}:{applied:!1}}function te(e,t){if(e instanceof i)return se(e,t)?{applied:!0,value:e}:{applied:!1};const a=new i;return se(a,t)?{applied:!0,value:a}:{applied:!1}}function ae(e,t){if(!Array.isArray(e)||e.length<t)return null;const a=new Array(t);for(let s=0;s<t;s++){if("number"!=typeof e[s])return null;a[s]=e[s]}return a}function se(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 ie(e){if(e instanceof l||e instanceof c||e instanceof h||e instanceof i||e instanceof r)return e.clone()}function re(e){const{owner:t,key:a}=e.resolution;e.hadOwnProperty?(!function(e,t){if(e instanceof l&&t instanceof l)return e.copy(t),!0;if(e instanceof c&&t instanceof c)return e.copy(t),!0;if(e instanceof h&&t instanceof h)return e.copy(t),!0;if(e instanceof 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[a]=e.value):delete t[a]}function ne(e){const t=[];for(const a of e)t.push(a),"group"===a.type&&t.push(...ne(a.childTracks));return t}function oe(e){if("string"!=typeof e)return null;const t=e.trim();return t.length>0?t:null}function le(e){const t=new a.Group;t.name=`SequenceLocatorMarker:${e}`,t.renderOrder=1e3;const s=new a.AxesHelper(.35);s.renderOrder=1e3;const i=Array.isArray(s.material)?s.material:[s.material];for(const e of i)e.depthTest=!1,e.transparent=!0,e.opacity=.9,e.toneMapped=!1;t.add(s);const r=function(e){if("undefined"==typeof document)return null;const t=document.createElement("canvas");t.width=256,t.height=64;const s=t.getContext("2d");if(!s)return null;s.clearRect(0,0,t.width,t.height),s.fillStyle="rgba(16, 18, 24, 0.78)",function(e,t,a,s,i,r){const n=t+s,o=a+i;e.beginPath(),e.moveTo(t+r,a),e.lineTo(n-r,a),e.quadraticCurveTo(n,a,n,a+r),e.lineTo(n,o-r),e.quadraticCurveTo(n,o,n-r,o),e.lineTo(t+r,o),e.quadraticCurveTo(t,o,t,o-r),e.lineTo(t,a+r),e.quadraticCurveTo(t,a,t+r,a),e.closePath()}(s,0,8,t.width,48,8),s.fill(),s.font="24px sans-serif",s.textAlign="center",s.textBaseline="middle",s.fillStyle="#f8fafc",s.fillText(e||"Locator",t.width/2,t.height/2);const i=new a.CanvasTexture(t);i.needsUpdate=!0;const r=new a.SpriteMaterial({map:i,transparent:!0,depthTest:!1});r.toneMapped=!1;const n=new a.Sprite(r);return n.scale.set(.9,.225,1),n}(e);return r&&(r.position.set(0,.45,0),r.renderOrder=1001,t.add(r)),t.traverse(e=>{e.raycast=()=>{}}),t}function ce(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 he=new c,ue=new c,pe=new c,de=new c,fe=new c,me=new c,ye=new o,ve=new o,Ce=new r,ge=new r,Ae=new i;/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,57 @@
1
+ export type GpuParticleArenaHandle = Readonly<{
2
+ slot: number;
3
+ generation: number;
4
+ }>;
5
+ export type GpuParticleArenaAllocation = Readonly<{
6
+ handle: GpuParticleArenaHandle;
7
+ capacity: number;
8
+ pages: readonly number[];
9
+ }>;
10
+ export type GpuParticleArenaStats = Readonly<{
11
+ pageSize: number;
12
+ committedPages: number;
13
+ usedPages: number;
14
+ freePages: number;
15
+ committedCapacity: number;
16
+ usedCapacity: number;
17
+ allocationCount: number;
18
+ requestedCapacity: number;
19
+ internalFragmentation: number;
20
+ utilization: number;
21
+ highWatermarkPages: number;
22
+ highWatermarkCapacity: number;
23
+ }>;
24
+ /**
25
+ * CPU-side ownership metadata for the shared GPU particle arena.
26
+ *
27
+ * Pages are deliberately non-contiguous: growing an effect never relocates its
28
+ * existing particles, and releasing an effect immediately makes its pages
29
+ * reusable by another instance. GPU buffers can grow in page-sized increments
30
+ * while gameplay retains only a small generational handle.
31
+ */
32
+ export declare class GpuParticleArena {
33
+ readonly pageSize: number;
34
+ readonly maximumPages: number;
35
+ private committedPages;
36
+ private usedPages;
37
+ private allocationCount;
38
+ private requestedCapacity;
39
+ private highWatermarkPages;
40
+ private readonly freePages;
41
+ private readonly freeSlots;
42
+ private readonly slots;
43
+ constructor(options?: {
44
+ pageSize?: number;
45
+ maximumParticles?: number;
46
+ });
47
+ allocate(capacity: number): GpuParticleArenaAllocation | null;
48
+ resize(handle: GpuParticleArenaHandle, capacity: number): GpuParticleArenaAllocation | null;
49
+ get(handle: GpuParticleArenaHandle): GpuParticleArenaAllocation | null;
50
+ has(handle: GpuParticleArenaHandle): boolean;
51
+ release(handle: GpuParticleArenaHandle): boolean;
52
+ getStats(): GpuParticleArenaStats;
53
+ private resolveSlot;
54
+ private canAcquirePages;
55
+ private acquirePages;
56
+ }
57
+ //# sourceMappingURL=gpu-particle-arena.d.ts.map
@@ -0,0 +1,4 @@
1
+ export class GpuParticleArena{constructor(e={}){this.committedPages=0,this.usedPages=0,this.allocationCount=0,this.requestedCapacity=0,this.highWatermarkPages=0,this.freePages=[],this.freeSlots=[],this.slots=[],this.pageSize=t(e.pageSize??256,"pageSize");const s=t(e.maximumParticles??1048576,"maximumParticles");if(this.maximumPages=Math.floor(s/this.pageSize),0===this.maximumPages)throw new Error("maximumParticles must contain at least one arena page")}allocate(t){const a=s(t,"capacity"),i=Math.ceil(a/this.pageSize);if(!this.canAcquirePages(i))return null;const r=this.freeSlots.pop()??this.slots.length,h=this.slots[r]??{generation:1,requestedCapacity:0,pages:null},n=this.acquirePages(i);return h.requestedCapacity=a,h.pages=n,this.slots[r]=h,this.usedPages+=i,this.allocationCount+=1,this.requestedCapacity+=a,this.highWatermarkPages=Math.max(this.highWatermarkPages,this.usedPages),e(r,h)}resize(t,a){const i=s(a,"capacity"),r=this.resolveSlot(t);if(null==r)return null;const h=r.pages,n=Math.ceil(i/this.pageSize),g=n-h.length;if(g>0){if(!this.canAcquirePages(g))return null;h.push(...this.acquirePages(g)),this.usedPages+=g}else if(g<0){const e=h.splice(n);this.freePages.push(...e),this.usedPages-=e.length}return this.requestedCapacity+=i-r.requestedCapacity,r.requestedCapacity=i,this.highWatermarkPages=Math.max(this.highWatermarkPages,this.usedPages),e(t.slot,r)}get(t){const s=this.resolveSlot(t);return null==s?null:e(t.slot,s)}has(e){return null!=this.resolveSlot(e)}release(e){const t=this.resolveSlot(e);return null!=t&&(this.usedPages-=t.pages.length,this.requestedCapacity-=t.requestedCapacity,this.freePages.push(...t.pages),t.pages=null,t.requestedCapacity=0,t.generation=(s=t.generation)===Number.MAX_SAFE_INTEGER?1:s+1,this.freeSlots.push(e.slot),this.allocationCount-=1,!0);var s}getStats(){return{pageSize:this.pageSize,committedPages:this.committedPages,usedPages:this.usedPages,freePages:this.committedPages-this.usedPages,committedCapacity:this.committedPages*this.pageSize,usedCapacity:this.usedPages*this.pageSize,allocationCount:this.allocationCount,requestedCapacity:this.requestedCapacity,internalFragmentation:this.usedPages*this.pageSize-this.requestedCapacity,utilization:0===this.usedPages?1:this.requestedCapacity/(this.usedPages*this.pageSize),highWatermarkPages:this.highWatermarkPages,highWatermarkCapacity:this.highWatermarkPages*this.pageSize}}resolveSlot(e){const t=this.slots[e.slot];return null!=t?.pages&&t.generation===e.generation?t:null}canAcquirePages(e){const t=Math.max(0,e-this.freePages.length);return this.committedPages+t<=this.maximumPages}acquirePages(e){const t=new Array(e);for(let s=0;s<e;s++)t[s]=this.freePages.pop()??this.committedPages++;return t}}function e(e,t){return{handle:{slot:e,generation:t.generation},capacity:t.requestedCapacity,pages:t.pages.slice()}}function t(e,t){if(!Number.isSafeInteger(e)||e<=0)throw new Error(`${t} must be a positive integer`);return e}function s(e,t){if(!Number.isSafeInteger(e)||e<0)throw new Error(`${t} must be a non-negative integer`);return e}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,33 @@
1
+ import type * as THREE from 'three';
2
+ import type { NodeShaderMaterial } from 'three-shader-graph';
3
+ import type { VfxAsset } from '../../scene/model.js';
4
+ import type { DecalOutput, MeshOutput, ShapeOutput, SpriteOutput } from './vfx-asset.js';
5
+ import type { VfxAssetProvider } from './vfx-materializer.js';
6
+ import type { GpuSpriteRenderClassCache } from './gpu-sprite-compiler.js';
7
+ import { type GpuSpriteCompatibilityReport, type VfxBackendPreference } from './gpu-sprite-compiler.js';
8
+ import { GpuSpriteRuntime } from './gpu-sprite-runtime.js';
9
+ export type PrepareGpuSpriteBackendOptions = {
10
+ asset: VfxAsset;
11
+ instancePositions: readonly THREE.Vector3[];
12
+ assets: Pick<VfxAssetProvider, 'getTexture'> & Partial<Pick<VfxAssetProvider, 'getMesh'>>;
13
+ preference?: VfxBackendPreference;
14
+ cache?: GpuSpriteRenderClassCache;
15
+ resolveCustomMaterial?: (output: SpriteOutput | MeshOutput | DecalOutput | ShapeOutput) => Promise<NodeShaderMaterial | null>;
16
+ device?: GPUDevice;
17
+ instanceLayout?: 'emitter-major' | 'instance-major';
18
+ particlePageSize?: number;
19
+ physicalParticleCapacity?: number;
20
+ };
21
+ export type PreparedGpuSpriteBackend = {
22
+ backend: 'cpu' | 'gpu';
23
+ runtime: GpuSpriteRuntime | null;
24
+ compatibility: GpuSpriteCompatibilityReport;
25
+ reasons: string[];
26
+ };
27
+ /**
28
+ * Production-facing compatibility gate. A caller can create its existing CPU
29
+ * runtime when this returns `cpu`, while compatible effects receive a fully
30
+ * materialized GPU runtime.
31
+ */
32
+ export declare function prepareGpuSpriteBackend(options: PrepareGpuSpriteBackendOptions): Promise<PreparedGpuSpriteBackend>;
33
+ //# sourceMappingURL=gpu-sprite-backend.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{compileGpuSpriteEmitters as e,materializeGpuSpriteRenderClasses as t,selectVfxBackend as i}from"./gpu-sprite-compiler.js";import{GpuSpriteRuntime as a,getCompiledGpuSpriteMaterial as s}from"./gpu-sprite-runtime.js";export async function prepareGpuSpriteBackend(r){const l=e(r.asset,r.instancePositions,r.instanceLayout),n=i(l.compatibility,r.preference);if("cpu"===n.backend)return{backend:"cpu",runtime:null,compatibility:l.compatibility,reasons:n.reasons};try{const e=await t(l.renderClasses,r.assets,r.resolveCustomMaterial,r.cache);for(const t of e.renderClasses)null!=t.material&&s(t.material);if(null!=r.device){const t=Math.max(l.emitters.reduce((e,t)=>e+t.capacity,0),r.physicalParticleCapacity??0),i=16*Math.max(1,t)*4,a=4*Math.max(1,t*e.renderClasses.length),s=e.renderClasses.some(e=>null!=e.meshVertices)?12*Math.max(1,t)*4:0,n=l.emitters.some(e=>e.hasVortex)?4*Math.max(1,t)*4:0,c=l.emitters.some(e=>e.hasDisperse)?4*Math.max(1,t)*4:0,o=r.device.limits.maxStorageBufferBindingSize,m=[i>o?`particle storage requires ${i} bytes`:null,a>o?`alive-index storage requires ${a} bytes`:null,s>o?`mesh-transform storage requires ${s} bytes`:null,n>o?`vortex-state storage requires ${n} bytes`:null,c>o?`disperse-state storage requires ${c} bytes`:null].filter(e=>null!=e);if(m.length>0&&"gpu"!==r.preference)return{backend:"cpu",runtime:null,compatibility:l.compatibility,reasons:m.map(e=>`${e}, device limit is ${o} bytes`)}}return{backend:"gpu",runtime:new a(l.emitters,e.renderClasses,void 0,null==r.particlePageSize&&null==r.physicalParticleCapacity?void 0:{pageSize:r.particlePageSize,capacity:r.physicalParticleCapacity}),compatibility:l.compatibility,reasons:[...n.reasons,...e.unsupported]}}catch(e){const t=e instanceof Error?e.message:String(e);return{backend:"cpu",runtime:null,compatibility:{compatible:!1,issues:[...l.compatibility.issues,{severity:"error",code:"material-graph",emitter:"material",message:t}]},reasons:[`GPU material compilation failed: ${t}`]}}}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,58 @@
1
+ import * as THREE from 'three';
2
+ import { NodeShaderMaterial } from 'three-shader-graph';
3
+ import { type VfxAsset } from '../../scene/model.js';
4
+ import type { DecalOutput, MeshOutput, ShapeOutput, SpriteOutput, StretchedSpriteOutput, TrailOutput } from './vfx-asset.js';
5
+ import type { VfxAssetProvider } from './vfx-materializer.js';
6
+ import type { GpuSpriteEmitter, GpuSpriteRenderClass } from './gpu-sprite-runtime.js';
7
+ export type GpuSpriteRenderClassSource = {
8
+ /** Stable within one compile result; suitable for cache and profiling labels. */
9
+ key: string;
10
+ output: SpriteOutput | StretchedSpriteOutput | MeshOutput | DecalOutput | ShapeOutput | TrailOutput;
11
+ };
12
+ export declare class GpuSpriteRenderClassCache {
13
+ private readonly entries;
14
+ resolve(key: string, create: () => Promise<GpuSpriteRenderClass>): Promise<GpuSpriteRenderClass>;
15
+ clear(): void;
16
+ }
17
+ export type GpuSpriteCompileResult = {
18
+ emitters: GpuSpriteEmitter[];
19
+ inputBindings: GpuSpriteInputBinding[];
20
+ renderClasses: GpuSpriteRenderClassSource[];
21
+ compatibility: GpuSpriteCompatibilityReport;
22
+ /** @deprecated Use compatibility.issues for structured fallback decisions. */
23
+ unsupported: string[];
24
+ };
25
+ export type GpuSpriteCompatibilityIssue = {
26
+ severity: 'warning' | 'error';
27
+ code: string;
28
+ emitter: string;
29
+ message: string;
30
+ };
31
+ export type GpuSpriteCompatibilityReport = {
32
+ compatible: boolean;
33
+ issues: GpuSpriteCompatibilityIssue[];
34
+ };
35
+ export type VfxBackendPreference = 'auto' | 'cpu' | 'gpu';
36
+ export declare function hasGpuUnsupportedVfxInputBindings(asset: VfxAsset): boolean;
37
+ export type GpuSpriteInputBinding = Readonly<{
38
+ inputId: string;
39
+ emitterIndex: number;
40
+ target: string;
41
+ /** Authored scalar used to preserve downstream scale-over-life multipliers. */
42
+ authoredScalar?: number;
43
+ baseScaleStart?: readonly [number, number];
44
+ baseScaleEnd?: readonly [number, number];
45
+ }>;
46
+ export type VfxBackendSelection = {
47
+ backend: 'cpu' | 'gpu';
48
+ reasons: string[];
49
+ };
50
+ export declare function selectVfxBackend(compatibility: GpuSpriteCompatibilityReport, preference?: VfxBackendPreference): VfxBackendSelection;
51
+ /** Compiles the Phase-one compatible subset of authored VFX data. */
52
+ export declare function compileGpuSpriteEmitters(asset: VfxAsset, instancePositions: readonly THREE.Vector3[], layout?: 'emitter-major' | 'instance-major'): GpuSpriteCompileResult;
53
+ /** Resolves authored class textures and creates the default graph material once per class. */
54
+ export declare function materializeGpuSpriteRenderClasses(sources: readonly GpuSpriteRenderClassSource[], assets: Pick<VfxAssetProvider, 'getTexture'> & Partial<Pick<VfxAssetProvider, 'getMesh'>>, resolveCustomMaterial?: (output: SpriteOutput | StretchedSpriteOutput | MeshOutput | DecalOutput | ShapeOutput | TrailOutput) => Promise<NodeShaderMaterial | null>, cache?: GpuSpriteRenderClassCache): Promise<{
55
+ renderClasses: GpuSpriteRenderClass[];
56
+ unsupported: string[];
57
+ }>;
58
+ //# sourceMappingURL=gpu-sprite-compiler.d.ts.map
@@ -0,0 +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 o,NodeShaderMaterial as s,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}from"./vfx-asset.js";import{getDefaultVfxSpriteTexture as f}from"./vfx-default-sprite-texture.js";import{ShapeLibrary as b}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,o]of Object.entries(a.params)){if("vfxInput"!==o?.binding?.type)continue;const s=o.type===p.Number?"number":o.type===p.Vector3?"vec3":o.type===p.Color?"color":void 0;if(null==s||t.get(o.binding.inputId)!==s)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=>"error"===e.severity).map(e=>e.message);return a.length>0&&"gpu"!==t?{backend:"cpu",reasons:a}:a.length>0?{backend:"gpu",reasons:["GPU backend explicitly forced despite incompatibilities",...a]}:{backend:"gpu",reasons:e.issues.filter(e=>"warning"===e.severity).map(e=>e.message)}}export function compileGpuSpriteEmitters(t,a,r="emitter-major"){const o=[],s=[],n=new Map,i=[],l=[],c=new Map((t.vfx.inputs??[]).map(e=>[e.id,e.type]));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 u=t.vfx.emitters.slice().sort((e,t)=>(e.output.renderOrder??0)-(t.output.renderOrder??0)),m=(t,r,u)=>{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 w(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 d="trail"===(h=t.output).type?JSON.stringify(h):"mesh"===h.type?JSON.stringify({type:h.type,assetId:h.assetId,renderOrder:h.renderOrder??0,useLegacyTransform:!0===h.useLegacyTransform,materialSource:h.materialSource??null,material:h.material??null,shader:h.shader??null,shaderParams:h.shaderParams??null,shaderGraph:h.shaderGraph??null,shaderGraphParams:h.shaderGraphParams??null,space:h.space}):"decal"===h.type?JSON.stringify({type:h.type,colorMap:h.colorMap,alphaMap:h.alphaMap,color:h.color,unlit:h.unlit,intensity:h.intensity,opacityChannel:h.opacityChannel??"red",blendingMode:h.blendingMode,renderOrder:h.renderOrder??0,materialSource:h.materialSource??null,shaderGraph:h.shaderGraph??null,shaderGraphParams:h.shaderGraphParams??null,space:h.space}):"shape"===h.type?JSON.stringify({type:h.type,shape:h.shape,params:h.params,material:h.material,renderOrder:h.renderOrder??0,materialSource:h.materialSource??null,shader:h.shader??null,shaderGraph:h.shaderGraph??null,shaderGraphParams:h.shaderGraphParams??null,space:h.space}):JSON.stringify({type:h.type,texture:h.texture,opacityChannel:h.opacityChannel??"red",blendingMode:h.blendingMode,softness:h.softness,renderOrder:h.renderOrder??0,bloom:h.bloom,materialSource:h.materialSource??null,shader:h.shader??null,shaderGraph:h.shaderGraph??null,shaderGraphParams:h.shaderGraphParams??null,space:h.space,lockY:"sprite"===h.type&&!0===h.lockY,stretchScale:"stretchedSprite"===h.type?h.scale:null});var h;let y=n.get(d);null==y&&(y=s.length,n.set(d,y),s.push({key:d,output:t.output}));const f=[];for(let s=0;s<a.length;s++){const n=g(t,null==r?a[s]:new e.Vector3,y,i);if(null!=n){if(null!=r){const e=o[r]?.instances[s];if(null==e)continue;const a=n.capacity,l=e.capacity*a;if(l>25e4){w(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=u,!0!==n.localSpace&&!0!==e.localSpace||w(i,t,"error","child-emitter-local-space","GPU child emitters currently require world-space parent and child outputs"),"trail"===t.output.type&&w(i,t,"error","child-emitter-trail","GPU child emitters do not yet support trail output")}f.push(n)}}if(f.length>0){const e=o.length;o.push({instances:f,parentSource:r});for(const a of[...t.initializers,...t.behaviours])if(!1!==a.enabled)for(const[r,o]of Object.entries(a.params)){const s=o?.binding;if("vfxInput"!==s?.type)continue;const n=o.type===p.Number?"number":o.type===p.Vector3?"vec3":o.type===p.Color?"color":void 0;null!=n&&c.get(s.inputId)===n&&("lifetime"===a.type&&"duration"===r&&"continuous"===t.rate.type||l.push({inputId:s.inputId,emitterIndex:e,target:`${t.initializers.includes(a)?"initializer":"behaviour"}:${a.type}:${r}`,authoredScalar:"number"==typeof o.value?o.value:void 0,baseScaleStart:[...f[0].scaleStart],baseScaleEnd:[...f[0].scaleEnd]}))}for(const a of t.children??[])m(a,e,u+1)}};for(const e of u)m(e,null,0);const d="instance-major"===r?a.flatMap((e,t)=>o.flatMap(e=>null==e.instances[t]?[]:[e.instances[t]])):o.flatMap(e=>e.instances);for(let e=0;e<o.length;e++){const t=o[e];if(null!=t.parentSource)for(let e=0;e<t.instances.length;e++)t.instances[e].parentEmitter="instance-major"===r?e*o.length+t.parentSource:t.parentSource*a.length+e}const h=s.map((e,t)=>({renderClass:e,oldIndex:t})).sort((e,t)=>(e.renderClass.output.renderOrder??0)-(t.renderClass.output.renderOrder??0)),y=new Array(s.length);for(let e=0;e<h.length;e++)y[h[e].oldIndex]=e;for(const e of d)e.renderClass=y[e.renderClass??0]??0;const f={compatible:!i.some(e=>"error"===e.severity),issues:i};return{emitters:d,inputBindings:l,renderClasses:h.map(e=>e.renderClass),compatibility:f,unsupported:[...new Set(i.map(e=>`${e.emitter}: ${e.message}`))]}}export async function materializeGpuSpriteRenderClasses(p,g,w,x){const v=async p=>{const x=p.output;if("trail"===x.type){const t=x.materialSource??("asset"===x.shaderGraph?.source?"shaderGraph":"default"),a="default"===t?null:await(w?.(x))??null;if(null==a&&"default"!==t)throw new Error(`${t} trail material requires a compatible GPU material resolver`);return{texture:null!=x.texture?await g.getTexture(x.texture):f(),material:a??void 0,localSpace:"local"===x.space,trail:{historyLength:Math.max(2,Math.round(x.length)+1),width:x.width??1,taper:x.taper,colorStart:new e.Color(x.color).multiplyScalar(x.intensity),colorEnd:new e.Color(x.colorEnd).multiplyScalar(x.intensityEnd),opacityStart:x.opacityStart,opacityEnd:x.opacityEnd,scrollSpeed:x.scrollSpeed??0,opacityChannel:x.opacityChannel??"red",blendingMode:x.blendingMode??"normal",billboard:x.billboard??!1}}}if("mesh"===x.type){if(null==g.getMesh)throw new Error("GPU mesh particles require a mesh asset provider");const a=await g.getMesh(x.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 ${x.assetId} resolved to ${r.length}`);const o=null==r[0].geometry.index?r[0].geometry.clone():r[0].geometry.toNonIndexed();!0!==x.useLegacyTransform&&t(r[0],o);const n=o.getAttribute("position");if(null==n)throw new Error(`GPU mesh particle asset ${x.assetId} has no position attribute`);const i=o.getAttribute("normal"),l=o.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}o.dispose();const p=Array.isArray(r[0].material)?r[0].material[0]:r[0].material,m="material"===x.materialSource&&null==x.material||"shaderGraph"===x.materialSource&&("asset"!==x.shaderGraph?.source||null==x.shaderGraph.assetId)||"shader"===x.materialSource&&null==x.shader?"default":x.materialSource??("asset"===x.shaderGraph?.source?"shaderGraph":null!=x.shader?"shader":null!=x.material?"material":"default"),d="default"===m?await(w?.(x))??function(){const e=u.opacity;return new s({color:u.color.rgb.rgba(e),opacity:e,transparent:!0})}():await(w?.(x))??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:f(),meshVertices:c,meshColor:h,meshOpacity:p?.opacity??1,localSpace:"local"===x.space,material:d??void 0}}if("decal"===x.type){const t=await(w?.(x))??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"),o=a.getAttribute("normal"),s=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]=o.getX(e),n[t+4]=o.getY(e),n[t+5]=o.getZ(e),n[t+6]=s.getX(e),n[t+7]=s.getY(e)}return a.dispose(),{texture:f(),meshVertices:n,meshColor:new e.Color(16777215),meshOpacity:1,localSpace:"local"===x.space,material:t}}if("shape"===x.type){const t=b[x.shape];if(null==t)throw new Error(`GPU shape output has unknown shape ${x.shape}`);const a=x.materialSource??("asset"===x.shaderGraph?.source?"shaderGraph":null!=x.shader?"shader":null!=x.material?"material":"default"),r="default"===a?function(){const e=u.opacity;return new s({color:o({color:u.color.rgb}).rgb.rgba(e),opacity:e,transparent:!0})}():await(w?.(x))??null;if(null==r&&"default"!==a)throw new Error(`${a} shape material requires a compatible GPU material resolver`);const n=Object.fromEntries(Object.entries(x.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:f(),meshVertices:d,meshColor:new e.Color(16777215),meshOpacity:1,localSpace:"local"===x.space,material:r??void 0}}const v=null!=x.texture?await g.getTexture(x.texture):f(),S="stretchedSprite"===x.type?"default":x.materialSource??("asset"===x.shaderGraph?.source?"shaderGraph":"default");let M="default"===S?null:await(w?.(x))??null;if(null==M&&"default"!==S)throw new Error(`${S} material requires a compatible GPU material resolver`);return M??(M=function(t,o){const p=l(o),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 s({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}(x,v)),{texture:v,material:M,lockY:"sprite"===x.type&&!0===x.lockY,localSpace:"local"===x.space,stretchScale:"stretchedSprite"===x.type?0===x.scale?.001:x.scale:void 0}};return{renderClasses:await Promise.all(p.map(e=>x?.resolve(e.key,()=>v(e))??v(e))),unsupported:[]}}function g(t,a,r,o){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 s="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,f=1;const b=new e.Vector3;let g=0,k=0,G=!1,C=0,P=!1;const I=new e.Vector3;let V,O=0,E=!1,U=!1,A=0,R=0,N=0,z=!1,B=[1,1],$=1,T=1,Y=new e.Color("sprite"===t.output.type||"stretchedSprite"===t.output.type?t.output.color:"#ffffff"),j=Y.clone(),F=!1,X=1,Z=1,D=0,q=0;const L=new e.Quaternion,Q=new e.Vector3,J=new e.Vector3;let W=0;const H=new e.Vector3(0,1,0);let K=0,_=0,ee=!1;const te=new e.Vector3;let ae=0,re=0,oe=!1;const se=new e.Vector3(0,1,0);let ne=0;const ie=new e.Vector3,le=new e.Vector3,ce=new e.Vector3(0,1,0);let pe=0,ue=!1,me=0,de=0,he=0,ye=!1;const fe=new e.Vector4(0,0,0,0),be=new e.Vector3(1,1,1),ge=new e.Vector3(1,1,1),we=new e.Vector3(1,1,1);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=S(a.params.velocity);m.copy(e),d.copy(e);break}case"randomVelocity":m.copy(S(a.params.min)),d.copy(S(a.params.max));break;case"randomDirection":{const e=x(a.params.speed,1);m.setScalar(-e),d.setScalar(e);break}case"radialVelocity":H.copy(S(a.params.direction)).normalize(),K=x(a.params.speed,1),_=e.MathUtils.degToRad(x(a.params.spread,0)),ee=!0;break;case"mass":f=Math.max(1e-6,x(a.params.min,1));break;case"positionPoint":p.copy(new e.Vector4(...S(a.params.position).toArray(),0));break;case"positionSphere":{l=x(a.params.radius,1);const e=S(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=S(a.params.position),t=S(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=S(a.params.a),t=S(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=S(a.params.position),r=S(a.params.rotation).multiplyScalar(Math.PI/180);l=x(a.params.radius,1);const o="positionRing"===a.type?Math.max(x(a.params.thickness,.2),1e-4):0;c=4,p.set(t.x,t.y,t.z,o),u.set(r.x,r.y,r.z,e.MathUtils.degToRad(Math.max(0,Math.min(360,x(a.params.angle,360)))));break}case"scale":{const e=x(a.params.scale,1);B=[e,e];break}case"scaleComponents":be.copy(S(a.params.scale));break;case"randomScale":B=[x(a.params.min,1),x(a.params.max,1)];break;case"randomColor":Y=M(a.params.a,Y),j=M(a.params.b,Y),F=!0;break;case"rotation":{const t=S(a.params.rotation);D=q=e.MathUtils.degToRad(t.z),Q.set(e.MathUtils.degToRad(t.x),e.MathUtils.degToRad(t.y),e.MathUtils.degToRad(t.z)),L.setFromEuler(new e.Euler(Q.x,Q.y,Q.z));break}case"randomRotation":{if(s){const e=a.params.axis?.value;W="X"===e?2:"Y"===e?3:"Z"===e?4:1;break}const e=a.params.axis?.value;"XYZ"!==e&&"Z"!==e&&null!=e||(q=2*Math.PI);break}case"alignRotation":{if(!s)break;const e=a.params.axis?.value;"+X"===e?se.set(1,0,0):"-X"===e?se.set(-1,0,0):"-Y"===e?se.set(0,-1,0):"+Z"===e?se.set(0,0,1):"-Z"===e?se.set(0,0,-1):se.set(0,1,0);const t=a.params.mode?.value;ne="TowardsCenter"===t?2:"AlongVelocity"===t?3:1,ie.copy(S(a.params.center)),le.copy(S(a.params.offset)).multiplyScalar(Math.PI/180);break}default:w(o,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(S(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":b.copy(S(e.params.drift)),g=Math.max(0,x(e.params.delay,0)),k=v(e.params.ease?.value),G=!0;break;case"followParent":C=x(e.params.speed,0),P=!0;break;case"moveTo":I.copy(S(e.params.target)),O=v(e.params.ease?.value),E=!0;break;case"attraction":case"repulsion":if(oe){w(o,t,"error","multiple-attraction-behaviours","multiple attraction or repulsion behaviours are not supported in one GPU emitter");break}te.copy(S(e.params.target)),ae=x(e.params.force,1)*("repulsion"===e.type?-1:1),re=Math.max(0,x(e.params.radius,1)),oe=!0;break;case"vortex":if(ue){w(o,t,"error","multiple-vortex-behaviours","multiple vortex behaviours are not supported in one GPU emitter");break}ce.copy(S(e.params.axis)),pe=x(e.params.amount,1),ue=!0;break;case"disperse":{if(ye){w(o,t,"error","multiple-disperse-behaviours","multiple disperse behaviours are not supported in one GPU emitter");break}me=x(e.params.distance,1);const a=e.params.axis?.value;de="XY"===a?1:"XZ"===a?2:"YZ"===a?3:0,he=v(e.params.ease?.value),ye=!0;break}case"worldCollision":U=!0,A=Math.max(0,x(e.params.bounce,0)),R=Math.max(0,Math.min(1,x(e.params.friction,0))),N=Math.max(0,x(e.params.lifeLoss,0)),z=!0===e.params.debug?.value;break;case"scale":$=x(e.params.a,1),T=x(e.params.b,1),fe.x=v(e.params.ease?.value);break;case"scaleComponents":ge.copy(be).multiply(S(e.params.a)),we.copy(be).multiply(S(e.params.b)),fe.w=v(e.params.ease?.value);break;case"changeColor":Y=M(e.params.a,Y),j=M(e.params.b,j),fe.y=v(e.params.ease?.value),F=!1;break;case"changeOpacity":X=x(e.params.a,1),Z=x(e.params.b,0),fe.z=v(e.params.ease?.value);break;case"rotate":case"rotateAdd":{const t=S(e.params.rotation);t.multiplyScalar(Math.PI/180*Math.PI/180),s?J.add(t):V=(V??0)+t.z;break}default:w(o,t,"error",`behaviour:${e.type}`,`behaviour ${e.type} is not supported on GPU`)}const xe=Math.max(0,Math.floor(t.rate.count)),ve="sprite"!==t.output.type&&"stretchedSprite"!==t.output.type||!Number.isFinite(t.output.intensity)?1:t.output.intensity;Y.multiplyScalar(ve),j.multiplyScalar(ve);const Se="once"===t.rate.type?xe:Math.max(xe,Math.ceil(n/Math.max(t.rate.time,1e-4))*xe),Me=Math.min(25e4,Se);return Me!==Se&&w(o,t,"warning","particle-capacity-clamped",`particle capacity ${Se} exceeds the current GPU per-emitter limit of ${Me}`),t.behaviours.some(e=>!1!==e.enabled&&"scaleComponents"===e.type)||(ge.copy(be),we.copy(be)),U&&"local"===t.output.space&&w(o,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:Me,rate:"once"===t.rate.type?{type:"once",count:xe,delay:Math.max(0,t.rate.delay??0)}:{type:"continuous",count:xe,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,velocityMin:m,velocityMax:d,force:h,damping:y,mass:f,randomDrift:b,randomDriftDelay:g,randomDriftEasing:k,hasRandomDrift:G,followParentSpeed:C,hasFollowParent:P,moveToTarget:I,moveToEasing:O,hasMoveTo:E,hasWorldCollision:U,collisionBounce:A,collisionFriction:R,collisionLifeLoss:N,collisionDebug:z,orientAlongVelocity:!1,scaleStart:[B[0]*$,B[1]*$],scaleEnd:[B[0]*T,B[1]*T],colorStart:Y,colorEnd:j,randomColor:F,alphaStart:X,alphaEnd:Z,rotationMin:D,rotationMax:q,spriteRotationStep:V,meshRotation:L,meshRotationEuler:Q,meshRotationStep:J,randomMeshRotationAxis:W,radialVelocityDirection:H,radialVelocitySpeed:K,radialVelocitySpread:_,hasRadialVelocity:ee,attractionTarget:te,attractionForce:ae,attractionRadius:re,hasAttraction:oe,alignRotationAxis:se,alignRotationMode:ne,alignRotationCenter:ie,alignRotationOffset:le,vortexAxis:ce,vortexAmount:pe,hasVortex:ue,disperseDistance:me,dispersePlane:de,disperseEasing:he,hasDisperse:ye,curveEasing:fe,meshScaleStart:ge,meshScaleEnd:we,renderClass:r}}function w(e,t,a,r,o){e.some(e=>e.emitter===t.name&&e.code===r)||e.push({severity:a,code:r,emitter:t.name||t.id,message:o})}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 v(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 S(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 M(t,a){const r=t?.value;if("string"==typeof r){const t=/^#([A-Fa-f0-9]{6})$/.exec(r);if(null!=t){const a=Number.parseInt(t[1],16);return(new e.Color).setRGB((a>>16&255)/255,(a>>8&255)/255,(255&a)/255)}const a=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(r);if(null!=a)return(new e.Color).setRGB(Math.min(255,Number.parseInt(a[1],10))/255,Math.min(255,Number.parseInt(a[2],10))/255,Math.min(255,Number.parseInt(a[3],10))/255)}if("number"==typeof r&&Number.isFinite(r)){const t=Math.floor(r);return(new e.Color).setRGB((t>>16&255)/255,(t>>8&255)/255,(255&t)/255)}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
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,10 @@
1
+ import type { FrameGraphBuilder, RendererCustomPassContext } from '@hology/webgpu-renderer';
2
+ export interface GpuSpriteRenderGraphRuntime {
3
+ executeCompute(context: RendererCustomPassContext): void;
4
+ executeRender(context: RendererCustomPassContext, colorTarget?: string): void;
5
+ getSceneTextureReads?(): readonly string[];
6
+ getComputeTextureReads?(): readonly string[];
7
+ }
8
+ /** Adds one shared simulation pass and one shared draw pass for a VFX runtime. */
9
+ export declare function addGpuSpriteRenderGraphPasses(graph: FrameGraphBuilder, runtime: GpuSpriteRenderGraphRuntime, color: string, name?: string): void;
10
+ //# sourceMappingURL=gpu-sprite-render-graph.d.ts.map
@@ -0,0 +1,4 @@
1
+ export function addGpuSpriteRenderGraphPasses(e,t,n,p="GpuSprite"){const s=`${p}Simulation`,u=t.getSceneTextureReads?.()??[],a=t.getComputeTextureReads?.()??[];e.addPass({name:s,inputs:Object.fromEntries(a.map(e=>[e,e])),execute:e=>t.executeCompute(e)}),e.addPass({name:`${p}Render`,inputs:{color:n,depth:e.mainDepth,...Object.fromEntries(u.map(e=>[e,e]))},outputs:n,dependsOn:[s],execute:e=>t.executeRender(e,n)})}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */