diff --git a/src/examples/basic-wrapper/index.ts b/src/examples/basic-wrapper/index.ts index ec0f3909e8bc94a53354dec4ccccdf80ee964e58..9b0ab69cbc8b6482e2e2126f4fcc7df5a3aec778 100644 --- a/src/examples/basic-wrapper/index.ts +++ b/src/examples/basic-wrapper/index.ts @@ -80,11 +80,11 @@ class BasicWrapper { animate = { modelIndex: { maxFPS: 8, - onceForward: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'forward' } } }); }, - onceBackward: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'backward' } } }); }, - palindrome: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'palindrome', params: {} } }); }, - loop: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'loop', params: {} } }); }, - stop: () => this.plugin.state.animation.stop() + onceForward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'forward' } } }); }, + onceBackward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'backward' } } }); }, + palindrome: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'palindrome', params: {} } }); }, + loop: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'loop', params: {} } }); }, + stop: () => this.plugin.managers.animation.stop() } } diff --git a/src/examples/proteopedia-wrapper/index.ts b/src/examples/proteopedia-wrapper/index.ts index d09e0e3ca4a126dc3c03a2a55d9151fa20701c8d..839ad32a08650f0f0bf68b63cdaeeb44e501c413 100644 --- a/src/examples/proteopedia-wrapper/index.ts +++ b/src/examples/proteopedia-wrapper/index.ts @@ -290,11 +290,11 @@ class MolStarProteopediaWrapper { animate = { modelIndex: { maxFPS: 8, - onceForward: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'forward' } } }); }, - onceBackward: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'backward' } } }); }, - palindrome: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'palindrome', params: {} } }); }, - loop: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'loop', params: {} } }); }, - stop: () => this.plugin.state.animation.stop() + onceForward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'forward' } } }); }, + onceBackward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'backward' } } }); }, + palindrome: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'palindrome', params: {} } }); }, + loop: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'loop', params: {} } }); }, + stop: () => this.plugin.managers.animation.stop() } } diff --git a/src/mol-plugin-state/animation/manager.ts b/src/mol-plugin-state/manager/animation.ts similarity index 99% rename from src/mol-plugin-state/animation/manager.ts rename to src/mol-plugin-state/manager/animation.ts index 13a57f56c803fc005b325ab3ea79e54162eb071a..9b3a0c4b8718e2e443860dda64338fc4faf32ac2 100644 --- a/src/mol-plugin-state/animation/manager.ts +++ b/src/mol-plugin-state/manager/animation.ts @@ -6,7 +6,7 @@ import { StatefulPluginComponent } from '../component'; import { PluginContext } from '../../mol-plugin/context'; -import { PluginStateAnimation } from './model'; +import { PluginStateAnimation } from '../animation/model'; import { ParamDefinition as PD } from '../../mol-util/param-definition'; export { PluginAnimationManager }; diff --git a/src/mol-plugin-state/manager/snapshots.ts b/src/mol-plugin-state/manager/snapshots.ts index da1126c74c34c7f5af03a96ec611d9d323e4f19e..a5a6d449d355816568119186829d94cd77bd0a09 100644 --- a/src/mol-plugin-state/manager/snapshots.ts +++ b/src/mol-plugin-state/manager/snapshots.ts @@ -283,7 +283,7 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{ togglePlay() { if (this.state.isPlaying) { this.stop(); - this.plugin.state.animation.stop(); + this.plugin.managers.animation.stop(); } else { this.play(); } diff --git a/src/mol-plugin-ui/controls.tsx b/src/mol-plugin-ui/controls.tsx index 5c8ff6ee16cd75e367df0b37565463f7a26fbcab..12e13fd98867b154ddcc4a7b57206b1fe07d59f6 100644 --- a/src/mol-plugin-ui/controls.tsx +++ b/src/mol-plugin-ui/controls.tsx @@ -208,7 +208,7 @@ export class AnimationViewportControls extends PluginUIComponent<{}, { isEmpty: } toggleExpanded = () => this.setState({ isExpanded: !this.state.isExpanded }); stop = () => { - this.plugin.state.animation.stop(); + this.plugin.managers.animation.stop(); this.plugin.managers.snapshot.stop(); } diff --git a/src/mol-plugin-ui/state/animation.tsx b/src/mol-plugin-ui/state/animation.tsx index 9ceef0a9d103724513eba77c70f62e2cc4006103..238c4ff83d4eafeb0e4c2f2ab523013967d8b3e0 100644 --- a/src/mol-plugin-ui/state/animation.tsx +++ b/src/mol-plugin-ui/state/animation.tsx @@ -12,19 +12,19 @@ import { PlayArrow } from '@material-ui/icons'; export class AnimationControls extends PluginUIComponent<{ onStart?: () => void }> { componentDidMount() { - this.subscribe(this.plugin.state.animation.events.updated, () => this.forceUpdate()); + this.subscribe(this.plugin.managers.animation.events.updated, () => this.forceUpdate()); } updateParams: ParamOnChange = p => { - this.plugin.state.animation.updateParams({ [p.name]: p.value }); + this.plugin.managers.animation.updateParams({ [p.name]: p.value }); } updateCurrentParams: ParamOnChange = p => { - this.plugin.state.animation.updateCurrentParams({ [p.name]: p.value }); + this.plugin.managers.animation.updateCurrentParams({ [p.name]: p.value }); } startOrStop = () => { - const anim = this.plugin.state.animation; + const anim = this.plugin.managers.animation; if (anim.state.animationState === 'playing') anim.stop(); else { if (this.props.onStart) this.props.onStart(); @@ -33,7 +33,7 @@ export class AnimationControls extends PluginUIComponent<{ onStart?: () => void } render() { - const anim = this.plugin.state.animation; + const anim = this.plugin.managers.animation; if (anim.isEmpty) return null; const isDisabled = anim.state.animationState === 'playing'; diff --git a/src/mol-plugin/context.ts b/src/mol-plugin/context.ts index 8bd0d05cc9ae8bf0154e658175961c2d798ec54c..bfdcc9e5e40fa07204ea198276339ff80b33bd1a 100644 --- a/src/mol-plugin/context.ts +++ b/src/mol-plugin/context.ts @@ -55,6 +55,8 @@ import { ViewportScreenshotHelper } from './util/viewport-screenshot'; import { PLUGIN_VERSION, PLUGIN_VERSION_DATE } from './version'; import { AssetManager } from '../mol-util/assets'; import { PluginStateSnapshotManager } from '../mol-plugin-state/manager/snapshots'; +import { PluginAnimationManager } from '../mol-plugin-state/manager/animation'; +import { objectForEach } from '../mol-util/object'; export class PluginContext { runTask = <T>(task: Task<T>) => this.tasks.run(task); @@ -149,6 +151,7 @@ export class PluginContext { }, interactivity: void 0 as any as InteractivityManager, camera: new CameraManager(this), + animation: new PluginAnimationManager(this), snapshot: new PluginStateSnapshotManager(this), lociLabels: void 0 as any as LociLabelManager, toast: new PluginToastManager(this), @@ -242,6 +245,10 @@ export class PluginContext { this.state.dispose(); this.tasks.dispose(); this.layout.dispose(); + + objectForEach(this.managers, m => (m as any).dispose?.()); + objectForEach(this.managers.structure, m => (m as any).dispose?.()); + this.disposed = true; } @@ -326,7 +333,7 @@ export class PluginContext { private initAnimations() { if (!this.spec.animations) return; for (const anim of this.spec.animations) { - this.state.animation.register(anim); + this.managers.animation.register(anim); } } diff --git a/src/mol-plugin/state.ts b/src/mol-plugin/state.ts index e37a003d55a0481983294fa3ea6cf9536a7c58c8..97b35c61ac9932db2cb1295d6552f0327f197812 100644 --- a/src/mol-plugin/state.ts +++ b/src/mol-plugin/state.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> */ @@ -8,23 +8,22 @@ import { State, StateTransform, StateTransformer } from '../mol-state'; import { PluginStateObject as SO } from '../mol-plugin-state/objects'; import { Camera } from '../mol-canvas3d/camera'; import { PluginBehavior } from './behavior'; -import { RxEventHelper } from '../mol-util/rx-event-helper'; import { Canvas3DProps } from '../mol-canvas3d/canvas3d'; import { PluginCommands } from './commands'; -import { PluginAnimationManager } from '../mol-plugin-state/animation/manager'; +import { PluginAnimationManager } from '../mol-plugin-state/manager/animation'; import { ParamDefinition as PD } from '../mol-util/param-definition'; import { UUID } from '../mol-util'; import { InteractivityManager } from '../mol-plugin-state/manager/interactivity'; import { produce } from 'immer'; import { StructureFocusSnapshot } from '../mol-plugin-state/manager/structure/focus'; + export { PluginState }; class PluginState { - private ev = RxEventHelper.create(); + private get animation() { return this.plugin.managers.animation; } readonly data: State; readonly behaviors: State; - readonly animation: PluginAnimationManager; getSnapshot(params?: PluginState.GetSnapshotParams): PluginState.Snapshot { const p = { ...PluginState.DefaultGetSnapshotParams, ...params }; @@ -76,11 +75,6 @@ class PluginState { } } - applyTransform(state: State, a: StateTransform.Ref, transformer: StateTransformer, params: any) { - const tree = state.build().to(a).apply(transformer, params); - return PluginCommands.State.Update(this.plugin, { state, tree }); - } - updateTransform(state: State, a: StateTransform.Ref, params: any, canUndo?: string | boolean) { const tree = state.build().to(a).update(params); return PluginCommands.State.Update(this.plugin, { state, tree, options: { canUndo } }); @@ -98,7 +92,6 @@ class PluginState { } dispose() { - this.ev.dispose(); this.data.dispose(); this.behaviors.dispose(); this.animation.dispose(); @@ -107,14 +100,10 @@ class PluginState { constructor(private plugin: import('./context').PluginContext) { this.data = State.create(new SO.Root({ }), { runTask: plugin.runTask, globalContext: plugin }); this.behaviors = State.create(new PluginBehavior.Root({ }), { runTask: plugin.runTask, globalContext: plugin, rootState: { isLocked: true } }); - - this.animation = new PluginAnimationManager(plugin); } } namespace PluginState { - export type Kind = 'data' | 'behavior' - export type CameraTransitionStyle = 'instant' | 'animate' export const GetSnapshotParams = { durationInMs: PD.Numeric(1500, { min: 100, max: 15000, step: 100 }, { label: 'Duration in ms' }), @@ -125,8 +114,6 @@ namespace PluginState { canvas3d: PD.Boolean(true), interactivity: PD.Boolean(true), camera: PD.Boolean(true), - // TODO: make camera snapshots same as the StateSnapshots with "child states?" - cameraSnapshots: PD.Boolean(false), cameraTranstion: PD.MappedStatic('animate', { animate: PD.Group({ durationInMs: PD.Numeric(250, { min: 100, max: 5000, step: 500 }, { label: 'Duration in ms' }),