Prechádzať zdrojové kódy

mol-plugin: isAnimating event

David Sehnal 6 rokov pred
rodič
commit
125ae7c99a

+ 11 - 1
src/mol-plugin/context.ts

@@ -55,7 +55,6 @@ export class PluginContext {
                 removed: merge(this.state.dataState.events.object.removed, this.state.behaviorState.events.object.removed),
                 updated: merge(this.state.dataState.events.object.updated, this.state.behaviorState.events.object.updated)
             },
-            isUpdating: merge(this.state.dataState.events.isUpdating, this.state.behaviorState.events.isUpdating),
             cameraSnapshots: this.state.cameraSnapshots.events,
             snapshots: this.state.snapshots.events,
         },
@@ -67,6 +66,10 @@ export class PluginContext {
     };
 
     readonly behaviors = {
+        state: {
+            isAnimating: this.ev.behavior<boolean>(false),
+            isUpdating: this.ev.behavior<boolean>(false)
+        },
         canvas3d: {
             highlight: this.ev.behavior<Canvas3D.HighlightEvent>({ current: Representation.Loci.Empty, prev: Representation.Loci.Empty }),
             click: this.ev.behavior<Canvas3D.ClickEvent>({ current: Representation.Loci.Empty, modifiers: ModifiersKeys.None, buttons: 0 })
@@ -160,6 +163,12 @@ export class PluginContext {
         return PluginCommands.State.Update.dispatch(this, { state, tree });
     }
 
+    private initBehaviorEvents() {
+        merge(this.state.dataState.events.isUpdating, this.state.behaviorState.events.isUpdating).subscribe(u => {
+            this.behaviors.state.isUpdating.next(u);
+        });
+    }
+
     private initBuiltInBehavior() {
         BuiltInPluginBehaviors.State.registerDefault(this);
         BuiltInPluginBehaviors.Representation.registerDefault(this);
@@ -207,6 +216,7 @@ export class PluginContext {
     constructor(public spec: PluginSpec) {
         this.events.log.subscribe(e => this.log.entries = this.log.entries.push(e));
 
+        this.initBehaviorEvents();
         this.initBuiltInBehavior();
 
         this.initBehaviors();

+ 6 - 0
src/mol-plugin/state/animation/manager.ts

@@ -91,6 +91,9 @@ class PluginAnimationManager extends PluginComponent<PluginAnimationManager.Stat
     start() {
         this.context.canvas3d.setSceneAnimating(true);
         this.updateState({ animationState: 'playing' });
+        if (!this.context.behaviors.state.isAnimating.value) {
+            this.context.behaviors.state.isAnimating.next(true);
+        }
         this.triggerUpdate();
 
         this._current.lastTime = 0;
@@ -103,6 +106,9 @@ class PluginAnimationManager extends PluginComponent<PluginAnimationManager.Stat
     stop() {
         this.context.canvas3d.setSceneAnimating(false);
         if (typeof this._frame !== 'undefined') cancelAnimationFrame(this._frame);
+        if (this.context.behaviors.state.isAnimating.value) {
+            this.context.behaviors.state.isAnimating.next(false);
+        }
 
         if (this.state.animationState !== 'stopped') {
             this.updateState({ animationState: 'stopped' });

+ 11 - 7
src/mol-plugin/ui/controls.tsx

@@ -56,6 +56,7 @@ export class TrajectoryControls extends PluginUIComponent<{}, { show: boolean, l
 
     componentDidMount() {
         this.subscribe(this.plugin.state.dataState.events.changed, this.update);
+        this.subscribe(this.plugin.behaviors.state.isAnimating, this.update);
     }
 
     reset = () => PluginCommands.State.ApplyAction.dispatch(this.plugin, {
@@ -76,22 +77,25 @@ export class TrajectoryControls extends PluginUIComponent<{}, { show: boolean, l
     render() {
         if (!this.state.show) return null;
 
+        const isAnimating = this.plugin.behaviors.state.isAnimating.value;
+
         return <div className='msp-traj-controls'>
-            <IconButton icon='model-first' title='First Model' onClick={this.reset} />
-            <IconButton icon='model-prev' title='Previous Model' onClick={this.prev} />
-            <IconButton icon='model-next' title='Next Model' onClick={this.next} />
+            <IconButton icon='model-first' title='First Model' onClick={this.reset} disabled={isAnimating} />
+            <IconButton icon='model-prev' title='Previous Model' onClick={this.prev} disabled={isAnimating} />
+            <IconButton icon='model-next' title='Next Model' onClick={this.next} disabled={isAnimating} />
             { !!this.state.label && <span>{this.state.label}</span> }
         </div>;
     }
 }
 
-export class StateSnapshotViewportControls extends PluginUIComponent<{}, { isBusy: boolean }> {
-    state = { isBusy: false }
+export class StateSnapshotViewportControls extends PluginUIComponent<{}, { isBusy: boolean, show: boolean }> {
+    state = { isBusy: false, show: true }
 
     componentDidMount() {
         // TODO: this needs to be diabled when the state is updating!
         this.subscribe(this.plugin.state.snapshots.events.changed, () => this.forceUpdate());
-        this.subscribe(this.plugin.events.state.isUpdating, (isBusy) => this.setState({ isBusy }));
+        this.subscribe(this.plugin.behaviors.state.isUpdating, isBusy => this.setState({ isBusy }));
+        this.subscribe(this.plugin.behaviors.state.isAnimating, isAnimating => this.setState({ show: !isAnimating }));
     }
 
     async update(id: string) {
@@ -121,7 +125,7 @@ export class StateSnapshotViewportControls extends PluginUIComponent<{}, { isBus
         const snapshots = this.plugin.state.snapshots;
         const count = snapshots.state.entries.size;
 
-        if (count < 2) {
+        if (count < 2 || !this.state.show) {
             return null;
         }