Procházet zdrojové kódy

tweaked structure and volume surroundings behaviors

Alexander Rose před 5 roky
rodič
revize
954a5b58e0

+ 11 - 7
src/mol-plugin/behavior/dynamic/selection/structure-representation-interaction.ts

@@ -20,14 +20,14 @@ import { ButtonsType, ModifiersKeys } from '../../../../mol-util/input/input-obs
 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';
 
 const B = ButtonsType
 const M = ModifiersKeys
 const Trigger = Binding.Trigger
 
 const DefaultStructureRepresentationInteractionBindings = {
-    clickShowInteractionOnly: Binding(Trigger(B.Flag.Secondary, M.create()), 'Show only the interaction of the clicked element.'),
-    clickClearInteractionOnEmpty: Binding(Trigger(B.Flag.Secondary, M.create({ control: true })), 'Clear all interactions when the clicked element is empty.'),
+    clickInteractionAroundOnly: Binding(Trigger(B.Flag.Secondary, M.create()), 'Show the structure interaction around only the clicked element.'),
 }
 const StructureRepresentationInteractionParams = {
     bindings: PD.Value(DefaultStructureRepresentationInteractionBindings, { isHidden: true }),
@@ -134,12 +134,16 @@ export class StructureRepresentationInteractionBehavior extends PluginBehavior.W
         });
 
         this.subscribeObservable(this.plugin.behaviors.interaction.click, ({ current, buttons, modifiers }) => {
-            const { clickShowInteractionOnly, clickClearInteractionOnEmpty } = this.params.bindings
+            const { clickInteractionAroundOnly } = this.params.bindings
 
-            if (current.loci.kind === 'empty-loci' && Binding.match(clickClearInteractionOnEmpty, buttons, modifiers)) {
-                this.clear(StateTransform.RootRef);
-            } else if (Binding.match(clickShowInteractionOnly, buttons, modifiers)) {
-                // TODO: support link loci as well?
+            if (Binding.match(clickInteractionAroundOnly, buttons, modifiers)) {
+                if (isEmptyLoci(current.loci)) {
+                    this.clear(StateTransform.RootRef);
+                    lastLoci = current;
+                    return;
+                }
+
+                // TODO: support link and structure loci as well?
                 if (!StructureElement.Loci.is(current.loci)) return;
 
                 const parent = this.plugin.helpers.substructureParent.get(current.loci.structure);

+ 26 - 12
src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts

@@ -2,6 +2,7 @@
  * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
 import { ParamDefinition as PD } from '../../../../mol-util/param-definition';
@@ -20,9 +21,14 @@ import { volumeFromDensityServerData } from '../../../../mol-model-formats/volum
 import { PluginCommands } from '../../../command';
 import { StateSelection } from '../../../../mol-state';
 import { Representation } from '../../../../mol-repr/representation';
-import { ButtonsType } from '../../../../mol-util/input/input-observer';
+import { ButtonsType, ModifiersKeys } from '../../../../mol-util/input/input-observer';
 import { StructureElement } from '../../../../mol-model/structure';
 import { PluginContext } from '../../../context';
+import { Binding } from '../../../../mol-util/binding';
+
+const B = ButtonsType
+const M = ModifiersKeys
+const Trigger = Binding.Trigger
 
 export class VolumeStreaming extends PluginStateObject.CreateBehavior<VolumeStreaming.Behavior>({ name: 'Volume Streaming' }) { }
 
@@ -43,6 +49,10 @@ export namespace VolumeStreaming {
         valuesInfo: [{ mean: 0, min: -1, max: 1, sigma: 0.1 }, { mean: 0, min: -1, max: 1, sigma: 0.1 }]
     };
 
+    const DefaultBindings = {
+        clickVolumeAroundOnly: Binding(Trigger(B.Flag.Secondary, M.create()), 'Show the volume around only the clicked element.'),
+    }
+
     export function createParams(data?: VolumeServerInfo.Data, defaultView?: ViewTypes) {
         // fake the info
         const info = data || { kind: 'em', header: { sampling: [fakeSampling], availablePrecisions: [{ precision: 0, maxVoxels: 0 }] }, emDefaultContourLevel: VolumeIsoValue.relative(0) };
@@ -50,6 +60,7 @@ export namespace VolumeStreaming {
 
         return {
             view: PD.MappedStatic(defaultView || (info.kind === 'em' ? 'cell' : 'selection-box'), {
+                'off': PD.Group({}),
                 'box': PD.Group({
                     bottomLeft: PD.Vec3(box.min),
                     topRight: PD.Vec3(box.max),
@@ -60,8 +71,8 @@ export namespace VolumeStreaming {
                     topRight: PD.Vec3(Vec3.create(0, 0, 0), { isHidden: true }),
                 }, { description: 'Box around last-interacted element.', isFlat: true }),
                 'cell': PD.Group({}),
-                // 'auto': PD.Group({  }), // based on camera distance/active selection/whatever, show whole structure or slice.
-            }, { options: [['box', 'Bounded Box'], ['selection-box', 'Selection'], ['cell', 'Whole Structure']] }),
+                // 'auto': PD.Group({  }), // TODO based on camera distance/active selection/whatever, show whole structure or slice.
+            }, { options: [['off', 'Off'], ['box', 'Bounded Box'], ['selection-box', 'Surroundings'], ['cell', 'Whole Structure']] }),
             detailLevel: PD.Select<number>(Math.min(3, info.header.availablePrecisions.length - 1),
                 info.header.availablePrecisions.map((p, i) => [i, `${i + 1} [ ${Math.pow(p.maxVoxels, 1 / 3) | 0}^3 cells ]`] as [number, string])),
             channels: info.kind === 'em'
@@ -72,11 +83,12 @@ export namespace VolumeStreaming {
                     '2fo-fc': channelParam('2Fo-Fc', Color(0x3362B2), VolumeIsoValue.relative(1.5), info.header.sampling[0].valuesInfo[0]),
                     'fo-fc(+ve)': channelParam('Fo-Fc(+ve)', Color(0x33BB33), VolumeIsoValue.relative(3), info.header.sampling[0].valuesInfo[1]),
                     'fo-fc(-ve)': channelParam('Fo-Fc(-ve)', Color(0xBB3333), VolumeIsoValue.relative(-3), info.header.sampling[0].valuesInfo[1]),
-                }, { isFlat: true })
+                }, { isFlat: true }),
+            bindings: PD.Value(DefaultBindings, { isHidden: true }),
         };
     }
 
-    export type ViewTypes = 'box' | 'selection-box' | 'cell'
+    export type ViewTypes = 'off' | 'box' | 'selection-box' | 'cell'
 
     export type ParamDefinition = typeof createParams extends (...args: any[]) => (infer T) ? T : never
     export type Params = ParamDefinition extends PD.Params ? PD.Values<ParamDefinition> : {}
@@ -196,17 +208,16 @@ export namespace VolumeStreaming {
             });
 
             this.subscribeObservable(this.plugin.behaviors.interaction.click, ({ current, buttons, modifiers }) => {
-                if (buttons !== ButtonsType.Flag.Secondary || this.params.view.name !== 'selection-box') return;
+                if (this.params.view.name !== 'selection-box') return;
+                if (!Binding.match(this.params.bindings.clickVolumeAroundOnly, buttons, modifiers)) return;
 
                 if (current.loci.kind === 'empty-loci') {
-                    if (modifiers.control && buttons === ButtonsType.Flag.Secondary) {
-                        this.updateDynamicBox(ref, Box3D.empty());
-                        return;
-                    }
+                    this.updateDynamicBox(ref, Box3D.empty());
+                    lastLoci = current;
+                    return;
                 }
 
-                // TODO: support link loci as well?
-                // Perhaps structure loci too?
+                // TODO: support link and structure loci as well?
                 if (!StructureElement.Loci.is(current.loci)) return;
 
                 const parent = this.plugin.helpers.substructureParent.get(current.loci.structure);
@@ -233,6 +244,9 @@ export namespace VolumeStreaming {
             let box: Box3D | undefined = void 0, emptyData = false;
 
             switch (params.view.name) {
+                case 'off':
+                    emptyData = true;
+                    break;
                 case 'box':
                     box = Box3D.create(params.view.params.bottomLeft, params.view.params.topRight);
                     emptyData = Box3D.volume(box) < 0.0001;

+ 3 - 2
src/mol-plugin/ui/custom/volume.tsx

@@ -146,6 +146,7 @@ export class VolumeStreamingCustomControls extends PluginUIComponent<StateTransf
         // TODO: factor common things out
         const OptionsParams = {
             view: PD.MappedStatic(params.view.name, {
+                'off': PD.Group({}, { description: 'Display off.' }),
                 'box': PD.Group({
                     bottomLeft: PD.Vec3(Vec3.zero()),
                     topRight: PD.Vec3(Vec3.zero()),
@@ -161,8 +162,8 @@ export class VolumeStreamingCustomControls extends PluginUIComponent<StateTransf
                     detailLevel: this.props.info.params.detailLevel,
                     isRelative: PD.Boolean(isRelative, { description: 'Use relative or absolute iso values.' })
                 }, { description: 'Box around the structure\'s bounding box.' }),
-                // 'auto': PD.Group({  }), // based on camera distance/active selection/whatever, show whole structure or slice.
-            }, { options: [['box', 'Bounded Box'], ['selection-box', 'Selection'], ['cell', 'Whole Structure']] })
+                // 'auto': PD.Group({  }), // TODO based on camera distance/active selection/whatever, show whole structure or slice.
+            }, { options: [['off', 'Off'], ['box', 'Bounded Box'], ['selection-box', 'Surroundings'], ['cell', 'Whole Structure']] })
         };
         const options = {
             view: {