diff --git a/src/mol-plugin/behavior/dynamic/selection/structure-representation-interaction.ts b/src/mol-plugin/behavior/dynamic/selection/structure-representation-interaction.ts index c794c2b0a8900c6c1cf8fa28bb83f9fcf16808c6..9580f61ace8f815f2c6ea62e08b3efff67cb0709 100644 --- a/src/mol-plugin/behavior/dynamic/selection/structure-representation-interaction.ts +++ b/src/mol-plugin/behavior/dynamic/selection/structure-representation-interaction.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Structure, StructureElement } from '../../../../mol-model/structure'; +import { Structure, StructureElement, Link } from '../../../../mol-model/structure'; import { PluginBehavior } from '../../../../mol-plugin/behavior'; import { PluginCommands } from '../../../../mol-plugin/command'; import { PluginStateObject } from '../../../../mol-plugin/state/objects'; @@ -17,10 +17,9 @@ import { StateObjectCell, StateSelection, StateTransform } from '../../../../mol import { BuiltInColorThemes } from '../../../../mol-theme/color'; import { BuiltInSizeThemes } from '../../../../mol-theme/size'; import { ButtonsType, ModifiersKeys } from '../../../../mol-util/input/input-observer'; -import { Representation } from '../../../../mol-repr/representation'; import { Binding } from '../../../../mol-util/binding'; import { ParamDefinition as PD } from '../../../../mol-util/param-definition'; -import { isEmptyLoci } from '../../../../mol-model/loci'; +import { isEmptyLoci, Loci, EmptyLoci } from '../../../../mol-model/loci'; const B = ButtonsType const M = ModifiersKeys @@ -117,19 +116,19 @@ export class StructureRepresentationInteractionBehavior extends PluginBehavior.W } register(ref: string): void { - let lastLoci: Representation.Loci = Representation.Loci.Empty; + let lastLoci: Loci = EmptyLoci; this.subscribeObservable(this.plugin.events.state.object.removed, o => { - if (!PluginStateObject.Molecule.Structure.is(o.obj) || lastLoci.loci.kind !== 'element-loci') return; - if (lastLoci.loci.structure === o.obj.data) { - lastLoci = Representation.Loci.Empty; + if (!PluginStateObject.Molecule.Structure.is(o.obj) || !StructureElement.Loci.is(lastLoci)) return; + if (lastLoci.structure === o.obj.data) { + lastLoci = EmptyLoci; } }); this.subscribeObservable(this.plugin.events.state.object.updated, o => { - if (!PluginStateObject.Molecule.Structure.is(o.oldObj) || lastLoci.loci.kind !== 'element-loci') return; - if (lastLoci.loci.structure === o.oldObj.data) { - lastLoci = Representation.Loci.Empty; + if (!PluginStateObject.Molecule.Structure.is(o.oldObj) || !StructureElement.Loci.is(lastLoci)) return; + if (lastLoci.structure === o.oldObj.data) { + lastLoci = EmptyLoci; } }); @@ -139,26 +138,36 @@ export class StructureRepresentationInteractionBehavior extends PluginBehavior.W if (Binding.match(clickInteractionAroundOnly, buttons, modifiers)) { if (isEmptyLoci(current.loci)) { this.clear(StateTransform.RootRef); - lastLoci = current; + lastLoci = current.loci; return; } - // TODO: support link and structure loci as well? - if (!StructureElement.Loci.is(current.loci)) return; + let loci: StructureElement.Loci; + if (StructureElement.Loci.is(current.loci)) { + loci = current.loci; + } else if (Link.isLoci(current.loci)) { + loci = Link.toStructureElementLoci(current.loci); + } else if (Structure.isLoci(current.loci)) { + loci = Structure.toStructureElementLoci(current.loci); + } else { + return; + } + + if (StructureElement.Loci.isEmpty(loci)) return; - const parent = this.plugin.helpers.substructureParent.get(current.loci.structure); + const parent = this.plugin.helpers.substructureParent.get(loci.structure); if (!parent || !parent.obj) return; - if (Representation.Loci.areEqual(lastLoci, current)) { - lastLoci = Representation.Loci.Empty; + if (Loci.areEqual(lastLoci, loci)) { + lastLoci = EmptyLoci; this.clear(parent.transform.ref); return; } - lastLoci = current; + lastLoci = loci; const core = MS.struct.modifier.wholeResidues([ - StructureElement.Loci.toExpression(current.loci) + StructureElement.Loci.toExpression(loci) ]); const surroundings = MS.struct.modifier.includeSurroundings({ diff --git a/src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts b/src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts index 0469f6895888095521d8384726740f55ff5d9592..c094202e698aec4585a78a5c9c6cb62b39925764 100644 --- a/src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts +++ b/src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts @@ -22,9 +22,10 @@ import { PluginCommands } from '../../../command'; import { StateSelection } from '../../../../mol-state'; import { Representation } from '../../../../mol-repr/representation'; import { ButtonsType, ModifiersKeys } from '../../../../mol-util/input/input-observer'; -import { StructureElement, Link } from '../../../../mol-model/structure'; +import { StructureElement, Link, Structure } from '../../../../mol-model/structure'; import { PluginContext } from '../../../context'; import { Binding } from '../../../../mol-util/binding'; +import { EmptyLoci, Loci, isEmptyLoci } from '../../../../mol-model/loci'; const B = ButtonsType const M = ModifiersKeys @@ -115,7 +116,7 @@ export namespace VolumeStreaming { export class Behavior extends PluginBehavior.WithSubscribers<Params> { private cache = LRUCache.create<ChannelsData>(25); public params: Params = {} as any; - private lastLoci: Representation.Loci = Representation.Loci.Empty; + private lastLoci: StructureElement.Loci | EmptyLoci = EmptyLoci; private ref: string = ''; channels: Channels = {} @@ -198,67 +199,70 @@ export namespace VolumeStreaming { this.ref = ref; this.subscribeObservable(this.plugin.events.state.object.removed, o => { - if (!PluginStateObject.Molecule.Structure.is(o.obj) || this.lastLoci.loci.kind !== 'element-loci') return; - if (this.lastLoci.loci.structure === o.obj.data) { - this.lastLoci = Representation.Loci.Empty; + if (!PluginStateObject.Molecule.Structure.is(o.obj) || !StructureElement.Loci.is(this.lastLoci)) return; + if (this.lastLoci.structure === o.obj.data) { + this.lastLoci = EmptyLoci; } }); this.subscribeObservable(this.plugin.events.state.object.updated, o => { - if (!PluginStateObject.Molecule.Structure.is(o.oldObj) || this.lastLoci.loci.kind !== 'element-loci') return; - if (this.lastLoci.loci.structure === o.oldObj.data) { - this.lastLoci = Representation.Loci.Empty; + if (!PluginStateObject.Molecule.Structure.is(o.oldObj) || !StructureElement.Loci.is(this.lastLoci)) return; + if (this.lastLoci.structure === o.oldObj.data) { + this.lastLoci = EmptyLoci; } }); this.subscribeObservable(this.plugin.behaviors.interaction.click, ({ current, buttons, modifiers }) => { if (!Binding.match(this.params.bindings.clickVolumeAroundOnly || DefaultBindings.clickVolumeAroundOnly, buttons, modifiers)) return; if (this.params.view.name !== 'selection-box') { - this.lastLoci = current; + this.lastLoci = this.getNormalizedLoci(current.loci); } else { this.updateInteraction(current); } }); } - private getBoxFromLoci(current: Representation.Loci) { - if (current.loci.kind === 'empty-loci') { - return; + private getNormalizedLoci(loci: Loci): StructureElement.Loci | EmptyLoci { + if (StructureElement.Loci.is(loci)) { + return loci; + } else if (Link.isLoci(loci)) { + return Link.toStructureElementLoci(loci); + } else if (Structure.isLoci(loci)) { + return Structure.toStructureElementLoci(loci); + } else { + return EmptyLoci; } + } - let loci: StructureElement.Loci; - - // TODO: support structure loci as well? - if (StructureElement.Loci.is(current.loci)) { - loci = current.loci; - } else if (Link.isLoci(current.loci) && current.loci.links.length !== 0) { - loci = Link.toStructureElementLoci(current.loci); - } else { - return; + private getBoxFromLoci(loci: StructureElement.Loci | EmptyLoci): Box3D { + if (isEmptyLoci(loci) || StructureElement.Loci.isEmpty(loci)) { + return Box3D.empty(); } const parent = this.plugin.helpers.substructureParent.get(loci.structure); - if (!parent) return; + if (!parent) return Box3D.empty(); const root = this.getStructureRoot(); - if (!root || !root.obj || root.obj !== parent.obj) return; + if (!root || !root.obj || root.obj !== parent.obj) return Box3D.empty(); return StructureElement.Loci.getBoundary(StructureElement.Loci.extendToWholeResidues(loci)).box; } private updateInteraction(current: Representation.Loci) { - if (Representation.Loci.areEqual(this.lastLoci, current)) { - this.lastLoci = Representation.Loci.Empty; + const loci = this.getNormalizedLoci(current.loci) + if (Loci.areEqual(this.lastLoci, loci)) { + this.lastLoci = EmptyLoci; this.updateDynamicBox(Box3D.empty()); return; } - if (current.loci.kind === 'empty-loci') { + this.lastLoci = loci; + + if (isEmptyLoci(loci)) { this.updateDynamicBox(Box3D.empty()); - this.lastLoci = current; return; } - const box = this.getBoxFromLoci(current); + const box = this.getBoxFromLoci(loci); if (!box) return; this.updateDynamicBox(box); } diff --git a/src/mol-plugin/behavior/dynamic/volume-streaming/transformers.ts b/src/mol-plugin/behavior/dynamic/volume-streaming/transformers.ts index d4f3940b79ea1ab73872ac2aadc09e9383b02759..0dd7284e7599ece28cd25786efda08053e1d6cce 100644 --- a/src/mol-plugin/behavior/dynamic/volume-streaming/transformers.ts +++ b/src/mol-plugin/behavior/dynamic/volume-streaming/transformers.ts @@ -148,7 +148,8 @@ const CreateVolumeStreamingBehavior = PluginStateTransform.BuiltIn({ })({ canAutoUpdate: ({ oldParams, newParams }) => { return oldParams.view === newParams.view - || (oldParams.view.name === newParams.view.name && oldParams.view.name === 'selection-box'); + || newParams.view.name === 'selection-box' + || newParams.view.name === 'off'; }, apply: ({ a, params }, plugin: PluginContext) => Task.create('Volume streaming', async _ => { const behavior = new VolumeStreaming.Behavior(plugin, a.data);