Compare commits

...

31 Commits

Author SHA1 Message Date
dsehnal
f5ecf5648e 3.7.0 2022-04-13 20:04:01 +02:00
dsehnal
821f82fc3f changelog 2022-04-13 20:01:04 +02:00
David Sehnal
92305fe628 Merge pull request #420 from molstar/transparentBackfaces
improve transparentBackfaces handling
2022-04-13 19:57:29 +02:00
David Sehnal
17fe57b8a5 Merge pull request #423 from jpattle/option-to-disable-drag-overlay
Added an option to disable the drag overlay
2022-04-13 16:31:21 +02:00
Jason Pattle
47433a51d3 Added an option to the components spec to allow disabling of the drag-and-drop overlap for Molstar that loads files into the viewer. By default the drag overlay is enabled, just as it was before 2022-04-13 15:00:03 +01:00
Alexander Rose
e090827ced Merge branch 'master' of https://github.com/molstar/molstar into transparentBackfaces 2022-04-10 13:20:22 -07:00
dsehnal
98afc27442 fix react typing 2022-04-09 21:24:14 +02:00
Alexander Rose
9d4f28a395 fix type deps 2022-04-09 11:36:17 -07:00
Alexander Rose
50266d9a56 package updates 2022-04-09 11:20:28 -07:00
Alexander Rose
b23d610c94 improve transparentBackfaces handling
- off: don't show (default)
- on: show with transparency
- opaque: show fully opaque
2022-04-09 10:17:41 -07:00
Alexander Rose
119c43d527 fix xrayShaded for texture-mesh geometries 2022-04-09 10:04:06 -07:00
Alexander Rose
124feeb790 color theme tweaks
- add optional grid property
- handle dColorType_direct for non direct-volume shaders
2022-04-09 09:57:31 -07:00
dsehnal
2c0e7e84da 3.6.2 2022-04-05 17:59:48 +02:00
dsehnal
0d1e105343 changelog 2022-04-05 17:57:14 +02:00
dsehnal
f040c89ab3 React 18 friendly useBehavior hook 2022-04-05 17:51:13 +02:00
David Sehnal
5e9d8298ef Merge pull request #415 from JonStargaryen/master
ModelServer Ligand Export: Fix Alternate Locations & Mismatching Atoms
2022-04-05 17:49:16 +02:00
Sebastian Bittrich
7766ca2793 CHANGELOG 2022-04-04 11:36:39 -07:00
Sebastian Bittrich
fb2f22f120 Merge remote-tracking branch 'upstream/master' 2022-04-04 11:33:01 -07:00
Sebastian Bittrich
146fed3504 CHANGELOG 2022-04-04 11:32:51 -07:00
Sebastian Bittrich
0b7a6e3375 cleanup 2022-04-04 10:55:44 -07:00
Sebastian Bittrich
f1fbdeaca0 handle missing atoms (ignore hydrogen, fail for heavy) 2022-04-04 10:49:40 -07:00
Sebastian Bittrich
ee7e37f6bc handle deuterated part 2 2022-04-04 09:45:42 -07:00
Sebastian Bittrich
861f665ab3 handle deuterated 2022-04-04 09:17:39 -07:00
dsehnal
456de23ad4 remove console.log 2022-04-03 14:45:41 +02:00
dsehnal
6d3578c17e fix alpha orbitals example 2022-04-03 14:08:31 +02:00
dsehnal
57da7267e2 3.6.1 2022-04-03 13:50:46 +02:00
dsehnal
578b764406 fix react 18 ui: use hooks for overlay components 2022-04-03 13:48:05 +02:00
dsehnal
f65a38a085 TransformControlBase fix 2022-04-03 13:00:09 +02:00
Sebastian Bittrich
b87beb4a6e better msg for UNL 2022-04-01 16:58:32 -07:00
Sebastian Bittrich
62a58facb2 better error msg for unknown components 2022-04-01 15:51:00 -07:00
Sebastian Bittrich
5fa8178df7 fix handling of alternate locations in ligand-encoder#_getAtoms 2022-04-01 11:47:59 -07:00
35 changed files with 1793 additions and 1219 deletions

View File

@@ -6,6 +6,23 @@ Note that since we don't clearly distinguish between a public and private interf
## [Unreleased]
## [v3.7.0] - 2022-04-13
- Fix ``xrayShaded`` for texture-mesh geometries
- [Breaking] Change ``allowTransparentBackfaces`` to ``transparentBackfaces`` with options ``off``, ``on``, ``opaque``. This was only added in 3.6.0, so allowing a breaking change here.
- ``off``: don't show (default)
- ``on``: show with transparency
- ``opaque``: show fully opaque
- Add option to disable file drop overlay.
## [v3.6.2] - 2022-04-05
- ModelServer ligand queries: fixes for alternate locations, additional atoms & UNL ligand
- React 18 friendly ``useBehavior`` hook.
## [v3.6.1] - 2022-04-03
- Fix React18 related UI regressions.
## [v3.6.0] - 2022-04-03
@@ -19,8 +36,8 @@ Note that since we don't clearly distinguish between a public and private interf
- Fix handling of case insensitive mmCIF enumeration fields (including entity.type)
- Fix ``disable-wboit`` Viewer GET param
- Add support for React 18.
- Used by importing ``createPluginUI`` from ``mol-plugin-ui/react18``;
- In Mol* 4.0, React 18 will become the default option.
- Used by importing ``createPluginUI`` from ``mol-plugin-ui/react18``;
- In Mol* 4.0, React 18 will become the default option.
## [v3.5.0] - 2022-03-25

2531
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "molstar",
"version": "3.6.0",
"version": "3.7.0",
"description": "A comprehensive macromolecular library.",
"homepage": "https://github.com/molstar/molstar#readme",
"repository": {
@@ -94,23 +94,23 @@
"@graphql-codegen/add": "^3.1.1",
"@graphql-codegen/cli": "^2.6.2",
"@graphql-codegen/time": "^3.1.1",
"@graphql-codegen/typescript": "^2.4.7",
"@graphql-codegen/typescript": "^2.4.8",
"@graphql-codegen/typescript-graphql-files-modules": "^2.1.1",
"@graphql-codegen/typescript-graphql-request": "^4.4.2",
"@graphql-codegen/typescript-operations": "^2.3.4",
"@graphql-codegen/typescript-graphql-request": "^4.4.5",
"@graphql-codegen/typescript-operations": "^2.3.5",
"@types/cors": "^2.8.12",
"@types/gl": "^4.1.0",
"@types/jest": "^27.4.1",
"@types/react": "^17.0.43",
"@types/react-dom": "^17.0.14",
"@typescript-eslint/eslint-plugin": "^5.14.0",
"@typescript-eslint/parser": "^5.14.0",
"@types/react": "^18.0.1",
"@types/react-dom": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.18.0",
"@typescript-eslint/parser": "^5.18.0",
"benchmark": "^2.1.4",
"concurrently": "^7.0.0",
"concurrently": "^7.1.0",
"cpx2": "^4.2.0",
"crypto-browserify": "^3.12.0",
"css-loader": "^6.7.1",
"eslint": "^8.11.0",
"eslint": "^8.13.0",
"extra-watch-webpack-plugin": "^1.0.3",
"file-loader": "^6.2.0",
"fs-extra": "^10.0.1",
@@ -122,14 +122,14 @@
"raw-loader": "^4.0.2",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"sass": "^1.49.9",
"sass": "^1.50.0",
"sass-loader": "^12.6.0",
"simple-git": "^3.3.0",
"simple-git": "^3.5.0",
"stream-browserify": "^3.0.0",
"style-loader": "^3.3.1",
"ts-jest": "^27.1.3",
"ts-jest": "^27.1.4",
"typescript": "^4.6.3",
"webpack": "^5.70.0",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2"
},
"dependencies": {
@@ -141,7 +141,7 @@
"@types/node-fetch": "^2.6.1",
"@types/swagger-ui-dist": "3.30.1",
"argparse": "^2.0.1",
"body-parser": "^1.19.2",
"body-parser": "^1.20.0",
"compression": "^1.7.4",
"cors": "^2.8.5",
"express": "^4.17.3",
@@ -150,7 +150,7 @@
"immutable": "^4.0.0",
"node-fetch": "^2.6.7",
"rxjs": "^7.5.5",
"swagger-ui-dist": "^4.6.2",
"swagger-ui-dist": "^4.10.3",
"tslib": "^2.3.1",
"util.promisify": "^1.1.1",
"xhr2": "^0.2.1"

View File

@@ -80,20 +80,24 @@ export class AlphaOrbitalsExample {
this.plugin.managers.interactivity.setProps({ granularity: 'element' });
if (!canComputeGrid3dOnGPU(this.plugin.canvas3d?.webgl)) {
PluginCommands.Toast.Show(this.plugin, {
title: 'Error',
message: `Browser/device does not support required WebGL extension (OES_texture_float).`
this.plugin.behaviors.canvas3d.initialized.subscribe(init => {
if (!init) return;
if (!canComputeGrid3dOnGPU(this.plugin.canvas3d?.webgl)) {
PluginCommands.Toast.Show(this.plugin, {
title: 'Error',
message: `Browser/device does not support required WebGL extension (OES_texture_float).`
});
return;
}
this.load({
moleculeSdf: DemoMoleculeSDF,
...DemoOrbitals
});
return;
}
this.load({
moleculeSdf: DemoMoleculeSDF,
...DemoOrbitals
mountControls(this, document.getElementById('controls')!);
});
mountControls(this, document.getElementById('controls')!);
}
readonly params = new BehaviorSubject<ParamDefinition.For<Params>>({} as any);

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author David Sehnal <david.sehnal@gmail.com>
@@ -11,7 +11,7 @@ import { Color } from '../../mol-util/color';
import { Vec2, Vec3, Vec4 } from '../../mol-math/linear-algebra';
import { LocationIterator } from '../util/location-iterator';
import { NullLocation } from '../../mol-model/location';
import { LocationColor, ColorTheme } from '../../mol-theme/color';
import { LocationColor, ColorTheme, ColorVolume } from '../../mol-theme/color';
import { Geometry } from './geometry';
import { createNullTexture, Texture } from '../../mol-gl/webgl/texture';
@@ -48,8 +48,18 @@ function _createColors(locationIt: LocationIterator, positionIt: LocationIterato
case 'groupInstance': return createGroupInstanceColor(locationIt, colorTheme.color, colorData);
case 'vertex': return createVertexColor(positionIt, colorTheme.color, colorData);
case 'vertexInstance': return createVertexInstanceColor(positionIt, colorTheme.color, colorData);
case 'volume': return createGridColor((colorTheme as any).grid, 'volume', colorData);
case 'volumeInstance': return createGridColor((colorTheme as any).grid, 'volumeInstance', colorData);
case 'volume':
if (colorTheme.grid) {
return createGridColor(colorTheme.grid, 'volume', colorData);
} else {
throw new Error('Grid missing for "volume" color theme');
}
case 'volumeInstance':
if (colorTheme.grid) {
return createGridColor(colorTheme.grid, 'volumeInstance', colorData);
} else {
throw new Error('Grid missing for "volume" color theme');
}
case 'direct': return createDirectColor(colorData);
}
}
@@ -207,12 +217,6 @@ function createVertexInstanceColor(locationIt: LocationIterator, color: Location
//
interface ColorVolume {
colors: Texture
dimension: Vec3
transform: Vec4
}
export function createGridColor(grid: ColorVolume, type: ColorType, colorData?: ColorData): ColorData {
const { colors, dimension, transform } = grid;
const width = colors.getWidth();

View File

@@ -157,7 +157,7 @@ export namespace Cylinders {
doubleSided: PD.Boolean(false, BaseGeometry.CustomQualityParamInfo),
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
allowTransparentBackfaces: PD.Boolean(false, BaseGeometry.ShadingCategory),
transparentBackfaces: PD.Select('off', PD.arrayToOptions(['off', 'on', 'opaque']), BaseGeometry.ShadingCategory),
bumpFrequency: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
bumpAmplitude: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }, BaseGeometry.ShadingCategory),
};
@@ -242,6 +242,7 @@ export namespace Cylinders {
uDoubleSided: ValueCell.create(props.doubleSided),
dIgnoreLight: ValueCell.create(props.ignoreLight),
dXrayShaded: ValueCell.create(props.xrayShaded),
dOpaqueBackfaces: ValueCell.create(props.transparentBackfaces === 'opaque'),
uBumpFrequency: ValueCell.create(props.bumpFrequency),
uBumpAmplitude: ValueCell.create(props.bumpAmplitude),
};
@@ -259,6 +260,7 @@ export namespace Cylinders {
ValueCell.updateIfChanged(values.uDoubleSided, props.doubleSided);
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
ValueCell.updateIfChanged(values.dOpaqueBackfaces, props.transparentBackfaces === 'opaque');
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
ValueCell.updateIfChanged(values.uBumpAmplitude, props.bumpAmplitude);
}

View File

@@ -625,7 +625,7 @@ export namespace Mesh {
flatShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
allowTransparentBackfaces: PD.Boolean(false, BaseGeometry.ShadingCategory),
transparentBackfaces: PD.Select('off', PD.arrayToOptions(['off', 'on', 'opaque']), BaseGeometry.ShadingCategory),
bumpFrequency: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
bumpAmplitude: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }, BaseGeometry.ShadingCategory),
};
@@ -701,6 +701,7 @@ export namespace Mesh {
dFlipSided: ValueCell.create(props.flipSided),
dIgnoreLight: ValueCell.create(props.ignoreLight),
dXrayShaded: ValueCell.create(props.xrayShaded),
dOpaqueBackfaces: ValueCell.create(props.transparentBackfaces === 'opaque'),
uBumpFrequency: ValueCell.create(props.bumpFrequency),
uBumpAmplitude: ValueCell.create(props.bumpAmplitude),
@@ -721,6 +722,7 @@ export namespace Mesh {
ValueCell.updateIfChanged(values.dFlipSided, props.flipSided);
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
ValueCell.updateIfChanged(values.dOpaqueBackfaces, props.transparentBackfaces === 'opaque');
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
ValueCell.updateIfChanged(values.uBumpAmplitude, props.bumpAmplitude);
}

View File

@@ -129,7 +129,7 @@ export namespace Spheres {
doubleSided: PD.Boolean(false, BaseGeometry.CustomQualityParamInfo),
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
allowTransparentBackfaces: PD.Boolean(false, BaseGeometry.ShadingCategory),
transparentBackfaces: PD.Select('off', PD.arrayToOptions(['off', 'on', 'opaque']), BaseGeometry.ShadingCategory),
bumpFrequency: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
bumpAmplitude: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }, BaseGeometry.ShadingCategory),
};
@@ -209,6 +209,7 @@ export namespace Spheres {
uDoubleSided: ValueCell.create(props.doubleSided),
dIgnoreLight: ValueCell.create(props.ignoreLight),
dXrayShaded: ValueCell.create(props.xrayShaded),
dOpaqueBackfaces: ValueCell.create(props.transparentBackfaces === 'opaque'),
uBumpFrequency: ValueCell.create(props.bumpFrequency),
uBumpAmplitude: ValueCell.create(props.bumpAmplitude),
};
@@ -226,6 +227,7 @@ export namespace Spheres {
ValueCell.updateIfChanged(values.uDoubleSided, props.doubleSided);
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
ValueCell.updateIfChanged(values.dOpaqueBackfaces, props.transparentBackfaces === 'opaque');
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
ValueCell.updateIfChanged(values.uBumpAmplitude, props.bumpAmplitude);
}

View File

@@ -24,6 +24,7 @@ import { Vec2, Vec4 } from '../../../mol-math/linear-algebra';
import { createEmptyClipping } from '../clipping-data';
import { NullLocation } from '../../../mol-model/location';
import { createEmptySubstance } from '../substance-data';
import { RenderableState } from '../../../mol-gl/renderable';
export interface TextureMesh {
readonly kind: 'texture-mesh',
@@ -113,7 +114,7 @@ export namespace TextureMesh {
flatShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
allowTransparentBackfaces: PD.Boolean(false, BaseGeometry.ShadingCategory),
transparentBackfaces: PD.Select('off', PD.arrayToOptions(['off', 'on', 'opaque']), BaseGeometry.ShadingCategory),
bumpFrequency: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
bumpAmplitude: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }, BaseGeometry.ShadingCategory),
};
@@ -126,8 +127,8 @@ export namespace TextureMesh {
createValuesSimple,
updateValues,
updateBoundingSphere,
createRenderableState: BaseGeometry.createRenderableState,
updateRenderableState: BaseGeometry.updateRenderableState,
createRenderableState,
updateRenderableState,
createPositionIterator: () => LocationIterator(1, 1, 1, () => NullLocation)
};
@@ -173,6 +174,7 @@ export namespace TextureMesh {
dFlipSided: ValueCell.create(props.flipSided),
dIgnoreLight: ValueCell.create(props.ignoreLight),
dXrayShaded: ValueCell.create(props.xrayShaded),
dOpaqueBackfaces: ValueCell.create(props.transparentBackfaces === 'opaque'),
uBumpFrequency: ValueCell.create(props.bumpFrequency),
uBumpAmplitude: ValueCell.create(props.bumpAmplitude),
@@ -193,6 +195,7 @@ export namespace TextureMesh {
ValueCell.updateIfChanged(values.dFlipSided, props.flipSided);
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
ValueCell.updateIfChanged(values.dOpaqueBackfaces, props.transparentBackfaces === 'opaque');
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
ValueCell.updateIfChanged(values.uBumpAmplitude, props.bumpAmplitude);
}
@@ -209,4 +212,16 @@ export namespace TextureMesh {
ValueCell.update(values.uInvariantBoundingSphere, Vec4.fromSphere(values.uInvariantBoundingSphere.ref.value, invariantBoundingSphere));
}
}
function createRenderableState(props: PD.Values<Params>): RenderableState {
const state = BaseGeometry.createRenderableState(props);
updateRenderableState(state, props);
return state;
}
function updateRenderableState(state: RenderableState, props: PD.Values<Params>) {
BaseGeometry.updateRenderableState(state, props);
state.opaque = state.opaque && !props.xrayShaded;
state.writeDepth = state.opaque;
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2020-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -26,6 +26,7 @@ export const CylindersSchema = {
uDoubleSided: UniformSpec('b'),
dIgnoreLight: DefineSpec('boolean'),
dXrayShaded: DefineSpec('boolean'),
dOpaqueBackfaces: DefineSpec('boolean'),
uBumpFrequency: UniformSpec('f'),
uBumpAmplitude: UniformSpec('f'),
};

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -22,6 +22,7 @@ export const MeshSchema = {
dFlipSided: DefineSpec('boolean'),
dIgnoreLight: DefineSpec('boolean'),
dXrayShaded: DefineSpec('boolean'),
dOpaqueBackfaces: DefineSpec('boolean'),
uBumpFrequency: UniformSpec('f'),
uBumpAmplitude: UniformSpec('f'),
meta: ValueSpec('unknown')

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -23,6 +23,7 @@ export const SpheresSchema = {
uDoubleSided: UniformSpec('b'),
dIgnoreLight: DefineSpec('boolean'),
dXrayShaded: DefineSpec('boolean'),
dOpaqueBackfaces: DefineSpec('boolean'),
uBumpFrequency: UniformSpec('f'),
uBumpAmplitude: UniformSpec('f'),
};

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -23,6 +23,7 @@ export const TextureMeshSchema = {
dFlipSided: DefineSpec('boolean'),
dIgnoreLight: DefineSpec('boolean'),
dXrayShaded: DefineSpec('boolean'),
dOpaqueBackfaces: DefineSpec('boolean'),
uBumpFrequency: UniformSpec('f'),
uBumpAmplitude: UniformSpec('f'),
meta: ValueSpec('unknown')

View File

@@ -135,6 +135,12 @@ function getLight(props: RendererProps['light'], light?: Light): Light {
}
namespace Renderer {
const enum Flag {
None = 0,
BlendedFront = 1,
BlendedBack = 2
}
export function create(ctx: WebGLContext, props: Partial<RendererProps> = {}): Renderer {
const { gl, state, stats } = ctx;
const p = PD.merge(RendererParams, PD.getDefaultValues(RendererParams), props);
@@ -220,7 +226,7 @@ namespace Renderer {
let globalUniformsNeedUpdate = true;
const renderObject = (r: GraphicsRenderable, variant: GraphicsRenderVariant) => {
const renderObject = (r: GraphicsRenderable, variant: GraphicsRenderVariant, flag: Flag) => {
if (r.state.disposed || !r.state.visible || (!r.state.pickable && variant === 'pick')) {
return;
}
@@ -259,6 +265,24 @@ namespace Renderer {
state.disable(gl.DEPTH_TEST);
state.depthMask(false);
}
} else if (flag === Flag.BlendedFront) {
state.enable(gl.CULL_FACE);
if (r.values.dFlipSided?.ref.value) {
state.frontFace(gl.CW);
state.cullFace(gl.FRONT);
} else {
state.frontFace(gl.CCW);
state.cullFace(gl.BACK);
}
} else if (flag === Flag.BlendedBack) {
state.enable(gl.CULL_FACE);
if (r.values.dFlipSided?.ref.value) {
state.frontFace(gl.CW);
state.cullFace(gl.BACK);
} else {
state.frontFace(gl.CCW);
state.cullFace(gl.FRONT);
}
} else {
if (r.values.uDoubleSided) {
if (r.values.uDoubleSided.ref.value || r.values.hasReflection.ref.value) {
@@ -271,14 +295,9 @@ namespace Renderer {
state.disable(gl.CULL_FACE);
}
if (r.values.dFlipSided) {
if (r.values.dFlipSided.ref.value) {
state.frontFace(gl.CW);
state.cullFace(gl.FRONT);
} else {
state.frontFace(gl.CCW);
state.cullFace(gl.BACK);
}
if (r.values.dFlipSided?.ref.value) {
state.frontFace(gl.CW);
state.cullFace(gl.FRONT);
} else {
// webgl default
state.frontFace(gl.CCW);
@@ -342,7 +361,7 @@ namespace Renderer {
const { renderables } = group;
for (let i = 0, il = renderables.length; i < il; ++i) {
if (!renderables[i].state.colorOnly) {
renderObject(renderables[i], variant);
renderObject(renderables[i], variant, Flag.None);
}
}
};
@@ -356,7 +375,7 @@ namespace Renderer {
const { renderables } = group;
for (let i = 0, il = renderables.length; i < il; ++i) {
renderObject(renderables[i], 'depth');
renderObject(renderables[i], 'depth', Flag.None);
}
};
@@ -373,7 +392,7 @@ namespace Renderer {
const r = renderables[i];
if (r.values.markerAverage.ref.value !== 1) {
renderObject(renderables[i], 'marking');
renderObject(renderables[i], 'marking', Flag.None);
}
}
};
@@ -391,7 +410,7 @@ namespace Renderer {
const r = renderables[i];
if (r.values.markerAverage.ref.value > 0) {
renderObject(renderables[i], 'marking');
renderObject(renderables[i], 'marking', Flag.None);
}
}
};
@@ -412,7 +431,9 @@ namespace Renderer {
for (let i = 0, il = renderables.length; i < il; ++i) {
const r = renderables[i];
if (r.state.opaque) {
renderObject(r, 'colorBlended');
renderObject(r, 'colorBlended', Flag.None);
} else if (r.values.uDoubleSided?.ref.value && r.values.dOpaqueBackfaces?.ref.value) {
renderObject(r, 'colorBlended', Flag.BlendedBack);
}
}
};
@@ -435,7 +456,7 @@ namespace Renderer {
for (let i = 0, il = renderables.length; i < il; ++i) {
const r = renderables[i];
if (!r.state.opaque && r.state.writeDepth) {
renderObject(r, 'colorBlended');
renderObject(r, 'colorBlended', Flag.None);
}
}
@@ -443,7 +464,15 @@ namespace Renderer {
for (let i = 0, il = renderables.length; i < il; ++i) {
const r = renderables[i];
if (!r.state.opaque && !r.state.writeDepth) {
renderObject(r, 'colorBlended');
if (r.values.uDoubleSided?.ref.value) {
// render frontfaces and backfaces separately to avoid artefacts
if (!r.values.dOpaqueBackfaces?.ref.value) {
renderObject(r, 'colorBlended', Flag.BlendedBack);
}
renderObject(r, 'colorBlended', Flag.BlendedFront);
} else {
renderObject(r, 'colorBlended', Flag.None);
}
}
}
};
@@ -462,7 +491,7 @@ namespace Renderer {
// uAlpha is updated in "render" so we need to recompute it here
const alpha = clamp(r.values.alpha.ref.value * r.state.alphaFactor, 0, 1);
if (alpha === 1 && r.values.transparencyAverage.ref.value !== 1 && !r.values.dXrayShaded?.ref.value) {
renderObject(r, 'colorBlended');
renderObject(r, 'colorBlended', Flag.None);
}
}
};
@@ -481,7 +510,7 @@ namespace Renderer {
// uAlpha is updated in "render" so we need to recompute it here
const alpha = clamp(r.values.alpha.ref.value * r.state.alphaFactor, 0, 1);
if (alpha < 1 || r.values.transparencyAverage.ref.value > 0 || r.values.dXrayShaded?.ref.value) {
renderObject(r, 'colorBlended');
renderObject(r, 'colorBlended', Flag.None);
}
}
};
@@ -500,8 +529,8 @@ namespace Renderer {
// TODO: simplify, handle in renderable.state???
// uAlpha is updated in "render" so we need to recompute it here
const alpha = clamp(r.values.alpha.ref.value * r.state.alphaFactor, 0, 1);
if (alpha === 1 && r.values.transparencyAverage.ref.value !== 1 && r.values.dGeometryType.ref.value !== 'directVolume' && r.values.dPointStyle?.ref.value !== 'fuzzy' && !r.values.dXrayShaded?.ref.value) {
renderObject(r, 'colorWboit');
if ((alpha === 1 && r.values.transparencyAverage.ref.value !== 1 && r.values.dGeometryType.ref.value !== 'directVolume' && r.values.dPointStyle?.ref.value !== 'fuzzy' && !r.values.dXrayShaded?.ref.value) || r.values.dOpaqueBackfaces?.ref.value) {
renderObject(r, 'colorWboit', Flag.None);
}
}
};
@@ -517,7 +546,7 @@ namespace Renderer {
// uAlpha is updated in "render" so we need to recompute it here
const alpha = clamp(r.values.alpha.ref.value * r.state.alphaFactor, 0, 1);
if (alpha < 1 || r.values.transparencyAverage.ref.value > 0 || r.values.dGeometryType.ref.value === 'directVolume' || r.values.dPointStyle?.ref.value === 'fuzzy' || !!r.values.uBackgroundColor || r.values.dXrayShaded?.ref.value) {
renderObject(r, 'colorWboit');
renderObject(r, 'colorWboit', Flag.None);
}
}
};

View File

@@ -5,5 +5,9 @@ if (interior) {
} else {
gl_FragColor.rgb *= 1.0 - uInteriorDarkening;
}
#ifdef dOpaqueBackfaces
gl_FragColor.a = 1.0;
#endif
}
`;

View File

@@ -2,6 +2,12 @@ export const check_picking_alpha = `
float viewZ = depthToViewZ(uIsOrtho, fragmentDepth, uNear, uFar);
float fogFactor = smoothstep(uFogNear, uFogFar, abs(viewZ));
float alpha = (1.0 - fogFactor) * uAlpha;
if (uAlpha < uPickingAlphaThreshold || alpha < 0.1)
discard; // ignore so the element below can be picked
// if not opaque enough ignore so the element below can be picked
if (uAlpha < uPickingAlphaThreshold || alpha < 0.1) {
#ifdef dOpaqueBackfaces
if (!interior) discard;
#else
discard;
#endif
}
`;

View File

@@ -19,6 +19,8 @@ uniform float uBumpiness;
uniform vec3 uColorGridDim;
uniform vec4 uColorGridTransform;
uniform sampler2D tColorGrid;
#elif defined(dColorType_direct)
varying vec4 vColor;
#endif
#ifdef dUsePalette

View File

@@ -9,12 +9,14 @@ import { Writer } from './writer';
import { Encoder, Category, Field } from './cif/encoder';
import { ComponentAtom } from '../../mol-model-formats/structure/property/atoms/chem_comp';
import { ComponentBond } from '../../mol-model-formats/structure/property/bonds/chem_comp';
import { getElementIdx, isHydrogen } from '../../mol-model/structure/structure/unit/bonds/common';
import { ElementSymbol } from '../../mol-model/structure/model/types';
interface Atom {
Cartn_x: number,
Cartn_y: number,
Cartn_z: number,
type_symbol: string,
type_symbol: ElementSymbol,
index: number
}
@@ -109,11 +111,12 @@ export abstract class LigandEncoder implements Encoder<string> {
const key = it.move();
const lai = label_atom_id.value(key, data, index) as string;
const ts = type_symbol.value(key, data, index) as string;
if (this.skipHydrogen(ts)) {
index++;
continue;
}
// ignore all alternate locations after the first
if (atoms.has(lai)) continue;
const ts = type_symbol.value(key, data, index) as ElementSymbol;
if (this.skipHydrogen(ts)) continue;
const a: { [k: string]: (string | number) } = {};
for (let _f = 0, _fl = fields.length; _f < _fl; _f++) {
@@ -131,11 +134,15 @@ export abstract class LigandEncoder implements Encoder<string> {
return atoms;
}
protected skipHydrogen(type_symbol: string) {
protected skipHydrogen(type_symbol: ElementSymbol) {
if (this.hydrogens) {
return false;
}
return type_symbol === 'H';
return this.isHydrogen(type_symbol);
}
protected isHydrogen(type_symbol: ElementSymbol) {
return isHydrogen(getElementIdx(type_symbol));
}
private getSortedFields<Ctx>(instance: Category.Instance<Ctx>, names: string[]) {

View File

@@ -26,14 +26,27 @@ export class MolEncoder extends LigandEncoder {
const atomMap = this.componentAtomData.entries.get(name)!;
const bondMap = this.componentBondData.entries.get(name)!;
// happens for the unknown ligands (UNL)
if (!atomMap) throw Error(`The Chemical Component Dictionary doesn't hold any atom data for ${name}`);
let bondCount = 0;
let chiral = false;
// traverse once to determine all actually present atoms
const atoms = this.getAtoms(instance, source);
atoms.forEach((atom1, label_atom_id1) => {
const { index: i1 } = atom1;
const { charge, stereo_config } = atomMap.map.get(label_atom_id1)!;
const { index: i1, type_symbol: type_symbol1 } = atom1;
const atomMapData1 = atomMap.map.get(label_atom_id1);
if (!atomMapData1) {
if (this.isHydrogen(type_symbol1)) {
return;
} else {
throw Error(`Unknown atom ${label_atom_id1} for component ${name}`);
}
}
const { charge, stereo_config } = atomMapData1;
StringBuilder.writePadLeft(ctab, atom1.Cartn_x.toFixed(4), 10);
StringBuilder.writePadLeft(ctab, atom1.Cartn_y.toFixed(4), 10);
StringBuilder.writePadLeft(ctab, atom1.Cartn_z.toFixed(4), 10);
@@ -50,8 +63,8 @@ export class MolEncoder extends LigandEncoder {
const atom2 = atoms.get(label_atom_id2);
if (!atom2) return;
const { index: i2, type_symbol: type_symbol2 } = atom2;
if (i1 < i2 && !this.skipHydrogen(type_symbol2)) {
const { index: i2 } = atom2;
if (i1 < i2) {
const { order } = bond;
StringBuilder.writeIntegerPadLeft(bonds, i1 + 1, 3);
StringBuilder.writeIntegerPadLeft(bonds, i2 + 1, 3);

View File

@@ -29,21 +29,34 @@ export class Mol2Encoder extends LigandEncoder {
const name = this.getName(instance, source);
StringBuilder.writeSafe(this.builder, `# Name: ${name}\n# Created by ${this.encoder}\n\n`);
const atomMap = this.componentAtomData.entries.get(name)!;
const bondMap = this.componentBondData.entries.get(name)!;
// happens for the unknown ligands (UNL)
if (!atomMap) throw Error(`The Chemical Component Dictionary doesn't hold any atom data for ${name}`);
let bondCount = 0;
const atoms = this.getAtoms(instance, source);
StringBuilder.writeSafe(a, '@<TRIPOS>ATOM\n');
StringBuilder.writeSafe(b, '@<TRIPOS>BOND\n');
atoms.forEach((atom1, label_atom_id1) => {
const { index: i1 } = atom1;
const { index: i1, type_symbol: type_symbol1 } = atom1;
const atomMapData1 = atomMap.map.get(label_atom_id1);
if (!atomMapData1) {
if (this.isHydrogen(type_symbol1)) {
return;
} else {
throw Error(`Unknown atom ${label_atom_id1} for component ${name}`);
}
}
if (bondMap?.map) {
bondMap.map.get(label_atom_id1)!.forEach((bond, label_atom_id2) => {
const atom2 = atoms.get(label_atom_id2);
if (!atom2) return;
const { index: i2, type_symbol: type_symbol2 } = atom2;
if (i1 < i2 && !this.skipHydrogen(type_symbol2)) {
const { index: i2 } = atom2;
if (i1 < i2) {
const { order, flags } = bond;
const ar = BondType.is(BondType.Flag.Aromatic, flags);
StringBuilder.writeSafe(b, `${++bondCount} ${i1 + 1} ${i2 + 1} ${ar ? 'ar' : order}`);
@@ -52,7 +65,7 @@ export class Mol2Encoder extends LigandEncoder {
});
}
const sybyl = bondMap?.map ? this.mapToSybyl(label_atom_id1, atom1.type_symbol, bondMap) : atom1.type_symbol;
const sybyl = bondMap?.map ? this.mapToSybyl(label_atom_id1, type_symbol1, bondMap) : type_symbol1;
StringBuilder.writeSafe(a, `${i1 + 1} ${label_atom_id1} ${atom1.Cartn_x.toFixed(3)} ${atom1.Cartn_y.toFixed(3)} ${atom1.Cartn_z.toFixed(3)} ${sybyl} 1 ${name} 0.000\n`);
});

View File

@@ -13,7 +13,7 @@ import { Icon, ArrowRightSvg, ArrowDropDownSvg } from './controls/icons';
export const PluginReactContext = React.createContext(void 0 as any as PluginUIContext);
export abstract class PluginUIComponent<P = {}, S = {}, SS = {}> extends React.Component<P, S, SS> {
export abstract class PluginUIComponent<P = {}, S = {}, SS = {}> extends React.Component<P & { children?: any }, S, SS> {
static contextType = PluginReactContext;
readonly plugin: PluginUIContext;

View File

@@ -92,7 +92,7 @@ export class CombinedColorControl extends React.PureComponent<ParamProps<PD.Colo
}
}
let _colors: React.ReactFragment | undefined = void 0;
let _colors: any = void 0;
export function ColorOptions() {
if (_colors) return _colors;
_colors = <>{DefaultColorSwatch.map(v =>

View File

@@ -21,7 +21,8 @@ export class ControlGroup extends React.Component<{
onHeaderClick?: () => void,
noTopMargin?: boolean,
childrenClassName?: string,
maxHeight?: string
maxHeight?: string,
children?: any
}, { isExpanded: boolean }> {
state = { isExpanded: !!this.props.initialExpanded };
@@ -335,7 +336,7 @@ export class ToggleButton extends React.PureComponent<ToggleButtonProps> {
}
}
export class ExpandGroup extends React.PureComponent<{ header: string, headerStyle?: React.CSSProperties, initiallyExpanded?: boolean, accent?: boolean, noOffset?: boolean, marginTop?: 0 | string, headerLeftMargin?: string }, { isExpanded: boolean }> {
export class ExpandGroup extends React.PureComponent<{ children?: any, header: string, headerStyle?: React.CSSProperties, initiallyExpanded?: boolean, accent?: boolean, noOffset?: boolean, marginTop?: 0 | string, headerLeftMargin?: string }, { isExpanded: boolean }> {
state = { isExpanded: !!this.props.initiallyExpanded };
toggleExpanded = () => this.setState({ isExpanded: !this.state.isExpanded });

View File

@@ -1,26 +1,23 @@
/**
* Copyright (c) 2020-21 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2020-22 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { useEffect, useRef, useState } from 'react';
import React from 'react';
import { skip } from 'rxjs';
interface Behavior<T> {
value: T;
subscribe(f: (v: T) => void): { unsubscribe(): void };
}
export function useBehavior<T>(s: Behavior<T>): T;
// eslint-disable-next-line
export function useBehavior<T>(s: Behavior<T> | undefined): T | undefined;
// eslint-disable-next-line
export function useBehavior<T>(s: Behavior<T> | undefined): T | undefined {
const [, next] = useState({});
const current = useRef<T>();
function useBehaviorLegacy<T>(s: Behavior<T> | undefined): T | undefined {
const [, next] = React.useState({});
const current = React.useRef<T>();
current.current = s?.value;
useEffect(() => {
React.useEffect(() => {
if (!s) {
return;
}
@@ -32,4 +29,29 @@ export function useBehavior<T>(s: Behavior<T> | undefined): T | undefined {
}, [s]);
return s?.value;
}
function useBehaviorReact18<T>(s: Behavior<T> | undefined) {
return (React as any).useSyncExternalStore(
React.useCallback(
(callback: () => void) => {
const sub = (s as any)?.pipe!(skip(1)).subscribe(callback)!;
return () => sub?.unsubscribe();
},
[s]
),
React.useCallback(() => s?.value, [s])
);
}
const _useBehavior = !!(React as any).useSyncExternalStore
? useBehaviorReact18
: useBehaviorLegacy;
export function useBehavior<T>(s: Behavior<T>): T;
// eslint-disable-next-line
export function useBehavior<T>(s: Behavior<T> | undefined): T | undefined;
// eslint-disable-next-line
export function useBehavior<T>(s: Behavior<T> | undefined): T | undefined {
return _useBehavior(s);
}

View File

@@ -23,7 +23,7 @@ import { Asset } from '../mol-util/assets';
import { BehaviorSubject } from 'rxjs';
import { useBehavior } from './hooks/use-behavior';
export class Plugin extends React.Component<{ plugin: PluginUIContext }, {}> {
export class Plugin extends React.Component<{ plugin: PluginUIContext, children?: any }, {}> {
region(kind: 'left' | 'right' | 'bottom' | 'main', element: JSX.Element) {
return <div className={`msp-layout-region msp-layout-${kind}`}>
<div className='msp-layout-static'>
@@ -39,7 +39,7 @@ export class Plugin extends React.Component<{ plugin: PluginUIContext }, {}> {
}
}
export class PluginContextContainer extends React.Component<{ plugin: PluginUIContext }> {
export class PluginContextContainer extends React.Component<{ plugin: PluginUIContext, children?: any }> {
render() {
return <PluginReactContext.Provider value={this.props.plugin}>
<div className='msp-plugin'>
@@ -159,7 +159,7 @@ class Layout extends PluginUIComponent {
{layout.showControls && controls.bottom !== 'none' && this.region('bottom', controls.bottom || Log)}
</div>
{!this.plugin.spec.components?.hideTaskOverlay && <OverlayTaskProgress />}
<DragOverlay plugin={this.plugin} showDragOverlay={this.showDragOverlay} />
{!this.plugin.spec.components?.disableDragOverlay && <DragOverlay plugin={this.plugin} showDragOverlay={this.showDragOverlay} />}
</div>
</div>;
}

View File

@@ -24,7 +24,8 @@ interface PluginUISpec extends PluginSpec {
view?: React.ComponentClass,
controls?: React.ComponentClass
},
hideTaskOverlay?: boolean
hideTaskOverlay?: boolean,
disableDragOverlay?: boolean,
},
}

View File

@@ -10,7 +10,7 @@ import { PurePluginUIComponent } from '../base';
import { ParameterControls, ParamOnChange } from '../controls/parameters';
import { PluginContext } from '../../mol-plugin/context';
import { ParamDefinition as PD } from '../../mol-util/param-definition';
import { Subject } from 'rxjs';
import { BehaviorSubject, skip } from 'rxjs';
import { Icon, RefreshSvg, CheckSvg, ArrowRightSvg, ArrowDropDownSvg, TuneSvg } from '../controls/icons';
import { ExpandGroup, ToggleButton, Button, IconButton } from '../controls/common';
@@ -124,7 +124,7 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS
abstract getSourceAndTarget(): { a?: StateObject, b?: StateObject, bCell?: StateObjectCell };
abstract state: S;
private busy: Subject<boolean> = new Subject();
private busy = new BehaviorSubject(false);
private onEnter = () => {
if (this.state.error) return;
@@ -167,11 +167,11 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS
};
componentDidMount() {
this.subscribe(this.plugin.behaviors.state.isBusy, b => {
if (this.state.busy !== b) this.busy.next(b);
this.subscribe(this.plugin.behaviors.state.isBusy, busy => {
if (this.busy.value !== busy) this.busy.next(busy);
});
this.subscribe(this.busy, busy => {
if (this.state.busy !== busy) this.setState({ busy });
this.subscribe(this.busy.pipe(skip(1)), busy => {
this.setState({ busy });
});
}

View File

@@ -4,32 +4,39 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { PluginUIComponent } from './base';
import { PluginReactContext, PluginUIComponent } from './base';
import { OrderedMap } from 'immutable';
import { TaskManager } from '../mol-plugin/util/task-manager';
import { filter } from 'rxjs/operators';
import { Progress } from '../mol-task';
import { IconButton } from './controls/common';
import { CancelSvg } from './controls/icons';
import { useContext, useEffect, useState } from 'react';
export class BackgroundTaskProgress extends PluginUIComponent<{ }, { tracked: OrderedMap<number, TaskManager.ProgressEvent> }> {
componentDidMount() {
const hideOverlay = !!this.plugin.spec.components?.hideTaskOverlay;
this.subscribe(this.plugin.events.task.progress.pipe(filter(e => e.level === 'background' && (hideOverlay || !e.useOverlay))), e => {
this.setState({ tracked: this.state.tracked.set(e.id, e) });
export function BackgroundTaskProgress() {
const plugin = useContext(PluginReactContext);
const [tracked, setTracked] = useState<OrderedMap<number, TaskManager.ProgressEvent>>(OrderedMap());
useEffect(() => {
const started = plugin.events.task.progress.subscribe(e => {
const hideOverlay = !!plugin.spec.components?.hideTaskOverlay;
if (e.level === 'background' && (hideOverlay || !e.useOverlay)) {
setTracked(tracked => tracked.set(e.id, e));
}
});
this.subscribe(this.plugin.events.task.finished, ({ id }) => {
this.setState({ tracked: this.state.tracked.delete(id) });
const finished = plugin.events.task.finished.subscribe(({ id }) => {
setTracked(tracked => tracked.delete(id));
});
}
state = { tracked: OrderedMap<number, TaskManager.ProgressEvent>() };
return () => {
started.unsubscribe();
finished.unsubscribe();
};
}, [plugin]);
render() {
return <div className='msp-background-tasks'>
{this.state.tracked.valueSeq().map(e => <ProgressEntry key={e!.id} event={e!} />)}
</div>;
}
return <div className='msp-background-tasks'>
{tracked.valueSeq().map(e => <ProgressEntry key={e!.id} event={e!} />)}
</div>;
}
class ProgressEntry extends PluginUIComponent<{ event: TaskManager.ProgressEvent }> {
@@ -65,23 +72,30 @@ function countSubtasks(progress: Progress.Node) {
return sum;
}
export class OverlayTaskProgress extends PluginUIComponent<{ }, { tracked: OrderedMap<number, TaskManager.ProgressEvent> }> {
componentDidMount() {
this.subscribe(this.plugin.events.task.progress.pipe(filter(e => !!e.useOverlay)), e => {
this.setState({ tracked: this.state.tracked.set(e.id, e) });
export function OverlayTaskProgress() {
const plugin = useContext(PluginReactContext);
const [tracked, setTracked] = useState<OrderedMap<number, TaskManager.ProgressEvent>>(OrderedMap());
useEffect(() => {
const started = plugin.events.task.progress.subscribe(e => {
if (!!e.useOverlay) {
setTracked(tracked => tracked.set(e.id, e));
}
});
this.subscribe(this.plugin.events.task.finished, ({ id }) => {
this.setState({ tracked: this.state.tracked.delete(id) });
const finished = plugin.events.task.finished.subscribe(({ id }) => {
setTracked(tracked => tracked.delete(id));
});
}
state = { tracked: OrderedMap<number, TaskManager.ProgressEvent>() };
return () => {
started.unsubscribe();
finished.unsubscribe();
};
}, [plugin]);
render() {
if (this.state.tracked.size === 0) return null;
if (tracked.size === 0) return null;
return <div className='msp-overlay-tasks'>
{this.state.tracked.valueSeq().map(e => <ProgressEntry key={e!.id} event={e!} />)}
</div>;
}
}
return <div className='msp-overlay-tasks'>
{tracked.valueSeq().map(e => <ProgressEntry key={e!.id} event={e!} />)}
</div>;
}

View File

@@ -37,7 +37,7 @@ export class BindingsHelp extends React.PureComponent<{ bindings: { [k: string]:
}
}
export class HelpText extends React.PureComponent {
export class HelpText extends React.PureComponent<{ children?: any }> {
render() {
return <div className='msp-help-text'>
<div>{this.props.children}</div>
@@ -45,7 +45,7 @@ export class HelpText extends React.PureComponent {
}
}
export class HelpGroup extends React.PureComponent<{ header: string, initiallyExpanded?: boolean }, { isExpanded: boolean }> {
export class HelpGroup extends React.PureComponent<{ children?: any, header: string, initiallyExpanded?: boolean }, { isExpanded: boolean }> {
state = {
header: this.props.header,
isExpanded: !!this.props.initiallyExpanded

View File

@@ -80,7 +80,6 @@ export async function getContourLevelEmdb(plugin: PluginContext, taskCtx: Runtim
}
}
const contourLevel = parseFloat(primaryContour.getElementsByTagName('level')[0].textContent!);
return contourLevel;
}

View File

@@ -57,7 +57,7 @@ export interface QualityProps {
doubleSided: boolean
xrayShaded: boolean
alpha: number
allowTransparentBackfaces: boolean
transparentBackfaces: 'off' | 'on' | 'opaque'
}
export const DefaultQualityThresholds = {
@@ -193,7 +193,7 @@ export function getQualityProps(props: Partial<QualityProps>, data?: any) {
resolution = Math.max(resolution, volume / 500_000_000);
resolution = Math.min(resolution, 20);
if (!props.allowTransparentBackfaces && ((props.alpha !== undefined && props.alpha < 1) || !!props.xrayShaded)) {
if (props.transparentBackfaces === 'off' && ((props.alpha !== undefined && props.alpha < 1) || !!props.xrayShaded)) {
doubleSided = false;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -35,17 +35,25 @@ import { OperatorHklColorThemeProvider } from './color/operator-hkl';
import { PartialChargeColorThemeProvider } from './color/partial-charge';
import { AtomIdColorThemeProvider } from './color/atom-id';
import { EntityIdColorThemeProvider } from './color/entity-id';
import { TextureFilter } from '../mol-gl/webgl/texture';
import { Texture, TextureFilter } from '../mol-gl/webgl/texture';
import { VolumeValueColorThemeProvider } from './color/volume-value';
import { Vec3, Vec4 } from '../mol-math/linear-algebra';
export type LocationColor = (location: Location, isSecondary: boolean) => Color
export interface ColorVolume {
colors: Texture
dimension: Vec3
transform: Vec4
}
export { ColorTheme };
interface ColorTheme<P extends PD.Params> {
readonly factory: ColorTheme.Factory<P>
readonly granularity: ColorType
readonly color: LocationColor
readonly props: Readonly<PD.Values<P>>
readonly grid?: ColorVolume
/**
* if palette is defined, 24bit RGB color value normalized to interval [0, 1]
* is used as index to the colors

View File

@@ -1,3 +1,9 @@
# 0.9.9
* /ligand queries: fix behavior for alternate locations
* /ligand queries: handle additional atoms more gracefully
* /ligand queries: better error message for UNL
* /ligand queries: treat deuterium/tritium as hydrogen
# 0.9.8
* fix support for chem_comp_bond and struct_conn categories

View File

@@ -237,10 +237,8 @@ async function resolveJobEntry(entry: JobEntry, structure: StructureWrapper, enc
encoder.writeCategory(_model_server_params, entry);
if (entry.queryDefinition.niceName === 'Ligand') {
if (encoder instanceof MolEncoder) {
encoder.setComponentAtomData(ComponentAtom.Provider.get(structure.models[0])!);
}
if (encoder instanceof MolEncoder || encoder instanceof Mol2Encoder) {
encoder.setComponentAtomData(ComponentAtom.Provider.get(structure.models[0])!);
encoder.setComponentBondData(ComponentBond.Provider.get(structure.models[0])!);
}
}

View File

@@ -4,4 +4,4 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
export const VERSION = '0.9.8';
export const VERSION = '0.9.9';