Browse Source

various interaction behaviors improvements

Alexander Rose 5 years ago
parent
commit
b0cdf22cb8

+ 27 - 18
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({

+ 32 - 28
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);
         }

+ 2 - 1
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);