diff options
author | andrewdkim <adkim414@gmail.com> | 2019-07-10 17:13:17 -0400 |
---|---|---|
committer | andrewdkim <adkim414@gmail.com> | 2019-07-10 17:13:17 -0400 |
commit | 918b0567a071e4fcb61c2afed676c850f8616e89 (patch) | |
tree | 19fabc7668773994fb54bf494c96959f0d2b1443 /src | |
parent | eeff89a0607eaa6a0204ec2cbac794706f3ab393 (diff) |
Interpolation and keyframe modifications
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/Keyframe.tsx | 87 | ||||
-rw-r--r-- | src/client/views/nodes/Timeline.tsx | 170 | ||||
-rw-r--r-- | src/client/views/nodes/Track.tsx | 74 |
4 files changed, 185 insertions, 148 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1a99ac383..5ee16970b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -365,8 +365,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { <CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" /> </CollectionFreeFormViewPannableContents> </MarqueeView> + <CollectionFreeFormOverlayView {...this.props} {...this.getDocumentViewProps(this.props.Document)} /> <Timeline {...this.props} /> - <CollectionFreeFormOverlayView {...this.props} {...this.getDocumentViewProps(this.props.Document)} /> </div> ); } diff --git a/src/client/views/nodes/Keyframe.tsx b/src/client/views/nodes/Keyframe.tsx index 2f75a4b03..4de311057 100644 --- a/src/client/views/nodes/Keyframe.tsx +++ b/src/client/views/nodes/Keyframe.tsx @@ -14,6 +14,11 @@ import { number } from "prop-types"; import { CollectionSchemaView, CollectionSchemaPreview } from "../collections/CollectionSchemaView"; export namespace KeyframeFunc{ + export enum KeyframeType{ + fade = "fade", + default = "default", + new = "new" + } export enum Direction{ left = "left", right = "right" @@ -80,32 +85,22 @@ export class Keyframe extends React.Component<IProps> { @action componentDidMount() { - let fadeIn = this.makeKeyData(this.regiondata.position + this.regiondata.fadeIn)!; - let fadeOut = this.makeKeyData(this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut)!; - let fadeInIndex = this.regiondata.keyframes!.indexOf(fadeIn); - let fadeOutIndex = this.regiondata.keyframes!.indexOf(fadeOut); - + let fadeIn = this.makeKeyData(this.regiondata.position + this.regiondata.fadeIn, KeyframeFunc.KeyframeType.fade)!; + let fadeOut = this.makeKeyData(this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, KeyframeFunc.KeyframeType.fade)!; + let start = this.makeKeyData(this.regiondata.position, KeyframeFunc.KeyframeType.fade)!; + let finish = this.makeKeyData(this.regiondata.position + this.regiondata.duration, KeyframeFunc.KeyframeType.fade)!; (fadeIn.key! as Doc).opacity = 1; (fadeOut.key! as Doc).opacity = 1; - - this.regiondata.keyframes![fadeInIndex] =fadeIn; - this.regiondata.keyframes![fadeOutIndex] =fadeOut; - - - let start = this.makeKeyData(this.regiondata.position)!; - let finish = this.makeKeyData(this.regiondata.position + this.regiondata.duration)!; - - - let startIndex = this.regiondata.keyframes!.indexOf(start); - let finishIndex = this.regiondata.keyframes!.indexOf(finish); - (start.key! as Doc).opacity = 0.1; (finish.key! as Doc).opacity = 0.1; - + let fadeInIndex = this.regiondata.keyframes!.indexOf(fadeIn); + let fadeOutIndex = this.regiondata.keyframes!.indexOf(fadeOut); + let startIndex = this.regiondata.keyframes!.indexOf(start); + let finishIndex = this.regiondata.keyframes!.indexOf(finish); + this.regiondata.keyframes![fadeInIndex] =fadeIn; + this.regiondata.keyframes![fadeOutIndex] =fadeOut; this.regiondata.keyframes![startIndex] = start; this.regiondata.keyframes![finishIndex] = finish; - - } componentWillUnmount() { @@ -126,7 +121,7 @@ export class Keyframe extends React.Component<IProps> { @action - makeKeyData = (kfpos: number) => { //Kfpos is mouse offsetX, representing time + makeKeyData = (kfpos: number, type:KeyframeFunc.KeyframeType = KeyframeFunc.KeyframeType.new) => { //Kfpos is mouse offsetX, representing time let hasData = false; this.regiondata.keyframes!.forEach(TK => { //TK is TimeAndKey TK = TK as Doc; @@ -136,8 +131,14 @@ export class Keyframe extends React.Component<IProps> { }); if (!hasData) { let TK: Doc = new Doc(); - TK.time = kfpos; - TK.key = Doc.MakeCopy(this.props.node); + TK.time = kfpos; + if (type === KeyframeFunc.KeyframeType.fade){ + TK.key = new Doc(); + } else { + TK.key = Doc.MakeCopy(this.props.node, true); + console.log(toJS(TK.key)); + } + TK.type = type; this.regiondata.keyframes!.push(TK); return TK; } @@ -175,7 +176,6 @@ export class Keyframe extends React.Component<IProps> { } } - @action onResizeLeft = (e: React.PointerEvent) => { e.preventDefault(); @@ -242,9 +242,9 @@ export class Keyframe extends React.Component<IProps> { e.stopPropagation(); let bar = this._bar.current!; let offset = e.clientX - bar.getBoundingClientRect().left; - let position = NumCast(this.regiondata.position); - this.makeKeyData(Math.round(position + offset)); - this.props.changeCurrentBarX(NumCast(Math.round(position + offset))); + let position = NumCast(this.regiondata.position); + this.makeKeyData(Math.round(position + offset)); + this.props.changeCurrentBarX(NumCast(Math.round(position + offset))); //first move the keyframe to the correct location and make a copy so the correct file gets coppied } @action @@ -255,7 +255,25 @@ export class Keyframe extends React.Component<IProps> { } - + @action + private createKeyframeJSX = (kf:Doc, type = KeyframeFunc.KeyframeType.default) => { + if (type === KeyframeFunc.KeyframeType.default){ + return ( + <div className="keyframe" style={{ left: `${NumCast(kf.time) - this.regiondata.position}px` }}> + {this.createDivider()} + <div className="keyframeCircle" onPointerDown={(e) => {this.moveKeyframe(e, kf as Doc);} } onContextMenu={(e:React.MouseEvent)=>{ + e.preventDefault(); + e.stopPropagation(); + console.log(toJS(kf.key)); + }}></div> + </div>); + } + return ( + <div className="keyframe" style={{ left: `${NumCast(kf.time) - this.regiondata.position}px` }}> + {this.createDivider()} + </div> + ); + } render() { return ( @@ -274,19 +292,8 @@ export class Keyframe extends React.Component<IProps> { })}> <div className="leftResize" onPointerDown={this.onResizeLeft} ></div> <div className="rightResize" onPointerDown={this.onResizeRight}></div> - {/* <div className="fadeLeft" style={{ width: `${this.regiondata.fadeIn}px` }}>{this.createDivider(KeyframeFunc.Direction.left)}</div> - <div className="fadeRight" style={{ width: `${this.regiondata.fadeOut}px` }}>{this.createDivider(KeyframeFunc.Direction.right)}</div> */} - {this.regiondata.keyframes!.map(kf => { - kf = kf as Doc; - return <div className="keyframe" style={{ left: `${NumCast(kf.time) - this.regiondata.position}px` }}> - {this.createDivider()} - <div className="keyframeCircle" onPointerDown={(e) => {this.moveKeyframe(e, kf as Doc);} } onContextMenu={(e:React.MouseEvent)=>{ - e.preventDefault(); - e.stopPropagation(); - - }}></div> - </div>; + return this.createKeyframeJSX(kf as Doc, (kf! as Doc).type as KeyframeFunc.KeyframeType); })} {this.createDivider(KeyframeFunc.Direction.left)} {this.createDivider(KeyframeFunc.Direction.right)} diff --git a/src/client/views/nodes/Timeline.tsx b/src/client/views/nodes/Timeline.tsx index 1c51dbcad..d25aa7953 100644 --- a/src/client/views/nodes/Timeline.tsx +++ b/src/client/views/nodes/Timeline.tsx @@ -4,7 +4,7 @@ import { CollectionSubView } from "../collections/CollectionSubView"; import { Document, listSpec, createSchema, makeInterface, defaultSpec } from "../../../new_fields/Schema"; import { observer } from "mobx-react"; import { Track } from "./Track"; -import { observable, reaction, action, IReactionDisposer, observe, IObservableArray, computed, toJS, Reaction, IObservableObject } from "mobx"; +import { observable, reaction, action, IReactionDisposer, observe, IObservableArray, computed, toJS, Reaction, IObservableObject, trace, autorun, runInAction } from "mobx"; import { Cast, NumCast } from "../../../new_fields/Types"; import { SelectionManager } from "../../util/SelectionManager"; import { List } from "../../../new_fields/List"; @@ -22,30 +22,30 @@ export interface FlyoutProps { x?: number; y?: number; display?: string; - regiondata?:Doc; - regions?:List<Doc>; + regiondata?: Doc; + regions?: List<Doc>; } @observer export class Timeline extends CollectionSubView(Document) { private readonly DEFAULT_CONTAINER_HEIGHT: number = 300; - private readonly DEFAULT_TICK_SPACING:number = 50; + private readonly DEFAULT_TICK_SPACING: number = 50; private readonly MIN_CONTAINER_HEIGHT: number = 205; private readonly MAX_CONTAINER_HEIGHT: number = 800; - + @observable private _isMinimized = false; @observable private _tickSpacing = this.DEFAULT_TICK_SPACING; @observable private _scrubberbox = React.createRef<HTMLDivElement>(); - @observable private _scrubber = React.createRef<HTMLDivElement>(); + @observable private _scrubber = React.createRef<HTMLDivElement>(); @observable private _trackbox = React.createRef<HTMLDivElement>(); @observable private _titleContainer = React.createRef<HTMLDivElement>(); @observable private _timelineContainer = React.createRef<HTMLDivElement>(); - @observable private _timeInput = React.createRef<HTMLInputElement>(); - @observable private _durationInput = React.createRef<HTMLInputElement>(); - @observable private _fadeInInput = React.createRef<HTMLInputElement>(); - @observable private _fadeOutInput = React.createRef<HTMLInputElement>(); + @observable private _timeInput = React.createRef<HTMLInputElement>(); + @observable private _durationInput = React.createRef<HTMLInputElement>(); + @observable private _fadeInInput = React.createRef<HTMLInputElement>(); + @observable private _fadeOutInput = React.createRef<HTMLInputElement>(); @observable private _currentBarX: number = 0; @@ -59,12 +59,25 @@ export class Timeline extends CollectionSubView(Document) { @observable private _infoContainer = React.createRef<HTMLDivElement>(); @observable private _ticks: number[] = []; - @observable private flyoutInfo: FlyoutProps = { x: 0, y: 0, display: "none", regiondata: new Doc(), regions: new List<Doc>()}; + @observable private flyoutInfo: FlyoutProps = { x: 0, y: 0, display: "none", regiondata: new Doc(), regions: new List<Doc>() }; private block = false; - @action componentDidMount() { + this.initialize(); + } + + componentWillMount() { + runInAction(() => { + //check if this is a video frame + for (let i = 0; i < this._time;) { + this._ticks.push(i); + i += 1000; + } + }); + } + + initialize = action(() => { let scrubber = this._scrubberbox.current!; this._boxLength = scrubber.getBoundingClientRect().width; let children = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)); @@ -81,17 +94,12 @@ export class Timeline extends CollectionSubView(Document) { trackbox.style.width = `${this._boxLength}`; }); - //check if this is a video frame - for (let i = 0; i < this._time;) { - this._ticks.push(i); - i += 1000; - } document.addEventListener("pointerdown", this.closeFlyout); - } + }); - @action + @action changeCurrentBarX = (x: number) => { - this._currentBarX = x; + this._currentBarX = x; } @action onFlyoutDown = (e: React.PointerEvent) => { @@ -108,10 +116,10 @@ export class Timeline extends CollectionSubView(Document) { this.flyoutInfo.display = "none"; } - @action componentDidUpdate() { - this._time = 100001; + runInAction(() => this._time = 100001); } + componentWillUnmount() { document.removeEventListener("pointerdown", this.closeFlyout); } @@ -182,7 +190,7 @@ export class Timeline extends CollectionSubView(Document) { this._currentBarX = offset; } - + @action onPanDown = (e: React.PointerEvent) => { @@ -230,22 +238,22 @@ export class Timeline extends CollectionSubView(Document) { } } - @action - onTimelineDown = (e:React.PointerEvent) => { - e.preventDefault(); - e.stopPropagation(); - document.addEventListener("pointermove", this.onTimelineMove); - document.addEventListener("pointerup", () => {document.removeEventListener("pointermove", this.onTimelineMove);}); + @action + onTimelineDown = (e: React.PointerEvent) => { + e.preventDefault(); + e.stopPropagation(); + document.addEventListener("pointermove", this.onTimelineMove); + document.addEventListener("pointerup", () => { document.removeEventListener("pointermove", this.onTimelineMove); }); } - @action - onTimelineMove = (e:PointerEvent) => { - e.preventDefault(); - e.stopPropagation(); - let timelineContainer = this._timelineContainer.current!; - timelineContainer.style.transform = `translate(${timelineContainer.getBoundingClientRect().left + 1}px, ${timelineContainer.getBoundingClientRect().top + 1}px)`; - console.log("mouse move!"); - timelineContainer.style.width = "500px"; + @action + onTimelineMove = (e: PointerEvent) => { + e.preventDefault(); + e.stopPropagation(); + let timelineContainer = this._timelineContainer.current!; + timelineContainer.style.transform = `translate(${timelineContainer.getBoundingClientRect().left + 1}px, ${timelineContainer.getBoundingClientRect().top + 1}px)`; + console.log("mouse move!"); + timelineContainer.style.width = "500px"; } @action @@ -292,54 +300,54 @@ export class Timeline extends CollectionSubView(Document) { }), icon: "pinterest" }); ContextMenu.Instance.addItem({ description: "Timeline Funcs...", subitems: subitems }); - + } @action changeTime = (e: React.KeyboardEvent) => { - let time = this._timeInput.current!; - if (e.keyCode === 13){ - if (!Number.isNaN(Number(time.value))){ - this.flyoutInfo.regiondata!.position = Number(time.value) / 1000 * this._tickSpacing; - time.placeholder = time.value +"ms"; + let time = this._timeInput.current!; + if (e.keyCode === 13) { + if (!Number.isNaN(Number(time.value))) { + this.flyoutInfo.regiondata!.position = Number(time.value) / 1000 * this._tickSpacing; + time.placeholder = time.value + "ms"; time.value = ""; } } } - @action - changeDuration = (e:React.KeyboardEvent) => { - let duration = this._durationInput.current!; - if (e.keyCode === 13){ - if (!Number.isNaN(Number(duration.value))){ - this.flyoutInfo.regiondata!.duration = Number(duration.value) / 1000 * this._tickSpacing; - duration.placeholder = duration.value +"ms"; + @action + changeDuration = (e: React.KeyboardEvent) => { + let duration = this._durationInput.current!; + if (e.keyCode === 13) { + if (!Number.isNaN(Number(duration.value))) { + this.flyoutInfo.regiondata!.duration = Number(duration.value) / 1000 * this._tickSpacing; + duration.placeholder = duration.value + "ms"; duration.value = ""; } } } - @action - changeFadeIn = (e:React.KeyboardEvent) => { - let fadeIn = this._fadeInInput.current!; - if (e.keyCode === 13){ - if (!Number.isNaN(Number(fadeIn.value))){ + @action + changeFadeIn = (e: React.KeyboardEvent) => { + let fadeIn = this._fadeInInput.current!; + if (e.keyCode === 13) { + if (!Number.isNaN(Number(fadeIn.value))) { this.flyoutInfo.regiondata!.fadeIn = Number(fadeIn.value); - fadeIn.placeholder = fadeIn.value +"ms"; + fadeIn.placeholder = fadeIn.value + "ms"; fadeIn.value = ""; } } } - @action - changeFadeOut = (e:React.KeyboardEvent) => { - let fadeOut = this._fadeOutInput.current!; - if (e.keyCode === 13){ - if (!Number.isNaN(Number(fadeOut.value))){ - this.flyoutInfo.regiondata!.fadeOut = Number(fadeOut.value); - fadeOut.placeholder = fadeOut.value +"ms"; - fadeOut.value = ""; + @action + changeFadeOut = (e: React.KeyboardEvent) => { + let fadeOut = this._fadeOutInput.current!; + if (e.keyCode === 13) { + if (!Number.isNaN(Number(fadeOut.value))) { + this.flyoutInfo.regiondata!.fadeOut = Number(fadeOut.value); + fadeOut.placeholder = fadeOut.value + "ms"; + fadeOut.value = ""; } } } @@ -348,23 +356,23 @@ export class Timeline extends CollectionSubView(Document) { return ( <div> <button className="minimize" onClick={this.minimize}>Minimize</button> - <div className="flyout-container" style={{left:`${this.flyoutInfo.x}px`, top:`${this.flyoutInfo.y}px`, display: `${this.flyoutInfo.display!}` }} onPointerDown={this.onFlyoutDown}> - <FontAwesomeIcon className="flyout" icon="comment-alt" color="grey" /> - <div className="text-container"> - <p>Time:</p> - <p>Duration:</p> - <p>Fade-in</p> - <p>Fade-out</p> - </div> - <div className="input-container"> - <input ref = {this._timeInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.position)/ this._tickSpacing * 1000)}ms`} onKeyDown={this.changeTime} /> - <input ref = {this._durationInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.duration) / this._tickSpacing * 1000)}ms`} onKeyDown={this.changeDuration}/> - <input ref = {this._fadeInInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.fadeIn))}ms`} onKeyDown={this.changeFadeIn}/> - <input ref = {this._fadeOutInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.fadeOut))}ms`} onKeyDown={this.changeFadeOut}/> - - </div> - <button onClick={action((e:React.MouseEvent)=>{this.flyoutInfo.regions!.splice(this.flyoutInfo.regions!.indexOf(this.flyoutInfo.regiondata!), 1); this.flyoutInfo.display = "none";})}>delete</button> + <div className="flyout-container" style={{ left: `${this.flyoutInfo.x}px`, top: `${this.flyoutInfo.y}px`, display: `${this.flyoutInfo.display!}` }} onPointerDown={this.onFlyoutDown}> + <FontAwesomeIcon className="flyout" icon="comment-alt" color="grey" /> + <div className="text-container"> + <p>Time:</p> + <p>Duration:</p> + <p>Fade-in</p> + <p>Fade-out</p> </div> + <div className="input-container"> + <input ref={this._timeInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.position) / this._tickSpacing * 1000)}ms`} onKeyDown={this.changeTime} /> + <input ref={this._durationInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.duration) / this._tickSpacing * 1000)}ms`} onKeyDown={this.changeDuration} /> + <input ref={this._fadeInInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.fadeIn))}ms`} onKeyDown={this.changeFadeIn} /> + <input ref={this._fadeOutInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.fadeOut))}ms`} onKeyDown={this.changeFadeOut} /> + + </div> + <button onClick={action((e: React.MouseEvent) => { this.flyoutInfo.regions!.splice(this.flyoutInfo.regions!.indexOf(this.flyoutInfo.regiondata!), 1); this.flyoutInfo.display = "none"; })}>delete</button> + </div> <div className="timeline-container" style={{ height: `${this._containerHeight}px` }} ref={this._timelineContainer} onContextMenu={this.timelineContextMenu} > <div className="toolbox"> <div onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="2x" /> </div> @@ -387,7 +395,7 @@ export class Timeline extends CollectionSubView(Document) { </div> <div className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown}> {this._nodes.map(doc => { - return <Track node={(doc as any).value() as Doc} currentBarX={this._currentBarX} changeCurrentBarX = {this.changeCurrentBarX} setFlyout={this.getFlyout} />; + return <Track node={(doc as any).value() as Doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} setFlyout={this.getFlyout} />; })} </div> </div> diff --git a/src/client/views/nodes/Track.tsx b/src/client/views/nodes/Track.tsx index e6d5189af..5f7d7619c 100644 --- a/src/client/views/nodes/Track.tsx +++ b/src/client/views/nodes/Track.tsx @@ -25,6 +25,7 @@ interface IProps { export class Track extends React.Component<IProps> { @observable private _inner = React.createRef<HTMLDivElement>(); @observable private _keys = ["x", "y", "width", "height", "panX", "panY", "scale", "opacity"]; + @observable private _onInterpolate:boolean = false; private _reactionDisposers: IReactionDisposer[] = []; private _selectionManagerChanged?: IReactionDisposer; @@ -43,35 +44,43 @@ export class Track extends React.Component<IProps> { componentDidMount() { this.props.node.hidden = true; this.props.node.opacity = 1; - reaction(() => this.props.currentBarX, () => { - let region: (Doc | undefined) = this.findRegion(this.props.currentBarX); - if (region !== undefined) { - this.props.node.hidden = false; - this.timeChange(this.props.currentBarX); + + this._reactionDisposers.push(reaction(() => this.props.currentBarX, () => { + let regiondata: (Doc | undefined) = this.findRegion(this.props.currentBarX); + if (regiondata) { + this.timeChange(this.props.currentBarX); //first interpolates over to that position; + (Cast(regiondata.keyframes!, listSpec(Doc)) as List<Doc>).forEach((kf) => { + kf = kf as Doc; + if(NumCast(kf.time!) === this.props.currentBarX && kf.type !== KeyframeFunc.KeyframeType.fade){ + kf.key = Doc.MakeCopy(this.props.node, true); + if (kf.type === KeyframeFunc.KeyframeType.new){ + kf.type = KeyframeFunc.KeyframeType.default; + } + } + }); + this.props.node.hidden = false; } else { this.props.node.hidden = true; } - }); - - reaction(() => { + })); + this._reactionDisposers.push(reaction(() => { if (!this._onInterpolate){ let keys = Doc.allKeys(this.props.node); return keys.map(key => FieldValue(this.props.node[key])); } }, data => { - let regiondata = this.findRegion(this.props.currentBarX); + let regiondata = this.findRegion(this.props.currentBarX); if (regiondata){ (Cast(regiondata.keyframes!, listSpec(Doc)) as List<Doc>).forEach((kf) => { kf = kf as Doc; - if(NumCast(kf.time!) === this.props.currentBarX){ - kf.key = Doc.MakeCopy(this.props.node); - console.log("key updated"); - } + if(NumCast(kf.time!) === this.props.currentBarX && kf.type !== KeyframeFunc.KeyframeType.fade){ + kf.key = Doc.MakeCopy(this.props.node, true); + } }); } - - }); + })); } + /** * removes reaction when the component is removed from the timeline */ @@ -81,24 +90,22 @@ export class Track extends React.Component<IProps> { } - @observable private _onInterpolate:boolean = false; @action timeChange = async (time: number) => { let region = this.findRegion(time); let leftkf: (Doc | undefined) = this.calcMinLeft(region!); let rightkf: (Doc | undefined) = this.calcMinRight(region!); let currentkf: (Doc | undefined) = this.calcCurrent(region!); - if (currentkf){ + if (currentkf && (currentkf.type !== KeyframeFunc.KeyframeType.new)){ this._onInterpolate = true; - console.log(this.filterKeys(Doc.allKeys(currentkf.key as Doc))); this.filterKeys(Doc.allKeys(currentkf.key as Doc)).forEach(k => { - console.log(k); this.props.node[k] = (currentkf!.key as Doc)[k]; }); this._onInterpolate = false; } else if (leftkf && rightkf) { this.interpolate(leftkf, rightkf); - } else if (leftkf) { + } else if (leftkf) { + console.log(Doc.GetProto(leftkf!.key as Doc)); this.filterKeys(Doc.allKeys(leftkf.key as Doc)).forEach(k => { this.props.node[k] = (leftkf!.key as Doc)[k]; }); @@ -164,17 +171,32 @@ export class Track extends React.Component<IProps> { @action interpolate = async (kf1: Doc, kf2: Doc) => { - console.log("interpolation"); let node1 = kf1.key as Doc; let node2 = kf2.key as Doc; - + let mainNode = new Doc(); const dif_time = NumCast(kf2.time) - NumCast(kf1.time); const ratio = (this.props.currentBarX - NumCast(kf1.time)) / dif_time; //linear - this._keys.forEach(key => { - const diff = NumCast(node2[key]) - NumCast(node1[key]); - const adjusted = diff * ratio; - this.props.node[key] = NumCast(node1[key]) + adjusted; + let keys = []; + if (this.filterKeys(Doc.allKeys(node1)).length === Math.max(this.filterKeys(Doc.allKeys(node1)).length, this.filterKeys(Doc.allKeys(node2)).length )){ + keys = this.filterKeys(Doc.allKeys(node1)); + mainNode = node1; + } else { + keys = this.filterKeys(Doc.allKeys(node2)); + mainNode = node2; + } + + + keys.forEach(key => { + if (node1[key] && node2[key] && typeof(node1[key]) === "number" && typeof(node2[key]) === "number"){ + const diff = NumCast(node2[key]) - NumCast(node1[key]); + const adjusted = diff * ratio; + this.props.node[key] = NumCast(node1[key]) + adjusted; + } else if (key === "title") { + Doc.SetOnPrototype(this.props.node, "title", mainNode[key] as string); + } else if (key === "documentText"){ + Doc.SetOnPrototype(this.props.node, "documentText", mainNode[key] as string); + } }); } |