aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/animationtimeline/Region.tsx53
-rw-r--r--src/client/views/animationtimeline/Timeline.tsx62
-rw-r--r--src/client/views/animationtimeline/Track.tsx68
3 files changed, 98 insertions, 85 deletions
diff --git a/src/client/views/animationtimeline/Region.tsx b/src/client/views/animationtimeline/Region.tsx
index b09456cd7..15cbbc16f 100644
--- a/src/client/views/animationtimeline/Region.tsx
+++ b/src/client/views/animationtimeline/Region.tsx
@@ -10,6 +10,7 @@ import '../global/globalCssVariables.module.scss';
import './Region.scss';
import './Timeline.scss';
import { TimelineMenu } from './TimelineMenu';
+import { ObservableReactComponent } from '../ObservableReactComponent';
/**
* Useful static functions that you can use. Mostly for logic, but you can also add UI logic here also
@@ -156,31 +157,31 @@ interface IProps {
* @author Andrew Kim
*/
@observer
-export class Region extends React.Component<IProps> {
+export class Region extends ObservableReactComponent<IProps> {
@observable private _bar = React.createRef<HTMLDivElement>();
@observable private _mouseToggled = false;
@observable private _doubleClickEnabled = false;
@computed private get regiondata() {
- return RegionData(this.props.RegionData);
+ return RegionData(this._props.RegionData);
}
@computed private get regions() {
- return DocListCast(this.props.animatedDoc.regions);
+ return DocListCast(this._props.animatedDoc.regions);
}
@computed private get keyframes() {
return DocListCast(this.regiondata.keyframes);
}
@computed private get pixelPosition() {
- return RegionHelpers.convertPixelTime(this.regiondata.position, 'mili', 'pixel', this.props.tickSpacing, this.props.tickIncrement);
+ return RegionHelpers.convertPixelTime(this.regiondata.position, 'mili', 'pixel', this._props.tickSpacing, this._props.tickIncrement);
}
@computed private get pixelDuration() {
- return RegionHelpers.convertPixelTime(this.regiondata.duration, 'mili', 'pixel', this.props.tickSpacing, this.props.tickIncrement);
+ return RegionHelpers.convertPixelTime(this.regiondata.duration, 'mili', 'pixel', this._props.tickSpacing, this._props.tickIncrement);
}
@computed private get pixelFadeIn() {
- return RegionHelpers.convertPixelTime(this.regiondata.fadeIn, 'mili', 'pixel', this.props.tickSpacing, this.props.tickIncrement);
+ return RegionHelpers.convertPixelTime(this.regiondata.fadeIn, 'mili', 'pixel', this._props.tickSpacing, this._props.tickIncrement);
}
@computed private get pixelFadeOut() {
- return RegionHelpers.convertPixelTime(this.regiondata.fadeOut, 'mili', 'pixel', this.props.tickSpacing, this.props.tickIncrement);
+ return RegionHelpers.convertPixelTime(this.regiondata.fadeOut, 'mili', 'pixel', this._props.tickSpacing, this._props.tickIncrement);
}
constructor(props: any) {
@@ -191,10 +192,10 @@ export class Region extends React.Component<IProps> {
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, RegionHelpers.KeyframeType.end);
- const fadeIn = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.fadeIn, RegionHelpers.KeyframeType.fade);
- const fadeOut = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, RegionHelpers.KeyframeType.fade);
- const finish = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration, RegionHelpers.KeyframeType.end);
+ const start = this._props.makeKeyData(this.regiondata, this.regiondata.position, RegionHelpers.KeyframeType.end);
+ const fadeIn = this._props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.fadeIn, RegionHelpers.KeyframeType.fade);
+ const fadeOut = this._props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, RegionHelpers.KeyframeType.fade);
+ const finish = this._props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration, RegionHelpers.KeyframeType.end);
fadeIn.opacity = 1;
fadeOut.opacity = 1;
start.opacity = 0.1;
@@ -213,7 +214,7 @@ export class Region extends React.Component<IProps> {
this._doubleClickEnabled = false;
} else {
setTimeout(() => {
- if (!this._mouseToggled && this._doubleClickEnabled) this.props.changeCurrentBarX(this.pixelPosition + (clientX - this._bar.current!.getBoundingClientRect().left) * this.props.transform.Scale);
+ 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);
@@ -235,7 +236,7 @@ export class Region extends React.Component<IProps> {
const left = RegionHelpers.findAdjacentRegion(RegionHelpers.Direction.left, this.regiondata, this.regions)!;
const right = RegionHelpers.findAdjacentRegion(RegionHelpers.Direction.right, this.regiondata, this.regions)!;
const prevX = this.regiondata.position;
- const futureX = this.regiondata.position + RegionHelpers.convertPixelTime(e.movementX, 'mili', 'time', this.props.tickSpacing, this.props.tickIncrement);
+ const futureX = this.regiondata.position + RegionHelpers.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) {
@@ -274,7 +275,7 @@ export class Region extends React.Component<IProps> {
e.preventDefault();
e.stopPropagation();
const bar = this._bar.current!;
- const offset = RegionHelpers.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), 'mili', 'time', this.props.tickSpacing, this.props.tickIncrement);
+ const offset = RegionHelpers.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().left) * this._props.transform.Scale), 'mili', 'time', this._props.tickSpacing, this._props.tickIncrement);
const leftRegion = RegionHelpers.findAdjacentRegion(RegionHelpers.Direction.left, this.regiondata, this.regions);
if (leftRegion && this.regiondata.position + offset <= leftRegion.position + leftRegion.duration) {
this.regiondata.position = leftRegion.position + leftRegion.duration;
@@ -298,7 +299,7 @@ export class Region extends React.Component<IProps> {
e.preventDefault();
e.stopPropagation();
const bar = this._bar.current!;
- const offset = RegionHelpers.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().right) * this.props.transform.Scale), 'mili', 'time', this.props.tickSpacing, this.props.tickIncrement);
+ const offset = RegionHelpers.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().right) * this._props.transform.Scale), 'mili', 'time', this._props.tickSpacing, this._props.tickIncrement);
const rightRegion = RegionHelpers.findAdjacentRegion(RegionHelpers.Direction.right, this.regiondata, this.regions);
const fadeOutKeyframeTime = NumCast(this.keyframes[this.keyframes.length - 3].time);
if (this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut + offset <= fadeOutKeyframeTime) {
@@ -317,13 +318,13 @@ export class Region extends React.Component<IProps> {
createKeyframe = (clientX: number) => {
this._mouseToggled = true;
const bar = this._bar.current!;
- const offset = RegionHelpers.convertPixelTime(Math.round((clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), 'mili', 'time', this.props.tickSpacing, this.props.tickIncrement);
+ const offset = RegionHelpers.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
const position = this.regiondata.position;
- this.props.makeKeyData(this.regiondata, Math.round(position + offset), RegionHelpers.KeyframeType.default);
+ this._props.makeKeyData(this.regiondata, Math.round(position + offset), RegionHelpers.KeyframeType.default);
this.regiondata.hasData = true;
- this.props.changeCurrentBarX(RegionHelpers.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
+ this._props.changeCurrentBarX(RegionHelpers.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
}
};
@@ -331,7 +332,7 @@ export class Region extends React.Component<IProps> {
moveKeyframe = (e: React.MouseEvent, kf: Doc) => {
e.preventDefault();
e.stopPropagation();
- this.props.changeCurrentBarX(RegionHelpers.convertPixelTime(NumCast(kf.time!), 'mili', 'pixel', this.props.tickSpacing, this.props.tickIncrement));
+ this._props.changeCurrentBarX(RegionHelpers.convertPixelTime(NumCast(kf.time!), 'mili', 'pixel', this._props.tickSpacing, this._props.tickIncrement));
};
/**
@@ -374,7 +375,7 @@ export class Region extends React.Component<IProps> {
*/
@action
makeRegionMenu = (kf: Doc, e: MouseEvent) => {
- TimelineMenu.Instance.addItem('button', 'Remove Region', () => Cast(this.props.animatedDoc.regions, listSpec(Doc))?.splice(this.regions.indexOf(this.props.RegionData), 1)),
+ TimelineMenu.Instance.addItem('button', 'Remove Region', () => Cast(this._props.animatedDoc.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;
@@ -460,7 +461,7 @@ export class Region extends React.Component<IProps> {
e.stopPropagation();
const div = ref.current!;
div.style.opacity = '1';
- Doc.BrushDoc(this.props.animatedDoc);
+ Doc.BrushDoc(this._props.animatedDoc);
};
/**
@@ -472,7 +473,7 @@ export class Region extends React.Component<IProps> {
e.stopPropagation();
const div = ref.current!;
div.style.opacity = '0';
- Doc.UnBrushDoc(this.props.animatedDoc);
+ Doc.UnBrushDoc(this._props.animatedDoc);
};
///////////////////////UI STUFF /////////////////////////
@@ -486,12 +487,12 @@ export class Region extends React.Component<IProps> {
return DocListCast(this.regiondata.keyframes).map(kf => {
return (
<>
- <div className="keyframe" style={{ left: `${RegionHelpers.convertPixelTime(NumCast(kf.time), 'mili', 'pixel', this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
+ <div className="keyframe" style={{ left: `${RegionHelpers.convertPixelTime(NumCast(kf.time), 'mili', 'pixel', this._props.tickSpacing, this._props.tickIncrement) - this.pixelPosition}px` }}>
<div className="divider"></div>
<div
className="keyframeCircle keyframe-indicator"
style={{
- borderColor: this.props.saveStateKf === kf ? 'red' : undefined,
+ borderColor: this._props.saveStateKf === kf ? 'red' : undefined,
}}
onPointerDown={e => {
e.preventDefault();
@@ -526,8 +527,8 @@ export class Region extends React.Component<IProps> {
if (index !== this.keyframes.length - 1) {
const right = this.keyframes[index + 1];
const bodyRef = React.createRef<HTMLDivElement>();
- const kfPos = RegionHelpers.convertPixelTime(NumCast(kf.time), 'mili', 'pixel', this.props.tickSpacing, this.props.tickIncrement);
- const rightPos = RegionHelpers.convertPixelTime(NumCast(right.time), 'mili', 'pixel', this.props.tickSpacing, this.props.tickIncrement);
+ const kfPos = RegionHelpers.convertPixelTime(NumCast(kf.time), 'mili', 'pixel', this._props.tickSpacing, this._props.tickIncrement);
+ const rightPos = RegionHelpers.convertPixelTime(NumCast(right.time), 'mili', 'pixel', this._props.tickSpacing, this._props.tickIncrement);
keyframeDividers.push(
<div
ref={bodyRef}
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 4be3b05ab..f27a2d2fd 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -1,7 +1,7 @@
import { IconLookup } from '@fortawesome/fontawesome-svg-core';
import { faBackward, faForward, faGripLines, faPauseCircle, faPlayCircle } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable } from 'mobx';
+import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, DocListCast } from '../../../fields/Doc';
@@ -14,6 +14,7 @@ import { RegionHelpers } from './Region';
import './Timeline.scss';
import { TimelineOverview } from './TimelineOverview';
import { Track } from './Track';
+import { ObservableReactComponent } from '../ObservableReactComponent';
/**
* Timeline class controls most of timeline functions besides individual region and track mechanism. Main functions are
@@ -43,7 +44,7 @@ import { Track } from './Track';
*/
@observer
-export class Timeline extends React.Component<FieldViewProps> {
+export class Timeline extends ObservableReactComponent<FieldViewProps> {
//readonly constants
private readonly DEFAULT_TICK_SPACING: number = 50;
private readonly MAX_TITLE_HEIGHT = 75;
@@ -54,6 +55,11 @@ export class Timeline extends React.Component<FieldViewProps> {
private DEFAULT_CONTAINER_HEIGHT: number = 330;
private MIN_CONTAINER_HEIGHT: number = 205;
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
//react refs
@observable private _trackbox = React.createRef<HTMLDivElement>();
@observable private _titleContainer = React.createRef<HTMLDivElement>();
@@ -82,11 +88,11 @@ export class Timeline extends React.Component<FieldViewProps> {
*/
@computed
private get children(): Doc[] {
- const annotatedDoc = [DocumentType.IMG, DocumentType.VID, DocumentType.PDF, DocumentType.MAP].includes(StrCast(this.props.Document.type) as any);
+ const annotatedDoc = [DocumentType.IMG, DocumentType.VID, DocumentType.PDF, DocumentType.MAP].includes(StrCast(this._props.Document.type) as any);
if (annotatedDoc) {
- return DocListCast(this.props.Document[Doc.LayoutFieldKey(this.props.Document) + '_annotations']);
+ return DocListCast(this._props.Document[Doc.LayoutFieldKey(this._props.Document) + '_annotations']);
}
- return DocListCast(this.props.Document[this.props.fieldKey]);
+ return DocListCast(this._props.Document[this._props.fieldKey]);
}
/////////lifecycle functions////////////
@@ -96,21 +102,21 @@ export class Timeline extends React.Component<FieldViewProps> {
this._titleHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //check if relHeight is less than Maxheight. Else, just set relheight to max
this.MIN_CONTAINER_HEIGHT = this._titleHeight + 130; //offset
this.DEFAULT_CONTAINER_HEIGHT = this._titleHeight * 2 + 130; //twice the titleheight + offset
- if (!this.props.Document.AnimationLength) {
+ if (!this._props.Document.AnimationLength) {
//if animation length did not exist
- this.props.Document.AnimationLength = this._time; //set it to default time
+ this._props.Document.AnimationLength = this._time; //set it to default time
} else {
- this._time = NumCast(this.props.Document.AnimationLength); //else, set time to animationlength stored from before
+ this._time = NumCast(this._props.Document.AnimationLength); //else, set time to animationlength stored from before
}
this._totalLength = this._tickSpacing * (this._time / this._tickIncrement); //the entire length of the timeline div (actual div part itself)
this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width; //the visible length of the timeline (the length that you current see)
this._visibleStart = this._infoContainer.current!.scrollLeft; //where the div starts
- this.props.Document.isATOn = !this.props.Document.isATOn; //turns the boolean on, saying AT (animation timeline) is on
+ this._props.Document.isATOn = !this._props.Document.isATOn; //turns the boolean on, saying AT (animation timeline) is on
this.toggleHandle();
}
componentWillUnmount() {
- this.props.Document.AnimationLength = this._time; //save animation length
+ this._props.Document.AnimationLength = this._time; //save animation length
}
/////////////////////////////////////////////////
@@ -206,7 +212,7 @@ export class Timeline extends React.Component<FieldViewProps> {
onScrubberMove = (e: PointerEvent) => {
const scrubberbox = this._infoContainer.current!;
const left = scrubberbox.getBoundingClientRect().left;
- const offsetX = Math.round(e.clientX - left) * this.props.ScreenToLocalTransform().Scale;
+ const offsetX = Math.round(e.clientX - left) * this._props.ScreenToLocalTransform().Scale;
this.changeCurrentBarX(offsetX + this._visibleStart); //changes scrubber to clicked scrubber position
return false;
};
@@ -233,7 +239,7 @@ export class Timeline extends React.Component<FieldViewProps> {
this._visibleStart -= e.movementX;
this._totalLength -= e.movementX;
this._time -= RegionHelpers.convertPixelTime(e.movementX, 'mili', 'time', this._tickSpacing, this._tickIncrement);
- this.props.Document.AnimationLength = this._time;
+ this._props.Document.AnimationLength = this._time;
}
return false;
};
@@ -349,8 +355,8 @@ export class Timeline extends React.Component<FieldViewProps> {
private timelineToolBox = (scale: number, totalTime: number) => {
const size = 40 * scale; //50 is default
const iconSize = 25;
- const width: number = this.props.PanelWidth();
- const modeType = this.props.Document.isATOn ? 'Author' : 'Play';
+ const width: number = this._props.PanelWidth();
+ const modeType = this._props.Document.isATOn ? 'Author' : 'Play';
//decides if information should be omitted because the timeline is very small
// if its less than 950 pixels then it's going to be overlapping
@@ -389,7 +395,7 @@ export class Timeline extends React.Component<FieldViewProps> {
tickIncrement={this._tickIncrement}
time={this._time}
parent={this}
- isAuthoring={BoolCast(this.props.Document.isATOn)}
+ isAuthoring={BoolCast(this._props.Document.isATOn)}
currentBarX={this._currentBarX}
totalLength={this._totalLength}
visibleLength={this._visibleLength}
@@ -410,10 +416,10 @@ export class Timeline extends React.Component<FieldViewProps> {
</div>
<div className="time-box overview-tool" style={{ display: 'flex' }}>
{this.timeIndicator(lengthString, totalTime)}
- <div className="resetView-tool" title="Return to Default View" onClick={() => this.resetView(this.props.Document)}>
+ <div className="resetView-tool" title="Return to Default View" onClick={() => this.resetView(this._props.Document)}>
<FontAwesomeIcon icon="compress-arrows-alt" size="lg" />
</div>
- <div className="resetView-tool" style={{ display: this.props.Document.isATOn ? 'flex' : 'none' }} title="Set Default View" onClick={() => this.setView(this.props.Document)}>
+ <div className="resetView-tool" style={{ display: this._props.Document.isATOn ? 'flex' : 'none' }} title="Set Default View" onClick={() => this.setView(this._props.Document)}>
<FontAwesomeIcon icon="expand-arrows-alt" size="lg" />
</div>
</div>
@@ -423,17 +429,17 @@ export class Timeline extends React.Component<FieldViewProps> {
};
timeIndicator(lengthString: string, totalTime: number) {
- if (this.props.Document.isATOn) {
- return <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? 'visible' : 'hidden', display: this.props.Document.isATOn ? 'flex' : 'none' }}>{`Total: ${this.toReadTime(totalTime)}`}</div>;
+ if (this._props.Document.isATOn) {
+ return <div key="time-text" className="animation-text" style={{ visibility: this._props.Document.isATOn ? 'visible' : 'hidden', display: this._props.Document.isATOn ? 'flex' : 'none' }}>{`Total: ${this.toReadTime(totalTime)}`}</div>;
} else {
const ctime = `Current: ${this.getCurrentTime()}`;
const ttime = `Total: ${this.toReadTime(this._time)}`;
return (
<div style={{ flexDirection: 'column' }}>
- <div className="animation-text" style={{ fontSize: '10px', width: '100%', display: !this.props.Document.isATOn ? 'block' : 'none' }}>
+ <div className="animation-text" style={{ fontSize: '10px', width: '100%', display: !this._props.Document.isATOn ? 'block' : 'none' }}>
{ctime}
</div>
- <div className="animation-text" style={{ fontSize: '10px', width: '100%', display: !this.props.Document.isATOn ? 'block' : 'none' }}>
+ <div className="animation-text" style={{ fontSize: '10px', width: '100%', display: !this._props.Document.isATOn ? 'block' : 'none' }}>
{ttime}
</div>
</div>
@@ -459,8 +465,8 @@ export class Timeline extends React.Component<FieldViewProps> {
const roundToggleContainer = this._roundToggleContainerRef.current!;
const timelineContainer = this._timelineContainer.current!;
- this.props.Document.isATOn = !this.props.Document.isATOn;
- if (!BoolCast(this.props.Document.isATOn)) {
+ this._props.Document.isATOn = !this._props.Document.isATOn;
+ if (!BoolCast(this._props.Document.isATOn)) {
//turning on playmode...
roundToggle.style.transform = 'translate(0px, 0px)';
roundToggle.style.animationName = 'turnoff';
@@ -535,7 +541,7 @@ export class Timeline extends React.Component<FieldViewProps> {
// change visible and total width
return (
<div style={{ visibility: 'visible' }}>
- <div key="timeline_wrapper" style={{ visibility: this.props.Document.isATOn ? 'visible' : 'hidden', left: '0px', top: '0px', position: 'absolute', width: '100%', transform: 'translate(0px, 0px)' }}>
+ <div key="timeline_wrapper" style={{ visibility: this._props.Document.isATOn ? '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" onPointerDown={this.onPanDown} ref={this._infoContainer} onWheel={this.onWheelZoom}>
{this.drawTicks()}
@@ -543,18 +549,18 @@ export class Timeline extends React.Component<FieldViewProps> {
<div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown}></div>
</div>
<div key="timeline_trackbox" className="trackbox" ref={this._trackbox} style={{ width: `${this._totalLength}px` }}>
- {[...this.children, this.props.Document].map(doc => (
+ {[...this.children, this._props.Document].map(doc => (
<Track
ref={ref => this.mapOfTracks.push(ref)}
timeline={this}
animatedDoc={doc}
currentBarX={this._currentBarX}
changeCurrentBarX={this.changeCurrentBarX}
- transform={this.props.ScreenToLocalTransform()}
+ transform={this._props.ScreenToLocalTransform()}
time={this._time}
tickSpacing={this._tickSpacing}
tickIncrement={this._tickIncrement}
- collection={this.props.Document}
+ collection={this._props.Document}
timelineVisible={true}
/>
))}
@@ -562,7 +568,7 @@ export class Timeline extends React.Component<FieldViewProps> {
</div>
<div className="currentTime">Current: {this.getCurrentTime()}</div>
<div key="timeline_title" className="title-container" ref={this._titleContainer}>
- {[...this.children, this.props.Document].map(doc => (
+ {[...this.children, this._props.Document].map(doc => (
<div style={{ height: `${this._titleHeight}px` }} className="datapane" onPointerOver={() => Doc.BrushDoc(doc)} onPointerOut={() => Doc.UnBrushDoc(doc)}>
<p>{StrCast(doc.title)}</p>
</div>
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index d959241d0..00aa51cac 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -1,4 +1,4 @@
-import { action, computed, intercept, observable, reaction, runInAction } from 'mobx';
+import { action, computed, intercept, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, DocListCast, DocListCastAsync, Opt } from '../../../fields/Doc';
@@ -11,6 +11,7 @@ import { Transform } from '../../util/Transform';
import { Region, RegionData, RegionHelpers } from './Region';
import { Timeline } from './Timeline';
import './Track.scss';
+import { ObservableReactComponent } from '../ObservableReactComponent';
interface IProps {
timeline: Timeline;
@@ -26,7 +27,7 @@ interface IProps {
}
@observer
-export class Track extends React.Component<IProps> {
+export class Track extends ObservableReactComponent<IProps> {
@observable private _inner = React.createRef<HTMLDivElement>();
@observable private _currentBarXReaction: any;
@observable private _timelineVisibleReaction: any;
@@ -37,24 +38,29 @@ export class Track extends React.Component<IProps> {
private primitiveWhitelist = ['x', 'y', '_freeform_panX', '_freeform_panY', '_width', '_height', '_rotation', 'opacity', '_layout_scrollTop'];
private objectWhitelist = ['data'];
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
@computed private get regions() {
- return DocListCast(this.props.animatedDoc.regions);
+ return DocListCast(this._props.animatedDoc.regions);
}
@computed private get time() {
- return NumCast(RegionHelpers.convertPixelTime(this.props.currentBarX, 'mili', 'time', this.props.tickSpacing, this.props.tickIncrement));
+ return NumCast(RegionHelpers.convertPixelTime(this._props.currentBarX, 'mili', 'time', this._props.tickSpacing, this._props.tickIncrement));
}
componentDidMount() {
- DocListCastAsync(this.props.animatedDoc.regions).then(regions => {
- if (!regions) this.props.animatedDoc.regions = new List<Doc>(); //if there is no region, then create new doc to store stuff
+ DocListCastAsync(this._props.animatedDoc.regions).then(regions => {
+ if (!regions) this._props.animatedDoc.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;
runInAction(() => (this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT)); //for responsiveness
this._timelineVisibleReaction = this.timelineVisibleReaction();
this._currentBarXReaction = this.currentBarXReaction();
- if (DocListCast(this.props.animatedDoc.regions).length === 0) this.createRegion(this.time);
- this.props.animatedDoc.hidden = false;
- this.props.animatedDoc.opacity = 1;
+ if (DocListCast(this._props.animatedDoc.regions).length === 0) this.createRegion(this.time);
+ this._props.animatedDoc.hidden = false;
+ this._props.animatedDoc.opacity = 1;
// this.autoCreateKeyframe();
});
}
@@ -88,7 +94,7 @@ export class Track extends React.Component<IProps> {
*/
@action
saveKeyframe = () => {
- if (this.props.timeline.IsPlaying || !this.saveStateRegion || !this.saveStateKf) {
+ if (this._props.timeline.IsPlaying || !this.saveStateRegion || !this.saveStateKf) {
this.saveStateKf = undefined;
this.saveStateRegion = undefined;
return;
@@ -130,13 +136,13 @@ export class Track extends React.Component<IProps> {
*/
@action
autoCreateKeyframe = () => {
- const objects = this.objectWhitelist.map(key => this.props.animatedDoc[key]);
- intercept(this.props.animatedDoc, change => {
+ const objects = this.objectWhitelist.map(key => this._props.animatedDoc[key]);
+ intercept(this._props.animatedDoc, change => {
return change;
});
return reaction(
() => {
- return [...this.primitiveWhitelist.map(key => this.props.animatedDoc[key]), ...objects];
+ return [...this.primitiveWhitelist.map(key => this._props.animatedDoc[key]), ...objects];
},
(changed, reaction) => {
//check for region
@@ -170,18 +176,18 @@ export class Track extends React.Component<IProps> {
@action
currentBarXReaction = () => {
return reaction(
- () => this.props.currentBarX,
+ () => this._props.currentBarX,
() => {
const regiondata = this.findRegion(this.time);
if (regiondata) {
- this.props.animatedDoc.hidden = false;
+ this._props.animatedDoc.hidden = false;
// if (!this._autoKfReaction) {
// // this._autoKfReaction = this.autoCreateKeyframe();
// }
this.timeChange();
} else {
- this.props.animatedDoc.hidden = true;
- this.props.animatedDoc !== this.props.collection && (this.props.animatedDoc.opacity = 0);
+ this._props.animatedDoc.hidden = true;
+ this._props.animatedDoc !== this._props.collection && (this._props.animatedDoc.opacity = 0);
//if (this._autoKfReaction) this._autoKfReaction();
}
}
@@ -195,7 +201,7 @@ export class Track extends React.Component<IProps> {
timelineVisibleReaction = () => {
return reaction(
() => {
- return this.props.timelineVisible;
+ return this._props.timelineVisible;
},
isVisible => {
if (isVisible) {
@@ -252,14 +258,14 @@ export class Track extends React.Component<IProps> {
@action
private applyKeys = (kf: Doc) => {
this.primitiveWhitelist.forEach(key => {
- if (key === 'opacity' && this.props.animatedDoc === this.props.collection) {
+ if (key === 'opacity' && this._props.animatedDoc === this._props.collection) {
return;
}
if (!kf[key]) {
- this.props.animatedDoc[key] = undefined;
+ this._props.animatedDoc[key] = undefined;
} else {
const stored = kf[key];
- this.props.animatedDoc[key] = stored instanceof ObjectField ? stored[Copy]() : stored;
+ this._props.animatedDoc[key] = stored instanceof ObjectField ? stored[Copy]() : stored;
}
});
};
@@ -283,7 +289,7 @@ export class Track extends React.Component<IProps> {
@action
interpolate = (left: Doc, right: Doc) => {
this.primitiveWhitelist.forEach(key => {
- if (key === 'opacity' && this.props.animatedDoc === this.props.collection) {
+ if (key === 'opacity' && this._props.animatedDoc === this._props.collection) {
return;
}
if (typeof left[key] === 'number' && typeof right[key] === 'number') {
@@ -291,11 +297,11 @@ export class Track extends React.Component<IProps> {
const dif = NumCast(right[key]) - NumCast(left[key]);
const deltaLeft = this.time - NumCast(left.time);
const ratio = deltaLeft / (NumCast(right.time) - NumCast(left.time));
- this.props.animatedDoc[key] = NumCast(left[key]) + dif * ratio;
+ this._props.animatedDoc[key] = NumCast(left[key]) + dif * ratio;
} else {
// case data
const stored = left[key];
- this.props.animatedDoc[key] = stored instanceof ObjectField ? stored[Copy]() : stored;
+ this._props.animatedDoc[key] = stored instanceof ObjectField ? stored[Copy]() : stored;
}
});
};
@@ -314,8 +320,8 @@ export class Track extends React.Component<IProps> {
@action
onInnerDoubleClick = (e: React.MouseEvent) => {
const inner = this._inner.current!;
- const offsetX = Math.round((e.clientX - inner.getBoundingClientRect().left) * this.props.transform.Scale);
- this.createRegion(RegionHelpers.convertPixelTime(offsetX, 'mili', 'time', this.props.tickSpacing, this.props.tickIncrement));
+ const offsetX = Math.round((e.clientX - inner.getBoundingClientRect().left) * this._props.transform.Scale);
+ this.createRegion(RegionHelpers.convertPixelTime(offsetX, 'mili', 'time', this._props.tickSpacing, this._props.tickIncrement));
};
/**
@@ -335,7 +341,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))) {
- Cast(this.props.animatedDoc.regions, listSpec(Doc))?.push(regiondata);
+ Cast(this._props.animatedDoc.regions, listSpec(Doc))?.push(regiondata);
this._newKeyframe = true;
this.saveStateRegion = regiondata;
return regiondata;
@@ -370,7 +376,7 @@ export class Track extends React.Component<IProps> {
copyDocDataToKeyFrame = (doc: Doc) => {
var somethingChanged = false;
this.primitiveWhitelist.map(key => {
- const originalVal = this.props.animatedDoc[key];
+ const originalVal = this._props.animatedDoc[key];
somethingChanged = somethingChanged || originalVal !== doc[key];
if (doc.type === RegionHelpers.KeyframeType.end && key === 'opacity') doc.opacity = 0;
else doc[key] = originalVal instanceof ObjectField ? originalVal[Copy]() : originalVal;
@@ -391,10 +397,10 @@ export class Track extends React.Component<IProps> {
ref={this._inner}
style={{ height: `${this._trackHeight}px` }}
onDoubleClick={this.onInnerDoubleClick}
- onPointerOver={() => Doc.BrushDoc(this.props.animatedDoc)}
- onPointerOut={() => Doc.UnBrushDoc(this.props.animatedDoc)}>
+ onPointerOver={() => Doc.BrushDoc(this._props.animatedDoc)}
+ onPointerOut={() => Doc.UnBrushDoc(this._props.animatedDoc)}>
{this.regions?.map((region, i) => {
- return <Region key={`${i}`} {...this.props} saveStateKf={saveStateKf} RegionData={region} makeKeyData={this.makeKeyData} />;
+ return <Region key={`${i}`} {...this._props} saveStateKf={saveStateKf} RegionData={region} makeKeyData={this.makeKeyData} />;
})}
</div>
</div>