Browse Source

Merge pull request #683 from molstar/misc

Misc tweaks
Alexander Rose 2 năm trước cách đây
mục cha
commit
0e197b1885

+ 8 - 2
CHANGELOG.md

@@ -6,9 +6,15 @@ Note that since we don't clearly distinguish between a public and private interf
 
 ## [Unreleased]
 
-- `meshes` extension: Fixed a bug in mesh visualization (show backfaces when opacity < 1) 
+- `meshes` extension: Fixed a bug in mesh visualization (show backfaces when opacity < 1)
 - Add color quick select control to Volume controls
-- Fix `dropFiles` bug
+- Fix `dropFiles` bug (#679)
+- Add `input type='color'` picker to `CombinedColorControl`
+- Set `ParameterMappingControl` disabled when state is updating
+- Performance tweaks
+    - Update clip `defines` only when changed
+    - Check for identity in structure/unit areEqual methods
+    - Avoid cloning of structure representation parameters
 
 ## [v3.28.0] - 2022-12-20
 

+ 2 - 2
src/mol-geo/geometry/base.ts

@@ -132,8 +132,8 @@ export namespace BaseGeometry {
         ValueCell.updateIfChanged(values.uBumpiness, props.material.bumpiness);
 
         const clip = Clip.getClip(props.clip);
-        ValueCell.update(values.dClipObjectCount, clip.objects.count);
-        ValueCell.update(values.dClipVariant, clip.variant);
+        ValueCell.updateIfChanged(values.dClipObjectCount, clip.objects.count);
+        ValueCell.updateIfChanged(values.dClipVariant, clip.variant);
         ValueCell.update(values.uClipObjectType, clip.objects.type);
         ValueCell.update(values.uClipObjectInvert, clip.objects.invert);
         ValueCell.update(values.uClipObjectPosition, clip.objects.position);

+ 1 - 0
src/mol-model/structure/structure/structure.ts

@@ -1059,6 +1059,7 @@ namespace Structure {
     }
 
     export function areUnitIdsAndIndicesEqual(a: Structure, b: Structure) {
+        if (a === b) return true;
         if (!areUnitIdsEqual(a, b)) return false;
 
         for (let i = 0, il = a.units.length; i < il; i++) {

+ 1 - 0
src/mol-model/structure/structure/unit.ts

@@ -490,6 +490,7 @@ namespace Unit {
     }
 
     export function areConformationsEqual(a: Unit, b: Unit) {
+        if (a === b) return true;
         if (!SortedArray.areEqual(a.elements, b.elements)) return false;
         return isSameConformation(a, b.model);
     }

+ 8 - 2
src/mol-plugin-ui/controls/color.tsx

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2019 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 David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -30,7 +30,7 @@ export class CombinedColorControl extends React.PureComponent<ParamProps<PD.Colo
     };
 
     onClickSwatch = (e: React.MouseEvent<HTMLButtonElement>) => {
-        const value = Color(+(e.currentTarget.getAttribute('data-color') || '0'));
+        const value = Color.fromHexString(e.currentTarget.getAttribute('data-color') || '0');
         if (value !== this.props.value) {
             if (!this.props.param.isExpanded) this.setState({ isExpanded: false });
             this.update(value);
@@ -55,6 +55,11 @@ export class CombinedColorControl extends React.PureComponent<ParamProps<PD.Colo
         if (value !== this.props.value) this.update(value);
     };
 
+    onRGB = (e: React.MouseEvent<HTMLInputElement>) => {
+        const value = Color.fromHexStyle(e.currentTarget.value || '0');
+        if (value !== this.props.value) this.update(value);
+    };
+
     onLighten = () => {
         this.update(Color.lighten(this.props.value, 0.1));
     };
@@ -79,6 +84,7 @@ export class CombinedColorControl extends React.PureComponent<ParamProps<PD.Colo
                 <TextInput onChange={this.onR} numeric value={r} delayMs={250} style={{ order: 1, flex: '1 1 auto', minWidth: 0 }} className='msp-form-control' onEnter={this.props.onEnter} blurOnEnter={true} blurOnEscape={true} />
                 <TextInput onChange={this.onG} numeric value={g} delayMs={250} style={{ order: 2, flex: '1 1 auto', minWidth: 0 }} className='msp-form-control' onEnter={this.props.onEnter} blurOnEnter={true} blurOnEscape={true} />
                 <TextInput onChange={this.onB} numeric value={b} delayMs={250} style={{ order: 3, flex: '1 1 auto', minWidth: 0 }} className='msp-form-control' onEnter={this.props.onEnter} blurOnEnter={true} blurOnEscape={true} />
+                <input onInput={this.onRGB} type='color' value={Color.toHexStyle(this.props.value)} style={{ order: 4, flex: '1 1 auto', minWidth: '32px', width: '32px', height: '32px', padding: '0 2px 0 2px', background: 'none', border: 'none', cursor: 'pointer' }}></input>
             </div>} />
             <div style={{ display: 'flex', textAlignLast: 'center' }}>
                 <Button onClick={this.onLighten} style={{ order: 1, flex: '1 1 auto', minWidth: 0 }} className='msp-form-control'>Lighten</Button>

+ 11 - 3
src/mol-plugin-ui/controls/parameters.tsx

@@ -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 David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -106,7 +106,11 @@ export class ParameterControls<P extends PD.Params> extends React.PureComponent<
     }
 }
 
-export class ParameterMappingControl<S, T> extends PluginUIComponent<{ mapping: ParamMapping<S, T, PluginUIContext> }> {
+export class ParameterMappingControl<S, T> extends PluginUIComponent<{ mapping: ParamMapping<S, T, PluginUIContext> }, { isDisabled: boolean }> {
+    state = {
+        isDisabled: false,
+    };
+
     setSettings = (p: { param: PD.Base<any>, name: string, value: any }, old: any) => {
         const values = { ...old, [p.name]: p.value };
         const t = this.props.mapping.update(values, this.plugin);
@@ -115,13 +119,17 @@ export class ParameterMappingControl<S, T> extends PluginUIComponent<{ mapping:
 
     componentDidMount() {
         this.subscribe(this.plugin.events.canvas3d.settingsUpdated, () => this.forceUpdate());
+
+        this.subscribe(this.plugin.state.data.behaviors.isUpdating, v => {
+            this.setState({ isDisabled: v });
+        });
     }
 
     render() {
         const t = this.props.mapping.getTarget(this.plugin);
         const values = this.props.mapping.getValues(t, this.plugin);
         const params = this.props.mapping.params(this.plugin) as any as PD.Params;
-        return <ParameterControls params={params} values={values} onChange={this.setSettings} />;
+        return <ParameterControls params={params} values={values} onChange={this.setSettings} isDisabled={this.state.isDisabled} />;
     }
 }
 

+ 1 - 1
src/mol-repr/structure/representation/ball-and-stick.ts

@@ -37,7 +37,7 @@ export const BallAndStickParams = {
 };
 export type BallAndStickParams = typeof BallAndStickParams
 export function getBallAndStickParams(ctx: ThemeRegistryContext, structure: Structure) {
-    return PD.clone(BallAndStickParams);
+    return BallAndStickParams;
 }
 
 export type BallAndStickRepresentation = StructureRepresentation<BallAndStickParams>

+ 2 - 2
src/mol-repr/structure/representation/carbohydrate.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018 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>
  */
@@ -30,7 +30,7 @@ export const CarbohydrateParams = {
 };
 export type CarbohydrateParams = typeof CarbohydrateParams
 export function getCarbohydrateParams(ctx: ThemeRegistryContext, structure: Structure) {
-    return PD.clone(CarbohydrateParams);
+    return CarbohydrateParams;
 }
 
 export type CarbohydrateRepresentation = StructureRepresentation<CarbohydrateParams>

+ 2 - 2
src/mol-repr/structure/representation/ellipsoid.ts

@@ -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>
  */
@@ -37,7 +37,7 @@ export const EllipsoidParams = {
 };
 export type EllipsoidParams = typeof EllipsoidParams
 export function getEllipsoidParams(ctx: ThemeRegistryContext, structure: Structure) {
-    return PD.clone(EllipsoidParams);
+    return EllipsoidParams;
 }
 
 export type EllipsoidRepresentation = StructureRepresentation<EllipsoidParams>

+ 2 - 2
src/mol-repr/structure/representation/gaussian-surface.ts

@@ -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>
  */
@@ -28,7 +28,7 @@ export const GaussianSurfaceParams = {
 };
 export type GaussianSurfaceParams = typeof GaussianSurfaceParams
 export function getGaussianSurfaceParams(ctx: ThemeRegistryContext, structure: Structure) {
-    return PD.clone(GaussianSurfaceParams);
+    return GaussianSurfaceParams;
 }
 
 export type GaussianSurfaceRepresentation = StructureRepresentation<GaussianSurfaceParams>

+ 3 - 4
src/mol-repr/structure/representation/gaussian-volume.ts

@@ -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>
  */
@@ -18,13 +18,12 @@ const GaussianVolumeVisuals = {
 
 export const GaussianVolumeParams = {
     ...GaussianDensityVolumeParams,
+    jumpLength: PD.Numeric(4, { min: 0, max: 20, step: 0.1 }),
     visuals: PD.MultiSelect(['gaussian-volume'], PD.objectToOptions(GaussianVolumeVisuals)),
 };
 export type GaussianVolumeParams = typeof GaussianVolumeParams
 export function getGaussianVolumeParams(ctx: ThemeRegistryContext, structure: Structure) {
-    const p = PD.clone(GaussianVolumeParams);
-    p.jumpLength = PD.Numeric(4, { min: 0, max: 20, step: 0.1 });
-    return p;
+    return GaussianVolumeParams;
 }
 
 export type GaussianVolumeRepresentation = StructureRepresentation<GaussianVolumeParams>

+ 2 - 2
src/mol-repr/structure/representation/label.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2019 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>
  */
@@ -22,7 +22,7 @@ export const LabelParams = {
 };
 export type LabelParams = typeof LabelParams
 export function getLabelParams(ctx: ThemeRegistryContext, structure: Structure) {
-    return PD.clone(LabelParams);
+    return LabelParams;
 }
 
 export type LabelRepresentation = StructureRepresentation<LabelParams>

+ 3 - 3
src/mol-repr/structure/representation/line.ts

@@ -16,6 +16,7 @@ import { Structure } from '../../../mol-model/structure';
 import { getUnitKindsParam } from '../params';
 import { ElementPointParams, ElementPointVisual } from '../visual/element-point';
 import { ElementCrossParams, ElementCrossVisual } from '../visual/element-cross';
+import { Points } from '../../../mol-geo/geometry/points/points';
 
 const LineVisuals = {
     'intra-bond': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, IntraUnitBondLineParams>) => UnitsRepresentation('Intra-unit bond line', ctx, getParams, IntraUnitBondLineVisual),
@@ -29,6 +30,7 @@ export const LineParams = {
     ...InterUnitBondLineParams,
     ...ElementPointParams,
     ...ElementCrossParams,
+    pointStyle: PD.Select('circle', PD.objectToOptions(Points.StyleTypes)),
     multipleBonds: PD.Select('offset', PD.arrayToOptions(['off', 'symmetric', 'offset'] as const)),
     includeParent: PD.Boolean(false),
     sizeFactor: PD.Numeric(2, { min: 0.01, max: 10, step: 0.01 }),
@@ -37,9 +39,7 @@ export const LineParams = {
 };
 export type LineParams = typeof LineParams
 export function getLineParams(ctx: ThemeRegistryContext, structure: Structure) {
-    const params = PD.clone(LineParams);
-    params.pointStyle.defaultValue = 'circle';
-    return params;
+    return LineParams;
 }
 
 export type LineRepresentation = StructureRepresentation<LineParams>

+ 1 - 1
src/mol-repr/structure/representation/molecular-surface.ts

@@ -28,7 +28,7 @@ export const MolecularSurfaceParams = {
 };
 export type MolecularSurfaceParams = typeof MolecularSurfaceParams
 export function getMolecularSurfaceParams(ctx: ThemeRegistryContext, structure: Structure) {
-    return PD.clone(MolecularSurfaceParams);
+    return MolecularSurfaceParams;
 }
 
 export type MolecularSurfaceRepresentation = StructureRepresentation<MolecularSurfaceParams>

+ 2 - 2
src/mol-repr/structure/representation/orientation.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2019 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>
  */
@@ -24,7 +24,7 @@ export const OrientationParams = {
 };
 export type OrientationParams = typeof OrientationParams
 export function getOrientationParams(ctx: ThemeRegistryContext, structure: Structure) {
-    return PD.clone(OrientationParams);
+    return OrientationParams;
 }
 
 export type OrientationRepresentation = StructureRepresentation<OrientationParams>

+ 2 - 2
src/mol-repr/structure/representation/point.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018 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>
  */
@@ -21,7 +21,7 @@ export const PointParams = {
 };
 export type PointParams = typeof PointParams
 export function getPointParams(ctx: ThemeRegistryContext, structure: Structure) {
-    return PD.clone(PointParams);
+    return PointParams;
 }
 
 export type PointRepresentation = StructureRepresentation<PointParams>

+ 9 - 4
src/mol-repr/structure/representation/spacefill.ts

@@ -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,12 +22,17 @@ export const SpacefillParams = {
     bumpFrequency: PD.Numeric(1, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
 };
 export type SpacefillParams = typeof SpacefillParams
+
+let CoarseGrainedSpacefillParams: SpacefillParams;
 export function getSpacefillParams(ctx: ThemeRegistryContext, structure: Structure) {
-    const params = PD.clone(SpacefillParams);
     if (structure.isCoarseGrained) {
-        params.sizeFactor.defaultValue = 2;
+        if (!CoarseGrainedSpacefillParams) {
+            CoarseGrainedSpacefillParams = PD.clone(SpacefillParams);
+            CoarseGrainedSpacefillParams.sizeFactor.defaultValue = 2;
+        }
+        return CoarseGrainedSpacefillParams;
     }
-    return params;
+    return SpacefillParams;
 }
 
 export type SpacefillRepresentation = StructureRepresentation<SpacefillParams>

+ 12 - 0
src/mol-util/color/color.ts

@@ -19,6 +19,10 @@ export namespace Color {
         return `rgb(${hexColor >> 16 & 255}, ${hexColor >> 8 & 255}, ${hexColor & 255})`;
     }
 
+    export function toHexStyle(hexColor: Color) {
+        return '#' + ('000000' + hexColor.toString(16)).slice(-6);
+    }
+
     export function toHexString(hexColor: Color) {
         return '0x' + ('000000' + hexColor.toString(16)).slice(-6);
     }
@@ -35,6 +39,14 @@ export namespace Color {
         return [(hexColor >> 16 & 255) / 255, (hexColor >> 8 & 255) / 255, (hexColor & 255) / 255];
     }
 
+    export function fromHexStyle(s: string): Color {
+        return parseInt(s.replace('#', '0x')) as Color;
+    }
+
+    export function fromHexString(s: string): Color {
+        return parseInt(s) as Color;
+    }
+
     export function fromRgb(r: number, g: number, b: number): Color {
         return ((r << 16) | (g << 8) | b) as Color;
     }