From 9263422913f30b54922f3c0d7290e36d4a509455 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 26 Aug 2022 12:43:00 -0400 Subject: extending pres trails to allow ink animation without using keyframes. --- src/client/views/MainView.tsx | 2 +- src/client/views/collections/CollectionMenu.tsx | 20 +++---- src/client/views/collections/TabDocView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 1 - .../views/nodes/CollectionFreeFormDocumentView.tsx | 10 ++-- src/client/views/nodes/trails/PresBox.tsx | 67 +++++++++++++++------- 6 files changed, 61 insertions(+), 41 deletions(-) (limited to 'src/client') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 06be4d194..515faa316 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -154,10 +154,10 @@ export class MainView extends React.Component { if (!MainView.Live) { DocServer.setPlaygroundFields([ 'dataTransition', + 'viewTransition', 'treeViewOpen', 'showSidebar', 'sidebarWidthPercent', - 'viewTransition', 'panX', 'panY', 'fitWidth', diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 0dc30e0fd..6a0f69359 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -726,18 +726,16 @@ export class CollectionFreeFormViewChrome extends React.Component { const presSelected: Doc | undefined = presArray && size ? presArray[size - 1] : undefined; const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null); - PresBox.pinDocView(pinDoc, pinProps); + PresBox.pinDocView(pinDoc, pinProps, doc); pinDoc.onClick = ScriptField.MakeFunction('navigateToDoc(self.presentationTargetDoc, self)'); Doc.AddDocToList(curPres, 'data', pinDoc, presSelected); if (!pinProps?.audioRange && duration !== undefined) { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index c44b33ed0..210370d39 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -278,7 +278,6 @@ export class CollectionFreeFormView extends CollectionSubView { - p[val.key] = Cast(`${val}-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); + 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 }); } public static getStringValues(doc: Doc, time: number) { return CollectionFreeFormDocumentView.animStringFields.reduce((p, val) => { - p[val] = Cast(`${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); + 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 }); } @@ -140,8 +140,8 @@ export class CollectionFreeFormDocumentView extends DocComponent (doc._viewTransition = doc.dataTransition = 'all 1s')); + public static gotoKeyframe(docs: Doc[], duration = 1000) { + docs.forEach(doc => (doc._viewTransition = doc.dataTransition = `all ${duration}ms`)); setTimeout( () => docs.forEach(doc => { @@ -226,7 +226,6 @@ export class CollectionFreeFormDocumentView extends DocComponent {this.props.renderCutoffProvider(this.props.Document) ? ( diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index eb40089ec..f254eaba6 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -6,7 +6,7 @@ import { observer } from 'mobx-react'; import { ColorState, SketchPicker } from 'react-color'; import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal'; import { Doc, DocListCast, DocListCastAsync, FieldResult } from '../../../../fields/Doc'; -import { InkTool } from '../../../../fields/InkField'; +import { InkField, InkTool } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; @@ -19,8 +19,7 @@ import { SelectionManager } from '../../../util/SelectionManager'; import { SettingsManager } from '../../../util/SettingsManager'; import { undoBatch, UndoManager } from '../../../util/UndoManager'; import { CollectionDockingView } from '../../collections/CollectionDockingView'; -import { MarqueeViewBounds } from '../../collections/collectionFreeForm'; -import { CollectionFreeFormViewChrome } from '../../collections/CollectionMenu'; +import { CollectionFreeFormView, MarqueeViewBounds } from '../../collections/collectionFreeForm'; import { CollectionView } from '../../collections/CollectionView'; import { TabDocView } from '../../collections/TabDocView'; import { ViewBoxBaseComponent } from '../../DocComponent'; @@ -30,6 +29,8 @@ import { CollectionFreeFormDocumentView } from '../CollectionFreeFormDocumentVie import { FieldView, FieldViewProps } from '../FieldView'; import './PresBox.scss'; import { PresEffect, PresMovement, PresStatus } from './PresEnums'; +import { Copy } from '../../../../fields/FieldSymbols'; +import { CollectionFreeFormViewChrome } from '../../collections/CollectionMenu'; export interface PinProps { audioRange?: boolean; @@ -317,8 +318,15 @@ export class PresBox extends ViewBoxBaseComponent() { const activeItem: Doc = this.activeItem; const targetDoc: Doc = this.targetDoc; if (activeItem.presActiveFrame !== undefined) { + const transTime = NumCast(activeItem.presDuration, 500); const context = DocCast(DocCast(activeItem.presentationTargetDoc).context); - context && CollectionFreeFormViewChrome.gotoKeyFrame(context, NumCast(activeItem.presActiveFrame)); + if (context) { + const contextView = DocumentManager.Instance.getFirstDocumentView(context); + if (contextView?.ComponentView) { + CollectionFreeFormDocumentView.gotoKeyframe((contextView.ComponentView as CollectionFreeFormView).childDocs.slice(), transTime); + context._currentFrame = NumCast(activeItem.presActiveFrame); + } + } } if (from?.mediaStopTriggerList && this.layoutDoc.presStatus !== PresStatus.Edit) { DocListCast(from.mediaStopTriggerList).forEach(this.stopTempMedia); @@ -353,8 +361,6 @@ export class PresBox extends ViewBoxBaseComponent() { navigateToView = (targetDoc: Doc, activeItem: Doc) => { clearTimeout(this._navTimer); const bestTarget = DocumentManager.Instance.getFirstDocumentView(targetDoc)?.props.Document; - if (bestTarget) console.log(bestTarget.title, bestTarget.type); - else console.log('no best target'); if (bestTarget) this._navTimer = PresBox.navigateToDoc(bestTarget, activeItem, false); }; @@ -363,17 +369,29 @@ export class PresBox extends ViewBoxBaseComponent() { const pannable = [DocumentType.IMG].includes(target.type as any) || (target.type === DocumentType.COL && target._viewType === CollectionViewType.Freeform); const temporal = [DocumentType.AUDIO, DocumentType.VID].includes(target.type as any); const clippable = [DocumentType.COMPARISON].includes(target.type as any); - return { scrollable, pannable, temporal, clippable }; + const dataview = [DocumentType.INK].includes(target.type as any) && target.activeFrame === undefined; + return { scrollable, pannable, temporal, clippable, dataview }; } // navigates to the bestTarget document by making sure it is on screen, // then it applies the view specs stored in activeItem to @action static navigateToDoc(bestTarget: Doc, activeItem: Doc, jumpToDoc: boolean) { - bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s'; - const { scrollable, pannable, temporal, clippable } = this.pinDataTypes(bestTarget); + const transTime = NumCast(activeItem.presDuration, 500); + const presTransitionTime = `all ${transTime}ms`; + bestTarget._viewTransition = presTransitionTime; + const { scrollable, pannable, temporal, clippable, dataview } = this.pinDataTypes(bestTarget); if (clippable) bestTarget._clipWidth = activeItem.presPinClipWidth; if (temporal) bestTarget._currentTimecode = activeItem.presStartTime; if (scrollable) bestTarget._scrollTop = activeItem.presPinViewScroll; + if (dataview) { + bestTarget._dataTransition = presTransitionTime; + bestTarget.data = (activeItem.presData as any as InkField)[Copy](); + bestTarget.x = NumCast(activeItem.presX); + bestTarget.y = NumCast(activeItem.presY); + bestTarget.width = NumCast(activeItem.presWidth); + bestTarget.height = NumCast(activeItem.presHeight); + } + if (pannable) { const contentBounds = Cast(activeItem.contentBounds, listSpec('number')); if (contentBounds) { @@ -389,14 +407,17 @@ export class PresBox extends ViewBoxBaseComponent() { bestTarget._viewScale = activeItem.presPinViewScale; } } - return setTimeout(() => (bestTarget._viewTransition = undefined), activeItem.presTransition ? NumCast(activeItem.presTransition) + 10 : 510); + return setTimeout(() => { + bestTarget._viewTransition = undefined; + if (dataview) bestTarget._dataTransition = undefined; + }, transTime + 10); } /// copies values from the targetDoc (which is the prototype of the pinDoc) to /// reserved fields on the pinDoc so that those values can be restored to the /// target doc when navigating to it. @action - static pinDocView(pinDoc: Doc, pinProps: PinProps | undefined) { + static pinDocView(pinDoc: Doc, pinProps: PinProps | undefined, targetDoc: Doc) { if (pinProps?.pinWithView) { // If pinWithView option set then update scale and x / y props of slide const bounds = pinProps.pinWithView.bounds; @@ -407,13 +428,20 @@ export class PresBox extends ViewBoxBaseComponent() { pinDoc.contentBounds = new List([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]); } if (pinProps?.pinDocView) { - const { scrollable, pannable, temporal, clippable } = this.pinDataTypes(pinDoc); - pinDoc.presPinView = (pinProps?.pinWithView ? true : false) || scrollable || temporal || pannable || clippable; + const { scrollable, pannable, temporal, clippable, dataview } = this.pinDataTypes(pinDoc); + pinDoc.presPinView = (pinProps?.pinWithView ? true : false) || scrollable || temporal || pannable || clippable || dataview || pinProps.activeFrame !== undefined; if (scrollable) pinDoc.presPinViewScroll = pinDoc._scrollTop; - else if (clippable) pinDoc.presPinClipWidth = pinDoc._clipWidth; - else if (temporal) pinDoc.presEndTime = NumCast((pinDoc.presStartTime = pinDoc._currentTimecode)) + 0.1; - else if (pannable) { + if (clippable) pinDoc.presPinClipWidth = pinDoc._clipWidth; + if (temporal) pinDoc.presEndTime = NumCast((pinDoc.presStartTime = pinDoc._currentTimecode)) + 0.1; + if (dataview) { + pinDoc.presData = (targetDoc.data as InkField)[Copy](); + pinDoc.presX = NumCast(targetDoc.x); + pinDoc.presY = NumCast(targetDoc.y); + pinDoc.presWidth = NumCast(targetDoc.width); + pinDoc.presHeight = NumCast(targetDoc.height); + } + if (pannable) { const panX = NumCast(pinDoc._panX); const panY = NumCast(pinDoc._panY); const pw = NumCast(pinProps.panelWidth); @@ -493,8 +521,6 @@ export class PresBox extends ViewBoxBaseComponent() { // After navigating to the document, if it is added as a presPinView then it will // adjust the pan and scale to that of the pinView when it was added. if (activeItem.presPinView) { - console.log(targetDoc.title); - console.log('presPinView in PresBox.tsx:420'); // if targetDoc is not displayed but one of its aliases is, then we need to modify that alias, not the original target this.navigateToView(targetDoc, activeItem); } @@ -866,10 +892,9 @@ export class PresBox extends ViewBoxBaseComponent() { //Regular click @action selectElement = async (doc: Doc) => { - const context = Cast(doc.context, Doc, null); this.gotoDocument(this.childDocs.indexOf(doc), this.activeItem); - if (doc.presPinView || doc.presentationTargetDoc === this.layoutDoc.presCollection) setTimeout(() => this.updateCurrentPresentation(context), 0); - else this.updateCurrentPresentation(context); + if (doc.presPinView || doc.presentationTargetDoc === this.layoutDoc.presCollection) setTimeout(() => this.updateCurrentPresentation(DocCast(doc.context)), 0); + else this.updateCurrentPresentation(DocCast(doc.context)); }; //Command click -- cgit v1.2.3-70-g09d2