diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/animationtimeline/Keyframe.tsx | 43 | ||||
-rw-r--r-- | src/client/views/animationtimeline/Timeline.tsx | 41 | ||||
-rw-r--r-- | src/client/views/animationtimeline/Track.tsx | 239 |
3 files changed, 135 insertions, 188 deletions
diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx index 76c3e63be..a3407f653 100644 --- a/src/client/views/animationtimeline/Keyframe.tsx +++ b/src/client/views/animationtimeline/Keyframe.tsx @@ -4,7 +4,7 @@ import "./Timeline.scss"; import "../globalCssVariables.scss"; import { observer } from "mobx-react"; import { observable, reaction, action, IReactionDisposer, observe, computed, runInAction, trace } from "mobx"; -import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; +import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../new_fields/Doc"; import { Cast, NumCast } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; import { createSchema, defaultSpec, makeInterface, listSpec } from "../../../new_fields/Schema"; @@ -55,11 +55,11 @@ export namespace KeyframeFunc { } }; - export const calcMinLeft = async (region: Doc, currentBarX: number, ref?: Doc) => { //returns the time of the closet keyframe to the left - let leftKf: (Doc | undefined) = undefined; + export const calcMinLeft = (region: Doc, currentBarX: number, ref?: Doc) => { //returns the time of the closet keyframe to the left + let leftKf: Opt<Doc>; let time: number = 0; - const keyframes = await DocListCastAsync(region.keyframes!); - keyframes!.forEach((kf) => { + const keyframes = DocListCast(region.keyframes!); + keyframes.map((kf) => { let compTime = currentBarX; if (ref) compTime = NumCast(ref.time); if (NumCast(kf.time) < compTime && NumCast(kf.time) >= time) { @@ -71,11 +71,10 @@ export namespace KeyframeFunc { }; - export const calcMinRight = async (region: Doc, currentBarX: number, ref?: Doc) => { //returns the time of the closest keyframe to the right - let rightKf: (Doc | undefined) = undefined; + export const calcMinRight = (region: Doc, currentBarX: number, ref?: Doc) => { //returns the time of the closest keyframe to the right + let rightKf: Opt<Doc>; let time: number = Infinity; - const keyframes = await DocListCastAsync(region.keyframes!); - keyframes!.forEach((kf) => { + DocListCast(region.keyframes!).forEach((kf) => { let compTime = currentBarX; if (ref) compTime = NumCast(ref.time); if (NumCast(kf.time) > compTime && NumCast(kf.time) <= NumCast(time)) { @@ -239,9 +238,7 @@ export class Keyframe extends React.Component<IProps> { this.regiondata.position = futureX; } const movement = this.regiondata.position - prevX; - this.keyframes.forEach(kf => { - kf.time = NumCast(kf.time) + movement; - }); + this.keyframes.forEach(kf => kf.time = NumCast(kf.time) + movement); } @action @@ -338,7 +335,7 @@ export class Keyframe extends React.Component<IProps> { makeKeyframeMenu = (kf: Doc, e: MouseEvent) => { TimelineMenu.Instance.addItem("button", "Show Data", () => { runInAction(() => { - const kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { _width: 300, _height: 300 }); + const kvp = Docs.Create.KVPDocument(kf, { _width: 300, _height: 300 }); CollectionDockingView.AddRightSplit(kvp, emptyPath); }); }), @@ -370,12 +367,8 @@ export class Keyframe extends React.Component<IProps> { */ @action makeRegionMenu = (kf: Doc, e: MouseEvent) => { - TimelineMenu.Instance.addItem("button", "Remove Region", () => { - runInAction(() => { - this.regions.splice(this.regions.indexOf(this.props.RegionData), 1); - } - ); - }), + TimelineMenu.Instance.addItem("button", "Remove Region", () => + Cast(this.props.node.regions, listSpec(Doc))?.splice(this.regions.indexOf(this.props.RegionData), 1)), TimelineMenu.Instance.addItem("input", `fadeIn: ${this.regiondata.fadeIn}ms`, (val) => { runInAction(() => { let cannotMove: boolean = false; @@ -404,9 +397,9 @@ export class Keyframe extends React.Component<IProps> { runInAction(() => { const prevPosition = this.regiondata.position; let cannotMove: boolean = false; - 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)))) { + this.regions.map(region => ({ pos: NumCast(region.position), dur: NumCast(region.duration) })).forEach(({ pos, dur }) => { + if (pos !== this.regiondata.position) { + if ((val < 0) || (val > pos && val < pos + dur || (this.regiondata.duration + val > pos && this.regiondata.duration + val < pos + dur))) { cannotMove = true; } } @@ -420,10 +413,10 @@ export class Keyframe extends React.Component<IProps> { TimelineMenu.Instance.addItem("input", `duration: ${this.regiondata.duration}ms`, (val) => { runInAction(() => { let cannotMove: boolean = false; - this.regions.forEach(region => { - if (NumCast(region.position) !== this.regiondata.position) { + this.regions.map(region => ({ pos: NumCast(region.position), dur: NumCast(region.duration) })).forEach(({ pos, dur }) => { + if (pos !== this.regiondata.position) { val += this.regiondata.position; - if ((val < 0) || (val > NumCast(region.position) && val < NumCast(region.position) + NumCast(region.duration))) { + if ((val < 0) || (val > pos && val < pos + dur)) { cannotMove = true; } } diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx index 7d245ab6f..234d560f1 100644 --- a/src/client/views/animationtimeline/Timeline.tsx +++ b/src/client/views/animationtimeline/Timeline.tsx @@ -593,33 +593,30 @@ export class Timeline extends React.Component<FieldViewProps> { trace(); // change visible and total width return ( - <div> - <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}> - <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isATOn && this._timelineVisible) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}> - <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `0px` }}> - <div key="timeline_info" className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}> - {this.drawTicks()} - <div key="timeline_scrubber" className="scrubber" style={{ transform: `translate(${this._currentBarX}px)` }}> - <div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown} ></div> - </div> - <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{ width: `${this._totalLength}px` }}> - {DocListCast(this.children).map(doc => { - const track = <Track ref={ref => { this.mapOfTracks.push(ref); }} node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} /> - return track; - })} - </div> + <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}> + <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isATOn && this._timelineVisible) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}> + <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `0px` }}> + <div key="timeline_info" className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}> + {this.drawTicks()} + <div key="timeline_scrubber" className="scrubber" style={{ transform: `translate(${this._currentBarX}px)` }}> + <div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown} ></div> </div> - <div className="currentTime">Current: {this.getCurrentTime()}</div> - <div key="timeline_title" className="title-container" ref={this._titleContainer}> - {DocListCast(this.children).map(doc => <div style={{ height: `${(this._titleHeight)}px` }} className="datapane" onPointerOver={() => { Doc.BrushDoc(doc); }} onPointerOut={() => { Doc.UnBrushDoc(doc); }}><p>{doc.title}</p></div>)} - </div> - <div key="timeline_resize" onPointerDown={this.onResizeDown}> - <FontAwesomeIcon className="resize" icon={faGripLines} /> + <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{ width: `${this._totalLength}px` }}> + {DocListCast(this.children).map(doc => + <Track ref={ref => this.mapOfTracks.push(ref)} node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} /> + )} </div> </div> + <div className="currentTime">Current: {this.getCurrentTime()}</div> + <div key="timeline_title" className="title-container" ref={this._titleContainer}> + {DocListCast(this.children).map(doc => <div style={{ height: `${(this._titleHeight)}px` }} className="datapane" onPointerOver={() => { Doc.BrushDoc(doc); }} onPointerOut={() => { Doc.UnBrushDoc(doc); }}><p>{doc.title}</p></div>)} + </div> + <div key="timeline_resize" onPointerDown={this.onResizeDown}> + <FontAwesomeIcon className="resize" icon={faGripLines} /> + </div> </div> - {this.timelineToolBox(1, longestTime)} </div> + {this.timelineToolBox(1, longestTime)} </div> ); } diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx index 0e3c209dc..9e2ec8886 100644 --- a/src/client/views/animationtimeline/Track.tsx +++ b/src/client/views/animationtimeline/Track.tsx @@ -1,15 +1,15 @@ -import * as React from "react"; +import { action, computed, intercept, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { observable, reaction, action, IReactionDisposer, computed, runInAction, autorun, toJS, isObservableArray, IObservableArray, trace, observe, intercept } from "mobx"; -import "./Track.scss"; -import { Doc, DocListCastAsync, DocListCast, Field } from "../../../new_fields/Doc"; -import { listSpec } from "../../../new_fields/Schema"; -import { FieldValue, Cast, NumCast, BoolCast, StrCast } from "../../../new_fields/Types"; -import { List } from "../../../new_fields/List"; -import { Keyframe, KeyframeFunc, RegionData } from "./Keyframe"; -import { Transform } from "../../util/Transform"; +import * as React from "react"; +import { Doc, DocListCast, Opt } from "../../../new_fields/Doc"; import { Copy } from "../../../new_fields/FieldSymbols"; +import { List } from "../../../new_fields/List"; import { ObjectField } from "../../../new_fields/ObjectField"; +import { listSpec } from "../../../new_fields/Schema"; +import { Cast, NumCast } from "../../../new_fields/Types"; +import { Transform } from "../../util/Transform"; +import { Keyframe, KeyframeFunc, RegionData } from "./Keyframe"; +import "./Track.scss"; interface IProps { node: Doc; @@ -43,48 +43,41 @@ export class Track extends React.Component<IProps> { "data" ]; - @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>; } + @computed private get regions() { return DocListCast(this.props.node.regions); } @computed private get time() { return NumCast(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement)); } ////////// life cycle functions/////////////// componentWillMount() { - runInAction(() => { - if (!this.props.node.regions) this.props.node.regions = new List<Doc>(); //if there is no region, then create new doc to store stuff - //these two lines are exactly same from timeline.tsx - let relativeHeight = window.innerHeight / 20; - this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //for responsiveness - }); + if (!this.props.node.regions) this.props.node.regions = new List<Doc>(); //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; + this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //for responsiveness } componentDidMount() { - runInAction(async () => { - this._timelineVisibleReaction = this.timelineVisibleReaction(); - this._currentBarXReaction = this.currentBarXReaction(); - if (this.regions.length === 0) this.createRegion(this.time); - this.props.node.hidden = false; - this.props.node.opacity = 1; - // this.autoCreateKeyframe(); - }); + this._timelineVisibleReaction = this.timelineVisibleReaction(); + this._currentBarXReaction = this.currentBarXReaction(); + if (this.regions.length === 0) this.createRegion(this.time); + this.props.node.hidden = false; + this.props.node.opacity = 1; + // this.autoCreateKeyframe(); } /** * mainly for disposing reactions */ componentWillUnmount() { - runInAction(() => { - //disposing reactions - if (this._currentBarXReaction) this._currentBarXReaction(); - if (this._timelineVisibleReaction) this._timelineVisibleReaction(); - if (this._autoKfReaction) this._autoKfReaction(); - }); + this._currentBarXReaction?.(); + this._timelineVisibleReaction?.(); + this._autoKfReaction?.(); } //////////////////////////////// getLastRegionTime = () => { let lastTime: number = 0; - let lastRegion: (Doc | undefined); - DocListCast(this.regions).forEach(region => { + let lastRegion: Opt<Doc>; + this.regions.forEach(region => { const time = NumCast(region.position); if (lastTime <= time) { lastTime = time; @@ -100,41 +93,34 @@ export class Track extends React.Component<IProps> { */ @action saveKeyframe = async () => { - console.log("saving keyframe"); - let keyframes: List<Doc> = (Cast(this.saveStateRegion!.keyframes, listSpec(Doc)) as List<Doc>); - let kfIndex: number = keyframes.indexOf(this.saveStateKf!); + let keyframes = Cast(this.saveStateRegion?.keyframes, listSpec(Doc)) as List<Doc>; + let kfIndex = keyframes.indexOf(this.saveStateKf!); let kf = keyframes[kfIndex] as Doc; //index in the keyframe if (this._newKeyframe) { - console.log("new keyframe registering"); - 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; - } + DocListCast(this.saveStateRegion?.keyframes).forEach((kf, index) => { + this.copyDocDataToKeyFrame(kf); + kf.opacity = (index === 0 || index === 3) ? 0.1 : 1; }); this._newKeyframe = false; } if (!kf) return; if (kf.type === KeyframeFunc.KeyframeType.default) { // only save for non-fades - kf.key = this.makeCopy(); - let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(this.saveStateRegion!, this.time, kf); // lef keyframe, if it exists - let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(this.saveStateRegion!, this.time, kf); //right keyframe, if it exists - if (leftkf!.type === KeyframeFunc.KeyframeType.fade) { //replicating this keyframe to fades - let edge: (Doc | undefined) = await KeyframeFunc.calcMinLeft(this.saveStateRegion!, this.time, leftkf!); - edge!.key = this.makeCopy(); - leftkf!.key = this.makeCopy(); - (Cast(edge!.key, Doc)! as Doc).opacity = 0.1; - (Cast(leftkf!.key, Doc)! as Doc).opacity = 1; + this.copyDocDataToKeyFrame(kf); + let leftkf = KeyframeFunc.calcMinLeft(this.saveStateRegion!, this.time, kf); // lef keyframe, if it exists + let rightkf = KeyframeFunc.calcMinRight(this.saveStateRegion!, this.time, kf); //right keyframe, if it exists + if (leftkf?.type === KeyframeFunc.KeyframeType.fade) { //replicating this keyframe to fades + let edge = KeyframeFunc.calcMinLeft(this.saveStateRegion!, this.time, leftkf); + edge && this.copyDocDataToKeyFrame(edge); + leftkf && this.copyDocDataToKeyFrame(leftkf); + edge && (edge!.opacity = 0.1); + leftkf && (leftkf!.opacity = 1); } - if (rightkf!.type === KeyframeFunc.KeyframeType.fade) { - let edge: (Doc | undefined) = await KeyframeFunc.calcMinRight(this.saveStateRegion!, this.time, rightkf!); - edge!.key = this.makeCopy(); - rightkf!.key = this.makeCopy(); - (Cast(edge!.key, Doc)! as Doc).opacity = 0.1; - (Cast(rightkf!.key, Doc)! as Doc).opacity = 1; + if (rightkf?.type === KeyframeFunc.KeyframeType.fade) { + let edge = KeyframeFunc.calcMinRight(this.saveStateRegion!, this.time, rightkf); + edge && this.copyDocDataToKeyFrame(edge); + rightkf && this.copyDocDataToKeyFrame(rightkf); + edge && (edge.opacity = 0.1); + rightkf && (rightkf.opacity = 1); } } keyframes[kfIndex] = kf; @@ -148,24 +134,22 @@ export class Track extends React.Component<IProps> { */ @action autoCreateKeyframe = () => { - const { node } = this.props; - const objects = this.objectWhitelist.map(key => node[key]); + const objects = this.objectWhitelist.map(key => this.props.node[key]); intercept(this.props.node, change => { console.log(change); return change; }); return reaction(() => { - return [...this.primitiveWhitelist.map(key => node[key]), ...objects]; + return [...this.primitiveWhitelist.map(key => this.props.node[key]), ...objects]; }, (changed, reaction) => { //check for region - this.findRegion(this.time).then((region) => { - if (region !== undefined) { //if region at scrub time exist - let r = region as any as RegionData; //for some region is returning undefined... which is not the case - if (DocListCast(r.keyframes).find(kf => kf.time === this.time) === undefined) { //basically when there is no additional keyframe at that timespot - this.makeKeyData(r, this.time, KeyframeFunc.KeyframeType.default); - } + const region = this.findRegion(this.time); + if (region !== undefined) { //if region at scrub time exist + let r = region as RegionData; //for some region is returning undefined... which is not the case + if (DocListCast(r.keyframes).find(kf => kf.time === this.time) === undefined) { //basically when there is no additional keyframe at that timespot + this.makeKeyData(r, this.time, KeyframeFunc.KeyframeType.default); } - }); + } }, { fireImmediately: false }); } @@ -188,20 +172,19 @@ export class Track extends React.Component<IProps> { @action currentBarXReaction = () => { return reaction(() => this.props.currentBarX, () => { - this.findRegion(this.time).then((regiondata: (Doc | undefined)) => { - if (regiondata) { - this.props.node.hidden = false; - // if (!this._autoKfReaction) { - // // console.log("creating another reaction"); - // // this._autoKfReaction = this.autoCreateKeyframe(); - // } - this.timeChange(); - } else { - this.props.node.hidden = true; - this.props.node.opacity = 0; - //if (this._autoKfReaction) this._autoKfReaction(); - } - }); + const regiondata = this.findRegion(this.time); + if (regiondata) { + this.props.node.hidden = false; + // if (!this._autoKfReaction) { + // // console.log("creating another reaction"); + // // this._autoKfReaction = this.autoCreateKeyframe(); + // } + this.timeChange(); + } else { + this.props.node.hidden = true; + this.props.node.opacity = 0; + //if (this._autoKfReaction) this._autoKfReaction(); + } }); } @@ -214,13 +197,11 @@ export class Track extends React.Component<IProps> { return this.props.timelineVisible; }, isVisible => { if (isVisible) { - DocListCast(this.regions).forEach(region => { - if (!BoolCast((Cast(region, Doc) as Doc).hasData)) { - for (let i = 0; i < 4; i++) { - DocListCast(((Cast(region, Doc) as Doc).keyframes as List<Doc>))[i].key = this.makeCopy(); - if (i === 0 || i === 3) { //manually inputing fades - (DocListCast(((Cast(region, Doc) as Doc).keyframes as List<Doc>))[i].key! as Doc).opacity = 0.1; - } + this.regions.filter(region => !region.hasData).forEach(region => { + for (let i = 0; i < 4; i++) { + this.copyDocDataToKeyFrame(DocListCast(region.keyframes)[i]); + if (i === 0 || i === 3) { //manually inputing fades + DocListCast(region.keyframes)[i].opacity = 0.1; } } }); @@ -266,12 +247,11 @@ export class Track extends React.Component<IProps> { */ @action private applyKeys = async (kf: Doc) => { - let kfNode = await Cast(kf.key, Doc) as Doc; this.primitiveWhitelist.forEach(key => { - if (!kfNode[key]) { + if (!kf[key]) { this.props.node[key] = undefined; } else { - let stored = kfNode[key]; + let stored = kf[key]; this.props.node[key] = stored instanceof ObjectField ? stored[Copy]() : stored; } }); @@ -297,16 +277,14 @@ export class Track extends React.Component<IProps> { */ @action interpolate = async (left: Doc, right: Doc) => { - let leftNode = await (left.key) as Doc; - let rightNode = await (right.key) as Doc; this.primitiveWhitelist.forEach(key => { - if (leftNode[key] && rightNode[key] && typeof (leftNode[key]) === "number" && typeof (rightNode[key]) === "number") { //if it is number, interpolate - let dif = NumCast(rightNode[key]) - NumCast(leftNode[key]); + if (left[key] && right[key] && typeof (left[key]) === "number" && typeof (right[key]) === "number") { //if it is number, interpolate + let dif = NumCast(right[key]) - NumCast(left[key]); let deltaLeft = this.time - NumCast(left.time); let ratio = deltaLeft / (NumCast(right.time) - NumCast(left.time)); - this.props.node[key] = NumCast(leftNode[key]) + (dif * ratio); + this.props.node[key] = NumCast(left[key]) + (dif * ratio); } else { // case data - let stored = leftNode[key]; + let stored = left[key]; this.props.node[key] = stored instanceof ObjectField ? stored[Copy]() : stored; } }); @@ -316,17 +294,8 @@ export class Track extends React.Component<IProps> { * finds region that corresponds to specific time (is there a region at this time?) * linear O(n) (maybe possible to optimize this with other Data structures?) */ - @action - findRegion = async (time: number) => { - let foundRegion: (Doc | undefined) = undefined; - let regions = await DocListCastAsync(this.regions); - regions!.forEach(region => { - region = region as RegionData; - if (time >= NumCast(region.position) && time <= (NumCast(region.position) + NumCast(region.duration))) { - foundRegion = region; - } - }); - return foundRegion; + findRegion = (time: number) => { + return this.regions?.find(rd => (time >= NumCast(rd.position) && time <= (NumCast(rd.position) + NumCast(rd.duration)))); } @@ -345,8 +314,8 @@ export class Track extends React.Component<IProps> { * creates a region (KEYFRAME.TSX stuff). */ @action - createRegion = async (time: number) => { - if (await this.findRegion(time) === undefined) { //check if there is a region where double clicking (prevents phantom regions) + createRegion = (time: number) => { + if (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 @@ -356,7 +325,7 @@ 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); + Cast(this.props.node.regions, listSpec(Doc))?.push(regiondata); this._newKeyframe = true; this.saveStateRegion = regiondata; return regiondata; @@ -366,48 +335,36 @@ export class Track extends React.Component<IProps> { @action makeKeyData = (regiondata: RegionData, time: number, type: KeyframeFunc.KeyframeType = KeyframeFunc.KeyframeType.default) => { //Kfpos is mouse offsetX, representing time - let doclist = DocListCast(regiondata.keyframes)!; - let existingkf: (Doc | undefined) = undefined; - doclist.forEach(TK => { - if (TK.time === time) existingkf = TK; - }); + const trackKeyFrames = DocListCast(regiondata.keyframes)!; + const existingkf = trackKeyFrames.find(TK => TK.time === time); if (existingkf) return existingkf; //else creates a new doc. - let TK: Doc = new Doc(); - TK.time = time; - TK.key = this.makeCopy(); - TK.type = type; + const newKeyFrame: Doc = new Doc(); + newKeyFrame.time = time; + newKeyFrame.type = type; + this.copyDocDataToKeyFrame(newKeyFrame); //assuming there are already keyframes (for keeping keyframes in order, sorted by time) - if (doclist.length === 0) regiondata.keyframes!.push(TK); - doclist.forEach(kf => { - let index = doclist.indexOf(kf); - let kfTime = NumCast(kf.time); - if ((kfTime < time && index === doclist.length - 1) || (kfTime < time && time < NumCast(doclist[index + 1].time))) { - regiondata.keyframes!.splice(index + 1, 0, TK); - return; + if (trackKeyFrames.length === 0) regiondata.keyframes!.push(newKeyFrame); + trackKeyFrames.map(kf => NumCast(kf.time)).forEach((kfTime, index) => { + if ((kfTime < time && index === trackKeyFrames.length - 1) || (kfTime < time && time < NumCast(trackKeyFrames[index + 1].time))) { + regiondata.keyframes!.splice(index + 1, 0, newKeyFrame); } }); - return TK; + return newKeyFrame; } @action - makeCopy = () => { - let doc = new Doc(); - this.primitiveWhitelist.forEach(key => { - let originalVal = this.props.node[key]; - if (key === "data") { - console.log(originalVal); - } - doc[key] = originalVal instanceof ObjectField ? originalVal[Copy]() : this.props.node[key]; + copyDocDataToKeyFrame = (doc: Doc) => { + this.primitiveWhitelist.map(key => { + const originalVal = this.props.node[key]; + doc[key] = originalVal instanceof ObjectField ? originalVal[Copy]() : originalVal; }); - return doc; } /** * UI sstuff here. Not really much to change */ render() { - trace(); return ( <div className="track-container"> <div className="track"> @@ -415,7 +372,7 @@ export class Track extends React.Component<IProps> { onDoubleClick={this.onInnerDoubleClick} onPointerOver={() => Doc.BrushDoc(this.props.node)} onPointerOut={() => Doc.UnBrushDoc(this.props.node)} > - {DocListCast(this.regions).map((region, i) => { + {this.regions?.map((region, i) => { return <Keyframe key={`${i}`} {...this.props} RegionData={region} makeKeyData={this.makeKeyData} />; })} </div> |