aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/animationtimeline/Keyframe.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/animationtimeline/Keyframe.tsx')
-rw-r--r--src/client/views/animationtimeline/Keyframe.tsx169
1 files changed, 93 insertions, 76 deletions
diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 4e58b07d8..b02d89bf0 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -82,16 +82,30 @@ export namespace KeyframeFunc {
};
export const defaultKeyframe = () => {
- let regiondata = new Doc(); //creating regiondata
- regiondata.duration = 200;
+ let regiondata = new Doc(); //creating regiondata in MILI
+ regiondata.duration = 4000;
regiondata.position = 0;
- regiondata.fadeIn = 20;
- regiondata.fadeOut = 20;
+ regiondata.fadeIn = 1000;
+ regiondata.fadeOut = 1000;
regiondata.functions = new List<Doc>();
return regiondata;
};
-
+ export const convertPixelTime = (pos: number, unit: "mili" | "sec" | "min" | "hr", dir: "pixel" | "time", tickSpacing:number, tickIncrement:number) => {
+ let time = dir === "pixel" ? (pos * tickSpacing) / tickIncrement : (pos / tickSpacing) * tickIncrement;
+ switch (unit) {
+ case "mili":
+ return time;
+ case "sec":
+ return dir === "pixel" ? time / 1000 : time * 1000;
+ case "min":
+ return dir === "pixel" ? time / 60000 : time * 60000;
+ case "hr":
+ return dir === "pixel" ? time / 3600000 : time * 3600000;
+ default:
+ return time;
+ }
+ };
}
export const RegionDataSchema = createSchema({
@@ -109,6 +123,9 @@ interface IProps {
node: Doc;
RegionData: Doc;
collection: Doc;
+ tickSpacing: number;
+ tickIncrement: number;
+ time: number;
changeCurrentBarX: (x: number) => void;
transform: Transform;
}
@@ -118,6 +135,8 @@ export class Keyframe extends React.Component<IProps> {
@observable private _bar = React.createRef<HTMLDivElement>();
@observable private _gain = 20; //default
+ @observable private _mouseToggled = false;
+ @observable private _doubleClickEnabled = false;
@computed
private get regiondata() {
@@ -155,6 +174,7 @@ export class Keyframe extends React.Component<IProps> {
});
return last;
}
+
@computed
private get keyframes(){
return DocListCast(this.regiondata.keyframes);
@@ -171,6 +191,26 @@ export class Keyframe extends React.Component<IProps> {
}
}
+ @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);
+ }
+
async componentWillMount() {
if (!this.regiondata.keyframes) {
this.regiondata.keyframes = new List<Doc>();
@@ -183,20 +223,6 @@ export class Keyframe extends React.Component<IProps> {
(fadeOut.key! as Doc).opacity = 1;
(start.key! as Doc).opacity = 0.1;
(finish.key! as Doc).opacity = 0.1;
-
- observe(this.regiondata, change => {
- if (change.type === "update") {
- fadeIn.time = this.regiondata.position + this.regiondata.fadeIn;
- fadeOut.time = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut;
- start.time = this.regiondata.position;
- finish.time = this.regiondata.position + this.regiondata.duration;
- this.regiondata.keyframes![this.regiondata.keyframes!.indexOf(fadeIn)] = fadeIn;
- this.regiondata.keyframes![this.regiondata.keyframes!.indexOf(fadeOut)] = fadeOut;
- this.regiondata.keyframes![this.regiondata.keyframes!.indexOf(start)] = start;
- this.regiondata.keyframes![this.regiondata.keyframes!.indexOf(finish)] = finish;
- this.forceUpdate();
- }
- });
}
@action
@@ -236,8 +262,7 @@ export class Keyframe extends React.Component<IProps> {
return TK;
}
- @observable private _mouseToggled = false;
- @observable private _doubleClickEnabled = false;
+
@action
onBarPointerDown = (e: React.PointerEvent) => {
e.preventDefault();
@@ -247,14 +272,14 @@ export class Keyframe extends React.Component<IProps> {
this.createKeyframe(clientX);
this._doubleClickEnabled = false;
} else {
- setTimeout(() => {if(!this._mouseToggled && this._doubleClickEnabled)this.props.changeCurrentBarX(this.regiondata.position + (clientX - this._bar.current!.getBoundingClientRect().left) * this.props.transform.Scale);
+ setTimeout(() => {if(!this._mouseToggled && this._doubleClickEnabled)this.props.changeCurrentBarX(this.pixelPosition + (clientX - this._bar.current!.getBoundingClientRect().left) * this.props.transform.Scale);
this._mouseToggled = false;
this._doubleClickEnabled = false; }, 200);
this._doubleClickEnabled = true;
document.addEventListener("pointermove", this.onBarPointerMove);
document.addEventListener("pointerup", (e: PointerEvent) => {
document.removeEventListener("pointermove", this.onBarPointerMove);
- });
+ });
}
}
@@ -269,23 +294,20 @@ export class Keyframe extends React.Component<IProps> {
let left = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, this.regiondata, this.regions)!;
let right = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions!);
let prevX = this.regiondata.position;
- let futureX = this.regiondata.position + e.movementX;
+ let futureX = this.regiondata.position + KeyframeFunc.convertPixelTime(e.movementX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
if (futureX <= 0) {
this.regiondata.position = 0;
} else if ((left && left.position + left.duration >= futureX)) {
this.regiondata.position = left.position + left.duration;
- } else if ((right && right.position <= futureX + this.regiondata.duration)) {
- this.regiondata.position = right.position - this.regiondata.duration;
+ } else if ((right && right.position <= futureX + this.pixelDuration)) {
+ this.regiondata.position = right.position - this.pixelDuration;
} else {
this.regiondata.position = futureX;
- }
- for (let i = 0; i < this.regiondata.keyframes!.length; i++) {
- if ((this.regiondata.keyframes![i] as Doc).type !== KeyframeFunc.KeyframeType.fade) {
- let movement = this.regiondata.position - prevX;
- (this.regiondata.keyframes![i] as Doc).time = NumCast((this.regiondata.keyframes![i] as Doc).time) + movement;
- }
- }
- this.forceUpdate();
+ }
+ let movement = this.regiondata.position - prevX;
+ this.keyframes.forEach(kf => {
+ kf.time = NumCast(kf.time) + movement;
+ });
}
@action
@@ -313,11 +335,11 @@ export class Keyframe extends React.Component<IProps> {
e.preventDefault();
e.stopPropagation();
let bar = this._bar.current!;
- let offset = Math.round((e.clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale);
+ let offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
let leftRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, this.regiondata, this.regions);
let firstkf: (Doc | undefined) = this.firstKeyframe;
if (firstkf && this.regiondata.position + this.regiondata.fadeIn + offset >= NumCast(firstkf!.time)) {
- let dif = NumCast(firstkf!.time) - (this.regiondata.position + this.regiondata.fadeIn);
+ let dif = NumCast(firstkf!.time) - (this.pixelPosition + this.pixelFadeIn);
this.regiondata.position = NumCast(firstkf!.time) - this.regiondata.fadeIn;
this.regiondata.duration -= dif;
} else if (this.regiondata.duration - offset < this.regiondata.fadeIn + this.regiondata.fadeOut) { // no keyframes, just fades
@@ -331,6 +353,7 @@ export class Keyframe extends React.Component<IProps> {
this.regiondata.duration -= offset;
this.regiondata.position += offset;
}
+
}
@@ -339,7 +362,7 @@ export class Keyframe extends React.Component<IProps> {
e.preventDefault();
e.stopPropagation();
let bar = this._bar.current!;
- let offset = Math.round((e.clientX - bar.getBoundingClientRect().right) * this.props.transform.Scale);
+ let offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().right) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
let rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions);
if (this.lastKeyframe! && this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut + offset <= NumCast((this.lastKeyframe! as Doc).time)) {
let dif = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut - NumCast((this.lastKeyframe! as Doc).time);
@@ -352,27 +375,18 @@ export class Keyframe extends React.Component<IProps> {
} else {
this.regiondata.duration += offset;
}
- }
-
- createDivider = (type?: KeyframeFunc.Direction): JSX.Element => {
- if (type === "left") {
- return <div className="divider" style={{ right: "0px" }}></div>;
- } else if (type === "right") {
- return <div className="divider" style={{ left: "0px" }}> </div>;
- }
- return <div className="divider"></div>;
+
}
@action
createKeyframe = async (clientX:number) => {
this._mouseToggled = true;
let bar = this._bar.current!;
- let offset = Math.round((clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale);
+ let offset = KeyframeFunc.convertPixelTime(Math.round((clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
if (offset > this.regiondata.fadeIn && offset < this.regiondata.duration - this.regiondata.fadeOut) { //make sure keyframe is not created inbetween fades and ends
- let position = NumCast(this.regiondata.position);
+ let position = this.regiondata.position;
await this.makeKeyData(Math.round(position + offset));
- console.log(this.regiondata.keyframes!.length);
- 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
+ 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
}
}
@@ -381,7 +395,7 @@ export class Keyframe extends React.Component<IProps> {
moveKeyframe = async (e: React.MouseEvent, kf: Doc) => {
e.preventDefault();
e.stopPropagation();
- this.props.changeCurrentBarX(NumCast(kf.time!));
+ this.props.changeCurrentBarX(KeyframeFunc.convertPixelTime(NumCast(kf.time!), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement));
}
@@ -390,33 +404,38 @@ export class Keyframe extends React.Component<IProps> {
e.preventDefault();
e.stopPropagation();
this.props.node.backgroundColor = "#000000";
-
}
+
+ @action
+ makeKeyframeMenu = (kf :Doc, e:MouseEvent) => {
+ let items = [
+ 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("input", "Move", (val) => {kf.time = parseInt(val, 10);})
+ ];
+ TimelineMenu.Instance.addMenu("Keyframe", items);
+ TimelineMenu.Instance.openMenu(e.clientX, e.clientY);
+}
@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="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 as Doc); }} onContextMenu={(e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
- let items = [
- 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("input", "Move", (val) => {kf.time = parseInt(val, 10);})
- ];
- TimelineMenu.Instance.addMenu("Keyframe", items);
- TimelineMenu.Instance.openMenu(e.clientX, e.clientY);
+ this.makeKeyframeMenu(kf, e.nativeEvent);
}}></div>
- </div>);
+ </div>
+ );
}
return (
- <div className="keyframe" style={{ left: `${NumCast(kf.time) - this.regiondata.position}px` }}>
- {this.createDivider()}
+ <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>
);
}
@@ -460,9 +479,6 @@ export class Keyframe extends React.Component<IProps> {
}
-
-
-
@action
onReactionListen = (e: PointerEvent) => {
e.preventDefault();
@@ -514,7 +530,6 @@ export class Keyframe extends React.Component<IProps> {
(Cast(this.regiondata.functions![index], Doc) as Doc).pathX = xPlots;
(Cast(this.regiondata.functions![index], Doc) as Doc).pathY = yPlots;
}
-
this._reac = undefined;
this._interpolationKeyframe = undefined;
this._plotList = undefined;
@@ -525,19 +540,21 @@ export class Keyframe extends React.Component<IProps> {
render() {
return (
<div>
- <div className="bar" ref={this._bar} style={{ transform: `translate(${this.regiondata.position}px)`, width: `${this.regiondata.duration}px`, background: `linear-gradient(90deg, rgba(77, 153, 0, 0) 0%, rgba(77, 153, 0, 1) ${this.regiondata.fadeIn / this.regiondata.duration * 100}%, rgba(77, 153, 0, 1) ${(this.regiondata.duration - this.regiondata.fadeOut) / this.regiondata.duration * 100}%, rgba(77, 153, 0, 0) 100% )` }}
+ <div className="bar" ref={this._bar} style={{ transform: `translate(${this.pixelPosition}px)`,
+ width: `${this.pixelDuration}px`,
+ background: `linear-gradient(90deg, rgba(77, 153, 0, 0) 0%, rgba(77, 153, 0, 1) ${this.pixelFadeIn / this.pixelDuration}%, rgba(77, 153, 0, 1) ${(this.pixelDuration - this.pixelFadeOut) / this.pixelDuration * 100}%, rgba(77, 153, 0, 0) 100% )` }}
onPointerDown={this.onBarPointerDown}>
<div className="leftResize" onPointerDown={this.onResizeLeft} ></div>
<div className="rightResize" onPointerDown={this.onResizeRight}></div>
- {this.regiondata.keyframes!.map(kf => {
- return this.createKeyframeJSX(kf as Doc, (kf! as Doc).type as KeyframeFunc.KeyframeType);
- })}
+ {this.keyframes.map(kf => { this.createKeyframeJSX(kf, kf.type as KeyframeFunc.KeyframeType); })}
{this.keyframes.map( kf => {
if(this.keyframes.indexOf(kf ) !== this.keyframes.length - 1) {
let left = this.keyframes[this.keyframes.indexOf(kf) + 1];
let bodyRef = React.createRef<HTMLDivElement>();
+ let kfPos = KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);
+ let leftPos = KeyframeFunc.convertPixelTime(NumCast(left!.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);
return (
- <div ref={bodyRef}className="body-container" style={{left: `${NumCast(kf.time) - this.regiondata.position}px`, width:`${NumCast(left!.time) - NumCast(kf.time)}px`}}
+ <div ref={bodyRef}className="body-container" style={{left: `${kfPos - this.pixelPosition}px`, width:`${leftPos - kfPos}px`}}
onPointerOver={(e) => { this.onContainerOver(e, bodyRef); }}
onPointerOut={(e) => { this.onContainerOut(e, bodyRef); }}
onContextMenu={(e) => {