Sfoglia il codice sorgente

Merge branch 'master' of https://github.com/molstar/molstar

David Sehnal 4 anni fa
parent
commit
4632a6f305
32 ha cambiato i file con 121 aggiunte e 71 eliminazioni
  1. 1 1
      src/examples/proteopedia-wrapper/index.ts
  2. 1 1
      src/extensions/alpha-orbitals/gpu/compute.ts
  3. 14 14
      src/extensions/alpha-orbitals/gpu/shader.frag.ts
  4. 3 3
      src/extensions/anvil/representation.ts
  5. 1 1
      src/extensions/cellpack/state.ts
  6. 5 5
      src/mol-canvas3d/canvas3d.ts
  7. 1 1
      src/mol-canvas3d/helper/bounding-sphere-helper.ts
  8. 10 10
      src/mol-canvas3d/helper/interaction-events.ts
  9. 35 5
      src/mol-canvas3d/passes/pick.ts
  10. 1 0
      src/mol-geo/geometry/base.ts
  11. 0 5
      src/mol-geo/geometry/picking.ts
  12. 1 0
      src/mol-gl/_spec/renderer.spec.ts
  13. 1 0
      src/mol-gl/renderable.ts
  14. 2 2
      src/mol-gl/renderable/schema.ts
  15. 7 5
      src/mol-gl/renderer.ts
  16. 1 1
      src/mol-gl/shader/chunks/apply-fog.glsl.ts
  17. 1 1
      src/mol-gl/shader/chunks/apply-interior-color.glsl.ts
  18. 2 2
      src/mol-gl/shader/chunks/common-frag-params.glsl.ts
  19. 2 2
      src/mol-gl/shader/direct-volume.frag.ts
  20. 4 2
      src/mol-gl/webgl/uniform.ts
  21. 3 3
      src/mol-plugin-state/manager/interactivity.ts
  22. 5 1
      src/mol-repr/representation.ts
  23. 1 0
      src/mol-repr/shape/representation.ts
  24. 3 0
      src/mol-repr/structure/complex-visual.ts
  25. 3 0
      src/mol-repr/structure/units-visual.ts
  26. 5 0
      src/mol-repr/visual.ts
  27. 3 0
      src/mol-repr/volume/representation.ts
  28. 1 1
      src/mol-task/execution/observable.ts
  29. 1 1
      src/mol-util/color/color.ts
  30. 1 2
      src/mol-util/is-little-endian.ts
  31. 1 1
      src/tests/browser/render-shape.ts
  32. 1 1
      src/tests/browser/render-structure.ts

+ 1 - 1
src/examples/proteopedia-wrapper/index.ts

@@ -403,7 +403,7 @@ class MolStarProteopediaWrapper {
         },
         },
         download: async (type: 'molj' | 'molx' = 'molj', params?: PluginState.SnapshotParams) => {
         download: async (type: 'molj' | 'molx' = 'molj', params?: PluginState.SnapshotParams) => {
             const data = await this.plugin.managers.snapshot.serialize({ type, params });
             const data = await this.plugin.managers.snapshot.serialize({ type, params });
-            download(data, `mol-star_state_${(name || getFormattedTime())}.${type}`);
+            download(data, `mol-star_state_${getFormattedTime()}.${type}`);
         },
         },
         fetch: async (url: string, type: 'molj' | 'molx' = 'molj') => {
         fetch: async (url: string, type: 'molj' | 'molx' = 'molj') => {
             try {
             try {

+ 1 - 1
src/extensions/alpha-orbitals/gpu/compute.ts

@@ -32,7 +32,7 @@ const AlphaOrbitalsSchema = {
     uNAlpha: UniformSpec('i'),
     uNAlpha: UniformSpec('i'),
     uNCoeff: UniformSpec('i'),
     uNCoeff: UniformSpec('i'),
     uMaxCoeffs: UniformSpec('i'),
     uMaxCoeffs: UniformSpec('i'),
-    uLittleEndian: UniformSpec('i') // TODO: boolean uniforms
+    uLittleEndian: UniformSpec('b')
 };
 };
 const AlphaOrbitalsShaderCode = ShaderCode('postprocessing', quad_vert, shader_frag);
 const AlphaOrbitalsShaderCode = ShaderCode('postprocessing', quad_vert, shader_frag);
 type AlphaOrbitalsRenderable = ComputeRenderable<Values<typeof AlphaOrbitalsSchema>>
 type AlphaOrbitalsRenderable = ComputeRenderable<Values<typeof AlphaOrbitalsSchema>>

+ 14 - 14
src/extensions/alpha-orbitals/gpu/shader.frag.ts

@@ -28,7 +28,7 @@ uniform float uWidth;
 uniform int uNCoeff;
 uniform int uNCoeff;
 uniform int uNAlpha;
 uniform int uNAlpha;
 
 
-uniform int uLittleEndian;
+uniform bool uLittleEndian;
 
 
 float shiftRight (float v, float amt) {
 float shiftRight (float v, float amt) {
   v = floor(v) + 0.5;
   v = floor(v) + 0.5;
@@ -61,9 +61,9 @@ vec4 floatToRgba(float texelFloat) {
     float byte2 = (last_bit_of_biased_exponent * 128.0 + extractBits(fraction, 16.0, 23.0)) / 255.0;
     float byte2 = (last_bit_of_biased_exponent * 128.0 + extractBits(fraction, 16.0, 23.0)) / 255.0;
     float byte1 = (sign * 128.0 + remaining_bits_of_biased_exponent) / 255.0;
     float byte1 = (sign * 128.0 + remaining_bits_of_biased_exponent) / 255.0;
     return (
     return (
-      uLittleEndian > 0
-      ? vec4(byte4, byte3, byte2, byte1)
-      : vec4(byte1, byte2, byte3, byte4)
+        uLittleEndian
+            ? vec4(byte4, byte3, byte2, byte1)
+            : vec4(byte1, byte2, byte3, byte4)
     );
     );
 }
 }
 
 
@@ -118,13 +118,13 @@ float L4(vec3 p, float a0, float a1, float a2, float a3, float a4, float a5, flo
 
 
 float alpha(float offset, float f) {
 float alpha(float offset, float f) {
     #ifdef uMaxCoeffs
     #ifdef uMaxCoeffs
-    // in webgl1, the value is in the alpha channel!
-    return texture2D(tAlpha, vec2(offset * f, 0.5)).a;
-    #endif 
+        // in webgl1, the value is in the alpha channel!
+        return texture2D(tAlpha, vec2(offset * f, 0.5)).a;
+    #endif
 
 
     #ifndef uMaxCoeffs
     #ifndef uMaxCoeffs
-    return texture2D(tAlpha, vec2(offset * f, 0.5)).x;
-    #endif 
+        return texture2D(tAlpha, vec2(offset * f, 0.5)).x;
+    #endif
 }
 }
 
 
 float Y(int L, vec3 X, float aO, float fA) {
 float Y(int L, vec3 X, float aO, float fA) {
@@ -140,12 +140,12 @@ float Y(int L, vec3 X, float aO, float fA) {
         );
         );
     } else if (L == 3) {
     } else if (L == 3) {
         return L3(X,
         return L3(X,
-            alpha(aO, fA), alpha(aO + 1.0, fA), alpha(aO + 2.0, fA), alpha(aO + 3.0, fA), alpha(aO + 4.0, fA), 
+            alpha(aO, fA), alpha(aO + 1.0, fA), alpha(aO + 2.0, fA), alpha(aO + 3.0, fA), alpha(aO + 4.0, fA),
             alpha(aO + 5.0, fA), alpha(aO + 6.0, fA)
             alpha(aO + 5.0, fA), alpha(aO + 6.0, fA)
         );
         );
     } else if (L == 4) {
     } else if (L == 4) {
         return L4(X,
         return L4(X,
-            alpha(aO, fA), alpha(aO + 1.0, fA), alpha(aO + 2.0, fA), alpha(aO + 3.0, fA), alpha(aO + 4.0, fA), 
+            alpha(aO, fA), alpha(aO + 1.0, fA), alpha(aO + 2.0, fA), alpha(aO + 3.0, fA), alpha(aO + 4.0, fA),
             alpha(aO + 5.0, fA), alpha(aO + 6.0, fA), alpha(aO + 7.0, fA), alpha(aO + 8.0, fA)
             alpha(aO + 5.0, fA), alpha(aO + 6.0, fA), alpha(aO + 7.0, fA), alpha(aO + 8.0, fA)
         );
         );
     }
     }
@@ -182,15 +182,15 @@ float Y(int L, vec3 X, float aO, float fA) {
 float intDiv(float a, float b) { return float(int(a) / int(b)); }
 float intDiv(float a, float b) { return float(int(a) / int(b)); }
 float intMod(float a, float b) { return a - b * float(int(a) / int(b)); }
 float intMod(float a, float b) { return a - b * float(int(a) / int(b)); }
 
 
-void main(void) { 
+void main(void) {
     float offset = floor(gl_FragCoord.x) + floor(gl_FragCoord.y) * uWidth;
     float offset = floor(gl_FragCoord.x) + floor(gl_FragCoord.y) * uWidth;
-    
+
     // axis order fast to slow Z, Y, X
     // axis order fast to slow Z, Y, X
     // TODO: support arbitrary axis orders?
     // TODO: support arbitrary axis orders?
     float k = intMod(offset, uDimensions.z), kk = intDiv(offset, uDimensions.z);
     float k = intMod(offset, uDimensions.z), kk = intDiv(offset, uDimensions.z);
     float j = intMod(kk, uDimensions.y);
     float j = intMod(kk, uDimensions.y);
     float i = intDiv(kk, uDimensions.y);
     float i = intDiv(kk, uDimensions.y);
-    
+
     vec3 xyz = uMin + uDelta * vec3(i, j, k);
     vec3 xyz = uMin + uDelta * vec3(i, j, k);
 
 
     float fCenter = 1.0 / float(uNCenters - 1);
     float fCenter = 1.0 / float(uNCenters - 1);

+ 3 - 3
src/extensions/anvil/representation.ts

@@ -106,7 +106,7 @@ function getBilayerRims(ctx: RuntimeContext, data: Structure, props: BilayerRims
     const builder = LinesBuilder.create(128, 64, shape?.geometry);
     const builder = LinesBuilder.create(128, 64, shape?.geometry);
     getLayerCircle(builder, p1, centroid, normal, scaledRadius, props);
     getLayerCircle(builder, p1, centroid, normal, scaledRadius, props);
     getLayerCircle(builder, p2, centroid, normal, scaledRadius, props);
     getLayerCircle(builder, p2, centroid, normal, scaledRadius, props);
-    return Shape.create(name, data, builder.getLines(), () => props.color, () => props.linesSize, () => membraneLabel(data));
+    return Shape.create('Bilayer rims', data, builder.getLines(), () => props.color, () => props.linesSize, () => membraneLabel(data));
 }
 }
 
 
 function getLayerCircle(builder: LinesBuilder, p: Vec3, centroid: Vec3, normal: Vec3, radius: number, props: BilayerRimsProps, shape?: Shape<Lines>) {
 function getLayerCircle(builder: LinesBuilder, p: Vec3, centroid: Vec3, normal: Vec3, radius: number, props: BilayerRimsProps, shape?: Shape<Lines>) {
@@ -142,7 +142,7 @@ function getBilayerPlanes(ctx: RuntimeContext, data: Structure, props: BilayerPl
     const scaledRadius = props.radiusFactor * radius;
     const scaledRadius = props.radiusFactor * radius;
     getLayerPlane(state, p1, centroid, normal, scaledRadius);
     getLayerPlane(state, p1, centroid, normal, scaledRadius);
     getLayerPlane(state, p2, centroid, normal, scaledRadius);
     getLayerPlane(state, p2, centroid, normal, scaledRadius);
-    return Shape.create(name, data, MeshBuilder.getMesh(state), () => props.color, () => 1, () => membraneLabel(data));
+    return Shape.create('Bilayer planes', data, MeshBuilder.getMesh(state), () => props.color, () => 1, () => membraneLabel(data));
 }
 }
 
 
 function getLayerPlane(state: MeshBuilder.State, p: Vec3, centroid: Vec3, normal: Vec3, radius: number) {
 function getLayerPlane(state: MeshBuilder.State, p: Vec3, centroid: Vec3, normal: Vec3, radius: number) {
@@ -160,7 +160,7 @@ function getBilayerSpheres(ctx: RuntimeContext, data: Structure, props: BilayerS
     const spheresBuilder = SpheresBuilder.create(256, 128, shape?.geometry);
     const spheresBuilder = SpheresBuilder.create(256, 128, shape?.geometry);
     getLayerSpheres(spheresBuilder, planePoint1, normalVector, density, scaledRadius);
     getLayerSpheres(spheresBuilder, planePoint1, normalVector, density, scaledRadius);
     getLayerSpheres(spheresBuilder, planePoint2, normalVector, density, scaledRadius);
     getLayerSpheres(spheresBuilder, planePoint2, normalVector, density, scaledRadius);
-    return Shape.create(name, data, spheresBuilder.getSpheres(), () => props.color, () => props.sphereSize, () => membraneLabel(data));
+    return Shape.create('Bilayer spheres', data, spheresBuilder.getSpheres(), () => props.color, () => props.sphereSize, () => membraneLabel(data));
 }
 }
 
 
 function getLayerSpheres(spheresBuilder: SpheresBuilder, point: Vec3, normalVector: Vec3, density: number, sqRadius: number) {
 function getLayerSpheres(spheresBuilder: SpheresBuilder, point: Vec3, normalVector: Vec3, density: number, sqRadius: number) {

+ 1 - 1
src/extensions/cellpack/state.ts

@@ -125,7 +125,7 @@ const StructureFromAssemblies = PluginStateTransform.BuiltIn({
                     const s = await StructureSymmetry.buildAssembly(initial_structure, a.id).runInContext(ctx);
                     const s = await StructureSymmetry.buildAssembly(initial_structure, a.id).runInContext(ctx);
                     structures.push(s);
                     structures.push(s);
                 }
                 }
-                const builder = Structure.Builder({ label: name });
+                const builder = Structure.Builder();
                 let offsetInvariantId = 0;
                 let offsetInvariantId = 0;
                 for (const s of structures) {
                 for (const s of structures) {
                     let maxInvariantId = 0;
                     let maxInvariantId = 0;

+ 5 - 5
src/mol-canvas3d/canvas3d.ts

@@ -27,7 +27,7 @@ import { Canvas3dInteractionHelper } from './helper/interaction-events';
 import { PostprocessingParams, PostprocessingPass } from './passes/postprocessing';
 import { PostprocessingParams, PostprocessingPass } from './passes/postprocessing';
 import { MultiSampleParams, MultiSamplePass } from './passes/multi-sample';
 import { MultiSampleParams, MultiSamplePass } from './passes/multi-sample';
 import { DrawPass } from './passes/draw';
 import { DrawPass } from './passes/draw';
-import { PickPass } from './passes/pick';
+import { PickData, PickPass } from './passes/pick';
 import { ImagePass, ImageProps } from './passes/image';
 import { ImagePass, ImageProps } from './passes/image';
 import { Sphere3D } from '../mol-math/geometry';
 import { Sphere3D } from '../mol-math/geometry';
 import { isDebugMode } from '../mol-util/debug';
 import { isDebugMode } from '../mol-util/debug';
@@ -100,7 +100,7 @@ interface Canvas3D {
     requestDraw(force?: boolean): void
     requestDraw(force?: boolean): void
     animate(): void
     animate(): void
     pause(): void
     pause(): void
-    identify(x: number, y: number): PickingId | undefined
+    identify(x: number, y: number): PickData | undefined
     mark(loci: Representation.Loci, action: MarkerAction): void
     mark(loci: Representation.Loci, action: MarkerAction): void
     getLoci(pickingId: PickingId | undefined): Representation.Loci
     getLoci(pickingId: PickingId | undefined): Representation.Loci
 
 
@@ -132,9 +132,9 @@ const cancelAnimationFrame = typeof window !== 'undefined'
     : (handle: number) => clearImmediate(handle as unknown as NodeJS.Immediate);
     : (handle: number) => clearImmediate(handle as unknown as NodeJS.Immediate);
 
 
 namespace Canvas3D {
 namespace Canvas3D {
-    export interface HoverEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys }
+    export interface HoverEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys, page?: Vec2, position?: Vec3 }
     export interface DragEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys, pageStart: Vec2, pageEnd: Vec2 }
     export interface DragEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys, pageStart: Vec2, pageEnd: Vec2 }
-    export interface ClickEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys }
+    export interface ClickEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys, position?: Vec3 }
 
 
     export function fromCanvas(canvas: HTMLCanvasElement, props: PartialCanvas3DProps = {}, attribs: Partial<{ antialias: boolean, pixelScale: number }> = {}) {
     export function fromCanvas(canvas: HTMLCanvasElement, props: PartialCanvas3DProps = {}, attribs: Partial<{ antialias: boolean, pixelScale: number }> = {}) {
         const gl = getGLContext(canvas, {
         const gl = getGLContext(canvas, {
@@ -346,7 +346,7 @@ namespace Canvas3D {
             animationFrameHandle = 0;
             animationFrameHandle = 0;
         }
         }
 
 
-        function identify(x: number, y: number): PickingId | undefined {
+        function identify(x: number, y: number): PickData | undefined {
             return webgl.isContextLost ? undefined : pickPass.identify(x, y);
             return webgl.isContextLost ? undefined : pickPass.identify(x, y);
         }
         }
 
 

+ 1 - 1
src/mol-canvas3d/helper/bounding-sphere-helper.ts

@@ -160,5 +160,5 @@ const instanceMaterialId = getNextMaterialId();
 
 
 function createBoundingSphereRenderObject(mesh: Mesh, color: Color, materialId: number, transform?: TransformData) {
 function createBoundingSphereRenderObject(mesh: Mesh, color: Color, materialId: number, transform?: TransformData) {
     const values = Mesh.Utils.createValuesSimple(mesh, { alpha: 0.1, doubleSided: false }, color, 1, transform);
     const values = Mesh.Utils.createValuesSimple(mesh, { alpha: 0.1, doubleSided: false }, color, 1, transform);
-    return createRenderObject('mesh', values, { visible: true, alphaFactor: 1, pickable: false, opaque: false, writeDepth: false }, materialId);
+    return createRenderObject('mesh', values, { visible: true, alphaFactor: 1, pickable: false, colorOnly: false, opaque: false, writeDepth: false }, materialId);
 }
 }

+ 10 - 10
src/mol-canvas3d/helper/interaction-events.ts

@@ -9,7 +9,7 @@ import { PickingId } from '../../mol-geo/geometry/picking';
 import { Representation } from '../../mol-repr/representation';
 import { Representation } from '../../mol-repr/representation';
 import InputObserver, { ModifiersKeys, ButtonsType } from '../../mol-util/input/input-observer';
 import InputObserver, { ModifiersKeys, ButtonsType } from '../../mol-util/input/input-observer';
 import { RxEventHelper } from '../../mol-util/rx-event-helper';
 import { RxEventHelper } from '../../mol-util/rx-event-helper';
-import { Vec2 } from '../../mol-math/linear-algebra';
+import { Vec2, Vec3 } from '../../mol-math/linear-algebra';
 import { Camera } from '../camera';
 import { Camera } from '../camera';
 
 
 type Canvas3D = import('../canvas3d').Canvas3D
 type Canvas3D = import('../canvas3d').Canvas3D
@@ -34,6 +34,7 @@ export class Canvas3dInteractionHelper {
     private endY = -1;
     private endY = -1;
 
 
     private id: PickingId | undefined = void 0;
     private id: PickingId | undefined = void 0;
+    private position: Vec3 | undefined = void 0;
 
 
     private currentIdentifyT = 0;
     private currentIdentifyT = 0;
     private isInteracting = false;
     private isInteracting = false;
@@ -61,14 +62,16 @@ export class Canvas3dInteractionHelper {
         }
         }
 
 
         if (xyChanged) {
         if (xyChanged) {
-            this.id = this.canvasIdentify(this.endX, this.endY);
+            const pickData = this.canvasIdentify(this.endX, this.endY);
+            this.id = pickData?.id;
+            this.position = pickData?.position;
             this.startX = this.endX;
             this.startX = this.endX;
             this.startY = this.endY;
             this.startY = this.endY;
         }
         }
 
 
         if (e === InputEvent.Click) {
         if (e === InputEvent.Click) {
             const loci = this.getLoci(this.id);
             const loci = this.getLoci(this.id);
-            this.events.click.next({ current: loci, buttons: this.buttons, button: this.button, modifiers: this.modifiers });
+            this.events.click.next({ current: loci, buttons: this.buttons, button: this.button, modifiers: this.modifiers, position: this.position });
             this.prevLoci = loci;
             this.prevLoci = loci;
             return;
             return;
         }
         }
@@ -78,11 +81,8 @@ export class Canvas3dInteractionHelper {
         }
         }
 
 
         const loci = this.getLoci(this.id);
         const loci = this.getLoci(this.id);
-        // only broadcast the latest hover
-        if (!Representation.Loci.areEqual(this.prevLoci, loci)) {
-            this.events.hover.next({ current: loci, buttons: this.buttons, button: this.button, modifiers: this.modifiers });
-            this.prevLoci = loci;
-        }
+        this.events.hover.next({ current: loci, buttons: this.buttons, button: this.button, modifiers: this.modifiers, page: Vec2.create(this.endX, this.endY), position: this.position });
+        this.prevLoci = loci;
     }
     }
 
 
     tick(t: number) {
     tick(t: number) {
@@ -129,9 +129,9 @@ export class Canvas3dInteractionHelper {
     }
     }
 
 
     private modify(modifiers: ModifiersKeys) {
     private modify(modifiers: ModifiersKeys) {
-        if (Representation.Loci.isEmpty(this.prevLoci) || ModifiersKeys.areEqual(modifiers, this.modifiers)) return;
+        if (ModifiersKeys.areEqual(modifiers, this.modifiers)) return;
         this.modifiers = modifiers;
         this.modifiers = modifiers;
-        this.events.hover.next({ current: this.prevLoci, buttons: this.buttons, button: this.button, modifiers: this.modifiers });
+        this.events.hover.next({ current: this.prevLoci, buttons: this.buttons, button: this.button, modifiers: this.modifiers, page: Vec2.create(this.endX, this.endY), position: this.position });
     }
     }
 
 
     private outsideViewport(x: number, y: number) {
     private outsideViewport(x: number, y: number) {

+ 35 - 5
src/mol-canvas3d/passes/pick.ts

@@ -10,26 +10,32 @@ import Scene from '../../mol-gl/scene';
 import { WebGLContext } from '../../mol-gl/webgl/context';
 import { WebGLContext } from '../../mol-gl/webgl/context';
 import { GraphicsRenderVariant } from '../../mol-gl/webgl/render-item';
 import { GraphicsRenderVariant } from '../../mol-gl/webgl/render-item';
 import { RenderTarget } from '../../mol-gl/webgl/render-target';
 import { RenderTarget } from '../../mol-gl/webgl/render-target';
-import { decodeFloatRGB } from '../../mol-util/float-packing';
+import { Vec3 } from '../../mol-math/linear-algebra';
+import { decodeFloatRGB, unpackRGBAToDepth } from '../../mol-util/float-packing';
 import { Camera, ICamera } from '../camera';
 import { Camera, ICamera } from '../camera';
 import { StereoCamera } from '../camera/stereo';
 import { StereoCamera } from '../camera/stereo';
+import { cameraUnproject } from '../camera/util';
 import { HandleHelper } from '../helper/handle-helper';
 import { HandleHelper } from '../helper/handle-helper';
 import { DrawPass } from './draw';
 import { DrawPass } from './draw';
 
 
 const NullId = Math.pow(2, 24) - 2;
 const NullId = Math.pow(2, 24) - 2;
 
 
+export type PickData = { id: PickingId, position: Vec3 }
+
 export class PickPass {
 export class PickPass {
     pickDirty = true
     pickDirty = true
 
 
     objectPickTarget: RenderTarget
     objectPickTarget: RenderTarget
     instancePickTarget: RenderTarget
     instancePickTarget: RenderTarget
     groupPickTarget: RenderTarget
     groupPickTarget: RenderTarget
+    depthPickTarget: RenderTarget
 
 
     isStereo = false
     isStereo = false
 
 
     private objectBuffer: Uint8Array
     private objectBuffer: Uint8Array
     private instanceBuffer: Uint8Array
     private instanceBuffer: Uint8Array
     private groupBuffer: Uint8Array
     private groupBuffer: Uint8Array
+    private depthBuffer: Uint8Array
 
 
     private pickScale: number
     private pickScale: number
     private pickWidth: number
     private pickWidth: number
@@ -43,6 +49,7 @@ export class PickPass {
         this.objectPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
         this.objectPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
         this.instancePickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
         this.instancePickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
         this.groupPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
         this.groupPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
+        this.depthPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight);
 
 
         this.setupBuffers();
         this.setupBuffers();
     }
     }
@@ -53,6 +60,7 @@ export class PickPass {
             this.objectBuffer = new Uint8Array(bufferSize);
             this.objectBuffer = new Uint8Array(bufferSize);
             this.instanceBuffer = new Uint8Array(bufferSize);
             this.instanceBuffer = new Uint8Array(bufferSize);
             this.groupBuffer = new Uint8Array(bufferSize);
             this.groupBuffer = new Uint8Array(bufferSize);
+            this.depthBuffer = new Uint8Array(bufferSize);
         }
         }
     }
     }
 
 
@@ -68,6 +76,7 @@ export class PickPass {
             this.objectPickTarget.setSize(this.pickWidth, this.pickHeight);
             this.objectPickTarget.setSize(this.pickWidth, this.pickHeight);
             this.instancePickTarget.setSize(this.pickWidth, this.pickHeight);
             this.instancePickTarget.setSize(this.pickWidth, this.pickHeight);
             this.groupPickTarget.setSize(this.pickWidth, this.pickHeight);
             this.groupPickTarget.setSize(this.pickWidth, this.pickHeight);
+            this.depthPickTarget.setSize(this.pickWidth, this.pickHeight);
 
 
             this.setupBuffers();
             this.setupBuffers();
         }
         }
@@ -107,6 +116,9 @@ export class PickPass {
         this.groupPickTarget.bind();
         this.groupPickTarget.bind();
         this.renderVariant('pickGroup');
         this.renderVariant('pickGroup');
 
 
+        this.depthPickTarget.bind();
+        this.renderVariant('depth');
+
         this.pickDirty = false;
         this.pickDirty = false;
     }
     }
 
 
@@ -121,14 +133,27 @@ export class PickPass {
 
 
         this.groupPickTarget.bind();
         this.groupPickTarget.bind();
         webgl.readPixels(0, 0, this.pickWidth, this.pickHeight, this.groupBuffer);
         webgl.readPixels(0, 0, this.pickWidth, this.pickHeight, this.groupBuffer);
+
+        this.depthPickTarget.bind();
+        webgl.readPixels(0, 0, this.pickWidth, this.pickHeight, this.depthBuffer);
+    }
+
+    private getBufferIdx(x: number, y: number): number {
+        return (y * this.pickWidth + x) * 4;
+    }
+
+    private getDepth(x: number, y: number): number {
+        const idx = this.getBufferIdx(x, y);
+        const b = this.depthBuffer;
+        return unpackRGBAToDepth(b[idx], b[idx + 1], b[idx + 2], b[idx + 3]);
     }
     }
 
 
     private getId(x: number, y: number, buffer: Uint8Array) {
     private getId(x: number, y: number, buffer: Uint8Array) {
-        const idx = (y * this.pickWidth + x) * 4;
+        const idx = this.getBufferIdx(x, y);
         return decodeFloatRGB(buffer[idx], buffer[idx + 1], buffer[idx + 2]);
         return decodeFloatRGB(buffer[idx], buffer[idx + 1], buffer[idx + 2]);
     }
     }
 
 
-    identify(x: number, y: number): PickingId | undefined {
+    identify(x: number, y: number): PickData | undefined {
         const { webgl, pickScale, camera: { viewport } } = this;
         const { webgl, pickScale, camera: { viewport } } = this;
         if (webgl.isContextLost) return;
         if (webgl.isContextLost) return;
 
 
@@ -168,7 +193,12 @@ export class PickPass {
         const groupId = this.getId(xp, yp, this.groupBuffer);
         const groupId = this.getId(xp, yp, this.groupBuffer);
         // console.log('groupId', groupId);
         // console.log('groupId', groupId);
         if (groupId === -1 || groupId === NullId) return;
         if (groupId === -1 || groupId === NullId) return;
-        // console.log({ objectId, instanceId, groupId });
-        return { objectId, instanceId, groupId };
+
+        const z = this.getDepth(xp, yp);
+        const position = Vec3.create(x, gl.drawingBufferHeight - y, z);
+        cameraUnproject(position, position, viewport, this.camera.inverseProjectionView);
+
+        // console.log({ { objectId, instanceId, groupId }, position} );
+        return { id: { objectId, instanceId, groupId }, position };
     }
     }
 }
 }

+ 1 - 0
src/mol-geo/geometry/base.ts

@@ -78,6 +78,7 @@ export namespace BaseGeometry {
             visible: true,
             visible: true,
             alphaFactor: 1,
             alphaFactor: 1,
             pickable: true,
             pickable: true,
+            colorOnly: false,
             opaque,
             opaque,
             writeDepth: opaque,
             writeDepth: opaque,
         };
         };

+ 0 - 5
src/mol-geo/geometry/picking.ts

@@ -15,8 +15,3 @@ export namespace PickingId {
         return a.objectId === b.objectId && a.instanceId === b.instanceId && a.groupId === b.groupId;
         return a.objectId === b.objectId && a.instanceId === b.instanceId && a.groupId === b.groupId;
     }
     }
 }
 }
-
-export interface PickingInfo {
-    label: string
-    data?: any
-}

+ 1 - 0
src/mol-gl/_spec/renderer.spec.ts

@@ -92,6 +92,7 @@ function createPoints() {
         visible: true,
         visible: true,
         alphaFactor: 1,
         alphaFactor: 1,
         pickable: true,
         pickable: true,
+        colorOnly: false,
         opaque: true,
         opaque: true,
         writeDepth: true
         writeDepth: true
     };
     };

+ 1 - 0
src/mol-gl/renderable.ts

@@ -17,6 +17,7 @@ export type RenderableState = {
     visible: boolean
     visible: boolean
     alphaFactor: number
     alphaFactor: number
     pickable: boolean
     pickable: boolean
+    colorOnly: boolean
     opaque: boolean
     opaque: boolean
     writeDepth: boolean,
     writeDepth: boolean,
 }
 }

+ 2 - 2
src/mol-gl/renderable/schema.ts

@@ -129,7 +129,7 @@ export const GlobalUniformSchema = {
     uFogFar: UniformSpec('f'),
     uFogFar: UniformSpec('f'),
     uFogColor: UniformSpec('v3'),
     uFogColor: UniformSpec('v3'),
 
 
-    uTransparentBackground: UniformSpec('i'),
+    uTransparentBackground: UniformSpec('b'),
 
 
     uClipObjectType: UniformSpec('i[]'),
     uClipObjectType: UniformSpec('i[]'),
     uClipObjectPosition: UniformSpec('v3[]'),
     uClipObjectPosition: UniformSpec('v3[]'),
@@ -149,7 +149,7 @@ export const GlobalUniformSchema = {
     uPickingAlphaThreshold: UniformSpec('f'),
     uPickingAlphaThreshold: UniformSpec('f'),
 
 
     uInteriorDarkening: UniformSpec('f'),
     uInteriorDarkening: UniformSpec('f'),
-    uInteriorColorFlag: UniformSpec('i'),
+    uInteriorColorFlag: UniformSpec('b'),
     uInteriorColor: UniformSpec('v3'),
     uInteriorColor: UniformSpec('v3'),
 
 
     uHighlightColor: UniformSpec('v3'),
     uHighlightColor: UniformSpec('v3'),

+ 7 - 5
src/mol-gl/renderer.ts

@@ -203,7 +203,7 @@ namespace Renderer {
             uFogNear: ValueCell.create(1),
             uFogNear: ValueCell.create(1),
             uFogFar: ValueCell.create(10000),
             uFogFar: ValueCell.create(10000),
             uFogColor: ValueCell.create(bgColor),
             uFogColor: ValueCell.create(bgColor),
-            uTransparentBackground: ValueCell.create(0),
+            uTransparentBackground: ValueCell.create(false),
 
 
             uClipObjectType: ValueCell.create(clip.objects.type),
             uClipObjectType: ValueCell.create(clip.objects.type),
             uClipObjectPosition: ValueCell.create(clip.objects.position),
             uClipObjectPosition: ValueCell.create(clip.objects.position),
@@ -221,7 +221,7 @@ namespace Renderer {
             uPickingAlphaThreshold: ValueCell.create(p.pickingAlphaThreshold),
             uPickingAlphaThreshold: ValueCell.create(p.pickingAlphaThreshold),
 
 
             uInteriorDarkening: ValueCell.create(p.interiorDarkening),
             uInteriorDarkening: ValueCell.create(p.interiorDarkening),
-            uInteriorColorFlag: ValueCell.create(p.interiorColorFlag ? 1 : 0),
+            uInteriorColorFlag: ValueCell.create(p.interiorColorFlag),
             uInteriorColor: ValueCell.create(Color.toVec3Normalized(Vec3(), p.interiorColor)),
             uInteriorColor: ValueCell.create(Color.toVec3Normalized(Vec3(), p.interiorColor)),
 
 
             uHighlightColor: ValueCell.create(Color.toVec3Normalized(Vec3(), p.highlightColor)),
             uHighlightColor: ValueCell.create(Color.toVec3Normalized(Vec3(), p.highlightColor)),
@@ -322,7 +322,7 @@ namespace Renderer {
             ValueCell.update(globalUniforms.uFogFar, camera.fogFar);
             ValueCell.update(globalUniforms.uFogFar, camera.fogFar);
             ValueCell.update(globalUniforms.uFogNear, camera.fogNear);
             ValueCell.update(globalUniforms.uFogNear, camera.fogNear);
 
 
-            ValueCell.update(globalUniforms.uTransparentBackground, transparentBackground ? 1 : 0);
+            ValueCell.update(globalUniforms.uTransparentBackground, transparentBackground);
 
 
             globalUniformsNeedUpdate = true;
             globalUniformsNeedUpdate = true;
             state.currentRenderItemId = -1;
             state.currentRenderItemId = -1;
@@ -368,7 +368,9 @@ namespace Renderer {
                 }
                 }
             } else { // picking & depth
             } else { // picking & depth
                 for (let i = 0, il = renderables.length; i < il; ++i) {
                 for (let i = 0, il = renderables.length; i < il; ++i) {
-                    renderObject(renderables[i], variant, depthTexture);
+                    if (!renderables[i].state.colorOnly) {
+                        renderObject(renderables[i], variant, depthTexture);
+                    }
                 }
                 }
             }
             }
 
 
@@ -407,7 +409,7 @@ namespace Renderer {
                 }
                 }
                 if (props.interiorColorFlag !== undefined && props.interiorColorFlag !== p.interiorColorFlag) {
                 if (props.interiorColorFlag !== undefined && props.interiorColorFlag !== p.interiorColorFlag) {
                     p.interiorColorFlag = props.interiorColorFlag;
                     p.interiorColorFlag = props.interiorColorFlag;
-                    ValueCell.update(globalUniforms.uInteriorColorFlag, p.interiorColorFlag ? 1 : 0);
+                    ValueCell.update(globalUniforms.uInteriorColorFlag, p.interiorColorFlag);
                 }
                 }
                 if (props.interiorColor !== undefined && props.interiorColor !== p.interiorColor) {
                 if (props.interiorColor !== undefined && props.interiorColor !== p.interiorColor) {
                     p.interiorColor = props.interiorColor;
                     p.interiorColor = props.interiorColor;

+ 1 - 1
src/mol-gl/shader/chunks/apply-fog.glsl.ts

@@ -2,7 +2,7 @@ export default `
 float fogDepth = length(vViewPosition);
 float fogDepth = length(vViewPosition);
 float fogFactor = smoothstep(uFogNear, uFogFar, fogDepth);
 float fogFactor = smoothstep(uFogNear, uFogFar, fogDepth);
 float fogAlpha = (1.0 - fogFactor) * gl_FragColor.a;
 float fogAlpha = (1.0 - fogFactor) * gl_FragColor.a;
-if (uTransparentBackground == 0) {
+if (!uTransparentBackground) {
     gl_FragColor.rgb = mix(gl_FragColor.rgb, uFogColor, fogFactor);
     gl_FragColor.rgb = mix(gl_FragColor.rgb, uFogColor, fogFactor);
     if (gl_FragColor.a < 1.0)
     if (gl_FragColor.a < 1.0)
         gl_FragColor.a = fogAlpha;
         gl_FragColor.a = fogAlpha;

+ 1 - 1
src/mol-gl/shader/chunks/apply-interior-color.glsl.ts

@@ -1,6 +1,6 @@
 export default `
 export default `
 if (interior) {
 if (interior) {
-    if (uInteriorColorFlag == 1) {
+    if (uInteriorColorFlag) {
         gl_FragColor.rgb = uInteriorColor;
         gl_FragColor.rgb = uInteriorColor;
     } else {
     } else {
         gl_FragColor.rgb *= 1.0 - uInteriorDarkening;
         gl_FragColor.rgb *= 1.0 - uInteriorDarkening;

+ 2 - 2
src/mol-gl/shader/chunks/common-frag-params.glsl.ts

@@ -37,10 +37,10 @@ uniform vec3 uFogColor;
 
 
 uniform float uAlpha;
 uniform float uAlpha;
 uniform float uPickingAlphaThreshold;
 uniform float uPickingAlphaThreshold;
-uniform int uTransparentBackground;
+uniform bool uTransparentBackground;
 
 
 uniform float uInteriorDarkening;
 uniform float uInteriorDarkening;
-uniform int uInteriorColorFlag;
+uniform bool uInteriorColorFlag;
 uniform vec3 uInteriorColor;
 uniform vec3 uInteriorColor;
 bool interior;
 bool interior;
 `;
 `;

+ 2 - 2
src/mol-gl/shader/direct-volume.frag.ts

@@ -51,10 +51,10 @@ uniform vec3 uFogColor;
 
 
 uniform float uAlpha;
 uniform float uAlpha;
 uniform float uPickingAlphaThreshold;
 uniform float uPickingAlphaThreshold;
-uniform int uTransparentBackground;
+uniform bool uTransparentBackground;
 
 
 uniform float uInteriorDarkening;
 uniform float uInteriorDarkening;
-uniform int uInteriorColorFlag;
+uniform bool uInteriorColorFlag;
 uniform vec3 uInteriorColor;
 uniform vec3 uInteriorColor;
 bool interior;
 bool interior;
 
 

+ 4 - 2
src/mol-gl/webgl/uniform.ts

@@ -11,6 +11,7 @@ import { RenderableSchema } from '../../mol-gl/renderable/schema';
 import { ValueOf } from '../../mol-util/type-helpers';
 import { ValueOf } from '../../mol-util/type-helpers';
 
 
 export type UniformKindValue = {
 export type UniformKindValue = {
+    'b': boolean; 'b[]': boolean[]
     'f': number; 'f[]': number[]
     'f': number; 'f[]': number[]
     'i': number; 'i[]': number[]
     'i': number; 'i[]': number[]
     'v2': Vec2; 'v2[]': number[]
     'v2': Vec2; 'v2[]': number[]
@@ -28,6 +29,7 @@ export type UniformsList = [string, ValueCell<UniformType>][]
 
 
 export function getUniformType(gl: GLRenderingContext, kind: UniformKind) {
 export function getUniformType(gl: GLRenderingContext, kind: UniformKind) {
     switch (kind) {
     switch (kind) {
+        case 'b': case 'b[]': return gl.BOOL;
         case 'f': case 'f[]': return gl.FLOAT;
         case 'f': case 'f[]': return gl.FLOAT;
         case 'i': case 'i[]': return gl.INT;
         case 'i': case 'i[]': return gl.INT;
         case 'v2': case 'v2[]': return gl.FLOAT_VEC2;
         case 'v2': case 'v2[]': return gl.FLOAT_VEC2;
@@ -56,8 +58,8 @@ function getUniformSetter(kind: UniformKind): UniformSetter {
     switch (kind) {
     switch (kind) {
         case 'f': return uniform1f;
         case 'f': return uniform1f;
         case 'f[]': return uniform1fv;
         case 'f[]': return uniform1fv;
-        case 'i': case 't': return uniform1i;
-        case 'i[]': case 't[]': return uniform1iv;
+        case 'i': case 't': case 'b': return uniform1i;
+        case 'i[]': case 't[]': case 'b[]': return uniform1iv;
         case 'v2': case 'v2[]': return uniform2fv;
         case 'v2': case 'v2[]': return uniform2fv;
         case 'v3': case 'v3[]': return uniform3fv;
         case 'v3': case 'v3[]': return uniform3fv;
         case 'v4': case 'v4[]': return uniform4fv;
         case 'v4': case 'v4[]': return uniform4fv;

+ 3 - 3
src/mol-plugin-state/manager/interactivity.ts

@@ -15,7 +15,7 @@ import { shallowEqual } from '../../mol-util/object';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { StatefulPluginComponent } from '../component';
 import { StatefulPluginComponent } from '../component';
 import { StructureSelectionManager } from './structure/selection';
 import { StructureSelectionManager } from './structure/selection';
-import { Vec2 } from '../../mol-math/linear-algebra';
+import { Vec2, Vec3 } from '../../mol-math/linear-algebra';
 
 
 export { InteractivityManager };
 export { InteractivityManager };
 
 
@@ -70,9 +70,9 @@ namespace InteractivityManager {
     export type Params = typeof Params
     export type Params = typeof Params
     export type Props = PD.Values<Params>
     export type Props = PD.Values<Params>
 
 
-    export interface HoverEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys }
+    export interface HoverEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys, page?: Vec2, position?: Vec3 }
     export interface DragEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys, pageStart: Vec2, pageEnd: Vec2 }
     export interface DragEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys, pageStart: Vec2, pageEnd: Vec2 }
-    export interface ClickEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys }
+    export interface ClickEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys, position?: Vec3 }
 
 
     export type LociMarkProvider = (loci: Representation.Loci, action: MarkerAction) => void
     export type LociMarkProvider = (loci: Representation.Loci, action: MarkerAction) => void
 
 

+ 5 - 1
src/mol-repr/representation.ts

@@ -174,6 +174,8 @@ namespace Representation {
         alphaFactor: number
         alphaFactor: number
         /** Controls if the representation's renderobjects are pickable or not */
         /** Controls if the representation's renderobjects are pickable or not */
         pickable: boolean
         pickable: boolean
+        /** Controls if the representation's renderobjects is rendered in color pass (i.e., not pick and depth) or not */
+        colorOnly: boolean
         /** Overpaint applied to the representation's renderobjects */
         /** Overpaint applied to the representation's renderobjects */
         overpaint: Overpaint
         overpaint: Overpaint
         /** Per group transparency applied to the representation's renderobjects */
         /** Per group transparency applied to the representation's renderobjects */
@@ -188,12 +190,13 @@ namespace Representation {
         markerActions: MarkerActions
         markerActions: MarkerActions
     }
     }
     export function createState(): State {
     export function createState(): State {
-        return { visible: true, alphaFactor: 1, pickable: true, syncManually: false, transform: Mat4.identity(), overpaint: Overpaint.Empty, transparency: Transparency.Empty, clipping: Clipping.Empty, markerActions: MarkerActions.All };
+        return { visible: true, alphaFactor: 1, pickable: true, colorOnly: false, syncManually: false, transform: Mat4.identity(), overpaint: Overpaint.Empty, transparency: Transparency.Empty, clipping: Clipping.Empty, markerActions: MarkerActions.All };
     }
     }
     export function updateState(state: State, update: Partial<State>) {
     export function updateState(state: State, update: Partial<State>) {
         if (update.visible !== undefined) state.visible = update.visible;
         if (update.visible !== undefined) state.visible = update.visible;
         if (update.alphaFactor !== undefined) state.alphaFactor = update.alphaFactor;
         if (update.alphaFactor !== undefined) state.alphaFactor = update.alphaFactor;
         if (update.pickable !== undefined) state.pickable = update.pickable;
         if (update.pickable !== undefined) state.pickable = update.pickable;
+        if (update.colorOnly !== undefined) state.colorOnly = update.colorOnly;
         if (update.overpaint !== undefined) state.overpaint = update.overpaint;
         if (update.overpaint !== undefined) state.overpaint = update.overpaint;
         if (update.transparency !== undefined) state.transparency = update.transparency;
         if (update.transparency !== undefined) state.transparency = update.transparency;
         if (update.clipping !== undefined) state.clipping = update.clipping;
         if (update.clipping !== undefined) state.clipping = update.clipping;
@@ -363,6 +366,7 @@ namespace Representation {
                 if (state.visible !== undefined) Visual.setVisibility(renderObject, state.visible);
                 if (state.visible !== undefined) Visual.setVisibility(renderObject, state.visible);
                 if (state.alphaFactor !== undefined) Visual.setAlphaFactor(renderObject, state.alphaFactor);
                 if (state.alphaFactor !== undefined) Visual.setAlphaFactor(renderObject, state.alphaFactor);
                 if (state.pickable !== undefined) Visual.setPickable(renderObject, state.pickable);
                 if (state.pickable !== undefined) Visual.setPickable(renderObject, state.pickable);
+                if (state.colorOnly !== undefined) Visual.setColorOnly(renderObject, state.colorOnly);
                 if (state.overpaint !== undefined) {
                 if (state.overpaint !== undefined) {
                     // TODO
                     // TODO
                 }
                 }

+ 1 - 0
src/mol-repr/shape/representation.ts

@@ -203,6 +203,7 @@ export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Pa
                 if (state.visible !== undefined) Visual.setVisibility(_renderObject, state.visible);
                 if (state.visible !== undefined) Visual.setVisibility(_renderObject, state.visible);
                 if (state.alphaFactor !== undefined) Visual.setAlphaFactor(_renderObject, state.alphaFactor);
                 if (state.alphaFactor !== undefined) Visual.setAlphaFactor(_renderObject, state.alphaFactor);
                 if (state.pickable !== undefined) Visual.setPickable(_renderObject, state.pickable);
                 if (state.pickable !== undefined) Visual.setPickable(_renderObject, state.pickable);
+                if (state.colorOnly !== undefined) Visual.setColorOnly(_renderObject, state.colorOnly);
                 if (state.overpaint !== undefined) {
                 if (state.overpaint !== undefined) {
                     Visual.setOverpaint(_renderObject, state.overpaint, lociApply, true);
                     Visual.setOverpaint(_renderObject, state.overpaint, lociApply, true);
                 }
                 }

+ 3 - 0
src/mol-repr/structure/complex-visual.ts

@@ -217,6 +217,9 @@ export function ComplexVisual<G extends Geometry, P extends StructureParams & Ge
         setPickable(pickable: boolean) {
         setPickable(pickable: boolean) {
             Visual.setPickable(renderObject, pickable);
             Visual.setPickable(renderObject, pickable);
         },
         },
+        setColorOnly(colorOnly: boolean) {
+            Visual.setColorOnly(renderObject, colorOnly);
+        },
         setTransform(matrix?: Mat4, instanceMatrices?: Float32Array | null) {
         setTransform(matrix?: Mat4, instanceMatrices?: Float32Array | null) {
             Visual.setTransform(renderObject, matrix, instanceMatrices);
             Visual.setTransform(renderObject, matrix, instanceMatrices);
         },
         },

+ 3 - 0
src/mol-repr/structure/units-visual.ts

@@ -274,6 +274,9 @@ export function UnitsVisual<G extends Geometry, P extends StructureParams & Geom
         setPickable(pickable: boolean) {
         setPickable(pickable: boolean) {
             Visual.setPickable(renderObject, pickable);
             Visual.setPickable(renderObject, pickable);
         },
         },
+        setColorOnly(colorOnly: boolean) {
+            Visual.setColorOnly(renderObject, colorOnly);
+        },
         setTransform(matrix?: Mat4, instanceMatrices?: Float32Array | null) {
         setTransform(matrix?: Mat4, instanceMatrices?: Float32Array | null) {
             Visual.setTransform(renderObject, matrix, instanceMatrices);
             Visual.setTransform(renderObject, matrix, instanceMatrices);
         },
         },

+ 5 - 0
src/mol-repr/visual.ts

@@ -41,6 +41,7 @@ interface Visual<D, P extends PD.Params> {
     setVisibility: (visible: boolean) => void
     setVisibility: (visible: boolean) => void
     setAlphaFactor: (alphaFactor: number) => void
     setAlphaFactor: (alphaFactor: number) => void
     setPickable: (pickable: boolean) => void
     setPickable: (pickable: boolean) => void
+    setColorOnly: (colorOnly: boolean) => void
     setTransform: (matrix?: Mat4, instanceMatrices?: Float32Array | null) => void
     setTransform: (matrix?: Mat4, instanceMatrices?: Float32Array | null) => void
     setOverpaint: (overpaint: Overpaint) => void
     setOverpaint: (overpaint: Overpaint) => void
     setTransparency: (transparency: Transparency) => void
     setTransparency: (transparency: Transparency) => void
@@ -62,6 +63,10 @@ namespace Visual {
         if (renderObject) renderObject.state.pickable = pickable;
         if (renderObject) renderObject.state.pickable = pickable;
     }
     }
 
 
+    export function setColorOnly(renderObject: GraphicsRenderObject | undefined, colorOnly: boolean) {
+        if (renderObject) renderObject.state.colorOnly = colorOnly;
+    }
+
     export function mark(renderObject: GraphicsRenderObject | undefined, loci: Loci, action: MarkerAction, lociApply: LociApply) {
     export function mark(renderObject: GraphicsRenderObject | undefined, loci: Loci, action: MarkerAction, lociApply: LociApply) {
         if (!renderObject) return false;
         if (!renderObject) return false;
 
 

+ 3 - 0
src/mol-repr/volume/representation.ts

@@ -190,6 +190,9 @@ export function VolumeVisual<G extends Geometry, P extends VolumeParams & Geomet
         setPickable(pickable: boolean) {
         setPickable(pickable: boolean) {
             Visual.setPickable(renderObject, pickable);
             Visual.setPickable(renderObject, pickable);
         },
         },
+        setColorOnly(colorOnly: boolean) {
+            Visual.setColorOnly(renderObject, colorOnly);
+        },
         setTransform(matrix?: Mat4, instanceMatrices?: Float32Array | null) {
         setTransform(matrix?: Mat4, instanceMatrices?: Float32Array | null) {
             Visual.setTransform(renderObject, matrix, instanceMatrices);
             Visual.setTransform(renderObject, matrix, instanceMatrices);
         },
         },

+ 1 - 1
src/mol-task/execution/observable.ts

@@ -110,7 +110,7 @@ async function execute<T>(task: ExposedTask<T>, ctx: ObservableRuntimeContext) {
 
 
             // wait for all child computations to go thru the abort phase.
             // wait for all child computations to go thru the abort phase.
             if (ctx.node.children.length > 0) {
             if (ctx.node.children.length > 0) {
-                await new Promise(res => { ctx.onChildrenFinished = res; });
+                await new Promise<void>(res => { ctx.onChildrenFinished = res; });
             }
             }
             if (task.onAbort) {
             if (task.onAbort) {
                 task.onAbort();
                 task.onAbort();

+ 1 - 1
src/mol-util/color/color.ts

@@ -146,7 +146,7 @@ export namespace Color {
     }
     }
 }
 }
 
 
-export type ColorListEntry = Color | [color: Color, offset: number /** normalized value from 0 to 1 */]
+export type ColorListEntry = Color | [Color, number /** normalized value from 0 to 1 */]
 
 
 export interface ColorList {
 export interface ColorList {
     label: string
     label: string

+ 1 - 2
src/mol-util/is-little-endian.ts

@@ -10,6 +10,5 @@ export function isLittleEndian() {
     const uint16array = new Uint16Array(arrayBuffer);
     const uint16array = new Uint16Array(arrayBuffer);
     uint8Array[0] = 0xAA;
     uint8Array[0] = 0xAA;
     uint8Array[1] = 0xBB;
     uint8Array[1] = 0xBB;
-    if (uint16array[0] === 0xBBAA) return 1;
-    return 0;
+    return uint16array[0] === 0xBBAA;
 }
 }

+ 1 - 1
src/tests/browser/render-shape.ts

@@ -41,7 +41,7 @@ let prevReprLoci = Representation.Loci.Empty;
 const canvas3d = Canvas3D.fromCanvas(canvas);
 const canvas3d = Canvas3D.fromCanvas(canvas);
 canvas3d.animate();
 canvas3d.animate();
 canvas3d.input.move.subscribe(({x, y}) => {
 canvas3d.input.move.subscribe(({x, y}) => {
-    const pickingId = canvas3d.identify(x, y);
+    const pickingId = canvas3d.identify(x, y)?.id;
     let label = '';
     let label = '';
     if (pickingId) {
     if (pickingId) {
         const reprLoci = canvas3d.getLoci(pickingId);
         const reprLoci = canvas3d.getLoci(pickingId);

+ 1 - 1
src/tests/browser/render-structure.ts

@@ -51,7 +51,7 @@ parent.appendChild(info);
 
 
 let prevReprLoci = Representation.Loci.Empty;
 let prevReprLoci = Representation.Loci.Empty;
 canvas3d.input.move.pipe(throttleTime(100)).subscribe(({x, y}) => {
 canvas3d.input.move.pipe(throttleTime(100)).subscribe(({x, y}) => {
-    const pickingId = canvas3d.identify(x, y);
+    const pickingId = canvas3d.identify(x, y)?.id;
     let label = '';
     let label = '';
     if (pickingId) {
     if (pickingId) {
         const reprLoci = canvas3d.getLoci(pickingId);
         const reprLoci = canvas3d.getLoci(pickingId);