Ok clips updated to include objects Tracks

This commit is contained in:
Michael Chung committed 2024-03-23 22:33:25 -04:00
1 parent 1bbf97667a
commit 0067acea6e
3 files changed
+107 -67

No files matched your search

@@ -1,6 +1,7 @@
export interface AnimationTrackClip {
version: number
media_id: number
object_uuid: number
type: "animation"
location: "glb" | "remote"
speed: number
@@ -11,6 +12,7 @@ export interface AnimationTrackClip {
export class AnimationTrackClip implements AnimationTrackClip {
version: number
media_id: number // comes from the server
object_uuid: number
type: "animation"
location: "glb" | "remote"
speed: number
@@ -21,6 +23,7 @@ export class AnimationTrackClip implements AnimationTrackClip {
version: number,
media_id: number,
location: "glb" | "remote",
object_uuid: number,
speed: number,
length: number,
clip_name: string,
@@ -28,6 +31,7 @@ export class AnimationTrackClip implements AnimationTrackClip {
this.version = version
this.media_id = media_id
this.type = "animation"
this.object_uuid = object_uuid
this.location = location
this.speed = speed
this.length = length
@@ -38,6 +42,7 @@ export class AnimationTrackClip implements AnimationTrackClip {
return JSON.stringify({
version: this.version,
media_id: this.media_id,
object_uuid: this.object_uuid,
type: this.type,
speed: this.speed,
length: this.length,
@@ -1,34 +1,46 @@
export interface ClipOffset {
version: number;
type: "transform" | "audio" | "animation";
media_id: number;
start_offset: number; // in milliseconds (ms)
version: number
type: "transform" | "audio" | "animation"
media_id: number
object_uuid: number
start_offset: number // in frames so 60 frames per second on the timeline.
ending_offset: number // ending offset
}
// Clip offsets represent the state of the clip on the timeline as well as what type of clip it is.
// it is created from a media id.
export class ClipOffset implements ClipOffset {
version: number;
type: "transform" | "audio" | "animation";
media_id: number;
start_offset: number; // in milliseconds (ms)
version: number
type: "transform" | "audio" | "animation"
media_id: number
object_uuid: number
start_offset: number // in frames
ending_offset: number // in frames
constructor(
version: number,
type: "transform" | "audio" | "animation",
media_id: number,
object_uuid: number,
start_offset: number,
ending_offset: number,
) {
this.version = version;
this.type = type;
this.media_id = media_id;
this.start_offset = start_offset;
this.version = version
this.type = type
this.object_uuid = object_uuid
this.media_id = media_id
this.start_offset = start_offset
this.ending_offset = ending_offset
}
toJSON(): string {
return JSON.stringify({
version: this.version,
object_uuid: this.object_uuid,
type: this.type,
media_id: this.media_id,
start_offset: this.start_offset,
});
ending_offset: this.ending_offset
})
}
}
+77 -54
View File
@@ -1,5 +1,6 @@
import { AnyJson } from "three/examples/jsm/nodes/core/constants.js"
import { ClipOffset } from "../datastructures/clips/clip_offset"
import AudioEngine from "./audio_engine"
// Every object uuid / entity has a track.
export class TimelineCurrentReactState {
@@ -22,34 +23,44 @@ export class TimeLine {
isPlaying: boolean
timelineState: TimelineCurrentReactState
audioEngine: AudioEngine
// animation engine
// lip sync engine
// transform engine
constructor() {
constructor(audioEngine:AudioEngine) {
this.timelineItems = []
// this.timerID = null
this.timeLineLimit = 1000 * 10 // 10 seconds
this.runningClips = []
this.isPlaying = false
this.scrubberPosition = 0 // in ms into the tl
this.timelineState = new TimelineCurrentReactState()
}
async createClipOffset(clip: ClipOffset): Promise<void> {
// this will be used to play the audio clips
this.audioEngine = audioEngine
}
async addPlayableClip(clip: ClipOffset): Promise<void> {
this.timelineItems.push(clip)
}
// when given a media id item it will create the clip.
// Then the clip will be loaded by the engines, if they come from outside of the loaded scene.
async createClipOffset(media_id: string,type: string): Promise<void> {
// use engine to load based off media id and type animation | transform |
}
// this will update the state of the clips based off uuid easing?
async updateClip(clip_uuid: string, updates: AnyJson): Promise<void> {
}
async deleteClip(clip_uuid: string): Promise<void> {
}
// this will update the state of the clips based off uuid easing?
async modifyClip(clip_uuid: string, updates: AnyJson): Promise<void> {
}
// Events that will trigger from react
async clipDidEnterDropZone() {
}
@@ -59,15 +70,16 @@ export class TimeLine {
}
// timeline controls this.
async scrubberDidStart(offset_in_ms:number) {
async scrubberDidStart(offset_frame:number) {
}
async scrub(offset_in_ms:number): Promise<void> {
async scrub(offset_frame:number): Promise<void> {
// only stream through to the position and rotation keyframes
// debounce not really
}
async scrubberDidStop(offset_in_ms:number) {
async scrubberDidStop(offset_frame:number) {
}
// public streaming events into the timeline from
@@ -106,7 +118,9 @@ export class TimeLine {
// called by the editor update loop on each frame
async update() {
if (this.isPlaying == false) return; // start and stop
//2. allow stopping.
//3. smallest unit is a frame and it is set by the scene and is in fps, our videos will be 60fps but we can reprocess them using the pipeline.
for (const element of this.timelineItems) {
if (element.start_offset >= this.scrubberPosition) {
// run async
@@ -121,10 +135,13 @@ export class TimeLine {
else if (element.type == "animation") {
} else {
throw "Error New Type"
this.stop()
throw "Error New Type of element in the timeline"
}
this.timelineItems = this.timelineItems.filter(item => item !== element)
}
// find the offset of the longest clip and play until that clip is done
if (this.scrubberPosition == this.timeLineLimit) { // stops at where clips should // cannot throw clip
this.stop()
}
@@ -140,80 +157,86 @@ export class TimeLine {
// How much timeline precision we have
const percision = 100 // using a fake update loop mock
class AudioEngineMock {
async play(media_id:string) {
console.log("Audio Playing {media_id}")
}
}
// Visual verification tests.
function CheckIfBasicAudioClipWorks() {
const api = new TimeLine()
api.addPlayableClip(new ClipOffset(1.0,'audio',1,0))
api.play()
const timeline = new TimeLine()
timeline.addPlayableClip(new ClipOffset(1.0,'audio',1,0))
timeline.play()
}
function CheckIfBasicTransformClipWorks() {
const api = new TimeLine()
api.addPlayableClip(new ClipOffset(1.0,'transform',2,0))
api.play()
const timeline = new TimeLine()
timeline.addPlayableClip(new ClipOffset(1.0,'transform',2,0))
timeline.play()
}
function CheckIfBasicClipWorks() {
const api = new TimeLine()
api.addPlayableClip(new ClipOffset(1.0,'animation',3,0))
api.play()
const timeline = new TimeLine()
timeline.addPlayableClip(new ClipOffset(1.0,'animation',3,0))
timeline.play()
}
// function CheckIfBasicClipWorks3SecondsAfterTimelineStops() {
// const api = new TimeLine()
// api.addPlayableClip(new ClipOffset("clip1", 0, 10000))
// api.play()
// const timeline = new TimeLine()
// timeline.addPlayableClip(new ClipOffset("clip1", 0, 10000))
// timeline.play()
// }
// function CheckIfTwoClipsAtTheSameTimeWorks() {
// const api = new TimeLine()
// api.addPlayableClip(new ClipOffset("clip1", 0, 1000))
// api.play()
// const timeline = new TimeLine()
// timeline.addPlayableClip(new ClipOffset("clip1", 0, 1000))
// timeline.play()
// }
// function CheckIfTwoClipsOneAfterAnotherWorks() {
// const api = new TimeLine()
// api.addPlayableClip(new ClipOffset("clip1", 0, 1000))
// api.addPlayableClip(new ClipOffset("clip2", 0, 2000))
// api.play()
// const timeline = new TimeLine()
// timeline.addPlayableClip(new ClipOffset("clip1", 0, 1000))
// timeline.addPlayableClip(new ClipOffset("clip2", 0, 2000))
// timeline.play()
// }
// function CheckIfTimeLineStopBeforeClipPlays() {
// const api = new TimeLine()
// api.addPlayableClip(new ClipOffset("clip3",0,1000))
// api.play()
// const timeline = new TimeLine()
// timeline.addPlayableClip(new ClipOffset("clip3",0,1000))
// timeline.play()
// setInterval(async ()=> {
// api.stop()
// timeline.stop()
// },1100)
// console.log("Stopped")
// }
// function CheckIfTimeLineStartAfterClipPlays() {
// const api = new TimeLine()
// api.addPlayableClip(new ClipOffset("clip3",0,1000))
// api.play()
// const timeline = new TimeLine()
// timeline.addPlayableClip(new ClipOffset("clip3",0,1000))
// timeline.play()
// setInterval(async ()=> {
// api.stop()
// timeline.stop()
// },500)
// console.log("Stopped")
// }
// function CheckIfClipsPlayAllTogetherConcurrently() {
// const api = new TimeLine()
// api.addPlayableClip(new ClipOffset("clip1",0,1000))
// api.addPlayableClip(new ClipOffset("clip2",0,1000))
// api.addPlayableClip(new ClipOffset("clip3",0,1000))
// api.addPlayableClip(new ClipOffset("clip4",0,1000))
// api.play()
// const timeline = new TimeLine()
// timeline.addPlayableClip(new ClipOffset("clip1",0,1000))
// timeline.addPlayableClip(new ClipOffset("clip2",0,1000))
// timeline.addPlayableClip(new ClipOffset("clip3",0,1000))
// timeline.addPlayableClip(new ClipOffset("clip4",0,1000))
// timeline.play()
// }
// function CheckIfClipsPlayAllTogether() {
// const api = new TimeLine()
// api.addPlayableClip(new TrackClip("clip1",0,1000))
// api.addPlayableClip(new TrackClip("clip2",0,1000))
// api.addPlayableClip(new TrackClip("clip3",0,1000))
// api.addPlayableClip(new TrackClip("clip4",0,1000))
// api.play()
// const timeline = new TimeLine()
// timeline.addPlayableClip(new TrackClip("clip1",0,1000))
// timeline.addPlayableClip(new TrackClip("clip2",0,1000))
// timeline.addPlayableClip(new TrackClip("clip3",0,1000))
// timeline.addPlayableClip(new TrackClip("clip4",0,1000))
// timeline.play()
// }
CheckIfBasicClipWorks()