diff --git a/src/mol-plugin/context.ts b/src/mol-plugin/context.ts index 9f25b9e955f48852e297cba68b55bbfeca1d6037..58a870c7682f37ee7f610b123dfdd1d146364785 100644 --- a/src/mol-plugin/context.ts +++ b/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(); diff --git a/src/mol-plugin/state/animation/manager.ts b/src/mol-plugin/state/animation/manager.ts index 5e3cb09874eb55285ebbb7fd474f93f62357c5eb..4b9105afb18e8e22b57f41ad11a0c54dbe3416b4 100644 --- a/src/mol-plugin/state/animation/manager.ts +++ b/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' }); diff --git a/src/mol-plugin/ui/controls.tsx b/src/mol-plugin/ui/controls.tsx index 00517be8e85e82032ed0b3c5ccc348c23cee6e5d..0179aac3adc522a32522a031941874ebc5f8c56e 100644 --- a/src/mol-plugin/ui/controls.tsx +++ b/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; }