From 0fb0341287cfed4c5b846f6bc7126623599b34f5 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 28 Apr 2020 20:16:45 -0400 Subject: small timeline fixes --- src/client/views/animationtimeline/Keyframe.tsx | 103 ++++++++++----------- src/client/views/animationtimeline/Timeline.tsx | 16 +--- .../views/animationtimeline/TimelineOverview.tsx | 8 +- src/client/views/animationtimeline/Track.tsx | 60 ++++++------ 4 files changed, 92 insertions(+), 95 deletions(-) (limited to 'src') diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx index bb557289e..76c3e63be 100644 --- a/src/client/views/animationtimeline/Keyframe.tsx +++ b/src/client/views/animationtimeline/Keyframe.tsx @@ -3,7 +3,7 @@ import "./Keyframe.scss"; import "./Timeline.scss"; import "../globalCssVariables.scss"; import { observer } from "mobx-react"; -import { observable, reaction, action, IReactionDisposer, observe, computed, runInAction } from "mobx"; +import { observable, reaction, action, IReactionDisposer, observe, computed, runInAction, trace } from "mobx"; import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; import { Cast, NumCast } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; @@ -13,6 +13,7 @@ import { TimelineMenu } from "./TimelineMenu"; import { Docs } from "../../documents/Documents"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import { undoBatch, UndoManager } from "../../util/UndoManager"; +import { emptyPath } from "../../../Utils"; @@ -32,10 +33,10 @@ export namespace KeyframeFunc { right = "right" } - export const findAdjacentRegion = (dir: KeyframeFunc.Direction, currentRegion: Doc, regions: List): (RegionData | undefined) => { + export const findAdjacentRegion = (dir: KeyframeFunc.Direction, currentRegion: Doc, regions: Doc[]): (RegionData | undefined) => { let leftMost: (RegionData | undefined) = undefined; let rightMost: (RegionData | undefined) = undefined; - DocListCast(regions).forEach(region => { + regions.forEach(region => { const neighbor = RegionData(region); if (currentRegion.position! > neighbor.position) { if (!leftMost || neighbor.position > leftMost.position) { @@ -135,7 +136,7 @@ interface IProps { time: number; changeCurrentBarX: (x: number) => void; transform: Transform; - makeKeyData: (region:RegionData, pos: number, kftype:KeyframeFunc.KeyframeType) => Doc; + makeKeyData: (region: RegionData, pos: number, kftype: KeyframeFunc.KeyframeType) => Doc; } @@ -169,21 +170,24 @@ export class Keyframe extends React.Component { @observable private _mouseToggled = false; @observable private _doubleClickEnabled = false; - @computed private get regiondata() { return RegionData(this.regions[this.regions.indexOf(this.props.RegionData)] as Doc); } - @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List; } + @computed private get regiondata() { return RegionData(this.props.RegionData); } + @computed private get regions() { return DocListCast(this.props.node.regions); } @computed private get keyframes() { return DocListCast(this.regiondata.keyframes); } @computed private get pixelPosition() { return KeyframeFunc.convertPixelTime(this.regiondata.position, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); } @computed private get pixelDuration() { return KeyframeFunc.convertPixelTime(this.regiondata.duration, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); } @computed private get pixelFadeIn() { return KeyframeFunc.convertPixelTime(this.regiondata.fadeIn, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); } @computed private get pixelFadeOut() { return KeyframeFunc.convertPixelTime(this.regiondata.fadeOut, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); } - + + constructor(props: any) { + super(props); + } componentDidMount() { setTimeout(() => { //giving it a temporary 1sec delay... - if (!this.regiondata.keyframes) this.regiondata.keyframes = new List(); - const start = this.props.makeKeyData(this.regiondata, this.regiondata.position, KeyframeFunc.KeyframeType.end); + if (!this.regiondata.keyframes) this.regiondata.keyframes = new List(); + const start = this.props.makeKeyData(this.regiondata, this.regiondata.position, KeyframeFunc.KeyframeType.end); const fadeIn = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.fadeIn, KeyframeFunc.KeyframeType.fade); const fadeOut = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, KeyframeFunc.KeyframeType.fade); - const finish = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration,KeyframeFunc.KeyframeType.end); + const finish = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration, KeyframeFunc.KeyframeType.end); (fadeIn.key as Doc).opacity = 1; (fadeOut.key as Doc).opacity = 1; (start.key as Doc).opacity = 0.1; @@ -192,9 +196,6 @@ export class Keyframe extends React.Component { }, 1000); } - - - @action onBarPointerDown = (e: React.PointerEvent) => { e.preventDefault(); @@ -316,7 +317,7 @@ export class Keyframe extends React.Component { if (offset > this.regiondata.fadeIn && offset < this.regiondata.duration - this.regiondata.fadeOut) { //make sure keyframe is not created inbetween fades and ends const position = this.regiondata.position; this.props.makeKeyData(this.regiondata, Math.round(position + offset), KeyframeFunc.KeyframeType.default); - this.regiondata.hasData = true; + this.regiondata.hasData = true; this.props.changeCurrentBarX(KeyframeFunc.convertPixelTime(Math.round(position + offset), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement)); //first move the keyframe to the correct location and make a copy so the correct file gets coppied } @@ -338,7 +339,7 @@ export class Keyframe extends React.Component { TimelineMenu.Instance.addItem("button", "Show Data", () => { runInAction(() => { const kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { _width: 300, _height: 300 }); - CollectionDockingView.AddRightSplit(kvp, (kf.key as Doc).data as Doc); + CollectionDockingView.AddRightSplit(kvp, emptyPath); }); }), TimelineMenu.Instance.addItem("button", "Delete", () => { @@ -403,7 +404,7 @@ export class Keyframe extends React.Component { runInAction(() => { const prevPosition = this.regiondata.position; let cannotMove: boolean = false; - DocListCast(this.regions).forEach(region => { + this.regions.forEach(region => { if (NumCast(region.position) !== this.regiondata.position) { if ((val < 0) || (val > NumCast(region.position) && val < NumCast(region.position) + NumCast(region.duration) || (this.regiondata.duration + val > NumCast(region.position) && this.regiondata.duration + val < NumCast(region.position) + NumCast(region.duration)))) { cannotMove = true; @@ -419,7 +420,7 @@ export class Keyframe extends React.Component { TimelineMenu.Instance.addItem("input", `duration: ${this.regiondata.duration}ms`, (val) => { runInAction(() => { let cannotMove: boolean = false; - DocListCast(this.regions).forEach(region => { + this.regions.forEach(region => { if (NumCast(region.position) !== this.regiondata.position) { val += this.regiondata.position; if ((val < 0) || (val > NumCast(region.position) && val < NumCast(region.position) + NumCast(region.duration))) { @@ -479,34 +480,31 @@ export class Keyframe extends React.Component { * drawing keyframe. Handles both keyframe with a circle (one that you create by double clicking) and one without circle (fades) * this probably needs biggest change, since everyone expected all keyframes to have a circle (and draggable) */ - @action drawKeyframes = () => { const keyframeDivs: JSX.Element[] = []; - DocListCast(this.regiondata.keyframes).forEach(kf => { + return DocListCast(this.regiondata.keyframes).map(kf => { if (kf.type as KeyframeFunc.KeyframeType !== KeyframeFunc.KeyframeType.end) { - keyframeDivs.push( - <>
-
-
{ e.preventDefault(); e.stopPropagation(); this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - this.makeKeyframeMenu(kf, e.nativeEvent); - }} onDoubleClick={(e) => { e.preventDefault(); e.stopPropagation(); }}>
- -
-
- - - ); - } else { - keyframeDivs.push( + return <>
+
{ e.preventDefault(); e.stopPropagation(); this.moveKeyframe(e, kf); }} + onContextMenu={(e: React.MouseEvent) => { + e.preventDefault(); + e.stopPropagation(); + this.makeKeyframeMenu(kf, e.nativeEvent); + }} + onDoubleClick={(e) => { e.preventDefault(); e.stopPropagation(); }}> +
- ); +
+ ; + } else { + return
+
+
} }); - return keyframeDivs; } /** @@ -546,22 +544,23 @@ export class Keyframe extends React.Component { */ //154, 206, 223 render() { + trace(); + console.log(this.props.RegionData.position); + console.log(this.regiondata.position); + console.log(this.pixelPosition); return ( -
-
-
- {/*
*/} -
- {/*
*/} - {this.drawKeyframes()} - {this.drawKeyframeDividers()} -
+
+
+ {/*
*/} +
+ {/*
*/} + {this.drawKeyframes()} + {this.drawKeyframeDividers()}
); } diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx index e9caa2b2a..7d245ab6f 100644 --- a/src/client/views/animationtimeline/Timeline.tsx +++ b/src/client/views/animationtimeline/Timeline.tsx @@ -3,7 +3,7 @@ import "./Timeline.scss"; import { listSpec } from "../../../new_fields/Schema"; import { observer } from "mobx-react"; import { Track } from "./Track"; -import { observable, action, computed, runInAction, IReactionDisposer, reaction } from "mobx"; +import { observable, action, computed, runInAction, IReactionDisposer, reaction, trace } from "mobx"; import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; import { Doc, DocListCast } from "../../../new_fields/Doc"; @@ -14,8 +14,6 @@ import { TimelineOverview } from "./TimelineOverview"; import { FieldViewProps } from "../nodes/FieldView"; import { KeyframeFunc } from "./Keyframe"; import { Utils } from "../../../Utils"; -import { createPromiseCapability } from "../../../../deploy/assets/pdf.worker"; - /** * Timeline class controls most of timeline functions besides individual keyframe and track mechanism. Main functions are @@ -80,7 +78,6 @@ export class Timeline extends React.Component { // so a reaction can be made @observable public _isAuthoring = this.props.Document.isATOn; - @observable private _panelWidth = 0; /** * collection get method. Basically defines what defines collection's children. These will be tracked in the timeline. Do not edit. @@ -90,7 +87,7 @@ export class Timeline extends React.Component { const extendedDocument = ["image", "video", "pdf"].includes(StrCast(this.props.Document.type)); if (extendedDocument) { if (this.props.Document.data_ext) { - return Cast((Cast(this.props.Document.data_ext, Doc) as Doc).annotations, listSpec(Doc)) as List; + return Cast((Cast(this.props.Document[Doc.LayoutFieldKey(this.props.Document) + "-annotations"], Doc) as Doc).annotations, listSpec(Doc)) as List; } else { return new List(); } @@ -586,17 +583,14 @@ export class Timeline extends React.Component { * basically the only thing you need to edit besides render methods in track (individual track lines) and keyframe (green region) */ render() { - runInAction(() => { - this._panelWidth = this.props.PanelWidth(); + setTimeout(() => { this.changeLengths(); // this.toPlay(); - - // this._time = longestTime; - }); + }, 0); const longestTime = this.findLongestTime(); - + trace(); // change visible and total width return (
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx index e3a276737..31e248823 100644 --- a/src/client/views/animationtimeline/TimelineOverview.tsx +++ b/src/client/views/animationtimeline/TimelineOverview.tsx @@ -156,16 +156,16 @@ export class TimelineOverview extends React.Component{ const timeline = this.props.isAuthoring ? [
-
, -
+
, +
] : [ -
+
, -
+
]; return (
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx index 705cc33a2..0e3c209dc 100644 --- a/src/client/views/animationtimeline/Track.tsx +++ b/src/client/views/animationtimeline/Track.tsx @@ -29,7 +29,7 @@ export class Track extends React.Component { @observable private _currentBarXReaction: any; @observable private _timelineVisibleReaction: any; @observable private _autoKfReaction: any; - @observable private _newKeyframe: boolean = false; + @observable private _newKeyframe: boolean = false; private readonly MAX_TITLE_HEIGHT = 75; private _trackHeight = 0; private primitiveWhitelist = [ @@ -37,7 +37,7 @@ export class Track extends React.Component { "y", "width", "height", - "opacity", + "opacity", ]; private objectWhitelist = [ "data" @@ -81,17 +81,17 @@ export class Track extends React.Component { //////////////////////////////// - getLastRegionTime = () => { - let lastTime:number = 0; - let lastRegion:(Doc | undefined); + getLastRegionTime = () => { + let lastTime: number = 0; + let lastRegion: (Doc | undefined); DocListCast(this.regions).forEach(region => { - const time = NumCast(region.position); + const time = NumCast(region.position); if (lastTime <= time) { - lastTime = time; - lastRegion = region; + lastTime = time; + lastRegion = region; } - }); - return lastRegion ? lastTime + NumCast(lastRegion.duration) : 0; + }); + return lastRegion ? lastTime + NumCast(lastRegion.duration) : 0; } /** @@ -106,16 +106,16 @@ export class Track extends React.Component { let kf = keyframes[kfIndex] as Doc; //index in the keyframe if (this._newKeyframe) { console.log("new keyframe registering"); - let kfList = DocListCast(this.saveStateRegion!.keyframes); + let kfList = DocListCast(this.saveStateRegion!.keyframes); kfList.forEach(kf => { - kf.key = this.makeCopy(); - if (kfList.indexOf(kf) === 0 || kfList.indexOf(kf) === 3){ - (kf.key as Doc).opacity = 0.1; - } else{ - (kf.key as Doc).opacity = 1; + kf.key = this.makeCopy(); + if (kfList.indexOf(kf) === 0 || kfList.indexOf(kf) === 3) { + (kf.key as Doc).opacity = 0.1; + } else { + (kf.key as Doc).opacity = 1; } }); - this._newKeyframe = false; + this._newKeyframe = false; } if (!kf) return; if (kf.type === KeyframeFunc.KeyframeType.default) { // only save for non-fades @@ -225,7 +225,7 @@ export class Track extends React.Component { } }); } else { - console.log("reverting state"); + console.log("reverting state"); //this.revertState(); } }); @@ -241,7 +241,7 @@ export class Track extends React.Component { timeChange = async () => { if (this.saveStateKf !== undefined) { await this.saveKeyframe(); - } else if (this._newKeyframe){ + } else if (this._newKeyframe) { await this.saveKeyframe(); } let regiondata = await this.findRegion(Math.round(this.time)); //finds a region that the scrubber is on @@ -250,7 +250,7 @@ export class Track extends React.Component { let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata, this.time); //right keyframe, if it exists let currentkf: (Doc | undefined) = await this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe if (currentkf) { - console.log("is current"); + console.log("is current"); await this.applyKeys(currentkf); this.saveStateKf = currentkf; this.saveStateRegion = regiondata; @@ -348,7 +348,7 @@ export class Track extends React.Component { createRegion = async (time: number) => { if (await this.findRegion(time) === undefined) { //check if there is a region where double clicking (prevents phantom regions) let regiondata = KeyframeFunc.defaultKeyframe(); //create keyframe data - + regiondata.position = time; //set position let rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, regiondata, this.regions); @@ -356,9 +356,9 @@ export class Track extends React.Component { regiondata.duration = rightRegion.position - regiondata.position; } if (this.regions.length === 0 || !rightRegion || (rightRegion && rightRegion.position - regiondata.position >= NumCast(regiondata.fadeIn) + NumCast(regiondata.fadeOut))) { - this.regions.push(regiondata); - this._newKeyframe = true; - this.saveStateRegion = regiondata; + this.regions.push(regiondata); + this._newKeyframe = true; + this.saveStateRegion = regiondata; return regiondata; } } @@ -395,7 +395,7 @@ export class Track extends React.Component { let doc = new Doc(); this.primitiveWhitelist.forEach(key => { let originalVal = this.props.node[key]; - if (key === "data"){ + if (key === "data") { console.log(originalVal); } doc[key] = originalVal instanceof ObjectField ? originalVal[Copy]() : this.props.node[key]; @@ -407,12 +407,16 @@ export class Track extends React.Component { * UI sstuff here. Not really much to change */ render() { + trace(); return (
-
{ Doc.BrushDoc(this.props.node); }} onPointerOut={() => { Doc.UnBrushDoc(this.props.node); }} style={{ height: `${this._trackHeight}px` }}> - {DocListCast(this.regions).map((region) => { - return ; +
Doc.BrushDoc(this.props.node)} + onPointerOut={() => Doc.UnBrushDoc(this.props.node)} > + {DocListCast(this.regions).map((region, i) => { + return ; })}
-- cgit v1.2.3-70-g09d2