theatre-js / theatre

Motion design editor for the web
https://www.theatrejs.com
Apache License 2.0
10.86k stars 338 forks source link

How to get all keyframes #330

Open vimlesh1975 opened 1 year ago

vimlesh1975 commented 1 year ago

I need to have all keyframes and its value array to convert it to threejs standard AnimationClip. Please help.

AriaMinaei commented 1 year ago

It would be a hack but you can use studio.createContentOfSaveFile to get the underlying structure.

Out of curiosity, why do you need to convert the keyframes?

vimlesh1975 commented 1 year ago

Big thank you. 😊 It is working. I want to export it with gltf. Is there any other way I can do this without createcontestofsavefile method?

akre54 commented 1 year ago

I second this request - or a nice way to get the value at a given time, please!

akre54 commented 1 year ago

Here's a simple helper, with the typescript type spelled out (would be nice to include this instead of Record<string, unknown>).

function getKeyframes<T extends UnknownShorthandCompoundProps>(sheet: ISheetObject<T>, tracks: string[]) {
  const {projectId, sheetId, objectKey, sheetInstanceId} = sheet.address

  type TrackId = `["${keyof T extends string ? keyof T : never}"]`;
  type Keyframe = {value: number};
  type StudioSaveFile = {
    sheetsById: {
      [sId: typeof sheetId]: {
        sequence: {
          tracksByObject: {
            [oKey: typeof objectKey]: {
              trackData: {
                [propPath: typeof sheetInstanceId]: {
                  keyframes: Keyframe[]
                }
              },
              trackIdByPropPath: {
                [t in TrackId]: typeof sheetInstanceId
              },
            }
          }
        }
      }
    }
  };

  const json = studio.createContentOfSaveFile(projectId) as StudioSaveFile;

  const {trackData, trackIdByPropPath} = json.sheetsById[sheetId].sequence.tracksByObject[objectKey];

  return tracks.map(track =>
    trackData[trackIdByPropPath[`["${track}"]`]].keyframes.map(k => k.value);
  );
}

And then using it:

getKeyframes(positionSheet, ['x', 'y']);
akre54 commented 1 year ago

Looks like there's already a type for OnDiskState which does what my StudioSaveFile does. Awesome! I just opened a pull to fix the type.

Also the new createRafDriver helper looks great for my use case, but it would still be nice to be able to read values at a given timestamp without mutating the global clock, for things I want to do down the line. Any hope of supporting this?

clementroche commented 1 year ago

@akre54 something like val(prop, position) ?

akre54 commented 1 year ago

@clementroche yes correct.

My use case is that I want the first and last value of a track, but it would be nice to be able to pull arbitrary values too.

chrisgervang commented 1 year ago

@akre54 something like val(prop, position) ?

This would be very helpful for our use case where we're using objects in the timeline to generate geometry. Animating a point's position, but wanting to draw a trailing line for wherever it's been, for example.