aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/animationtimeline/Keyframe.tsx48
-rw-r--r--src/client/views/animationtimeline/Timeline.tsx10
-rw-r--r--src/client/views/animationtimeline/Track.tsx100
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx1
4 files changed, 88 insertions, 71 deletions
diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 2f0a968b9..253515dfd 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -410,14 +410,17 @@ export class Keyframe extends React.Component<IProps> {
@action
makeKeyframeMenu = (kf :Doc, e:MouseEvent) => {
-
TimelineMenu.Instance.addItem("button", "Show Data", () => {
runInAction(() => {let kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { width: 300, height: 300 });
CollectionDockingView.Instance.AddRightSplit(kvp, (kf.key as Doc).data as Doc); });
}),
- TimelineMenu.Instance.addItem("button", "Delete", () => {}),
+ TimelineMenu.Instance.addItem("button", "Delete", () => {
+ runInAction(() => {
+ console.log(this.keyframes.indexOf(kf));
+ this.keyframes.splice(this.keyframes.indexOf(kf), 1);
+ });
+ }),
TimelineMenu.Instance.addItem("input", "Move", (val) => {kf.time = parseInt(val, 10);});
-
TimelineMenu.Instance.addMenu("Keyframe");
TimelineMenu.Instance.openMenu(e.clientX, e.clientY);
}
@@ -425,7 +428,8 @@ export class Keyframe extends React.Component<IProps> {
@action
makeRegionMenu = (kf: Doc, e: MouseEvent) => {
TimelineMenu.Instance.addItem("button", "Add Ease", () => {this.onContainerDown(kf, "interpolate");}),
- TimelineMenu.Instance.addItem("button", "Add Path", () => {this.onContainerDown(kf, "path");}),
+ TimelineMenu.Instance.addItem("button", "Add Path", () => {this.onContainerDown(kf, "path");}),
+ TimelineMenu.Instance.addItem("button", "Remove Region", ()=>{this.regions.splice(this.regions.indexOf(this.regiondata), 1);}),
TimelineMenu.Instance.addItem("input", "fadeIn", (val) => {this.regiondata.fadeIn = parseInt(val, 10);}),
TimelineMenu.Instance.addItem("input", "fadeOut", (val) => {this.regiondata.fadeOut = parseInt(val, 10);}),
TimelineMenu.Instance.addItem("input", "position", (val) => {this.regiondata.position = parseInt(val, 10);}),
@@ -435,23 +439,7 @@ 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: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
- <div className="divider"></div>
- <div className="keyframeCircle" onPointerDown={(e) => { this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
- e.preventDefault();
- e.stopPropagation();
- this.makeKeyframeMenu(kf, e.nativeEvent);
- }}></div>
- </div>
- );
- }
- 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>
- );
+
}
onContainerOver = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
@@ -561,7 +549,23 @@ export class Keyframe extends React.Component<IProps> {
<div className="leftResize" onPointerDown={this.onResizeLeft} ></div>
<div className="rightResize" onPointerDown={this.onResizeRight}></div>
{this.keyframes.map(kf => {
- return this.createKeyframeJSX(kf, kf.type as KeyframeFunc.KeyframeType);
+ if (kf.type as KeyframeFunc.KeyframeType === KeyframeFunc.KeyframeType.default) {
+ 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" onPointerDown={(e) => { this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
+ this.makeKeyframeMenu(kf, e.nativeEvent);
+ }}></div>
+ </div>
+ );
+ }
+ 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>
+ );
})}
{this.keyframes.map( kf => {
if(this.keyframes.indexOf(kf ) !== this.keyframes.length - 1) {
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 4eb5958b5..187c9396d 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, reaction, action, IReactionDisposer, computed, runInAction, observe } from "mobx";
+import { observable, reaction, action, IReactionDisposer, computed, runInAction, observe, toJS } from "mobx";
import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
import { List } from "../../../new_fields/List";
import { Doc, DocListCast } from "../../../new_fields/Doc";
@@ -61,14 +61,12 @@ export class Timeline extends React.Component<FieldViewProps> {
@observable private _timelineVisible = false;
@observable private _mouseToggled = false;
@observable private _doubleClickEnabled = false;
- @observable private _mutationDisposer:MutationObserver[] = [];
@observable private _reactionDisposer:IReactionDisposer[] = [];
@computed
private get children(): List<Doc> {
let 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>;
@@ -86,7 +84,7 @@ export class Timeline extends React.Component<FieldViewProps> {
componentDidMount() {
if (StrCast(this.props.Document.type) === "video") {
- console.log("ran");
+ console.log("video");
console.log(this.props.Document.duration);
if (this.props.Document.duration) {
this._time = Math.round(NumCast(this.props.Document.duration)) * 1000;
@@ -358,7 +356,7 @@ export class Timeline extends React.Component<FieldViewProps> {
e.deltaY < 0 ? this.zoom(true) : this.zoom(false);
let currPixel = KeyframeFunc.convertPixelTime(prevTime, "mili", "pixel", this._tickSpacing, this._tickIncrement);
this._infoContainer.current!.scrollLeft = currPixel - offset;
- this._visibleStart = currPixel - offset;
+ this._visibleStart = currPixel - offset;
}
@action
@@ -418,7 +416,7 @@ export class Timeline extends React.Component<FieldViewProps> {
<div key="timeline_scrubberhead" className="scrubberhead"></div>
</div>
<div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{width: `${this._totalLength}px`}}>
- {DocListCast(this.children).map(doc => <Track 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}/>)}
+ {DocListCast(this.children).map(doc => <Track 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 key="timeline_title"className="title-container" ref={this._titleContainer}>
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 8f0e2d1cc..e99da6648 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -8,9 +8,8 @@ import { FieldValue, Cast, NumCast, BoolCast, StrCast } from "../../../new_field
import { List } from "../../../new_fields/List";
import { Keyframe, KeyframeFunc, RegionData } from "./Keyframe";
import { Transform } from "../../util/Transform";
-import { RichTextField } from "../../../new_fields/RichTextField";
-import { DateField } from "../../../new_fields/DateField";
import { Copy } from "../../../new_fields/FieldSymbols";
+import { ObjectField } from "../../../new_fields/ObjectField";
interface IProps {
node: Doc;
@@ -20,19 +19,20 @@ interface IProps {
time: number;
tickIncrement: number;
tickSpacing: number;
+ timelineVisible: boolean;
changeCurrentBarX: (x: number) => void;
}
@observer
export class Track extends React.Component<IProps> {
@observable private _inner = React.createRef<HTMLDivElement>();
- @observable private _reactionDisposers: IReactionDisposer[] = [];
@observable private _currentBarXReaction: any;
+ @observable private _timelineVisibleReaction: any;
@observable private _isOnKeyframe: boolean = false;
@observable private _onKeyframe: (Doc | undefined) = undefined;
@observable private _onRegionData: (Doc | undefined) = undefined;
- @observable private _leftCurrKeyframe: (Doc | undefined) = undefined;
-
+ @observable private _storedState: (Doc | undefined) = undefined;
+
@computed
private get regions() {
return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>;
@@ -40,22 +40,31 @@ export class Track extends React.Component<IProps> {
componentWillMount() {
if (!this.props.node.regions) {
- this.props.node.regions = new List<Doc>();
+ this.props.node.regions = new List<Doc>();
}
- this.props.node.opacity = 1;
+
+
}
componentDidMount() {
- runInAction(() => {
+ runInAction(async () => {
+ this._timelineVisibleReaction = this.timelineVisibleReaction();
this._currentBarXReaction = this.currentBarXReaction();
if (this.regions.length === 0) this.createRegion(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
- this.props.node.hidden = false;
+ this.props.node.hidden = false;
+ this.props.node.opacity = 1;
+ let state = new Doc();
+ state.key = Doc.MakeCopy(await this.props.node, true);
+ console.log(this.props.node.x);
+ this._storedState = state;
});
+
}
componentWillUnmount() {
runInAction(() => {
if (this._currentBarXReaction) this._currentBarXReaction();
+ if (this._timelineVisibleReaction) this._timelineVisibleReaction();
});
}
@@ -89,6 +98,15 @@ export class Track extends React.Component<IProps> {
this._isOnKeyframe = false;
}
+ @action
+ revertState = () => {
+ let copyDoc = Doc.MakeCopy(this.props.node, true);
+ this.applyKeys(this._storedState!);
+ let newState = new Doc();
+ newState.key = copyDoc;
+ this._storedState = newState;
+ }
+
@action
currentBarXReaction = () => {
return reaction(() => this.props.currentBarX, async () => {
@@ -100,9 +118,16 @@ export class Track extends React.Component<IProps> {
this.props.node.hidden = true;
this.props.node.opacity = 0;
}
- }, { fireImmediately: true });
+ });
+ }
+ @action
+ timelineVisibleReaction = () => {
+ return reaction(() => {
+ return this.props.timelineVisible;
+ }, isVisible => {
+ this.revertState();
+ });
}
-
@action
timeChange = async (time: number) => {
@@ -116,7 +141,6 @@ export class Track extends React.Component<IProps> {
let currentkf: (Doc | undefined) = await this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe
if (currentkf) {
await this.applyKeys(currentkf);
- this._leftCurrKeyframe = currentkf;
this._isOnKeyframe = true;
this._onKeyframe = currentkf;
this._onRegionData = regiondata;
@@ -129,39 +153,38 @@ export class Track extends React.Component<IProps> {
@action
private applyKeys = async (kf: Doc) => {
let kfNode = await Cast(kf.key, Doc) as Doc;
- let docFromApply = kfNode;
- console.log(Doc.allKeys(docFromApply));
+ let docFromApply = kfNode;
if (this.filterKeys(Doc.allKeys(this.props.node)).length > this.filterKeys(Doc.allKeys(kfNode)).length) docFromApply = this.props.node;
this.filterKeys(Doc.allKeys(docFromApply)).forEach(key => {
- console.log(key);
if (!kfNode[key]) {
this.props.node[key] = undefined;
} else {
- if (key === "data") {
- if (this.props.node.type === "text") {
- let nodeData = (kfNode[key] as RichTextField).Data;
- this.props.node[key] = new RichTextField(nodeData);
- }
- } else if (key === "creationDate") {
- this.props.node[key] = new DateField();
+ let stored = kfNode[key];
+ if(stored instanceof ObjectField){
+ this.props.node[key] = stored[Copy]();
} else {
- let stored = kfNode[key];
- if (stored instanceof DateField) {
- stored = stored[Copy]();
- }
- this.props.node[key] = stored;
+ this.props.node[key] = stored;
}
-
}
-
});
}
+ private filterList = [
+ "regions",
+ "cursors",
+ "hidden",
+ "nativeHeight",
+ "nativeWidth",
+ "schemaColumns",
+ "baseLayout",
+ "backgroundLayout",
+ "layout",
+ ];
@action
private filterKeys = (keys: string[]): string[] => {
return keys.reduce((acc: string[], key: string) => {
- if (key !== "regions" && key !== "cursors" && key !== "hidden" && key !== "nativeHeight" && key !== "nativeWidth" && key !== "schemaColumns" && key !== "creationDate") acc.push(key);
+ if (!this.filterList.includes(key)) acc.push(key);
return acc;
}, []);
}
@@ -226,18 +249,11 @@ export class Track extends React.Component<IProps> {
this.props.node[key] = NumCast(leftNode[key]) + adjusted;
}
} else {
- if (key === "data") {
- if (this.props.node.type === "text") {
- let nodeData = StrCast((leftNode[key] as RichTextField).Data);
- let currentNodeData = StrCast((this.props.node[key] as RichTextField).Data);
- if (nodeData !== currentNodeData) {
- this.props.node[key] = new RichTextField(nodeData);
- }
- }
- } else if (key === "creationDate") {
-
+ let stored = leftNode[key];
+ if(stored instanceof ObjectField){
+ this.props.node[key] = stored[Copy]();
} else {
- this.props.node[key] = leftNode[key];
+ this.props.node[key] = stored;
}
}
});
@@ -277,8 +293,6 @@ export class Track extends React.Component<IProps> {
}
}
-
-
render() {
return (
<div className="track-container">
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index d9fc388cd..67d700f1a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -912,6 +912,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
if (this.childDocs.some(d => BoolCast(d.isTemplate))) {
layoutItems.push({ description: "Template Layout Instance", event: () => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" });
}
+ this._timelineRef.current!.timelineContextMenu(e.nativeEvent);
layoutItems.push({ description: "reset view", event: () => { this.props.Document.panX = this.props.Document.panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" });
layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, event: this.fitToContainer, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" });
layoutItems.push({