|
@@ -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;
|