diff --git a/src/mol-model/location.ts b/src/mol-model/location.ts index 39546ddac69d0642e20e7f5d232b824d798e2c90..d5006c61710d8684b26c982e1529703a3cfcceda 100644 --- a/src/mol-model/location.ts +++ b/src/mol-model/location.ts @@ -1,12 +1,12 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { StructureElement } from './structure' import { Link } from './structure/structure/unit/links' -import { Shape } from './shape/shape'; +import { ShapeGroup } from './shape/shape'; /** A null value Location */ export const NullLocation = { kind: 'null-location' as 'null-location' } @@ -15,4 +15,4 @@ export function isNullLocation(x: any): x is NullLocation { return !!x && x.kind === 'null-location'; } -export type Location = StructureElement | Link.Location | Shape.Location | NullLocation \ No newline at end of file +export type Location = StructureElement | Link.Location | ShapeGroup.Location | NullLocation \ No newline at end of file diff --git a/src/mol-model/loci.ts b/src/mol-model/loci.ts index 35cad50ed5ecb596bf791d532455964f921db7af..517b0631ac0456006bc7fe62ec7a54690587980b 100644 --- a/src/mol-model/loci.ts +++ b/src/mol-model/loci.ts @@ -1,12 +1,12 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { StructureElement } from './structure' import { Link } from './structure/structure/unit/links' -import { Shape } from './shape'; +import { Shape, ShapeGroup } from './shape'; import { Sphere3D } from 'mol-math/geometry'; import { CentroidHelper } from 'mol-math/geometry/centroid-helper'; import { Vec3 } from 'mol-math/linear-algebra'; @@ -46,7 +46,7 @@ export function createDataLoci(data: any, tag: string, indices: OrderedSet<numbe export { Loci } -type Loci = StructureElement.Loci | Structure.Loci | Link.Loci | EveryLoci | EmptyLoci | DataLoci | Shape.Loci +type Loci = StructureElement.Loci | Structure.Loci | Link.Loci | EveryLoci | EmptyLoci | DataLoci | Shape.Loci | ShapeGroup.Loci namespace Loci { export function areEqual(lociA: Loci, lociB: Loci) { @@ -67,6 +67,9 @@ namespace Loci { if (Shape.isLoci(lociA) && Shape.isLoci(lociB)) { return Shape.areLociEqual(lociA, lociB) } + if (ShapeGroup.isLoci(lociA) && ShapeGroup.isLoci(lociB)) { + return ShapeGroup.areLociEqual(lociA, lociB) + } return false } @@ -96,6 +99,9 @@ namespace Loci { e.aUnit.conformation.position(e.bUnit.elements[e.bIndex], tempPos); sphereHelper.radiusStep(tempPos); } + } else if (loci.kind === 'shape-loci') { + // TODO + return void 0; } else if (loci.kind === 'group-loci') { // TODO return void 0; diff --git a/src/mol-model/shape/shape.ts b/src/mol-model/shape/shape.ts index 314af70fbfec3c4df1a7379c9359ead45f4fcc05..98188c58e360606021be9fa5ae25eb9e8421eeef 100644 --- a/src/mol-model/shape/shape.ts +++ b/src/mol-model/shape/shape.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ @@ -43,6 +43,13 @@ export namespace Shape { } } + export interface Loci { readonly kind: 'shape-loci', readonly shape: Shape } + export function Loci(shape: Shape): Loci { return { kind: 'shape-loci', shape } } + export function isLoci(x: any): x is Loci { return !!x && x.kind === 'shape-loci' } + export function areLociEqual(a: Loci, b: Loci) { return a.shape === b.shape } +} + +export namespace ShapeGroup { export interface Location { readonly kind: 'group-location' shape: Shape diff --git a/src/mol-repr/shape/representation.ts b/src/mol-repr/shape/representation.ts index 83f1edb96e25a5ed817d4cba918fb1d2a9ec803b..ebd0f7afcd791e1cb62c1a482beac1c677212c31 100644 --- a/src/mol-repr/shape/representation.ts +++ b/src/mol-repr/shape/representation.ts @@ -9,7 +9,7 @@ import { createRenderObject, GraphicsRenderObject } from 'mol-gl/render-object'; import { Representation } from '../representation'; import { Loci, EmptyLoci, isEveryLoci } from 'mol-model/loci'; import { ValueCell } from 'mol-util'; -import { Shape } from 'mol-model/shape'; +import { Shape, ShapeGroup } from 'mol-model/shape'; import { OrderedSet, Interval } from 'mol-data/int'; import { ParamDefinition as PD } from 'mol-util/param-definition'; import { createTransform, TransformData } from 'mol-geo/geometry/transform-data'; @@ -170,7 +170,7 @@ export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Pa getLoci(pickingId: PickingId) { const { objectId, groupId, instanceId } = pickingId if (_renderObject && _renderObject.id === objectId) { - return Shape.Loci(_shape, [{ ids: OrderedSet.ofSingleton(groupId) }], instanceId) + return ShapeGroup.Loci(_shape, [{ ids: OrderedSet.ofSingleton(groupId) }], instanceId) } return EmptyLoci }, @@ -210,7 +210,7 @@ function createShapeTransform(transforms: Mat4[], transformData?: TransformData) } function eachShapeGroup(loci: Loci, shape: Shape, apply: (interval: Interval) => boolean) { - if (!Shape.isLoci(loci)) return false + if (!ShapeGroup.isLoci(loci)) return false if (loci.shape !== shape) return false let changed = false const { groupCount } = shape @@ -233,7 +233,7 @@ function eachShapeGroup(loci: Loci, shape: Shape, apply: (interval: Interval) => export namespace ShapeGroupIterator { export function fromShape(shape: Shape): LocationIterator { const instanceCount = shape.transforms.length - const location = Shape.Location(shape) + const location = ShapeGroup.Location(shape) const getLocation = (groupIndex: number, instanceIndex: number) => { location.group = groupIndex location.instance = instanceIndex diff --git a/src/mol-theme/color/shape-group.ts b/src/mol-theme/color/shape-group.ts index b352ecd50e0581296b9cd59a3ac9669214a670ac..905cce02c84062540b7465a00d98868e5ffb946a 100644 --- a/src/mol-theme/color/shape-group.ts +++ b/src/mol-theme/color/shape-group.ts @@ -7,7 +7,7 @@ import { ColorTheme } from '../color'; import { Color } from 'mol-util/color'; import { Location } from 'mol-model/location'; -import { Shape } from 'mol-model/shape'; +import { ShapeGroup } from 'mol-model/shape'; import { ParamDefinition as PD } from 'mol-util/param-definition' import { ThemeDataContext } from 'mol-theme/theme'; @@ -25,7 +25,7 @@ export function ShapeGroupColorTheme(ctx: ThemeDataContext, props: PD.Values<Sha factory: ShapeGroupColorTheme, granularity: 'groupInstance', color: (location: Location): Color => { - if (Shape.isLocation(location)) { + if (ShapeGroup.isLocation(location)) { return location.shape.getColor(location.group, location.instance) } return DefaultColor diff --git a/src/mol-theme/label.ts b/src/mol-theme/label.ts index 8aac229a59d8db1ca68eeab84eb03b921ec55f0c..69b67a6b9b4559b4e12c9e1bc5bd8c52313d6bb8 100644 --- a/src/mol-theme/label.ts +++ b/src/mol-theme/label.ts @@ -33,6 +33,8 @@ export function labelFirst(loci: Loci): string { case 'link-loci': const link = loci.links[0] return link ? linkLabel(link) : 'Unknown' + case 'shape-loci': + return loci.shape.name case 'group-loci': const g = loci.groups[0] if (g) { diff --git a/src/mol-theme/size/shape-group.ts b/src/mol-theme/size/shape-group.ts index 60fa329f3aacd2ee175aedbc8122e9d6398dc505..8bfcdf4f715519e1e91b88c2914795671857c955 100644 --- a/src/mol-theme/size/shape-group.ts +++ b/src/mol-theme/size/shape-group.ts @@ -5,7 +5,7 @@ */ import { Location } from 'mol-model/location'; -import { Shape } from 'mol-model/shape'; +import { ShapeGroup } from 'mol-model/shape'; import { ParamDefinition as PD } from 'mol-util/param-definition' import { ThemeDataContext } from 'mol-theme/theme'; import { SizeTheme } from 'mol-theme/size'; @@ -24,7 +24,7 @@ export function ShapeGroupSizeTheme(ctx: ThemeDataContext, props: PD.Values<Shap factory: ShapeGroupSizeTheme, granularity: 'groupInstance', size: (location: Location): number => { - if (Shape.isLocation(location)) { + if (ShapeGroup.isLocation(location)) { return location.shape.getSize(location.group, location.instance) } return DefaultSize diff --git a/src/tests/browser/render-shape.ts b/src/tests/browser/render-shape.ts index 943a50476785bf19aedb3bd7b959cc210ce54c75..ce513f8132403be892bd02ffa87fe06d5a6f936a 100644 --- a/src/tests/browser/render-shape.ts +++ b/src/tests/browser/render-shape.ts @@ -15,6 +15,9 @@ import { ColorNames } from 'mol-util/color/tables'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { labelFirst } from 'mol-theme/label'; import { RuntimeContext, Progress } from 'mol-task'; +import { Representation } from 'mol-repr/representation'; +import { MarkerAction } from 'mol-geo/geometry/marker-data'; +import { EveryLoci } from 'mol-model/loci'; const parent = document.getElementById('app')! parent.style.width = '100%' @@ -34,14 +37,23 @@ info.style.right = '20px' info.style.color = 'white' parent.appendChild(info) +let prevReprLoci = Representation.Loci.Empty const canvas3d = Canvas3D.create(canvas, parent) canvas3d.animate() canvas3d.input.move.subscribe(async ({x, y}) => { const pickingId = await canvas3d.identify(x, y) let label = '' if (pickingId) { - const { loci } = canvas3d.getLoci(pickingId) - label = labelFirst(loci) + const reprLoci = canvas3d.getLoci(pickingId) + label = labelFirst(reprLoci.loci) + if (!Representation.Loci.areEqual(prevReprLoci, reprLoci)) { + canvas3d.mark(prevReprLoci, MarkerAction.RemoveHighlight) + canvas3d.mark(reprLoci, MarkerAction.Highlight) + prevReprLoci = reprLoci + } + } else { + canvas3d.mark({ loci: EveryLoci }, MarkerAction.RemoveHighlight) + prevReprLoci = Representation.Loci.Empty } info.innerText = label })