From baafa384741e3b11d9dac9f43cda627bda110cd9 Mon Sep 17 00:00:00 2001
From: Alexander Rose <alex.rose@rcsb.org>
Date: Tue, 4 Sep 2018 10:47:39 -0700
Subject: [PATCH] add isComplex flag to location-iterator to handle multiple
 units per instance

---
 src/apps/canvas/structure-view.ts              | 18 +++++++++---------
 .../representation/structure/complex-visual.ts | 11 ++++++-----
 .../representation/structure/units-visual.ts   |  1 -
 .../visual/carbohydrate-link-cylinder.ts       |  2 +-
 .../visual/carbohydrate-symbol-mesh.ts         |  2 +-
 .../visual/cross-link-restraint-cylinder.ts    |  2 +-
 .../structure/visual/util/common.ts            |  4 +++-
 .../structure/visual/util/link.ts              |  2 +-
 src/mol-geo/util/location-iterator.ts          |  5 ++++-
 9 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/src/apps/canvas/structure-view.ts b/src/apps/canvas/structure-view.ts
index 36865663a..4490697d5 100644
--- a/src/apps/canvas/structure-view.ts
+++ b/src/apps/canvas/structure-view.ts
@@ -156,24 +156,24 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
     async function createStructureRepr() {
         if (structure) {
             console.log('createStructureRepr')
-            // await cartoon.createOrUpdate({
-            //     colorTheme: { name: 'unit-index' },
-            //     sizeTheme: { name: 'uniform', value: 0.2 },
-            //     useFog: false // TODO fog not working properly
-            // }, structure).run()
-
-            await point.createOrUpdate({
+            await cartoon.createOrUpdate({
                 colorTheme: { name: 'unit-index' },
                 sizeTheme: { name: 'uniform', value: 0.2 },
                 useFog: false // TODO fog not working properly
             }, structure).run()
 
-            // await ballAndStick.createOrUpdate({
+            // await point.createOrUpdate({
             //     colorTheme: { name: 'unit-index' },
-            //     sizeTheme: { name: 'uniform', value: 0.1 },
+            //     sizeTheme: { name: 'uniform', value: 0.2 },
             //     useFog: false // TODO fog not working properly
             // }, structure).run()
 
+            await ballAndStick.createOrUpdate({
+                colorTheme: { name: 'unit-index' },
+                sizeTheme: { name: 'uniform', value: 0.1 },
+                useFog: false // TODO fog not working properly
+            }, structure).run()
+
             // await carbohydrate.createOrUpdate({
             //     colorTheme: { name: 'carbohydrate-symbol' },
             //     sizeTheme: { name: 'uniform', value: 1, factor: 1 },
diff --git a/src/mol-geo/representation/structure/complex-visual.ts b/src/mol-geo/representation/structure/complex-visual.ts
index 542d169e7..343a6082d 100644
--- a/src/mol-geo/representation/structure/complex-visual.ts
+++ b/src/mol-geo/representation/structure/complex-visual.ts
@@ -44,17 +44,18 @@ export function ComplexMeshVisual<P extends ComplexMeshProps>(builder: ComplexMe
     let mesh: Mesh
     let currentStructure: Structure
     let locationIt: LocationIterator
-    let conformationHashCode: number
+    let conformationHash: number
 
     async function create(ctx: RuntimeContext, structure: Structure, props: Partial<P> = {}) {
         currentProps = Object.assign({}, defaultProps, props)
         currentStructure = structure
 
-        conformationHashCode = Structure.conformationHash(currentStructure)
+        conformationHash = Structure.conformationHash(currentStructure)
         mesh = await createMesh(ctx, currentStructure, currentProps, mesh)
 
         locationIt = createLocationIterator(structure)
         renderObject = await createComplexMeshRenderObject(ctx, structure, mesh, locationIt, currentProps)
+        console.log(renderObject.values)
     }
 
     async function update(ctx: RuntimeContext, props: Partial<P>) {
@@ -66,9 +67,9 @@ export function ComplexMeshVisual<P extends ComplexMeshProps>(builder: ComplexMe
         MeshUpdateState.reset(updateState)
         setUpdateState(updateState, newProps, currentProps)
 
-        const newConformationHashCode = Structure.conformationHash(currentStructure)
-        if (newConformationHashCode !== conformationHashCode) {
-            conformationHashCode = newConformationHashCode
+        const newConformationHash = Structure.conformationHash(currentStructure)
+        if (newConformationHash !== conformationHash) {
+            conformationHash = newConformationHash
             updateState.createMesh = true
         }
 
diff --git a/src/mol-geo/representation/structure/units-visual.ts b/src/mol-geo/representation/structure/units-visual.ts
index 86ec2ac9d..40914b11b 100644
--- a/src/mol-geo/representation/structure/units-visual.ts
+++ b/src/mol-geo/representation/structure/units-visual.ts
@@ -61,7 +61,6 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu
         // TODO create empty location iterator when not in unitKinds
         locationIt = createLocationIterator(group)
         renderObject = await createUnitsMeshRenderObject(ctx, group, mesh, locationIt, currentProps)
-        console.log(renderObject.values.uInstanceCount.ref.value, renderObject.values.uGroupCount.ref.value)
     }
 
     async function update(ctx: RuntimeContext, props: Partial<P> = {}) {
diff --git a/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts b/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts
index 6526391f0..dca53ec6f 100644
--- a/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts
+++ b/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts
@@ -100,7 +100,7 @@ function CarbohydrateLinkIterator(structure: Structure): LocationIterator {
         location.bIndex = indexB as StructureElement.UnitIndex
         return location
     }
-    return LocationIterator(groupCount, instanceCount, getLocation)
+    return LocationIterator(groupCount, instanceCount, getLocation, true)
 }
 
 function getLinkLoci(pickingId: PickingId, structure: Structure, id: number) {
diff --git a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts b/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts
index 6546a2b2a..50b85fb4d 100644
--- a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts
+++ b/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts
@@ -172,7 +172,7 @@ function CarbohydrateElementIterator(structure: Structure): LocationIterator {
     function isSecondary (elementIndex: number, instanceIndex: number) {
         return (elementIndex % 2) === 1
     }
-    return LocationIterator(groupCount, instanceCount, getLocation, isSecondary)
+    return LocationIterator(groupCount, instanceCount, getLocation, true, isSecondary)
 }
 
 function getCarbohydrateLoci(pickingId: PickingId, structure: Structure, id: number) {
diff --git a/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts b/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts
index 6bd885217..735499fd2 100644
--- a/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts
+++ b/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts
@@ -84,7 +84,7 @@ function CrossLinkRestraintIterator(structure: Structure): LocationIterator {
         location.bIndex = pair.indexB
         return location
     }
-    return LocationIterator(groupCount, instanceCount, getLocation)
+    return LocationIterator(groupCount, instanceCount, getLocation, true)
 }
 
 function getLinkLoci(pickingId: PickingId, structure: Structure, id: number) {
diff --git a/src/mol-geo/representation/structure/visual/util/common.ts b/src/mol-geo/representation/structure/visual/util/common.ts
index de91023bf..6e5a74848 100644
--- a/src/mol-geo/representation/structure/visual/util/common.ts
+++ b/src/mol-geo/representation/structure/visual/util/common.ts
@@ -26,7 +26,9 @@ import { TransformData, createIdentityTransform, createTransforms } from '../../
 
 export function createColors(ctx: RuntimeContext, locationIt: LocationIterator, props: ColorThemeProps, colorData?: ColorData): Promise<ColorData> {
     const colorTheme = ColorTheme(props)
-    switch (colorTheme.kind) {
+    // Always use 'group' kind for 'complex' location iterators, i.e. an instance may include multiple units
+    const kind = colorTheme.kind === 'instance' && locationIt.isComplex ? 'group' : colorTheme.kind
+    switch (kind) {
         case 'uniform': return createUniformColor(ctx, locationIt, colorTheme.color, colorData)
         case 'group': return createGroupColor(ctx, locationIt, colorTheme.color, colorData)
         case 'groupInstance': return createGroupInstanceColor(ctx, locationIt, colorTheme.color, colorData)
diff --git a/src/mol-geo/representation/structure/visual/util/link.ts b/src/mol-geo/representation/structure/visual/util/link.ts
index 865e52d99..3978bfc9a 100644
--- a/src/mol-geo/representation/structure/visual/util/link.ts
+++ b/src/mol-geo/representation/structure/visual/util/link.ts
@@ -146,6 +146,6 @@ export namespace LinkIterator {
             location.bIndex = bond.indexB as StructureElement.UnitIndex
             return location
         }
-        return LocationIterator(groupCount, instanceCount, getLocation)
+        return LocationIterator(groupCount, instanceCount, getLocation, true)
     }
 }
\ No newline at end of file
diff --git a/src/mol-geo/util/location-iterator.ts b/src/mol-geo/util/location-iterator.ts
index 435d0c45c..16c351709 100644
--- a/src/mol-geo/util/location-iterator.ts
+++ b/src/mol-geo/util/location-iterator.ts
@@ -28,6 +28,8 @@ export interface LocationIterator extends Iterator<LocationValue> {
     readonly isNextNewInstance: boolean
     readonly groupCount: number
     readonly instanceCount: number
+    /** If true, may have multiple units per instance; if false one unit per instance */
+    readonly isComplex: boolean
     move(): LocationValue
     reset(): void
     skipInstance(): void
@@ -36,7 +38,7 @@ export interface LocationIterator extends Iterator<LocationValue> {
 type LocationGetter = (groupIndex: number, instanceIndex: number) => Location
 type IsSecondaryGetter = (groupIndex: number, instanceIndex: number) => boolean
 
-export function LocationIterator(groupCount: number, instanceCount: number, getLocation: LocationGetter, isSecondary: IsSecondaryGetter = () => false): LocationIterator {
+export function LocationIterator(groupCount: number, instanceCount: number, getLocation: LocationGetter, isComplex = false, isSecondary: IsSecondaryGetter = () => false): LocationIterator {
     const value: LocationValue = {
         location: NullLocation as Location,
         index: 0,
@@ -55,6 +57,7 @@ export function LocationIterator(groupCount: number, instanceCount: number, getL
         get isNextNewInstance () { return isNextNewInstance },
         get groupCount () { return groupCount },
         get instanceCount () { return instanceCount },
+        isComplex,
         move() {
             if (hasNext) {
                 value.groupIndex = groupIndex
-- 
GitLab