diff options
-rw-r--r-- | src/client/views/animationtimeline/Keyframe.tsx | 103 | ||||
-rw-r--r-- | src/client/views/animationtimeline/Timeline.tsx | 16 | ||||
-rw-r--r-- | src/client/views/animationtimeline/TimelineOverview.tsx | 8 | ||||
-rw-r--r-- | src/client/views/animationtimeline/Track.tsx | 60 |
4 files changed, 92 insertions, 95 deletions
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<Doc>): (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<IProps> { @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<Doc>; } + @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<Doc>(); - const start = this.props.makeKeyData(this.regiondata, this.regiondata.position, KeyframeFunc.KeyframeType.end); + if (!this.regiondata.keyframes) this.regiondata.keyframes = new List<Doc>(); + 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<IProps> { }, 1000); } - - - @action onBarPointerDown = (e: React.PointerEvent) => { e.preventDefault(); @@ -316,7 +317,7 @@ export class Keyframe extends React.Component<IProps> { 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<IProps> { 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<IProps> { 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<IProps> { 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<IProps> { * 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( - <><div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}> - <div className="divider"></div> - <div className="keyframeCircle keyframe-indicator" onPointerDown={(e) => { 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(); }}></div> - - </div> - <div className="keyframe-information"></div> - </> - - ); - } else { - keyframeDivs.push( + return <> <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}> <div className="divider"></div> + <div className="keyframeCircle keyframe-indicator" + onPointerDown={(e) => { 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(); }}> + </div> </div> - ); + <div className="keyframe-information" /> + </>; + } else { + return <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}> + <div className="divider" /> + </div> } }); - return keyframeDivs; } /** @@ -546,22 +544,23 @@ export class Keyframe extends React.Component<IProps> { */ //154, 206, 223 render() { + trace(); + console.log(this.props.RegionData.position); + console.log(this.regiondata.position); + console.log(this.pixelPosition); return ( - <div> - <div className="bar" ref={this._bar} style={{ - transform: `translate(${this.pixelPosition}px)`, - width: `${this.pixelDuration}px`, - background: `linear-gradient(90deg, rgba(154, 206, 223, 0) 0%, rgba(154, 206, 223, 1) ${this.pixelFadeIn / this.pixelDuration * 100}%, rgba(154, 206, 223, 1) ${(this.pixelDuration - this.pixelFadeOut) / this.pixelDuration * 100}%, rgba(154, 206, 223, 0) 100% )` - }} - onPointerDown={this.onBarPointerDown - }> - <div className="leftResize keyframe-indicator" onPointerDown={this.onResizeLeft} ></div> - {/* <div className="keyframe-information"></div> */} - <div className="rightResize keyframe-indicator" onPointerDown={this.onResizeRight}></div> - {/* <div className="keyframe-information"></div> */} - {this.drawKeyframes()} - {this.drawKeyframeDividers()} - </div> + <div className="bar" ref={this._bar} style={{ + transform: `translate(${this.pixelPosition}px)`, + width: `${this.pixelDuration}px`, + background: `linear-gradient(90deg, rgba(154, 206, 223, 0) 0%, rgba(154, 206, 223, 1) ${this.pixelFadeIn / this.pixelDuration * 100}%, rgba(154, 206, 223, 1) ${(this.pixelDuration - this.pixelFadeOut) / this.pixelDuration * 100}%, rgba(154, 206, 223, 0) 100% )` + }} + onPointerDown={this.onBarPointerDown}> + <div className="leftResize keyframe-indicator" onPointerDown={this.onResizeLeft} ></div> + {/* <div className="keyframe-information"></div> */} + <div className="rightResize keyframe-indicator" onPointerDown={this.onResizeRight}></div> + {/* <div className="keyframe-information"></div> */} + {this.drawKeyframes()} + {this.drawKeyframeDividers()} </div> ); } 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<FieldViewProps> { // 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<FieldViewProps> { 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<Doc>; + return Cast((Cast(this.props.Document[Doc.LayoutFieldKey(this.props.Document) + "-annotations"], Doc) as Doc).annotations, listSpec(Doc)) as List<Doc>; } else { return new List<Doc>(); } @@ -586,17 +583,14 @@ export class Timeline extends React.Component<FieldViewProps> { * 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 ( <div> 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<TimelineOverviewProps>{ const timeline = this.props.isAuthoring ? [ <div key="timeline-overview-container" className="timeline-overview-container overviewBar" id="timelineOverview" ref={this.authoringContainer}> - <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{ left: `${barStart}px`, width: `${visibleBarWidth}px` }} onPointerDown={this.onPointerDown}></div>, - <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{ left: `${scrubberStart}px` }} onPointerDown={this.onScrubberDown}> + <div ref={this._visibleRef} key="1" className="timeline-overview-visible" style={{ left: `${barStart}px`, width: `${visibleBarWidth}px` }} onPointerDown={this.onPointerDown}></div>, + <div ref={this._scrubberRef} key="2" className="timeline-overview-scrubber-container" style={{ left: `${scrubberStart}px` }} onPointerDown={this.onScrubberDown}> <div key="timeline-overview-scrubber-head" className="timeline-overview-scrubber-head"></div> </div> </div> ] : [ - <div key="timeline-play-container" className="timeline-play-bar overviewBar" id="timelinePlay" ref={this.playbackContainer}> + <div key="1" className="timeline-play-bar overviewBar" id="timelinePlay" ref={this.playbackContainer}> <div ref={this._scrubberRef} className="timeline-play-head" style={{ left: `${scrubberStart}px` }} onPointerDown={this.onScrubberDown}></div> </div>, - <div className="timeline-play-tail" style={{ width: `${playWidth}px` }}></div> + <div key="2" className="timeline-play-tail" style={{ width: `${playWidth}px` }}></div> ]; return ( <div className="timeline-flex"> 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<IProps> { @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<IProps> { "y", "width", "height", - "opacity", + "opacity", ]; private objectWhitelist = [ "data" @@ -81,17 +81,17 @@ export class Track extends React.Component<IProps> { //////////////////////////////// - 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<IProps> { 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<IProps> { } }); } else { - console.log("reverting state"); + console.log("reverting state"); //this.revertState(); } }); @@ -241,7 +241,7 @@ export class Track extends React.Component<IProps> { 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<IProps> { 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<IProps> { 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<IProps> { 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<IProps> { 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<IProps> { * UI sstuff here. Not really much to change */ render() { + trace(); return ( <div className="track-container"> <div className="track"> - <div className="inner" ref={this._inner} onDoubleClick={this.onInnerDoubleClick} onPointerOver={() => { Doc.BrushDoc(this.props.node); }} onPointerOut={() => { Doc.UnBrushDoc(this.props.node); }} style={{ height: `${this._trackHeight}px` }}> - {DocListCast(this.regions).map((region) => { - return <Keyframe {...this.props} RegionData={region} makeKeyData={this.makeKeyData} />; + <div className="inner" ref={this._inner} style={{ height: `${this._trackHeight}px` }} + onDoubleClick={this.onInnerDoubleClick} + onPointerOver={() => Doc.BrushDoc(this.props.node)} + onPointerOut={() => Doc.UnBrushDoc(this.props.node)} > + {DocListCast(this.regions).map((region, i) => { + return <Keyframe key={`${i}`} {...this.props} RegionData={region} makeKeyData={this.makeKeyData} />; })} </div> </div> |