@needle-tools/engine 5.1.0-alpha.4 → 5.1.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/components.needle.json +1 -1
- package/dist/{needle-engine.bundle-DQCuBTVp.umd.cjs → needle-engine.bundle-5avtTUMM.umd.cjs} +149 -148
- package/dist/{needle-engine.bundle-AjVIot3d.min.js → needle-engine.bundle-BHcw4C8f.min.js} +187 -186
- package/dist/{needle-engine.bundle-B7cqsI4c.js → needle-engine.bundle-C0gPOq4m.js} +7522 -7092
- package/dist/needle-engine.d.ts +715 -176
- package/dist/needle-engine.js +595 -593
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/three.js +1 -0
- package/dist/three.min.js +21 -21
- package/dist/three.umd.cjs +16 -16
- package/lib/engine/api.d.ts +3 -1
- package/lib/engine/api.js +3 -1
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/codegen/register_types.js +10 -10
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/engine_camera.fit.js +16 -4
- package/lib/engine/engine_camera.fit.js.map +1 -1
- package/lib/engine/engine_context.d.ts +20 -7
- package/lib/engine/engine_context.js +36 -14
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_context_eventbus.d.ts +47 -0
- package/lib/engine/engine_context_eventbus.js +47 -0
- package/lib/engine/engine_context_eventbus.js.map +1 -0
- package/lib/engine/engine_init.js +2 -2
- package/lib/engine/engine_init.js.map +1 -1
- package/lib/engine/engine_input.d.ts +23 -4
- package/lib/engine/engine_input.js +2 -1
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_license.d.ts +7 -7
- package/lib/engine/engine_license.js +185 -57
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_networking_blob.js +3 -3
- package/lib/engine/engine_networking_blob.js.map +1 -1
- package/lib/engine/engine_physics_rapier.d.ts +10 -0
- package/lib/engine/engine_physics_rapier.js +6 -0
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_types.d.ts +10 -0
- package/lib/engine/engine_utils_qrcode.js +2 -2
- package/lib/engine/engine_utils_qrcode.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.js +5 -5
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.js +2 -2
- package/lib/engine/webcomponents/needle-engine.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.loading.js +2 -2
- package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
- package/lib/engine/xr/TempXRContext.js +2 -2
- package/lib/engine/xr/TempXRContext.js.map +1 -1
- package/lib/engine-components/AnimationBuilder.d.ts +158 -0
- package/lib/engine-components/AnimationBuilder.js +305 -0
- package/lib/engine-components/AnimationBuilder.js.map +1 -0
- package/lib/engine-components/Animator.js +6 -1
- package/lib/engine-components/Animator.js.map +1 -1
- package/lib/engine-components/AnimatorController.builder.d.ts +101 -23
- package/lib/engine-components/AnimatorController.builder.js +88 -20
- package/lib/engine-components/AnimatorController.builder.js.map +1 -1
- package/lib/engine-components/AnimatorController.js +2 -0
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/ContactShadows.d.ts +1 -0
- package/lib/engine-components/ContactShadows.js +14 -1
- package/lib/engine-components/ContactShadows.js.map +1 -1
- package/lib/engine-components/DropListener.js +3 -0
- package/lib/engine-components/DropListener.js.map +1 -1
- package/lib/engine-components/OrbitControls.d.ts +0 -2
- package/lib/engine-components/OrbitControls.js +14 -1
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.js +3 -0
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/api.d.ts +1 -0
- package/lib/engine-components/api.js +1 -0
- package/lib/engine-components/api.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +6 -6
- package/lib/engine-components/codegen/components.js +6 -6
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/export/usdz/USDZExporter.js +4 -4
- package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
- package/lib/engine-components/timeline/PlayableDirector.d.ts +7 -7
- package/lib/engine-components/timeline/PlayableDirector.js +6 -6
- package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
- package/lib/engine-components/timeline/TimelineBuilder.d.ts +175 -9
- package/lib/engine-components/timeline/TimelineBuilder.js +108 -2
- package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -1
- package/lib/engine-components/timeline/TimelineTracks.d.ts +15 -7
- package/lib/engine-components/timeline/TimelineTracks.js +22 -14
- package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
- package/lib/engine-components/web/CursorFollow.d.ts +0 -1
- package/lib/engine-components/web/CursorFollow.js +0 -1
- package/lib/engine-components/web/CursorFollow.js.map +1 -1
- package/lib/engine-components/webxr/WebXRImageTracking.d.ts +62 -1
- package/lib/engine-components/webxr/WebXRImageTracking.js +55 -2
- package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
- package/package.json +1 -1
- package/plugins/common/cloud.js +6 -1
- package/plugins/common/license.js +26 -8
- package/plugins/vite/license.js +42 -7
- package/src/engine/api.ts +4 -1
- package/src/engine/codegen/register_types.ts +10 -10
- package/src/engine/engine_camera.fit.ts +15 -4
- package/src/engine/engine_context.ts +41 -16
- package/src/engine/engine_context_eventbus.ts +73 -0
- package/src/engine/engine_init.ts +2 -2
- package/src/engine/engine_input.ts +27 -6
- package/src/engine/engine_license.ts +201 -55
- package/src/engine/engine_networking_blob.ts +3 -3
- package/src/engine/engine_physics_rapier.ts +20 -6
- package/src/engine/engine_types.ts +22 -12
- package/src/engine/engine_utils_qrcode.ts +2 -2
- package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
- package/src/engine/webcomponents/needle menu/needle-menu.ts +5 -5
- package/src/engine/webcomponents/needle-engine.loading.ts +6 -6
- package/src/engine/webcomponents/needle-engine.ts +2 -2
- package/src/engine/xr/TempXRContext.ts +2 -2
- package/src/engine-components/AnimationBuilder.ts +472 -0
- package/src/engine-components/Animator.ts +6 -1
- package/src/engine-components/AnimatorController.builder.ts +163 -37
- package/src/engine-components/AnimatorController.ts +1 -0
- package/src/engine-components/ContactShadows.ts +15 -1
- package/src/engine-components/DropListener.ts +3 -0
- package/src/engine-components/OrbitControls.ts +16 -5
- package/src/engine-components/SceneSwitcher.ts +3 -0
- package/src/engine-components/api.ts +1 -0
- package/src/engine-components/codegen/components.ts +6 -6
- package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
- package/src/engine-components/timeline/PlayableDirector.ts +20 -20
- package/src/engine-components/timeline/TimelineBuilder.ts +277 -17
- package/src/engine-components/timeline/TimelineTracks.ts +24 -16
- package/src/engine-components/web/CursorFollow.ts +0 -1
- package/src/engine-components/webxr/WebXRImageTracking.ts +77 -7
- package/src/vite-env.d.ts +0 -16
|
@@ -44,7 +44,7 @@ export enum ClipExtrapolation {
|
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
/** @internal */
|
|
47
|
-
export type CreateTrackFunction = (director: PlayableDirector, track: Models.TrackModel) => Tracks.
|
|
47
|
+
export type CreateTrackFunction = (director: PlayableDirector, track: Models.TrackModel) => Tracks.TimelineTrackHandler | undefined | null;
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* PlayableDirector is the main component for controlling timelines in Needle Engine.
|
|
@@ -385,7 +385,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
385
385
|
/**
|
|
386
386
|
* @returns all audio tracks of the timeline
|
|
387
387
|
*/
|
|
388
|
-
get audioTracks(): Tracks.
|
|
388
|
+
get audioTracks(): Tracks.TimelineAudioTrack[] {
|
|
389
389
|
return this._audioTracks;
|
|
390
390
|
}
|
|
391
391
|
|
|
@@ -399,21 +399,21 @@ export class PlayableDirector extends Behaviour {
|
|
|
399
399
|
/**
|
|
400
400
|
* @returns all marker tracks of the timeline
|
|
401
401
|
*/
|
|
402
|
-
get markerTracks(): Tracks.
|
|
402
|
+
get markerTracks(): Tracks.TimelineMarkerTrack[] {
|
|
403
403
|
return this._markerTracks;
|
|
404
404
|
}
|
|
405
405
|
|
|
406
406
|
/**
|
|
407
407
|
* @returns all activation tracks of the timeline
|
|
408
408
|
*/
|
|
409
|
-
get activationTracks(): Tracks.
|
|
409
|
+
get activationTracks(): Tracks.TimelineActivationTrack[] {
|
|
410
410
|
return this._activationTracks;
|
|
411
411
|
}
|
|
412
412
|
|
|
413
413
|
/**
|
|
414
414
|
* @returns all tracks of the timeline
|
|
415
415
|
*/
|
|
416
|
-
get tracks(): ReadonlyArray<Tracks.
|
|
416
|
+
get tracks(): ReadonlyArray<Tracks.TimelineTrackHandler> {
|
|
417
417
|
return this._allTracks.flat();
|
|
418
418
|
}
|
|
419
419
|
|
|
@@ -452,16 +452,16 @@ export class PlayableDirector extends Behaviour {
|
|
|
452
452
|
private _time: number = 0;
|
|
453
453
|
private _duration: number = 0;
|
|
454
454
|
private _weight: number = 1;
|
|
455
|
-
private readonly _animationTracks: Array<Tracks.
|
|
456
|
-
private readonly _audioTracks: Array<Tracks.
|
|
455
|
+
private readonly _animationTracks: Array<Tracks.TimelineAnimationTrack> = [];
|
|
456
|
+
private readonly _audioTracks: Array<Tracks.TimelineAudioTrack> = [];
|
|
457
457
|
private readonly _signalTracks: Array<Tracks.SignalTrackHandler> = [];
|
|
458
|
-
private readonly _markerTracks: Array<Tracks.
|
|
459
|
-
private readonly _controlTracks: Array<Tracks.
|
|
460
|
-
private readonly _activationTracks: Array<Tracks.
|
|
461
|
-
private readonly _customTracks: Array<Tracks.
|
|
458
|
+
private readonly _markerTracks: Array<Tracks.TimelineMarkerTrack> = [];
|
|
459
|
+
private readonly _controlTracks: Array<Tracks.TimelineControlTrack> = [];
|
|
460
|
+
private readonly _activationTracks: Array<Tracks.TimelineActivationTrack> = [];
|
|
461
|
+
private readonly _customTracks: Array<Tracks.TimelineTrackHandler> = [];
|
|
462
462
|
|
|
463
|
-
private readonly _tracksArray: Array<Array<Tracks.
|
|
464
|
-
private get _allTracks(): Array<Array<Tracks.
|
|
463
|
+
private readonly _tracksArray: Array<Array<Tracks.TimelineTrackHandler>> = [];
|
|
464
|
+
private get _allTracks(): Array<Array<Tracks.TimelineTrackHandler>> {
|
|
465
465
|
this._tracksArray.length = 0;
|
|
466
466
|
this._tracksArray.push(this._animationTracks);
|
|
467
467
|
this._tracksArray.push(this._audioTracks);
|
|
@@ -535,7 +535,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
535
535
|
// When timeline reaches the end "stop()" is called which is evaluating with time 0
|
|
536
536
|
// We don't want to re-evaluate the animation then in case the timeline is blended with the Animator
|
|
537
537
|
// e.g then the timeline animation at time 0 is 100% applied on top of the animator animation
|
|
538
|
-
if (this._isStopping && handler instanceof Tracks.
|
|
538
|
+
if (this._isStopping && handler instanceof Tracks.TimelineAnimationTrack) {
|
|
539
539
|
continue;
|
|
540
540
|
}
|
|
541
541
|
handler.evaluate(time);
|
|
@@ -652,7 +652,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
652
652
|
const type = track.type;
|
|
653
653
|
const registered = PlayableDirector.createTrackFunctions[type];
|
|
654
654
|
if (registered !== null && registered !== undefined) {
|
|
655
|
-
const res = registered(this, track) as Tracks.
|
|
655
|
+
const res = registered(this, track) as Tracks.TimelineTrackHandler;
|
|
656
656
|
if (typeof res.evaluate === "function") {
|
|
657
657
|
res.director = this;
|
|
658
658
|
res.track = track;
|
|
@@ -675,7 +675,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
675
675
|
}
|
|
676
676
|
const animationClips = binding?.gameObject?.animations;
|
|
677
677
|
if (animationClips) {
|
|
678
|
-
const handler = new Tracks.
|
|
678
|
+
const handler = new Tracks.TimelineAnimationTrack();
|
|
679
679
|
handler.trackOffset = track.trackOffset;
|
|
680
680
|
handler.director = this;
|
|
681
681
|
handler.track = track;
|
|
@@ -725,7 +725,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
725
725
|
}
|
|
726
726
|
else if (track.type === Models.TrackType.Audio) {
|
|
727
727
|
if (!track.clips || track.clips.length <= 0) continue;
|
|
728
|
-
const audio = new Tracks.
|
|
728
|
+
const audio = new Tracks.TimelineAudioTrack();
|
|
729
729
|
audio.director = this;
|
|
730
730
|
audio.track = track;
|
|
731
731
|
audio.audioSource = track.outputs.find(o => o instanceof AudioSource) as AudioSource;
|
|
@@ -749,7 +749,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
749
749
|
signalHandler.director = this;
|
|
750
750
|
signalHandler.track = track;
|
|
751
751
|
|
|
752
|
-
const markerHandler: Tracks.
|
|
752
|
+
const markerHandler: Tracks.TimelineMarkerTrack = new Tracks.TimelineMarkerTrack();
|
|
753
753
|
markerHandler.director = this;
|
|
754
754
|
markerHandler.track = track;
|
|
755
755
|
|
|
@@ -795,7 +795,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
795
795
|
this._signalTracks.push(handler);
|
|
796
796
|
}
|
|
797
797
|
else if (track.type === Models.TrackType.Control) {
|
|
798
|
-
const handler = new Tracks.
|
|
798
|
+
const handler = new Tracks.TimelineControlTrack();
|
|
799
799
|
handler.director = this;
|
|
800
800
|
handler.track = track;
|
|
801
801
|
if (track.clips) {
|
|
@@ -807,7 +807,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
807
807
|
this._controlTracks.push(handler);
|
|
808
808
|
}
|
|
809
809
|
else if (track.type === Models.TrackType.Activation) {
|
|
810
|
-
const handler = new Tracks.
|
|
810
|
+
const handler = new Tracks.TimelineActivationTrack();
|
|
811
811
|
handler.director = this;
|
|
812
812
|
handler.track = track;
|
|
813
813
|
this._activationTracks.push(handler);
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { AnimationClip, Object3D } from "three";
|
|
2
|
+
import type { Light, Material, PerspectiveCamera } from "three";
|
|
2
3
|
|
|
3
4
|
import type { Animator } from "../Animator.js";
|
|
4
5
|
import type { AudioSource } from "../AudioSource.js";
|
|
5
6
|
import { GameObject } from "../Component.js";
|
|
6
7
|
import { InstantiateIdProvider } from "../../engine/engine_networking_instantiate.js";
|
|
7
8
|
import { EventList } from "../EventList.js";
|
|
9
|
+
import { isTrackDescriptor, resolveToClip, track as trackFn, type TrackDescriptor, type TrackOptions, type AnimationKeyframe, type Tween, type Vec3Value, type QuatValue, type EulerValue, type ColorValue } from "../AnimationBuilder.js";
|
|
10
|
+
|
|
11
|
+
/** Keyframe array or tween shorthand */
|
|
12
|
+
type KF<V> = AnimationKeyframe<V>[] | Tween<V>;
|
|
8
13
|
import { SignalAsset, SignalReceiver, SignalReceiverEvent } from "./SignalAsset.js";
|
|
9
14
|
import type { PlayableDirector } from "./PlayableDirector.js";
|
|
10
15
|
import { ClipExtrapolation, TrackType } from "./TimelineModels.js";
|
|
@@ -108,6 +113,7 @@ type BuilderTrack = {
|
|
|
108
113
|
volume?: number;
|
|
109
114
|
trackOffset?: TrackOffset;
|
|
110
115
|
cursor: number; // current time position for auto-advancing
|
|
116
|
+
inlineTracks: TrackDescriptor[]; // accumulated by .track() calls, committed at boundaries
|
|
111
117
|
};
|
|
112
118
|
|
|
113
119
|
type PendingSignal = {
|
|
@@ -116,6 +122,129 @@ type PendingSignal = {
|
|
|
116
122
|
callback: Function;
|
|
117
123
|
};
|
|
118
124
|
|
|
125
|
+
|
|
126
|
+
// ============================================================
|
|
127
|
+
// Track builder interfaces — typed views per track type
|
|
128
|
+
// ============================================================
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Shared methods available on all track builders and the TimelineBuilder entry point.
|
|
132
|
+
* Provides track creation, build, and install methods.
|
|
133
|
+
*
|
|
134
|
+
* @category Animation and Sequencing
|
|
135
|
+
*/
|
|
136
|
+
export interface TimelineBuilderBase {
|
|
137
|
+
/** Adds an animation track. Chain `.clip()` or `.track()` to add content. */
|
|
138
|
+
animationTrack(name: string, binding?: Animator | Object3D | null): AnimationTrackBuilder;
|
|
139
|
+
/** Adds an audio track. Chain `.clip()` to add audio clips. */
|
|
140
|
+
audioTrack(name: string, binding?: AudioSource | Object3D | null, volume?: number): AudioTrackBuilder;
|
|
141
|
+
/** Adds an activation track. Chain `.clip()` to define activation windows. */
|
|
142
|
+
activationTrack(name: string, binding?: Object3D | null): ActivationTrackBuilder;
|
|
143
|
+
/** Adds a control track. Chain `.clip()` to control nested objects/timelines. */
|
|
144
|
+
controlTrack(name: string): ControlTrackBuilder;
|
|
145
|
+
/** Adds a signal track. Chain `.signal()` or `.marker()` to add events. */
|
|
146
|
+
signalTrack(name: string, binding?: SignalReceiver | Object3D | null): SignalTrackBuilder;
|
|
147
|
+
/** Adds a marker track. Chain `.marker()` to add markers. */
|
|
148
|
+
markerTrack(name: string): MarkerTrackBuilder;
|
|
149
|
+
/** Builds and returns the {@link TimelineAssetModel}. */
|
|
150
|
+
build(): TimelineAssetModel;
|
|
151
|
+
/** Builds the timeline, assigns it to the director, and wires up signal callbacks. */
|
|
152
|
+
install(director: PlayableDirector): TimelineAssetModel;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Builder for animation tracks.
|
|
157
|
+
* Provides `.clip()` for pre-built AnimationClips and `.track()` for inline animation definition.
|
|
158
|
+
*
|
|
159
|
+
* @category Animation and Sequencing
|
|
160
|
+
*/
|
|
161
|
+
export interface AnimationTrackBuilder extends TimelineBuilderBase {
|
|
162
|
+
/** Adds a pre-built AnimationClip */
|
|
163
|
+
clip(asset: AnimationClip, options?: AnimationClipOptions): AnimationTrackBuilder;
|
|
164
|
+
/** Adds a clip from a single {@link TrackDescriptor} */
|
|
165
|
+
clip(descriptor: TrackDescriptor, options?: AnimationClipOptions): AnimationTrackBuilder;
|
|
166
|
+
/** Adds a clip from multiple {@link TrackDescriptor}s */
|
|
167
|
+
clip(descriptors: TrackDescriptor[], options?: AnimationClipOptions): AnimationTrackBuilder;
|
|
168
|
+
/** Adds an animation track for an Object3D's position or scale */
|
|
169
|
+
track(target: Object3D, property: "position" | "scale", keyframes: KF<Vec3Value>, options?: TrackOptions): AnimationTrackBuilder;
|
|
170
|
+
/** Adds an animation track for an Object3D's quaternion */
|
|
171
|
+
track(target: Object3D, property: "quaternion", keyframes: KF<QuatValue>, options?: TrackOptions): AnimationTrackBuilder;
|
|
172
|
+
/** Adds an animation track for an Object3D's rotation (Euler, converted to quaternion) */
|
|
173
|
+
track(target: Object3D, property: "rotation", keyframes: KF<EulerValue>, options?: TrackOptions): AnimationTrackBuilder;
|
|
174
|
+
/** Adds an animation track for an Object3D's visibility */
|
|
175
|
+
track(target: Object3D, property: "visible", keyframes: KF<boolean>, options?: TrackOptions): AnimationTrackBuilder;
|
|
176
|
+
/** Adds an animation track for a material's numeric property */
|
|
177
|
+
track(target: Material, property: "opacity" | "roughness" | "metalness" | "alphaTest" | "emissiveIntensity" | "envMapIntensity" | "bumpScale" | "displacementScale" | "displacementBias", keyframes: KF<number>, options?: TrackOptions): AnimationTrackBuilder;
|
|
178
|
+
/** Adds an animation track for a material's color property */
|
|
179
|
+
track(target: Material, property: "color" | "emissive", keyframes: KF<ColorValue>, options?: TrackOptions): AnimationTrackBuilder;
|
|
180
|
+
/** Adds an animation track for a light's numeric property */
|
|
181
|
+
track(target: Light, property: "intensity" | "distance" | "angle" | "penumbra" | "decay", keyframes: KF<number>, options?: TrackOptions): AnimationTrackBuilder;
|
|
182
|
+
/** Adds an animation track for a light's color */
|
|
183
|
+
track(target: Light, property: "color", keyframes: KF<ColorValue>, options?: TrackOptions): AnimationTrackBuilder;
|
|
184
|
+
/** Adds an animation track for a camera's numeric property */
|
|
185
|
+
track(target: PerspectiveCamera, property: "fov" | "near" | "far" | "zoom", keyframes: KF<number>, options?: TrackOptions): AnimationTrackBuilder;
|
|
186
|
+
/** Mutes this track so it is skipped during playback */
|
|
187
|
+
muted(muted?: boolean): AnimationTrackBuilder;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Builder for audio tracks. Provides `.clip()` for adding audio clips by URL.
|
|
192
|
+
* @category Animation and Sequencing
|
|
193
|
+
*/
|
|
194
|
+
export interface AudioTrackBuilder extends TimelineBuilderBase {
|
|
195
|
+
/** Adds an audio clip by URL */
|
|
196
|
+
clip(url: string, options: AudioClipOptions): AudioTrackBuilder;
|
|
197
|
+
/** Mutes this track so it is skipped during playback */
|
|
198
|
+
muted(muted?: boolean): AudioTrackBuilder;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Builder for activation tracks. Provides `.clip()` for defining activation windows.
|
|
203
|
+
* @category Animation and Sequencing
|
|
204
|
+
*/
|
|
205
|
+
export interface ActivationTrackBuilder extends TimelineBuilderBase {
|
|
206
|
+
/** Adds an activation clip that shows/hides the bound object */
|
|
207
|
+
clip(options: ActivationClipOptions): ActivationTrackBuilder;
|
|
208
|
+
/** Mutes this track so it is skipped during playback */
|
|
209
|
+
muted(muted?: boolean): ActivationTrackBuilder;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Builder for control tracks. Provides `.clip()` for controlling nested objects/timelines.
|
|
214
|
+
* @category Animation and Sequencing
|
|
215
|
+
*/
|
|
216
|
+
export interface ControlTrackBuilder extends TimelineBuilderBase {
|
|
217
|
+
/** Adds a control clip for a source object */
|
|
218
|
+
clip(sourceObject: Object3D, options: ControlClipOptions): ControlTrackBuilder;
|
|
219
|
+
/** Mutes this track so it is skipped during playback */
|
|
220
|
+
muted(muted?: boolean): ControlTrackBuilder;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Builder for signal tracks. Provides `.signal()` for callback-based signals and `.marker()` for asset-based markers.
|
|
225
|
+
* @category Animation and Sequencing
|
|
226
|
+
*/
|
|
227
|
+
export interface SignalTrackBuilder extends TimelineBuilderBase {
|
|
228
|
+
/** Adds a signal with a callback that fires at the given time */
|
|
229
|
+
signal(time: number, callback: Function, options?: SignalMarkerOptions): SignalTrackBuilder;
|
|
230
|
+
/** Adds a signal marker referencing a signal asset by guid */
|
|
231
|
+
marker(time: number, asset: string, options?: SignalMarkerOptions): SignalTrackBuilder;
|
|
232
|
+
/** Mutes this track so it is skipped during playback */
|
|
233
|
+
muted(muted?: boolean): SignalTrackBuilder;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Builder for marker tracks. Provides `.marker()` for adding markers.
|
|
238
|
+
* @category Animation and Sequencing
|
|
239
|
+
*/
|
|
240
|
+
export interface MarkerTrackBuilder extends TimelineBuilderBase {
|
|
241
|
+
/** Adds a marker referencing a signal asset by guid */
|
|
242
|
+
marker(time: number, asset: string, options?: SignalMarkerOptions): MarkerTrackBuilder;
|
|
243
|
+
/** Mutes this track so it is skipped during playback */
|
|
244
|
+
muted(muted?: boolean): MarkerTrackBuilder;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
|
|
119
248
|
/**
|
|
120
249
|
* A fluent builder for creating timeline assets ({@link TimelineAssetModel}) from code.
|
|
121
250
|
*
|
|
@@ -137,6 +266,19 @@ type PendingSignal = {
|
|
|
137
266
|
* director.play();
|
|
138
267
|
* ```
|
|
139
268
|
*
|
|
269
|
+
* @example With inline tracks (no pre-built clips needed)
|
|
270
|
+
* ```ts
|
|
271
|
+
* TimelineBuilder.create("DoorSequence")
|
|
272
|
+
* .animationTrack("Door", door)
|
|
273
|
+
* .track(door, "position", { from: [0, 0, 0], to: [2, 0, 0], duration: 1 })
|
|
274
|
+
* .track(light, "intensity", { from: 0, to: 5, duration: 1 })
|
|
275
|
+
* .signalTrack("Events")
|
|
276
|
+
* .signal(0.5, () => playSound("creak"))
|
|
277
|
+
* .install(director);
|
|
278
|
+
*
|
|
279
|
+
* director.play();
|
|
280
|
+
* ```
|
|
281
|
+
*
|
|
140
282
|
* @example Using install() with signal callbacks
|
|
141
283
|
* ```ts
|
|
142
284
|
* TimelineBuilder.create("WithSignals")
|
|
@@ -170,20 +312,37 @@ export class TimelineBuilder {
|
|
|
170
312
|
* @param name - Name for the timeline asset
|
|
171
313
|
* @param seed - Optional numeric seed for deterministic guid generation. Defaults to `Date.now()`.
|
|
172
314
|
*/
|
|
173
|
-
static create(name?: string, seed?: number):
|
|
315
|
+
static create(name?: string, seed?: number): TimelineBuilderBase {
|
|
174
316
|
return new TimelineBuilder(name ?? "Timeline", seed);
|
|
175
317
|
}
|
|
176
318
|
|
|
177
319
|
// #region Track creation
|
|
178
320
|
|
|
179
321
|
/**
|
|
180
|
-
* Adds an animation track.
|
|
322
|
+
* Adds an animation track. Chain `.clip()` calls to add pre-built clips,
|
|
323
|
+
* or chain `.track()` calls to define animation data inline:
|
|
324
|
+
*
|
|
325
|
+
* @example With pre-built AnimationClip
|
|
326
|
+
* ```ts
|
|
327
|
+
* .animationTrack("Character", animator)
|
|
328
|
+
* .clip(walkClip, { duration: 2, easeIn: 0.3 })
|
|
329
|
+
* .clip(runClip, { duration: 3 })
|
|
330
|
+
* ```
|
|
331
|
+
*
|
|
332
|
+
* @example With inline tracks
|
|
333
|
+
* ```ts
|
|
334
|
+
* .animationTrack("Door", door)
|
|
335
|
+
* .track(door, "position", { from: [0, 0, 0], to: [2, 0, 0], duration: 1 })
|
|
336
|
+
* .track(light, "intensity", { from: 0, to: 5, duration: 1 })
|
|
337
|
+
* ```
|
|
338
|
+
*
|
|
181
339
|
* @param name - Display name for the track
|
|
182
340
|
* @param binding - The Animator or Object3D to animate
|
|
183
341
|
*/
|
|
184
|
-
animationTrack(name: string, binding?: Animator | Object3D | null):
|
|
342
|
+
animationTrack(name: string, binding?: Animator | Object3D | null): AnimationTrackBuilder {
|
|
343
|
+
this.commitInlineTracks();
|
|
185
344
|
this._currentTrack = this.pushTrack(name, TrackType.Animation, binding ?? null);
|
|
186
|
-
return this;
|
|
345
|
+
return this as unknown as AnimationTrackBuilder;
|
|
187
346
|
}
|
|
188
347
|
|
|
189
348
|
/**
|
|
@@ -192,10 +351,11 @@ export class TimelineBuilder {
|
|
|
192
351
|
* @param binding - The AudioSource to play audio on (optional)
|
|
193
352
|
* @param volume - Track volume multiplier (default: 1)
|
|
194
353
|
*/
|
|
195
|
-
audioTrack(name: string, binding?: AudioSource | Object3D | null, volume?: number):
|
|
354
|
+
audioTrack(name: string, binding?: AudioSource | Object3D | null, volume?: number): AudioTrackBuilder {
|
|
355
|
+
this.commitInlineTracks();
|
|
196
356
|
this._currentTrack = this.pushTrack(name, TrackType.Audio, binding ?? null);
|
|
197
357
|
this._currentTrack.volume = volume;
|
|
198
|
-
return this;
|
|
358
|
+
return this as unknown as AudioTrackBuilder;
|
|
199
359
|
}
|
|
200
360
|
|
|
201
361
|
/**
|
|
@@ -203,18 +363,20 @@ export class TimelineBuilder {
|
|
|
203
363
|
* @param name - Display name for the track
|
|
204
364
|
* @param binding - The Object3D to show/hide
|
|
205
365
|
*/
|
|
206
|
-
activationTrack(name: string, binding?: Object3D | null):
|
|
366
|
+
activationTrack(name: string, binding?: Object3D | null): ActivationTrackBuilder {
|
|
367
|
+
this.commitInlineTracks();
|
|
207
368
|
this._currentTrack = this.pushTrack(name, TrackType.Activation, binding ?? null);
|
|
208
|
-
return this;
|
|
369
|
+
return this as unknown as ActivationTrackBuilder;
|
|
209
370
|
}
|
|
210
371
|
|
|
211
372
|
/**
|
|
212
373
|
* Adds a control track. Subsequent `.clip()` calls control nested timelines or objects.
|
|
213
374
|
* @param name - Display name for the track
|
|
214
375
|
*/
|
|
215
|
-
controlTrack(name: string):
|
|
376
|
+
controlTrack(name: string): ControlTrackBuilder {
|
|
377
|
+
this.commitInlineTracks();
|
|
216
378
|
this._currentTrack = this.pushTrack(name, TrackType.Control, null);
|
|
217
|
-
return this;
|
|
379
|
+
return this as unknown as ControlTrackBuilder;
|
|
218
380
|
}
|
|
219
381
|
|
|
220
382
|
/**
|
|
@@ -222,18 +384,20 @@ export class TimelineBuilder {
|
|
|
222
384
|
* @param name - Display name for the track
|
|
223
385
|
* @param binding - The SignalReceiver component (optional — if using `.signal()` with callbacks, one is created automatically by {@link install})
|
|
224
386
|
*/
|
|
225
|
-
signalTrack(name: string, binding?: SignalReceiver | Object3D | null):
|
|
387
|
+
signalTrack(name: string, binding?: SignalReceiver | Object3D | null): SignalTrackBuilder {
|
|
388
|
+
this.commitInlineTracks();
|
|
226
389
|
this._currentTrack = this.pushTrack(name, TrackType.Signal, binding ?? null);
|
|
227
|
-
return this;
|
|
390
|
+
return this as unknown as SignalTrackBuilder;
|
|
228
391
|
}
|
|
229
392
|
|
|
230
393
|
/**
|
|
231
394
|
* Adds a marker track. Use `.marker()` to add markers.
|
|
232
395
|
* @param name - Display name for the track
|
|
233
396
|
*/
|
|
234
|
-
markerTrack(name: string):
|
|
397
|
+
markerTrack(name: string): MarkerTrackBuilder {
|
|
398
|
+
this.commitInlineTracks();
|
|
235
399
|
this._currentTrack = this.pushTrack(name, TrackType.Marker, null);
|
|
236
|
-
return this;
|
|
400
|
+
return this as unknown as MarkerTrackBuilder;
|
|
237
401
|
}
|
|
238
402
|
|
|
239
403
|
// #endregion
|
|
@@ -243,23 +407,40 @@ export class TimelineBuilder {
|
|
|
243
407
|
/**
|
|
244
408
|
* Adds a clip to the current track. The clip type must match the track type.
|
|
245
409
|
*
|
|
246
|
-
* - On an **animation track**: pass an `AnimationClip` and optional {@link AnimationClipOptions}
|
|
410
|
+
* - On an **animation track**: pass an `AnimationClip`, a {@link TrackDescriptor}, or a `TrackDescriptor[]` — and optional {@link AnimationClipOptions}
|
|
247
411
|
* - On an **audio track**: pass a clip URL (string) and {@link AudioClipOptions}
|
|
248
412
|
* - On an **activation track**: pass {@link ActivationClipOptions}
|
|
249
413
|
* - On a **control track**: pass an Object3D and {@link ControlClipOptions}
|
|
250
414
|
*/
|
|
251
415
|
clip(asset: AnimationClip, options?: AnimationClipOptions): this;
|
|
416
|
+
clip(descriptor: TrackDescriptor, options?: AnimationClipOptions): this;
|
|
417
|
+
clip(descriptors: TrackDescriptor[], options?: AnimationClipOptions): this;
|
|
252
418
|
clip(url: string, options: AudioClipOptions): this;
|
|
253
419
|
clip(options: ActivationClipOptions): this;
|
|
254
420
|
clip(sourceObject: Object3D, options: ControlClipOptions): this;
|
|
255
|
-
clip(assetOrOptions: AnimationClip | string | Object3D | ActivationClipOptions, options?: AnimationClipOptions | AudioClipOptions | ControlClipOptions): this {
|
|
421
|
+
clip(assetOrOptions: AnimationClip | TrackDescriptor | TrackDescriptor[] | string | Object3D | ActivationClipOptions, options?: AnimationClipOptions | AudioClipOptions | ControlClipOptions): this {
|
|
256
422
|
if (!this._currentTrack) throw new Error("TimelineBuilder: .clip() must be called after a track method (e.g. .animationTrack())");
|
|
423
|
+
this.commitInlineTracks();
|
|
257
424
|
|
|
258
425
|
const track = this._currentTrack;
|
|
259
426
|
|
|
260
427
|
switch (track.type) {
|
|
261
428
|
case TrackType.Animation: {
|
|
262
|
-
|
|
429
|
+
// Resolve TrackDescriptor(s) to AnimationClip if needed
|
|
430
|
+
let animClip: AnimationClip;
|
|
431
|
+
if (assetOrOptions instanceof AnimationClip) {
|
|
432
|
+
animClip = assetOrOptions;
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
const descriptors = Array.isArray(assetOrOptions) ? assetOrOptions : [assetOrOptions as TrackDescriptor];
|
|
436
|
+
// Use the track's binding as root for resolution
|
|
437
|
+
const binding = track.outputs[0];
|
|
438
|
+
const root = binding instanceof Object3D ? binding
|
|
439
|
+
: (binding != null && "gameObject" in binding) ? (binding as any).gameObject as Object3D
|
|
440
|
+
: undefined;
|
|
441
|
+
animClip = resolveToClip(descriptors, root);
|
|
442
|
+
}
|
|
443
|
+
|
|
263
444
|
const opts = (options ?? {}) as AnimationClipOptions;
|
|
264
445
|
const duration = opts.duration ?? animClip.duration;
|
|
265
446
|
const start = opts.start ?? track.cursor;
|
|
@@ -459,6 +640,47 @@ export class TimelineBuilder {
|
|
|
459
640
|
return this;
|
|
460
641
|
}
|
|
461
642
|
|
|
643
|
+
// --- Object3D ---
|
|
644
|
+
/** Adds an animation track descriptor for an Object3D's position or scale to the current animation track */
|
|
645
|
+
track(target: Object3D, property: "position" | "scale", keyframes: KF<Vec3Value>, options?: TrackOptions): this;
|
|
646
|
+
/** Adds an animation track descriptor for an Object3D's quaternion to the current animation track */
|
|
647
|
+
track(target: Object3D, property: "quaternion", keyframes: KF<QuatValue>, options?: TrackOptions): this;
|
|
648
|
+
/** Adds an animation track descriptor for an Object3D's rotation (Euler, converted to quaternion) to the current animation track */
|
|
649
|
+
track(target: Object3D, property: "rotation", keyframes: KF<EulerValue>, options?: TrackOptions): this;
|
|
650
|
+
/** Adds an animation track descriptor for an Object3D's visibility to the current animation track */
|
|
651
|
+
track(target: Object3D, property: "visible", keyframes: KF<boolean>, options?: TrackOptions): this;
|
|
652
|
+
// --- Material ---
|
|
653
|
+
/** Adds an animation track descriptor for a material's numeric property to the current animation track */
|
|
654
|
+
track(target: Material, property: "opacity" | "roughness" | "metalness" | "alphaTest" | "emissiveIntensity" | "envMapIntensity" | "bumpScale" | "displacementScale" | "displacementBias", keyframes: KF<number>, options?: TrackOptions): this;
|
|
655
|
+
/** Adds an animation track descriptor for a material's color property to the current animation track */
|
|
656
|
+
track(target: Material, property: "color" | "emissive", keyframes: KF<ColorValue>, options?: TrackOptions): this;
|
|
657
|
+
// --- Light ---
|
|
658
|
+
/** Adds an animation track descriptor for a light's numeric property to the current animation track */
|
|
659
|
+
track(target: Light, property: "intensity" | "distance" | "angle" | "penumbra" | "decay", keyframes: KF<number>, options?: TrackOptions): this;
|
|
660
|
+
/** Adds an animation track descriptor for a light's color to the current animation track */
|
|
661
|
+
track(target: Light, property: "color", keyframes: KF<ColorValue>, options?: TrackOptions): this;
|
|
662
|
+
// --- Camera ---
|
|
663
|
+
/** Adds an animation track descriptor for a camera's numeric property to the current animation track */
|
|
664
|
+
track(target: PerspectiveCamera, property: "fov" | "near" | "far" | "zoom", keyframes: KF<number>, options?: TrackOptions): this;
|
|
665
|
+
/**
|
|
666
|
+
* Adds an animation track descriptor to the current animation track.
|
|
667
|
+
* Multiple `.track()` calls accumulate into a single animation clip that is
|
|
668
|
+
* committed when the next `.clip()`, track method, or `.build()`/`.install()` is called.
|
|
669
|
+
*
|
|
670
|
+
* Must be called after `.animationTrack()`.
|
|
671
|
+
*
|
|
672
|
+
* @param target - The object whose type determines valid properties and value types
|
|
673
|
+
* @param property - The property to animate
|
|
674
|
+
* @param keyframes - Keyframe array or {@link Tween} shorthand
|
|
675
|
+
* @param options - Optional {@link TrackOptions} with a `root` for named targeting
|
|
676
|
+
*/
|
|
677
|
+
track(target: object, property: string, keyframes: KF<any>, options?: TrackOptions): this {
|
|
678
|
+
if (!this._currentTrack) throw new Error("TimelineBuilder: .track() must be called after .animationTrack()");
|
|
679
|
+
if (this._currentTrack.type !== TrackType.Animation) throw new Error("TimelineBuilder: .track() is only supported on animation tracks");
|
|
680
|
+
this._currentTrack.inlineTracks.push(trackFn(target as Object3D, property as "position", keyframes, options));
|
|
681
|
+
return this;
|
|
682
|
+
}
|
|
683
|
+
|
|
462
684
|
// #endregion
|
|
463
685
|
|
|
464
686
|
/**
|
|
@@ -469,6 +691,7 @@ export class TimelineBuilder {
|
|
|
469
691
|
* internally and also wires up the SignalReceiver on the director's GameObject.
|
|
470
692
|
*/
|
|
471
693
|
build(): TimelineAssetModel {
|
|
694
|
+
this.commitInlineTracks();
|
|
472
695
|
const tracks: TrackModel[] = this._tracks.map(t => {
|
|
473
696
|
const track: TrackModel = {
|
|
474
697
|
name: t.name,
|
|
@@ -555,10 +778,47 @@ export class TimelineBuilder {
|
|
|
555
778
|
clips: [],
|
|
556
779
|
markers: [],
|
|
557
780
|
cursor: 0,
|
|
781
|
+
inlineTracks: [],
|
|
558
782
|
};
|
|
559
783
|
this._tracks.push(track);
|
|
560
784
|
return track;
|
|
561
785
|
}
|
|
562
786
|
|
|
787
|
+
/** Commits any pending `.track()` descriptors on the current animation track into a clip */
|
|
788
|
+
private commitInlineTracks(): void {
|
|
789
|
+
if (!this._currentTrack || this._currentTrack.inlineTracks.length === 0) return;
|
|
790
|
+
|
|
791
|
+
const t = this._currentTrack;
|
|
792
|
+
const binding = t.outputs[0];
|
|
793
|
+
const root = binding instanceof Object3D ? binding
|
|
794
|
+
: (binding != null && "gameObject" in binding) ? (binding as any).gameObject as Object3D
|
|
795
|
+
: undefined;
|
|
796
|
+
const animClip = resolveToClip(t.inlineTracks, root);
|
|
797
|
+
|
|
798
|
+
const start = t.cursor;
|
|
799
|
+
const duration = animClip.duration;
|
|
800
|
+
|
|
801
|
+
const clipModel: ClipModel = {
|
|
802
|
+
start,
|
|
803
|
+
end: start + duration,
|
|
804
|
+
duration,
|
|
805
|
+
timeScale: 1,
|
|
806
|
+
clipIn: 0,
|
|
807
|
+
easeInDuration: 0,
|
|
808
|
+
easeOutDuration: 0,
|
|
809
|
+
preExtrapolationMode: ClipExtrapolation.None,
|
|
810
|
+
postExtrapolationMode: ClipExtrapolation.None,
|
|
811
|
+
asset: {
|
|
812
|
+
clip: animClip,
|
|
813
|
+
loop: false,
|
|
814
|
+
duration: animClip.duration,
|
|
815
|
+
removeStartOffset: false,
|
|
816
|
+
} satisfies AnimationClipModel,
|
|
817
|
+
};
|
|
818
|
+
t.clips.push(clipModel);
|
|
819
|
+
t.cursor = start + duration;
|
|
820
|
+
t.inlineTracks = [];
|
|
821
|
+
}
|
|
822
|
+
|
|
563
823
|
// #endregion
|
|
564
824
|
}
|