Explorar el Código

various structure update related fixes- fixes #87- update on hierarchy changes- fix select mark on object update

Alexander Rose hace 4 años
padre
commit
667cacea12

+ 1 - 0
src/mol-model-props/computed/representations/interactions-inter-unit-cylinder.ts

@@ -100,6 +100,7 @@ export function InteractionsInterUnitVisual(materialId: number): ComplexVisual<I
             if ((state.info.interactionsHash as number) !== interactionsHash) {
                 state.createGeometry = true;
                 state.updateTransform = true;
+                state.updateColor = true;
                 state.info.interactionsHash = interactionsHash;
             }
         }

+ 1 - 0
src/mol-model-props/computed/representations/interactions-intra-unit-cylinder.ts

@@ -86,6 +86,7 @@ export function InteractionsIntraUnitVisual(materialId: number): UnitsVisual<Int
             if ((state.info.interactionsHash as number) !== interactionsHash) {
                 state.createGeometry = true;
                 state.updateTransform = true;
+                state.updateColor = true;
                 state.info.interactionsHash = interactionsHash;
             }
         }

+ 1 - 1
src/mol-model/structure/query/queries/combinators.ts

@@ -47,7 +47,7 @@ export function intersect(queries: ArrayLike<StructureQuery>): StructureQuery {
         }
 
         ctx.throwIfTimedOut();
-        const pivotSet = HashSet<Structure>(s => s.hashCode, Structure.areUnitAndIndicesEqual);
+        const pivotSet = HashSet<Structure>(s => s.hashCode, Structure.areUnitIdsAndIndicesEqual);
         StructureSelection.forEach(selections[pivotIndex], s => pivotSet.add(s));
 
         const ret = StructureSelection.UniqueBuilder(ctx.inputStructure);

+ 1 - 1
src/mol-model/structure/query/selection.ts

@@ -111,7 +111,7 @@ namespace StructureSelection {
     class HashBuilderImpl implements Builder {
         private structures: Structure[] = [];
         private allSingletons = true;
-        private uniqueSets = HashSet(Structure.hashCode, Structure.areUnitAndIndicesEqual);
+        private uniqueSets = HashSet(Structure.hashCode, Structure.areUnitIdsAndIndicesEqual);
 
         add(structure: Structure) {
             const atomCount = structure.elementCount;

+ 1 - 1
src/mol-model/structure/query/utils/builders.ts

@@ -12,7 +12,7 @@ import { StructureSubsetBuilder } from '../../structure/util/subset-builder';
 import { ElementIndex } from '../../model';
 
 export class UniqueStructuresBuilder {
-    private set = HashSet(Structure.hashCode, Structure.areUnitAndIndicesEqual);
+    private set = HashSet(Structure.hashCode, Structure.areUnitIdsAndIndicesEqual);
     private structures: Structure[] = [];
     private allSingletons = true;
 

+ 16 - 2
src/mol-model/structure/structure/structure.ts

@@ -943,7 +943,7 @@ namespace Structure {
     }
 
     // TODO: there should be a version that properly supports partitioned units
-    export function areUnitAndIndicesEqual(a: Structure, b: Structure) {
+    export function areUnitIdsEqual(a: Structure, b: Structure) {
         if (a === b) return true;
 
         if (a.elementCount !== b.elementCount) return false;
@@ -954,10 +954,24 @@ namespace Structure {
             if (a.units[i].id !== b.units[i].id) return false;
         }
 
-        for (let i = 0; i < len; i++) {
+        return true;
+    }
+
+    export function areUnitIdsAndIndicesEqual(a: Structure, b: Structure) {
+        if (!areUnitIdsEqual(a, b)) return false;
+
+        for (let i = 0, il = a.units.length; i < il; i++) {
             if (!SortedArray.areEqual(a.units[i].elements, b.units[i].elements)) return false;
         }
+        return true;
+    }
 
+    export function areHierarchiesEqual(a: Structure, b: Structure) {
+        if (!areUnitIdsEqual(a, b)) return false;
+
+        for (let i = 0, il = a.units.length; i < il; i++) {
+            if (Unit.getHierarchy(a.units[i]) !== Unit.getHierarchy(b.units[i])) return false;
+        }
         return true;
     }
 

+ 21 - 5
src/mol-model/structure/structure/unit.ts

@@ -465,10 +465,12 @@ namespace Unit {
         return a.chainGroupId === b.chainGroupId && a.conformation.operator.name === b.conformation.operator.name;
     }
 
-    export function areAreConformationsEquivalent(a: Unit, b: Unit) {
-        if (!SortedArray.areEqual(a.elements, b.elements)) return false;
-        if (!Mat4.areEqual(a.conformation.operator.matrix, b.conformation.operator.matrix, 1e-6)) return false;
+    export function areOperatorsEqual(a: Unit, b: Unit) {
+        return Mat4.areEqual(a.conformation.operator.matrix, b.conformation.operator.matrix, 1e-6);
+    }
 
+    export function areConformationsEqual(a: Unit, b: Unit) {
+        if (!SortedArray.areEqual(a.elements, b.elements)) return false;
         return isSameConformation(a, b.model);
     }
 
@@ -498,7 +500,7 @@ namespace Unit {
 
         const xs = u.elements;
         const { x: xa, y: ya, z: za } = u.conformation.coordinates;
-        const { x: xb, y: yb, z: zb } = getConformation(u.kind, model);
+        const { x: xb, y: yb, z: zb } = getModelConformationOfKind(u.kind, model);
 
         for (let i = 0, _i = xs.length; i < _i; i++) {
             const u = xs[i];
@@ -508,11 +510,25 @@ namespace Unit {
         return true;
     }
 
-    export function getConformation(kind: Unit.Kind, model: Model) {
+    export function getModelConformationOfKind(kind: Unit.Kind, model: Model) {
         return kind === Kind.Atomic ? model.atomicConformation :
             kind === Kind.Spheres ? model.coarseConformation.spheres :
                 model.coarseConformation.gaussians;
     }
+
+    export function getConformation(u: Unit) {
+        return getModelConformationOfKind(u.kind, u.model);
+    }
+
+    export function getModelHierarchyOfKind(kind: Unit.Kind, model: Model) {
+        return kind === Kind.Atomic ? model.atomicHierarchy :
+            kind === Kind.Spheres ? model.coarseHierarchy.spheres :
+                model.coarseHierarchy.gaussians;
+    }
+
+    export function getHierarchy(u: Unit) {
+        return getModelHierarchyOfKind(u.kind, u.model);
+    }
 }
 
 export default Unit;

+ 1 - 1
src/mol-plugin-state/helpers/structure-component.ts

@@ -108,7 +108,7 @@ export function updateStructureComponent(a: Structure, b: SO.Molecule.Structure,
             if (oldParams.type.params !== newParams.type.params) {
                 return StateTransformer.UpdateResult.Recreate;
             }
-            if (a.hashCode !== cache.source.hashCode) {
+            if (!Structure.areEquivalent(a, cache.source)) {
                 return StateTransformer.UpdateResult.Recreate;
             }
             if (b.data.model === a.model) return StateTransformer.UpdateResult.Unchanged;

+ 1 - 1
src/mol-plugin-state/manager/structure/selection.ts

@@ -260,7 +260,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
         if (!structure) return;
 
         // oldObj is not defined for inserts (e.g. TransformStructureConformation)
-        if (!oldObj?.data || Structure.areUnitAndIndicesEqual(oldObj.data, obj.data)) {
+        if (!oldObj?.data || Structure.areUnitIdsAndIndicesEqual(oldObj.data, obj.data)) {
             this.entries.set(ref, remapSelectionEntry(this.entries.get(ref)!, structure));
 
             // remap referenceLoci & prevHighlight if needed and possible

+ 1 - 1
src/mol-plugin-state/transforms/model.ts

@@ -615,7 +615,7 @@ const MultiStructureSelectionFromExpression = PluginStateTransform.BuiltIn({
                     let update = false;
 
                     if (!!newParams.isTransitive) {
-                        if (Structure.areUnitAndIndicesEqual(entry.originalStructure, structure)) {
+                        if (Structure.areUnitIdsAndIndicesEqual(entry.originalStructure, structure)) {
                             const selection = StructureQueryHelper.run(entry, entry.originalStructure);
                             entry.currentStructure = structure;
                             entries.set(sel.key, entry);

+ 6 - 3
src/mol-plugin/behavior/dynamic/representation.ts

@@ -161,9 +161,12 @@ export const SelectLoci = PluginBehavior.create({
             this.subscribeObservable(this.ctx.state.events.object.updated, ({ ref, obj, oldObj, oldData, action }) => {
                 const cell = this.ctx.state.data.cells.get(ref);
                 if (cell && SO.Molecule.Structure.is(cell.obj)) {
-                    const h = obj.data.hashCode;
-                    if (action === 'recreate' && h === oldObj?.data?.hashCode) return;
-                    if (action === 'in-place' && h === oldData?.hashCode) return;
+                    const structure: Structure = obj.data;
+                    const oldStructure: Structure | undefined = action === 'recreate' ? oldObj?.data :
+                        action === 'in-place' ? oldData : undefined;
+                    if (oldStructure &&
+                        Structure.areEquivalent(structure, oldStructure) &&
+                        Structure.areHierarchiesEqual(structure, oldStructure)) return;
 
                     const reprs = this.ctx.state.data.select(StateSelection.Generators.ofType(SO.Molecule.Structure.Representation3D, ref));
                     for (const repr of reprs) this.applySelectMark(repr.transform.ref, true);

+ 1 - 0
src/mol-plugin/behavior/static/state.ts

@@ -104,6 +104,7 @@ function setVisibilityVisitor(t: StateTransform, tree: StateTree, ctx: { state:
 
 export function Highlight(ctx: PluginContext) {
     PluginCommands.Interactivity.Object.Highlight.subscribe(ctx, ({ state, ref }) => {
+        if (!ctx.canvas3d || ctx.isBusy) return;
         ctx.managers.interactivity.lociHighlights.clearHighlights();
 
         const refs = typeof ref === 'string' ? [ref] : ref;

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

@@ -65,7 +65,7 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct
                     visuals.set(group.hashCode, { visual, group });
                     if (runtime.shouldUpdate) await runtime.update({ message: 'Creating or updating UnitsVisual', current: i, max: _groups.length });
                 }
-            } else if (structure && !Structure.areUnitAndIndicesEqual(structure, _structure)) {
+            } else if (structure && !Structure.areUnitIdsAndIndicesEqual(structure, _structure)) {
                 // console.log(label, 'structures not equivalent');
                 // Tries to re-use existing visuals for the groups of the new structure.
                 // Creates additional visuals if needed, destroys left-over visuals.
@@ -119,7 +119,7 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct
                 //     visuals.set(group.hashCode, { visual, group })
                 // })
                 // unusedVisuals.forEach(visual => visual.destroy())
-            } else if (structure && structure !== _structure && Structure.areUnitAndIndicesEqual(structure, _structure)) {
+            } else if (structure && structure !== _structure && Structure.areUnitIdsAndIndicesEqual(structure, _structure)) {
                 // console.log(label, 'structures equivalent but not identical');
                 // Expects that for structures with the same hashCode,
                 // the unitSymmetryGroups are the same as well.

+ 12 - 2
src/mol-repr/structure/units-visual.ts

@@ -107,6 +107,12 @@ export function UnitsVisual<G extends Geometry, P extends StructureParams & Geom
 
         setUpdateState(updateState, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup);
 
+        if (!Structure.areHierarchiesEqual(currentStructureGroup.structure, newStructureGroup.structure)) {
+            // console.log('new hierarchy');
+            updateState.updateTransform = true;
+            updateState.updateColor = true;
+        }
+
         if (!ColorTheme.areEqual(newTheme.color, currentTheme.color)) {
             // console.log('new colorTheme');
             updateState.updateColor = true;
@@ -126,10 +132,14 @@ export function UnitsVisual<G extends Geometry, P extends StructureParams & Geom
             }
         }
 
-        // check if the conformation of unit.model has changed
+        // check if the operator or conformation of unit has changed
         const newUnit = newStructureGroup.group.units[0];
         const currentUnit = currentStructureGroup.group.units[0];
-        if (!Unit.areAreConformationsEquivalent(newUnit, currentUnit)) {
+        if (!Unit.areOperatorsEqual(newUnit, currentUnit)) {
+            // console.log('new operators');
+            updateState.updateTransform = true;
+        }
+        if (!Unit.areConformationsEqual(newUnit, currentUnit)) {
             // console.log('new conformation');
             updateState.createGeometry = true;
         }

+ 1 - 0
src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts

@@ -144,6 +144,7 @@ export function IntraUnitBondCylinderVisual(materialId: number): UnitsVisual<Int
             if (Unit.isAtomic(newUnit) && Unit.isAtomic(currentUnit)) {
                 if (!IntAdjacencyGraph.areEqual(newUnit.bonds, currentUnit.bonds)) {
                     state.createGeometry = true;
+                    state.updateTransform = true;
                     state.updateColor = true;
                     state.updateSize = true;
                 }

+ 1 - 0
src/mol-repr/structure/visual/bond-intra-unit-line.ts

@@ -121,6 +121,7 @@ export function IntraUnitBondLineVisual(materialId: number): UnitsVisual<IntraUn
             if (Unit.isAtomic(newUnit) && Unit.isAtomic(currentUnit)) {
                 if (!IntAdjacencyGraph.areEqual(newUnit.bonds, currentUnit.bonds)) {
                     state.createGeometry = true;
+                    state.updateTransform = true;
                     state.updateColor = true;
                     state.updateSize = true;
                 }