aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/CollectionFreeFormDocumentView.tsx')
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx133
1 files changed, 68 insertions, 65 deletions
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index e154e8445..9bdb2cee7 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable, trace } from 'mobx';
+import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
import { Doc, Opt } from '../../../fields/Doc';
import { List } from '../../../fields/List';
@@ -6,25 +6,22 @@ import { listSpec } from '../../../fields/Schema';
import { ComputedField } from '../../../fields/ScriptField';
import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { DashColor, numberRange, OmitKeys } from '../../../Utils';
+import { numberRange } from '../../../Utils';
import { DocumentManager } from '../../util/DocumentManager';
import { SelectionManager } from '../../util/SelectionManager';
import { Transform } from '../../util/Transform';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { DocComponent } from '../DocComponent';
-import { InkingStroke } from '../InkingStroke';
import { StyleProp } from '../StyleProvider';
import './CollectionFreeFormDocumentView.scss';
-import { DocumentView, DocumentViewProps } from './DocumentView';
+import { DocumentView, DocumentViewProps, OpenWhere } from './DocumentView';
import React = require('react');
export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
- dataProvider?: (doc: Doc, replica: string) => { x: number; y: number; zIndex?: number; opacity?: number; highlight?: boolean; z: number; transition?: string } | undefined;
+ dataProvider?: (doc: Doc, replica: string) => { x: number; y: number; zIndex?: number; rotation?: number; color?: string; backgroundColor?: string; opacity?: number; highlight?: boolean; z: number; transition?: string } | undefined;
sizeProvider?: (doc: Doc, replica: string) => { width: number; height: number } | undefined;
renderCutoffProvider: (doc: Doc) => boolean;
zIndex?: number;
- highlight?: boolean;
- jitterRotation: number;
dataTransition?: string;
replica: string;
CollectionFreeFormView: CollectionFreeFormView;
@@ -32,35 +29,52 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
@observer
export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps>() {
- public static animFields = ['_height', '_width', 'x', 'y', '_scrollTop', 'opacity']; // fields that are configured to be animatable using animation frames
+ public static animFields: { key: string; val?: number }[] = [
+ { key: '_height' },
+ { key: '_width' },
+ { key: 'x' },
+ { key: 'y' },
+ { key: '_rotation', val: 0 },
+ { key: '_scrollTop' },
+ { key: 'opacity', val: 1 },
+ { key: '_currentFrame' },
+ { key: 'viewScale', val: 1 },
+ { key: 'viewScale', val: 1 },
+ { key: 'panX' },
+ { key: 'panY' },
+ ]; // fields that are configured to be animatable using animation frames
+ public static animStringFields = ['backgroundColor', 'color', 'fillColor']; // fields that are configured to be animatable using animation frames
+ public static animDataFields = (doc: Doc) => (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames
@observable _animPos: number[] | undefined = undefined;
@observable _contentView: DocumentView | undefined | null;
get displayName() {
+ // this makes mobx trace() statements more descriptive
return 'CollectionFreeFormDocumentView(' + this.rootDoc.title + ')';
- } // this makes mobx trace() statements more descriptive
- get maskCentering() {
- return this.props.Document.isInkMask ? InkingStroke.MaskDim / 2 : 0;
}
+
get transform() {
- return `translate(${this.X - this.maskCentering}px, ${this.Y - this.maskCentering}px) rotate(${NumCast(this.Document.jitterRotation, this.props.jitterRotation)}deg)`;
+ return `translate(${this.X}px, ${this.Y}px) rotate(${NumCast(this.Rot, this.Rot)}deg)`;
}
get X() {
- return this.dataProvider ? this.dataProvider.x : NumCast(this.Document.x);
+ return this.dataProvider?.x ?? NumCast(this.Document.x);
}
get Y() {
- return this.dataProvider ? this.dataProvider.y : NumCast(this.Document.y);
+ return this.dataProvider?.y ?? NumCast(this.Document.y);
}
get ZInd() {
- return this.dataProvider ? this.dataProvider.zIndex : NumCast(this.Document.zIndex);
+ return this.dataProvider?.zIndex ?? NumCast(this.Document.zIndex);
+ }
+ get Rot() {
+ return this.dataProvider?.rotation ?? NumCast(this.Document._rotation);
}
get Opacity() {
- return this.dataProvider ? this.dataProvider.opacity : undefined;
+ return this.dataProvider?.opacity;
}
- get Highlight() {
- return this.dataProvider?.highlight;
+ get BackgroundColor() {
+ return this.dataProvider?.backgroundColor ?? Cast(this.Document._backgroundColor, 'string', null);
}
- @computed get ShowTitle() {
- return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.ShowTitle) as Opt<string>;
+ get Color() {
+ return this.dataProvider?.color ?? Cast(this.Document._color, 'string', null);
}
@computed get dataProvider() {
return this.props.dataProvider?.(this.props.Document, this.props.replica);
@@ -70,17 +84,40 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
}
styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => {
- if (property === StyleProp.Opacity && doc === this.layoutDoc) return this.Opacity; // only change the opacity for this specific document, not its children
+ if (doc === this.layoutDoc) {
+ // prettier-ignore
+ switch (property) {
+ case StyleProp.Opacity: return this.Opacity; // only change the opacity for this specific document, not its children
+ case StyleProp.BackgroundColor: return this.BackgroundColor;
+ case StyleProp.Color: return this.Color;
+ }
+ }
return this.props.styleProvider?.(doc, props, property);
};
- public static getValues(doc: Doc, time: number) {
+ public static getValues(doc: Doc, time: number, fillIn: boolean = true) {
return CollectionFreeFormDocumentView.animFields.reduce((p, val) => {
- p[val] = Cast(`${val}-indexed`, listSpec('number'), [NumCast(doc[val])]).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as number);
+ p[val.key] = Cast(doc[`${val.key}-indexed`], listSpec('number'), fillIn ? [NumCast(doc[val.key], val.val)] : []).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as number);
return p;
}, {} as { [val: string]: Opt<number> });
}
+ public static getStringValues(doc: Doc, time: number) {
+ return CollectionFreeFormDocumentView.animStringFields.reduce((p, val) => {
+ p[val] = Cast(doc[`${val}-indexed`], listSpec('string'), [StrCast(doc[val])]).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as string);
+ return p;
+ }, {} as { [val: string]: Opt<string> });
+ }
+
+ public static setStringValues(time: number, d: Doc, vals: { [val: string]: Opt<string> }) {
+ const timecode = Math.round(time);
+ Object.keys(vals).forEach(val => {
+ const findexed = Cast(d[`${val}-indexed`], listSpec('string'), []).slice();
+ findexed[timecode] = vals[val] as any as string;
+ d[`${val}-indexed`] = new List<string>(findexed);
+ });
+ }
+
public static setValues(time: number, d: Doc, vals: { [val: string]: Opt<number> }) {
const timecode = Math.round(time);
Object.keys(vals).forEach(val => {
@@ -90,39 +127,6 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
});
}
- public static updateKeyframe(docs: Doc[], time: number, targetDoc?: Doc) {
- const timecode = Math.round(time);
- docs.forEach(
- action(doc => {
- doc._viewTransition = doc.dataTransition = 'all 1s';
- CollectionFreeFormDocumentView.animFields.forEach(val => {
- const findexed = Cast(doc[`${val}-indexed`], listSpec('number'), null);
- findexed?.length <= timecode + 1 && findexed.push(undefined as any as number);
- });
- })
- );
- setTimeout(
- () =>
- docs.forEach(doc => {
- doc._viewTransition = undefined;
- doc.dataTransition = 'inherit';
- }),
- 1010
- );
- }
-
- public static gotoKeyframe(docs: Doc[]) {
- docs.forEach(doc => (doc._viewTransition = doc.dataTransition = 'all 1s'));
- setTimeout(
- () =>
- docs.forEach(doc => {
- doc._viewTransition = undefined;
- doc.dataTransition = 'inherit';
- }),
- 1010
- );
- }
-
public static setupZoom(doc: Doc, targDoc: Doc) {
const width = new List<number>();
const height = new List<number>();
@@ -145,9 +149,13 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
// opacity is unlike other fields because it's value should not be undefined before it appears to enable it to fade-in
doc['opacity-indexed'] = new List<number>(numberRange(currTimecode + 1).map(t => (!doc.z && makeAppear && t < NumCast(doc.appearFrame) ? 0 : 1)));
}
- CollectionFreeFormDocumentView.animFields.forEach(val => (doc[val] = ComputedField.MakeInterpolated(val, 'activeFrame', doc, currTimecode)));
- doc.activeFrame = ComputedField.MakeFunction('self.context?._currentFrame||0');
- doc.dataTransition = 'inherit';
+ CollectionFreeFormDocumentView.animFields.forEach(val => (doc[val.key] = ComputedField.MakeInterpolatedNumber(val.key, 'activeFrame', doc, currTimecode, val.val)));
+ CollectionFreeFormDocumentView.animStringFields.forEach(val => (doc[val] = ComputedField.MakeInterpolatedString(val, 'activeFrame', doc, currTimecode)));
+ CollectionFreeFormDocumentView.animDataFields(doc).forEach(val => (doc[val] = ComputedField.MakeInterpolatedDataField(val, 'activeFrame', doc, currTimecode)));
+ const targetDoc = doc; // data fields, like rtf 'text' exist on the data doc, so
+ //doc !== targetDoc && (targetDoc.context = doc.context); // the computed fields don't see the layout doc -- need to copy the context to the data doc (HACK!!!) and set the activeFrame on the data doc (HACK!!!)
+ targetDoc.activeFrame = ComputedField.MakeFunction('self.context?._currentFrame||0');
+ targetDoc.dataTransition = 'inherit';
});
}
@@ -162,7 +170,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
topDoc.x = spt[0];
topDoc.y = spt[1];
this.props.removeDocument?.(topDoc);
- this.props.addDocTab(topDoc, 'inParent');
+ this.props.addDocTab(topDoc, OpenWhere.inParentFromScreen);
} else {
const spt = this.screenToLocalTransform().inverse().transformPoint(0, 0);
const fpt = screenXf.transformPoint(spt[0], spt[1]);
@@ -181,7 +189,6 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
panelWidth = () => this.sizeProvider?.width || this.props.PanelWidth?.();
panelHeight = () => this.sizeProvider?.height || this.props.PanelHeight?.();
screenToLocalTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.X, -this.Y);
- focusDoc = (doc: Doc) => this.props.focus(doc);
returnThis = () => this;
render() {
TraceMobx();
@@ -193,20 +200,16 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
PanelWidth: this.panelWidth,
PanelHeight: this.panelHeight,
};
- const background = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
- const mixBlendMode = (StrCast(this.layoutDoc.mixBlendMode) as any) || (typeof background === 'string' && background && !background.startsWith('linear') && DashColor(background).alpha() !== 1 ? 'multiply' : undefined);
return (
<div
className={'collectionFreeFormDocumentView-container'}
style={{
- outline: this.Highlight ? 'orange solid 2px' : '',
width: this.panelWidth(),
height: this.panelHeight(),
transform: this.transform,
transformOrigin: '50% 50%',
transition: this.dataProvider?.transition ?? (this.props.dataTransition ? this.props.dataTransition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.dataTransition)),
zIndex: this.ZInd,
- mixBlendMode: mixBlendMode,
display: this.ZInd === -99 ? 'none' : undefined,
}}>
{this.props.renderCutoffProvider(this.props.Document) ? (