From d75abea83d572d21872a726ddda191ff1789bef2 Mon Sep 17 00:00:00 2001
From: Alexander Rose <alex.rose@rcsb.org>
Date: Tue, 4 Sep 2018 17:30:25 -0700
Subject: [PATCH] wip, representations

---
 src/mol-geo/representation/shape/index.ts     |  1 +
 .../structure/representation/point.ts         | 29 ++++++++++++++++++-
 .../structure/representation/spacefill.ts     | 29 ++++++++++++++++++-
 .../structure/units-representation.ts         | 16 +++++-----
 .../representation/structure/units-visual.ts  | 12 ++++++--
 .../structure/visual/element-point.ts         | 12 ++++++--
 .../structure/visual/util/common.ts           |  3 +-
 7 files changed, 87 insertions(+), 15 deletions(-)

diff --git a/src/mol-geo/representation/shape/index.ts b/src/mol-geo/representation/shape/index.ts
index 52ee7ebc4..2aec89462 100644
--- a/src/mol-geo/representation/shape/index.ts
+++ b/src/mol-geo/representation/shape/index.ts
@@ -25,6 +25,7 @@ export interface ShapeRepresentation<P extends RepresentationProps = {}> extends
 
 export const DefaultShapeProps = {
     ...DefaultMeshProps,
+
     colorTheme: { name: 'shape-group' } as ColorThemeProps
 }
 export type ShapeProps = typeof DefaultShapeProps
diff --git a/src/mol-geo/representation/structure/representation/point.ts b/src/mol-geo/representation/structure/representation/point.ts
index 5a3e60475..d9a2de382 100644
--- a/src/mol-geo/representation/structure/representation/point.ts
+++ b/src/mol-geo/representation/structure/representation/point.ts
@@ -7,6 +7,10 @@
 import { UnitsRepresentation } from '..';
 import { ElementPointVisual, DefaultElementPointProps } from '../visual/element-point';
 import { StructureRepresentation } from '../units-representation';
+import { Structure } from 'mol-model/structure';
+import { MarkerAction } from '../../../util/marker-data';
+import { Loci } from 'mol-model/loci';
+import { PickingId } from '../../../util/picking';
 
 export const DefaultPointProps = {
     ...DefaultElementPointProps,
@@ -16,5 +20,28 @@ export type PointProps = typeof DefaultPointProps
 export type PointRepresentation = StructureRepresentation<PointProps>
 
 export function PointRepresentation(): PointRepresentation {
-    return UnitsRepresentation('Point', ElementPointVisual)
+    let currentProps: PointProps
+    const pointRepr = UnitsRepresentation('Point', ElementPointVisual)
+    return {
+        label: 'Point',
+        get renderObjects() {
+            return [ ...pointRepr.renderObjects ]
+        },
+        get props() {
+            return { ...pointRepr.props }
+        },
+        createOrUpdate: (props: Partial<PointProps> = {}, structure?: Structure) => {
+            currentProps = Object.assign({}, DefaultPointProps, props)
+            return pointRepr.createOrUpdate(currentProps, structure)
+        },
+        getLoci: (pickingId: PickingId) => {
+            return pointRepr.getLoci(pickingId)
+        },
+        mark: (loci: Loci, action: MarkerAction) => {
+            pointRepr.mark(loci, action)
+        },
+        destroy() {
+            pointRepr.destroy()
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/representation/spacefill.ts b/src/mol-geo/representation/structure/representation/spacefill.ts
index ede5bb1b7..355334932 100644
--- a/src/mol-geo/representation/structure/representation/spacefill.ts
+++ b/src/mol-geo/representation/structure/representation/spacefill.ts
@@ -7,6 +7,10 @@
 import { UnitsRepresentation } from '..';
 import { ElementSphereVisual, DefaultElementSphereProps } from '../visual/element-sphere';
 import { StructureRepresentation } from '../units-representation';
+import { Structure } from 'mol-model/structure';
+import { PickingId } from '../../../util/picking';
+import { MarkerAction } from '../../../util/marker-data';
+import { Loci } from 'mol-model/loci';
 
 export const DefaultSpacefillProps = {
     ...DefaultElementSphereProps
@@ -16,5 +20,28 @@ export type SpacefillProps = typeof DefaultSpacefillProps
 export type SpacefillRepresentation = StructureRepresentation<SpacefillProps>
 
 export function SpacefillRepresentation(): SpacefillRepresentation {
-    return UnitsRepresentation('Spacefill', ElementSphereVisual)
+    let currentProps: SpacefillProps
+    const sphereRepr = UnitsRepresentation('Sphere mesh', ElementSphereVisual)
+    return {
+        label: 'Spacefill',
+        get renderObjects() {
+            return [ ...sphereRepr.renderObjects ]
+        },
+        get props() {
+            return { ...sphereRepr.props }
+        },
+        createOrUpdate: (props: Partial<SpacefillProps> = {}, structure?: Structure) => {
+            currentProps = Object.assign({}, DefaultSpacefillProps, props)
+            return sphereRepr.createOrUpdate(currentProps, structure)
+        },
+        getLoci: (pickingId: PickingId) => {
+            return sphereRepr.getLoci(pickingId)
+        },
+        mark: (loci: Loci, action: MarkerAction) => {
+            sphereRepr.mark(loci, action)
+        },
+        destroy() {
+            sphereRepr.destroy()
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/units-representation.ts b/src/mol-geo/representation/structure/units-representation.ts
index 17f85e2f6..d88f68cb0 100644
--- a/src/mol-geo/representation/structure/units-representation.ts
+++ b/src/mol-geo/representation/structure/units-representation.ts
@@ -14,8 +14,9 @@ import { Loci, EmptyLoci, isEmptyLoci } from 'mol-model/loci';
 import { MarkerAction } from '../../util/marker-data';
 import { getQualityProps } from '../util';
 import { StructureProps } from '.';
+import { StructureGroup } from './units-visual';
 
-export interface UnitsVisual<P extends RepresentationProps = {}> extends Visual<Unit.SymmetryGroup, P> { }
+export interface UnitsVisual<P extends RepresentationProps = {}> extends Visual<StructureGroup, P> { }
 export interface  StructureVisual<P extends RepresentationProps = {}> extends Visual<Structure, P> { }
 
 export interface StructureRepresentation<P extends RepresentationProps = {}> extends Representation<Structure, P> { }
@@ -28,8 +29,8 @@ export function UnitsRepresentation<P extends StructureProps>(label: string, vis
     let _groups: ReadonlyArray<Unit.SymmetryGroup>
 
     function createOrUpdate(props: Partial<P> = {}, structure?: Structure) {
+        console.log(props)
         _props = Object.assign({}, _props, props, getQualityProps(props, structure))
-        _props.colorTheme.structure = structure
 
         return Task.create('Creating or updating StructureRepresentation', async ctx => {
             if (!_structure && !structure) {
@@ -40,7 +41,7 @@ export function UnitsRepresentation<P extends StructureProps>(label: string, vis
                 for (let i = 0; i < _groups.length; i++) {
                     const group = _groups[i];
                     const visual = visualCtor()
-                    await visual.createOrUpdate(ctx, _props, group)
+                    await visual.createOrUpdate(ctx, _props, { group, structure })
                     visuals.set(group.hashCode, { visual, group })
                 }
             } else if (structure && _structure.hashCode !== structure.hashCode) {
@@ -55,18 +56,19 @@ export function UnitsRepresentation<P extends StructureProps>(label: string, vis
                     const visualGroup = oldVisuals.get(group.hashCode)
                     if (visualGroup) {
                         const { visual } = visualGroup
-                        await visual.createOrUpdate(ctx, _props, group)
+                        await visual.createOrUpdate(ctx, _props, { group, structure })
                         visuals.set(group.hashCode, { visual, group })
                         oldVisuals.delete(group.hashCode)
                     } else {
                         // newGroups.push(group)
                         const visual = visualCtor()
-                        await visual.createOrUpdate(ctx, _props, group)
+                        await visual.createOrUpdate(ctx, _props, { group, structure })
                         visuals.set(group.hashCode, { visual, group })
                     }
                 }
                 oldVisuals.forEach(({ visual }) => visual.destroy())
 
+                // TODO review logic
                 // For new groups, re-use left-over visuals
                 // const unusedVisuals: UnitsVisual<P>[] = []
                 // oldVisuals.forEach(({ visual }) => unusedVisuals.push(visual))
@@ -85,7 +87,7 @@ export function UnitsRepresentation<P extends StructureProps>(label: string, vis
                     const group = _groups[i];
                     const visualGroup = visuals.get(group.hashCode)
                     if (visualGroup) {
-                        await visualGroup.visual.createOrUpdate(ctx, _props, group)
+                        await visualGroup.visual.createOrUpdate(ctx, _props, { group, structure })
                         visualGroup.group = group
                     } else {
                         throw new Error(`expected to find visual for hashCode ${group.hashCode}`)
@@ -94,7 +96,7 @@ export function UnitsRepresentation<P extends StructureProps>(label: string, vis
             } else {
                 // No new structure given, just update all visuals with new props.
                 visuals.forEach(async ({ visual, group }) => {
-                    await visual.createOrUpdate(ctx, _props, group)
+                    await visual.createOrUpdate(ctx, _props, { group, structure: _structure })
                 })
             }
             if (structure) _structure = structure
diff --git a/src/mol-geo/representation/structure/units-visual.ts b/src/mol-geo/representation/structure/units-visual.ts
index 40914b11b..fa7467ba0 100644
--- a/src/mol-geo/representation/structure/units-visual.ts
+++ b/src/mol-geo/representation/structure/units-visual.ts
@@ -4,7 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Unit } from 'mol-model/structure';
+import { Unit, Structure } from 'mol-model/structure';
 import { RepresentationProps, Visual } from '..';
 import { DefaultStructureMeshProps, MeshUpdateState } from '.';
 import { RuntimeContext } from 'mol-task';
@@ -20,7 +20,9 @@ import { updateMeshValues, updateRenderableState } from '../util';
 import { Interval } from 'mol-data/int';
 import { createTransforms } from '../../util/transform-data';
 
-export interface UnitsVisual<P extends RepresentationProps = {}> extends Visual<Unit.SymmetryGroup, P> { }
+export type StructureGroup = { structure: Structure, group: Unit.SymmetryGroup }
+
+export interface UnitsVisual<P extends RepresentationProps = {}> extends Visual<StructureGroup, P> { }
 
 export const DefaultUnitsMeshProps = {
     ...DefaultStructureMeshProps,
@@ -45,11 +47,13 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu
     let currentProps: P
     let mesh: Mesh
     let currentGroup: Unit.SymmetryGroup
+    let currentStructure: Structure
     let locationIt: LocationIterator
     let currentConformationId: UUID
 
     async function create(ctx: RuntimeContext, group: Unit.SymmetryGroup, props: Partial<P> = {}) {
         currentProps = Object.assign({}, defaultProps, props)
+        currentProps.colorTheme.structure = currentStructure
         currentGroup = group
 
         const unit = group.units[0]
@@ -115,7 +119,9 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu
 
     return {
         get renderObject () { return renderObject },
-        async createOrUpdate(ctx: RuntimeContext, props: Partial<P> = {}, group?: Unit.SymmetryGroup) {
+        async createOrUpdate(ctx: RuntimeContext, props: Partial<P> = {}, structureGroup?: StructureGroup) {
+            if (structureGroup) currentStructure = structureGroup.structure
+            const group = structureGroup ? structureGroup.group : undefined
             if (!group && !currentGroup) {
                 throw new Error('missing group')
             } else if (group && (!currentGroup || !renderObject)) {
diff --git a/src/mol-geo/representation/structure/visual/element-point.ts b/src/mol-geo/representation/structure/visual/element-point.ts
index 924db42c3..9c9dec03f 100644
--- a/src/mol-geo/representation/structure/visual/element-point.ts
+++ b/src/mol-geo/representation/structure/visual/element-point.ts
@@ -7,7 +7,7 @@
 
 import { ValueCell } from 'mol-util/value-cell'
 import { PointRenderObject } from 'mol-gl/render-object'
-import { Unit } from 'mol-model/structure';
+import { Unit, Structure } from 'mol-model/structure';
 import { RuntimeContext } from 'mol-task'
 import { UnitsVisual, DefaultStructureProps } from '..';
 import { getElementLoci, StructureElementIterator, markElement } from './util/element';
@@ -22,6 +22,8 @@ import { fillSerial } from 'mol-util/array';
 import { SizeThemeProps } from 'mol-view/theme/size';
 import { LocationIterator } from '../../../util/location-iterator';
 import { createTransforms } from '../../../util/transform-data';
+import { StructureGroup } from '../units-visual';
+import { updateRenderableState } from '../../util';
 
 export const DefaultElementPointProps = {
     ...DefaultStructureProps,
@@ -57,17 +59,21 @@ export function ElementPointVisual(): UnitsVisual<ElementPointProps> {
     let renderObject: PointRenderObject | undefined
     let currentProps = DefaultElementPointProps
     let currentGroup: Unit.SymmetryGroup
+    let currentStructure: Structure
     let locationIt: LocationIterator
     let vertices: ValueCell<Float32Array>
     let currentConformationId: UUID
 
     return {
         get renderObject () { return renderObject },
-        async createOrUpdate(ctx: RuntimeContext, props: ElementPointProps = {}, group?: Unit.SymmetryGroup) {
+        async createOrUpdate(ctx: RuntimeContext, props: ElementPointProps = {}, structureGroup?: StructureGroup) {
+            if (structureGroup) currentStructure = structureGroup.structure
+            const group = structureGroup ? structureGroup.group : undefined
             if (!group && !currentGroup) {
                 throw new Error('missing group')
             } else if (group && !currentGroup) {
                 currentProps = Object.assign({}, DefaultElementPointProps, props)
+                currentProps.colorTheme.structure = currentStructure
                 currentGroup = group
                 locationIt = StructureElementIterator.fromGroup(group)
 
@@ -124,6 +130,8 @@ export function ElementPointVisual(): UnitsVisual<ElementPointProps> {
                     await createSizes(ctx, locationIt, newProps.sizeTheme, renderObject.values)
                 }
 
+                updateRenderableState(renderObject.state, newProps)
+
                 currentProps = newProps
             }
         },
diff --git a/src/mol-geo/representation/structure/visual/util/common.ts b/src/mol-geo/representation/structure/visual/util/common.ts
index b5bc76743..0dfb1317b 100644
--- a/src/mol-geo/representation/structure/visual/util/common.ts
+++ b/src/mol-geo/representation/structure/visual/util/common.ts
@@ -25,7 +25,8 @@ import { fillSerial } from 'mol-util/array';
 import { TransformData, createIdentityTransform, createTransforms } from '../../../../util/transform-data';
 
 function getGranularity(locationIt: LocationIterator, granularity: ColorType | SizeType) {
-    // Always use 'group' kind for 'complex' location iterators, i.e. an instance may include multiple units
+    // Always use 'group' granularity for 'complex' location iterators,
+    // i.e. for which an instance may include multiple units
     return granularity === 'instance' && locationIt.isComplex ? 'group' : granularity
 }
 
-- 
GitLab