diff --git a/CHANGELOG.md b/CHANGELOG.md index e1909a6d71e27b8e8a97314b0de429054408260d..c434e06edc31c49e1a16d009a552be7287ed378c 100644 --- a/CHANGELOG.md +++ b/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 diff --git a/src/mol-geo/geometry/base.ts b/src/mol-geo/geometry/base.ts index d17a47077333819561ef57ceb5234b08b8bee45e..bbafbb8ac52b05e03fdb1222138eddc3c2fdc0c5 100644 --- a/src/mol-geo/geometry/base.ts +++ b/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); diff --git a/src/mol-model/structure/structure/structure.ts b/src/mol-model/structure/structure/structure.ts index 46abc6d3b7d90e4b719779330c187089e02890ed..e42d697cc127f7832100787a02b96c101453fd28 100644 --- a/src/mol-model/structure/structure/structure.ts +++ b/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++) { diff --git a/src/mol-model/structure/structure/unit.ts b/src/mol-model/structure/structure/unit.ts index fe2c5b7b8c9bdde0f498fcfb4e9a6f785eb72a5f..8d64234ad3e1d4a888e337233630a5562bfa00c9 100644 --- a/src/mol-model/structure/structure/unit.ts +++ b/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); } diff --git a/src/mol-plugin-ui/controls/color.tsx b/src/mol-plugin-ui/controls/color.tsx index d537c631be74c701a97bb79aeb11e8f34315141a..5b4d03ee19daa8238d215326a662006d8fe6194a 100644 --- a/src/mol-plugin-ui/controls/color.tsx +++ b/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> diff --git a/src/mol-plugin-ui/controls/parameters.tsx b/src/mol-plugin-ui/controls/parameters.tsx index 3030981e2931859192f2166570d0b8f0abc347b0..2dbf012ff6dce30515ff58a0997dc5e088da7a58 100644 --- a/src/mol-plugin-ui/controls/parameters.tsx +++ b/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} />; } } diff --git a/src/mol-repr/structure/representation/ball-and-stick.ts b/src/mol-repr/structure/representation/ball-and-stick.ts index 4de9b64180f5155bfacf83eeabec11c64096539d..ce9df14b625b5876cd8b88308cd92a20c06b1f8a 100644 --- a/src/mol-repr/structure/representation/ball-and-stick.ts +++ b/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> diff --git a/src/mol-repr/structure/representation/carbohydrate.ts b/src/mol-repr/structure/representation/carbohydrate.ts index 2ea4f8e63e371160154f8d13f47744e9aaf1fdf9..9d4d49e8552ef14bc2c5bb49738c538387bbef5d 100644 --- a/src/mol-repr/structure/representation/carbohydrate.ts +++ b/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> diff --git a/src/mol-repr/structure/representation/ellipsoid.ts b/src/mol-repr/structure/representation/ellipsoid.ts index 165b834f33559dea5188117cb113e9f4aa7aba09..fb35f59df80dcf621b652c007aca184898d89bb2 100644 --- a/src/mol-repr/structure/representation/ellipsoid.ts +++ b/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> diff --git a/src/mol-repr/structure/representation/gaussian-surface.ts b/src/mol-repr/structure/representation/gaussian-surface.ts index 4fa334354933db671fa7f81e9275801b077b9316..b7cf518d3e958327564785534227269a9116b2ab 100644 --- a/src/mol-repr/structure/representation/gaussian-surface.ts +++ b/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> diff --git a/src/mol-repr/structure/representation/gaussian-volume.ts b/src/mol-repr/structure/representation/gaussian-volume.ts index 17e70940e456d3ae5032f6cc28793894606b4ca4..152caf340d7b29e40028111a1501f947c3edf0e3 100644 --- a/src/mol-repr/structure/representation/gaussian-volume.ts +++ b/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> diff --git a/src/mol-repr/structure/representation/label.ts b/src/mol-repr/structure/representation/label.ts index 1d45b7210269698d971d4933e75e61062a3fd7b0..c8f54dc2ea128c07ad7086c7bdf3789715eed237 100644 --- a/src/mol-repr/structure/representation/label.ts +++ b/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> diff --git a/src/mol-repr/structure/representation/line.ts b/src/mol-repr/structure/representation/line.ts index 65bed46df5ad924cac3592670349ded599e93492..f34eba0e63c24f81ccc08f25aa2cf013744d8160 100644 --- a/src/mol-repr/structure/representation/line.ts +++ b/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> diff --git a/src/mol-repr/structure/representation/molecular-surface.ts b/src/mol-repr/structure/representation/molecular-surface.ts index e5d51cdb91d248931182ef3d0e3303aa5dcf685b..93786a7bd02788030e6b7c33ca1a7dd929ef21d3 100644 --- a/src/mol-repr/structure/representation/molecular-surface.ts +++ b/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> diff --git a/src/mol-repr/structure/representation/orientation.ts b/src/mol-repr/structure/representation/orientation.ts index 80b1a3aa0f55a16f491aa58f08c1b4c560226d9b..8b09d6c88a68001a191c95b76679a3a573ce0bdc 100644 --- a/src/mol-repr/structure/representation/orientation.ts +++ b/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> diff --git a/src/mol-repr/structure/representation/point.ts b/src/mol-repr/structure/representation/point.ts index 0bcddfe18913d220af265f931f988ca057117d70..504cbbd024271759ee053f4865a04438164bbf30 100644 --- a/src/mol-repr/structure/representation/point.ts +++ b/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> diff --git a/src/mol-repr/structure/representation/spacefill.ts b/src/mol-repr/structure/representation/spacefill.ts index f03d0cf2de05988582caf3ab867589142bc62bc6..7a7da4953307fb52c26b6e1c863c4380c32a6a99 100644 --- a/src/mol-repr/structure/representation/spacefill.ts +++ b/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> diff --git a/src/mol-util/color/color.ts b/src/mol-util/color/color.ts index a8c855d14d646a6345b052e211de82cccdb3df00..9bc745987476d8e70ee108524d3023295d56000a 100644 --- a/src/mol-util/color/color.ts +++ b/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; }