From 545508987903be8c2f361bbee8b3beae683c73b5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 26 Oct 2023 23:23:48 -0400 Subject: a variety of fixes to the animation timeline to make it make some sense. lots still broken. --- src/client/views/animationtimeline/Timeline.tsx | 49 ++++++++++++++----------- 1 file changed, 27 insertions(+), 22 deletions(-) (limited to 'src/client/views/animationtimeline/Timeline.tsx') diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx index 7ca13756a..3675238fd 100644 --- a/src/client/views/animationtimeline/Timeline.tsx +++ b/src/client/views/animationtimeline/Timeline.tsx @@ -1,28 +1,28 @@ +import { IconLookup } from '@fortawesome/fontawesome-svg-core'; import { faBackward, faForward, faGripLines, faPauseCircle, faPlayCircle } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable, runInAction, trace } from 'mobx'; +import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../../fields/Doc'; -import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; -import { Utils, setupMoveUpEvents, emptyFunction, returnFalse } from '../../../Utils'; +import { BoolCast, NumCast, StrCast } from '../../../fields/Types'; +import { emptyFunction, setupMoveUpEvents, Utils } from '../../../Utils'; +import { DocumentType } from '../../documents/DocumentTypes'; +import clamp from '../../util/clamp'; import { FieldViewProps } from '../nodes/FieldView'; -import { KeyframeFunc } from './Keyframe'; +import { RegionHelpers } from './Region'; import './Timeline.scss'; import { TimelineOverview } from './TimelineOverview'; import { Track } from './Track'; -import clamp from '../../util/clamp'; -import { DocumentType } from '../../documents/DocumentTypes'; -import { IconLookup } from '@fortawesome/fontawesome-svg-core'; /** - * Timeline class controls most of timeline functions besides individual keyframe and track mechanism. Main functions are + * Timeline class controls most of timeline functions besides individual region and track mechanism. Main functions are * zooming, panning, currentBarX (scrubber movement). Most of the UI stuff is also handled here. You shouldn't really make * any logical changes here. Most work is needed on UI. * * The hierarchy works this way: * - * Timeline.tsx --> Track.tsx --> Keyframe.tsx + * Timeline.tsx --> Track.tsx --> Region.tsx | | | TimelineMenu.tsx (timeline's custom contextmenu) | @@ -58,7 +58,6 @@ export class Timeline extends React.Component { //boolean vars and instance vars @observable private _currentBarX: number = 0; @observable private _windSpeed: number = 1; - @observable private _isPlaying: boolean = false; //scrubber playing @observable private _totalLength: number = 0; @observable private _visibleLength: number = 0; @observable private _visibleStart: number = 0; @@ -69,6 +68,8 @@ export class Timeline extends React.Component { @observable private _playButton = faPlayCircle; @observable private _titleHeight = 0; + @observable public IsPlaying: boolean = false; //scrubber playing + /** * collection get method. Basically defines what defines collection's children. These will be tracked in the timeline. Do not edit. */ @@ -144,14 +145,17 @@ export class Timeline extends React.Component { @action play = () => { const playTimeline = () => { - if (this._isPlaying) { + if (this.IsPlaying) { this.changeCurrentBarX(this._currentBarX >= this._totalLength ? 0 : this._currentBarX + this._windSpeed); setTimeout(playTimeline, 15); } }; - this._isPlaying = !this._isPlaying; - this._playButton = this._isPlaying ? faPauseCircle : faPlayCircle; - this._isPlaying && playTimeline(); + Array.from(this.mapOfTracks.values()) + .filter(key => key) + .forEach(key => key!.saveKeyframe()); + this.IsPlaying = !this.IsPlaying; + this._playButton = this.IsPlaying ? faPauseCircle : faPlayCircle; + this.IsPlaying && playTimeline(); }; /** @@ -221,7 +225,7 @@ export class Timeline extends React.Component { if (this._visibleStart + this._visibleLength + 20 >= this._totalLength) { this._visibleStart -= e.movementX; this._totalLength -= e.movementX; - this._time -= KeyframeFunc.convertPixelTime(e.movementX, 'mili', 'time', this._tickSpacing, this._tickIncrement); + this._time -= RegionHelpers.convertPixelTime(e.movementX, 'mili', 'time', this._tickSpacing, this._tickIncrement); this.props.Document.AnimationLength = this._time; } return false; @@ -278,11 +282,11 @@ export class Timeline extends React.Component { e.preventDefault(); e.stopPropagation(); const offset = e.clientX - this._infoContainer.current!.getBoundingClientRect().left; - const prevTime = KeyframeFunc.convertPixelTime(this._visibleStart + offset, 'mili', 'time', this._tickSpacing, this._tickIncrement); - const prevCurrent = KeyframeFunc.convertPixelTime(this._currentBarX, 'mili', 'time', this._tickSpacing, this._tickIncrement); + const prevTime = RegionHelpers.convertPixelTime(this._visibleStart + offset, 'mili', 'time', this._tickSpacing, this._tickIncrement); + const prevCurrent = RegionHelpers.convertPixelTime(this._currentBarX, 'mili', 'time', this._tickSpacing, this._tickIncrement); this.zoom(e.deltaY < 0); - const currPixel = KeyframeFunc.convertPixelTime(prevTime, 'mili', 'pixel', this._tickSpacing, this._tickIncrement); - const currCurrent = KeyframeFunc.convertPixelTime(prevCurrent, 'mili', 'pixel', this._tickSpacing, this._tickIncrement); + const currPixel = RegionHelpers.convertPixelTime(prevTime, 'mili', 'pixel', this._tickSpacing, this._tickIncrement); + const currCurrent = RegionHelpers.convertPixelTime(prevCurrent, 'mili', 'pixel', this._tickSpacing, this._tickIncrement); this._infoContainer.current!.scrollLeft = currPixel - offset; this._visibleStart = currPixel - offset > 0 ? currPixel - offset : 0; this._visibleStart += this._visibleLength + this._visibleStart > this._totalLength ? this._totalLength - (this._visibleStart + this._visibleLength) : 0; @@ -478,7 +482,7 @@ export class Timeline extends React.Component { // @computed getCurrentTime = () => { - const current = KeyframeFunc.convertPixelTime(this._currentBarX, 'mili', 'time', this._tickSpacing, this._tickIncrement); + const current = RegionHelpers.convertPixelTime(this._currentBarX, 'mili', 'time', this._tickSpacing, this._tickIncrement); return this.toReadTime(current > this._time ? this._time : current); }; @@ -505,13 +509,13 @@ export class Timeline extends React.Component { @action toAuthoring = () => { this._time = Math.ceil((this.findLongestTime() ?? 1) / 100000) * 100000; - this._totalLength = KeyframeFunc.convertPixelTime(this._time, 'mili', 'pixel', this._tickSpacing, this._tickIncrement); + this._totalLength = RegionHelpers.convertPixelTime(this._time, 'mili', 'pixel', this._tickSpacing, this._tickIncrement); }; @action toPlay = () => { this._time = this.findLongestTime(); - this._totalLength = KeyframeFunc.convertPixelTime(this._time, 'mili', 'pixel', this._tickSpacing, this._tickIncrement); + this._totalLength = RegionHelpers.convertPixelTime(this._time, 'mili', 'pixel', this._tickSpacing, this._tickIncrement); }; /** @@ -535,6 +539,7 @@ export class Timeline extends React.Component { {this.children.map(doc => ( this.mapOfTracks.push(ref)} + timeline={this} animatedDoc={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} -- cgit v1.2.3-70-g09d2 From b2233984df663be6554c935fe9e40f4778237e67 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 27 Oct 2023 10:23:21 -0400 Subject: removed async nonsense from tracks and regions. added some comments. --- src/client/views/animationtimeline/Region.tsx | 4 +-- src/client/views/animationtimeline/Timeline.tsx | 9 ++++- src/client/views/animationtimeline/Track.tsx | 47 +++++++++++++------------ 3 files changed, 34 insertions(+), 26 deletions(-) (limited to 'src/client/views/animationtimeline/Timeline.tsx') diff --git a/src/client/views/animationtimeline/Region.tsx b/src/client/views/animationtimeline/Region.tsx index df00924c6..53c5c4718 100644 --- a/src/client/views/animationtimeline/Region.tsx +++ b/src/client/views/animationtimeline/Region.tsx @@ -313,7 +313,7 @@ export class Region extends React.Component { }; @action - createKeyframe = async (clientX: number) => { + createKeyframe = (clientX: number) => { this._mouseToggled = true; const bar = this._bar.current!; const offset = RegionHelpers.convertPixelTime(Math.round((clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), 'mili', 'time', this.props.tickSpacing, this.props.tickIncrement); @@ -327,7 +327,7 @@ export class Region extends React.Component { }; @action - moveKeyframe = async (e: React.MouseEvent, kf: Doc) => { + moveKeyframe = (e: React.MouseEvent, kf: Doc) => { e.preventDefault(); e.stopPropagation(); this.props.changeCurrentBarX(RegionHelpers.convertPixelTime(NumCast(kf.time!), 'mili', 'pixel', this.props.tickSpacing, this.props.tickIncrement)); diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx index 3675238fd..71517d4fe 100644 --- a/src/client/views/animationtimeline/Timeline.tsx +++ b/src/client/views/animationtimeline/Timeline.tsx @@ -22,13 +22,20 @@ import { Track } from './Track'; * * The hierarchy works this way: * - * Timeline.tsx --> Track.tsx --> Region.tsx + * Timeline.tsx --> Track.tsx --> Region.tsx | | | TimelineMenu.tsx (timeline's custom contextmenu) | | TimelineOverview.tsx (youtube like dragging thing is play mode, complex dragging thing in editing mode) + + Timeline (Track[]) + Track(Region[],animatedDoc) -> Region1(K[]) Region2 ... + F1 K1 K2...FL K1 K2 K... + K(x,y,_width,opacity) + ... + Track Most style changes are in SCSS file. If you have any questions, email me or text me. diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx index 2fd062a88..b90ff5eaf 100644 --- a/src/client/views/animationtimeline/Track.tsx +++ b/src/client/views/animationtimeline/Track.tsx @@ -44,18 +44,19 @@ export class Track extends React.Component { return NumCast(RegionHelpers.convertPixelTime(this.props.currentBarX, 'mili', 'time', this.props.tickSpacing, this.props.tickIncrement)); } - async componentDidMount() { - const regions = await DocListCastAsync(this.props.animatedDoc.regions); - if (!regions) this.props.animatedDoc.regions = new List(); //if there is no region, then create new doc to store stuff - //these two lines are exactly same from timeline.tsx - const relativeHeight = window.innerHeight / 20; - runInAction(() => (this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT)); //for responsiveness - this._timelineVisibleReaction = this.timelineVisibleReaction(); - this._currentBarXReaction = this.currentBarXReaction(); - if (DocListCast(this.props.animatedDoc.regions).length === 0) this.createRegion(this.time); - this.props.animatedDoc.hidden = false; - this.props.animatedDoc.opacity = 1; - // this.autoCreateKeyframe(); + componentDidMount() { + DocListCastAsync(this.props.animatedDoc.regions).then(regions => { + if (!regions) this.props.animatedDoc.regions = new List(); //if there is no region, then create new doc to store stuff + //these two lines are exactly same from timeline.tsx + const relativeHeight = window.innerHeight / 20; + runInAction(() => (this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT)); //for responsiveness + this._timelineVisibleReaction = this.timelineVisibleReaction(); + this._currentBarXReaction = this.currentBarXReaction(); + if (DocListCast(this.props.animatedDoc.regions).length === 0) this.createRegion(this.time); + this.props.animatedDoc.hidden = false; + this.props.animatedDoc.opacity = 1; + // this.autoCreateKeyframe(); + }); } /** @@ -86,7 +87,7 @@ export class Track extends React.Component { * */ @action - saveKeyframe = async () => { + saveKeyframe = () => { if (this.props.timeline.IsPlaying || !this.saveStateRegion || !this.saveStateKf) { this.saveStateKf = undefined; this.saveStateRegion = undefined; @@ -223,23 +224,23 @@ export class Track extends React.Component { * when scrubber position changes. Need to edit the logic */ @action - timeChange = async () => { + timeChange = () => { if (this.saveStateKf !== undefined || this._newKeyframe) { - await this.saveKeyframe(); + this.saveKeyframe(); } - const regiondata = await this.findRegion(Math.round(this.time)); //finds a region that the scrubber is on + const regiondata = this.findRegion(Math.round(this.time)); //finds a region that the scrubber is on if (regiondata) { - const leftkf: Doc | undefined = await RegionHelpers.calcMinLeft(regiondata, this.time); // lef keyframe, if it exists - const rightkf: Doc | undefined = await RegionHelpers.calcMinRight(regiondata, this.time); //right keyframe, if it exists - const currentkf: Doc | undefined = await this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe + const leftkf: Doc | undefined = RegionHelpers.calcMinLeft(regiondata, this.time); // lef keyframe, if it exists + const rightkf: Doc | undefined = RegionHelpers.calcMinRight(regiondata, this.time); //right keyframe, if it exists + const currentkf: Doc | undefined = this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe if (currentkf) { - await this.applyKeys(currentkf); + this.applyKeys(currentkf); runInAction(() => { this.saveStateKf = currentkf; this.saveStateRegion = regiondata; }); } else if (leftkf && rightkf) { - await this.interpolate(leftkf, rightkf); + this.interpolate(leftkf, rightkf); } } }; @@ -249,7 +250,7 @@ export class Track extends React.Component { * need to change the logic here */ @action - private applyKeys = async (kf: Doc) => { + private applyKeys = (kf: Doc) => { this.primitiveWhitelist.forEach(key => { if (!kf[key]) { this.props.animatedDoc[key] = undefined; @@ -277,7 +278,7 @@ export class Track extends React.Component { * basic linear interpolation function */ @action - interpolate = async (left: Doc, right: Doc) => { + interpolate = (left: Doc, right: Doc) => { this.primitiveWhitelist.forEach(key => { if (typeof left[key] === 'number' && typeof right[key] === 'number') { //if it is number, interpolate -- cgit v1.2.3-70-g09d2 From a866baea5fdbf30650cbfbf4aa383019ef61ec3d Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 27 Oct 2023 13:39:04 -0400 Subject: added collection itself to timeline --- src/client/views/animationtimeline/Timeline.tsx | 14 +++----------- src/client/views/animationtimeline/Track.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- 3 files changed, 5 insertions(+), 13 deletions(-) (limited to 'src/client/views/animationtimeline/Timeline.tsx') diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx index 71517d4fe..4be3b05ab 100644 --- a/src/client/views/animationtimeline/Timeline.tsx +++ b/src/client/views/animationtimeline/Timeline.tsx @@ -543,7 +543,7 @@ export class Timeline extends React.Component {
- {this.children.map(doc => ( + {[...this.children, this.props.Document].map(doc => ( this.mapOfTracks.push(ref)} timeline={this} @@ -562,16 +562,8 @@ export class Timeline extends React.Component {
Current: {this.getCurrentTime()}
- {this.children.map(doc => ( -
{ - Doc.BrushDoc(doc); - }} - onPointerOut={() => { - Doc.UnBrushDoc(doc); - }}> + {[...this.children, this.props.Document].map(doc => ( +
Doc.BrushDoc(doc)} onPointerOut={() => Doc.UnBrushDoc(doc)}>

{StrCast(doc.title)}

))} diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx index b90ff5eaf..dfab849a4 100644 --- a/src/client/views/animationtimeline/Track.tsx +++ b/src/client/views/animationtimeline/Track.tsx @@ -34,7 +34,7 @@ export class Track extends React.Component { @observable private _newKeyframe: boolean = false; private readonly MAX_TITLE_HEIGHT = 75; @observable private _trackHeight = 0; - private primitiveWhitelist = ['x', 'y', '_width', '_height', '_rotation', 'opacity', '_layout_scrollTop']; + private primitiveWhitelist = ['x', 'y', '_freeform_panX', '_freeform_panY', '_width', '_height', '_rotation', 'opacity', '_layout_scrollTop']; private objectWhitelist = ['data']; @computed private get regions() { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 4a43ffe3e..43be4b724 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1312,7 +1312,7 @@ export class DocumentViewInternal extends DocComponent <> - {DocumentViewInternal.AnimationEffect(renderDoc, this.rootDoc[Animation], this.rootDoc)} + {this._componentView instanceof KeyValueBox ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.rootDoc[Animation], this.rootDoc)} {borderPath?.jsx}
-- cgit v1.2.3-70-g09d2