Quellcode durchsuchen

mol-plugin: refactored explore repr state

David Sehnal vor 6 Jahren
Ursprung
Commit
e769bf4589

+ 10 - 90
src/mol-plugin/behavior/dynamic/representation.ts

@@ -6,26 +6,24 @@
  */
 
 import { MarkerAction } from 'mol-geo/geometry/marker-data';
-import { Mat4, Vec3 } from 'mol-math/linear-algebra';
 import { EmptyLoci, EveryLoci } from 'mol-model/loci';
-import { StructureUnitTransforms } from 'mol-model/structure/structure/util/unit-transforms';
+import { QueryContext, StructureElement, StructureSelection } from 'mol-model/structure';
 import { PluginContext } from 'mol-plugin/context';
 import { PluginStateObject } from 'mol-plugin/state/objects';
-import { StateObjectTracker, StateSelection } from 'mol-state';
-import { labelFirst } from 'mol-theme/label';
-import { ParamDefinition as PD } from 'mol-util/param-definition';
-import { PluginBehavior } from '../behavior';
 import { Representation } from 'mol-repr/representation';
-import { ButtonsType } from 'mol-util/input/input-observer';
-import { StructureElement, StructureSelection, QueryContext } from 'mol-model/structure';
-import { ColorNames } from 'mol-util/color/tables';
 // import { MolScriptBuilder as MS } from 'mol-script/language/builder';
 import Expression from 'mol-script/language/expression';
-import { Color } from 'mol-util/color';
-import { compile } from 'mol-script/runtime/query/compiler';
-import { Overpaint } from 'mol-theme/overpaint';
 import { parseMolScript } from 'mol-script/language/parser';
+import { compile } from 'mol-script/runtime/query/compiler';
 import { transpileMolScript } from 'mol-script/script/mol-script/symbols';
+import { StateObjectTracker, StateSelection } from 'mol-state';
+import { labelFirst } from 'mol-theme/label';
+import { Overpaint } from 'mol-theme/overpaint';
+import { Color } from 'mol-util/color';
+import { ColorNames } from 'mol-util/color/tables';
+import { ButtonsType } from 'mol-util/input/input-observer';
+import { ParamDefinition as PD } from 'mol-util/param-definition';
+import { PluginBehavior } from '../behavior';
 
 export const HighlightLoci = PluginBehavior.create({
     name: 'representation-highlight-loci',
@@ -128,84 +126,6 @@ export const DefaultLociLabelProvider = PluginBehavior.create({
     display: { name: 'Provide Default Loci Label' }
 });
 
-export namespace ExplodeRepresentation3D {
-    export const Params = {
-        t: PD.Numeric(0, { min: 0, max: 1, step: 0.01 })
-    }
-    export type Params = PD.Values<typeof Params>
-
-    export class Behavior implements PluginBehavior<Params> {
-        private currentT = 0;
-        private repr: StateObjectTracker<PluginStateObject.Molecule.Structure.Representation3D>;
-        private structure: StateObjectTracker<PluginStateObject.Molecule.Structure>;
-        private transforms: StructureUnitTransforms;
-
-        private updateData() {
-            const reprUpdated = this.repr.update();
-            const strUpdated = this.structure.update();
-            if (strUpdated && this.structure.data) {
-                this.transforms = new StructureUnitTransforms(this.structure.data);
-            }
-            return reprUpdated || strUpdated;
-        }
-
-        register(ref: string): void {
-            this.repr.setQuery(StateSelection.Generators.byRef(ref).ancestorOfType([PluginStateObject.Molecule.Structure.Representation3D]));
-            this.structure.setQuery(StateSelection.Generators.byRef(ref).rootOfType([PluginStateObject.Molecule.Structure]));
-            this.update(this.params);
-        }
-
-        private centerVec = Vec3.zero();
-        private transVec = Vec3.zero();
-        private transMat = Mat4.zero();
-
-        update(params: Params): boolean | Promise<boolean> {
-            if (!this.updateData() && params.t === this.currentT) return false;
-            this.currentT = params.t;
-            if (!this.structure.data || !this.repr.data) return true;
-
-            const structure = this.structure.data;
-            const boundary = structure.boundary.sphere;
-            const d = boundary.radius * params.t;
-
-            for (let i = 0, _i = structure.units.length; i < _i; i++) {
-                const u = structure.units[i];
-
-                Vec3.transformMat4(this.centerVec, u.lookup3d.boundary.sphere.center, u.conformation.operator.matrix);
-                Vec3.sub(this.transVec, this.centerVec, boundary.center);
-                Vec3.setMagnitude(this.transVec, this.transVec, d);
-                Mat4.fromTranslation(this.transMat, this.transVec)
-
-                this.transforms.setTransform(this.transMat, u);
-            }
-
-            // TODO: should be be "auto updated"?
-            // perhaps have Representation3D.setState(state, autoSync = false)?
-
-            // TODO: where to handle unitTransforms composition?
-            // Manually or inside the representation? "inside" would better compose with future additions.
-            this.repr.data.repr.setState({ unitTransforms: this.transforms });
-            this.ctx.canvas3d.add(this.repr.data.repr);
-            this.ctx.canvas3d.requestDraw(true);
-
-            return true;
-        }
-
-        unregister(): void {
-            this.update({ t: 0 })
-            this.repr.cell = void 0;
-            this.structure.cell = void 0;
-        }
-
-        constructor(private ctx: PluginContext, private params: Params) {
-            this.repr = new StateObjectTracker(ctx.state.dataState);
-            this.structure = new StateObjectTracker(ctx.state.dataState);
-        }
-    }
-
-    export class Obj extends PluginStateObject.CreateBehavior<Behavior>({ name: 'Explode Representation3D Behavior' }) { }
-}
-
 type ColorMappings = { query: Expression, color: Color }[]
 namespace ColorMappings {
     export function areEqual(colorMappingsA: ColorMappings, colorMappingsB: ColorMappings) {

+ 18 - 2
src/mol-plugin/state/animation/helpers.ts

@@ -6,15 +6,31 @@
 
 
 import { SymmetryOperator } from 'mol-math/geometry';
-import { Mat4 } from 'mol-math/linear-algebra';
+import { Mat4, Vec3 } from 'mol-math/linear-algebra';
 import { Structure } from 'mol-model/structure';
 import { StructureUnitTransforms } from 'mol-model/structure/structure/util/unit-transforms';
 
 const _unwindMatrix = Mat4.zero();
-export function unwindStructureAssebmly(structure: Structure, unitTransforms: StructureUnitTransforms, t: number) {
+export function unwindStructureAssembly(structure: Structure, unitTransforms: StructureUnitTransforms, t: number) {
     for (let i = 0, _i = structure.units.length; i < _i; i++) {
         const u = structure.units[i];
         SymmetryOperator.lerpFromIdentity(_unwindMatrix, u.conformation.operator, t);
         unitTransforms.setTransform(_unwindMatrix, u);
     }
+}
+
+const _centerVec = Vec3.zero(), _transVec = Vec3.zero(), _transMat = Mat4.zero();
+export function explodeStructure(structure: Structure, unitTransforms: StructureUnitTransforms, t: number) {
+    const boundary = structure.boundary.sphere;
+    const d = boundary.radius * t;
+
+    for (let i = 0, _i = structure.units.length; i < _i; i++) {
+        const u = structure.units[i];
+        Vec3.transformMat4(_centerVec, u.lookup3d.boundary.sphere.center, u.conformation.operator.matrix);
+        Vec3.sub(_transVec, _centerVec, boundary.center);
+        Vec3.setMagnitude(_transVec, _transVec, d);
+        Mat4.fromTranslation(_transMat, _transVec);
+
+        unitTransforms.setTransform(_transMat, u);
+    }
 }

+ 22 - 15
src/mol-plugin/state/transforms/representation.ts

@@ -7,7 +7,7 @@
 
 import { Structure } from 'mol-model/structure';
 import { VolumeData, VolumeIsoValue } from 'mol-model/volume';
-import { ExplodeRepresentation3D, ColorRepresentation3D } from 'mol-plugin/behavior/dynamic/representation';
+import { ColorRepresentation3D } from 'mol-plugin/behavior/dynamic/representation';
 import { PluginContext } from 'mol-plugin/context';
 import { RepresentationProvider } from 'mol-repr/representation';
 import { BuiltInStructureRepresentationsName } from 'mol-repr/structure/registry';
@@ -26,7 +26,7 @@ import { ColorNames } from 'mol-util/color/tables';
 import { getLabelRepresentation } from 'mol-plugin/util/structure-labels';
 import { ShapeRepresentation } from 'mol-repr/shape/representation';
 import { StructureUnitTransforms } from 'mol-model/structure/structure/util/unit-transforms';
-import { unwindStructureAssebmly } from '../animation/helpers';
+import { unwindStructureAssembly, explodeStructure } from '../animation/helpers';
 
 export { StructureRepresentation3D }
 export { StructureRepresentation3DHelpers }
@@ -243,10 +243,10 @@ const UnwindStructureAssemblyRepresentation3D = PluginStateTransform.BuiltIn({
     canAutoUpdate() {
         return true;
     },
-    apply({ a, params }, plugin: PluginContext) {
+    apply({ a, params }) {
         const structure = a.data.source.data;
         const unitTransforms = new StructureUnitTransforms(structure);
-        unwindStructureAssebmly(structure, unitTransforms, params.t);
+        unwindStructureAssembly(structure, unitTransforms, params.t);
         return new SO.Molecule.Structure.Representation3DState({ state: { unitTransforms }, info: structure, source: a }, { label: `Unwind T = ${params.t.toFixed(2)}` });
     },
     update({ a, b, newParams, oldParams }) {
@@ -254,7 +254,7 @@ const UnwindStructureAssemblyRepresentation3D = PluginStateTransform.BuiltIn({
         if (a.data.source.data !== structure) return StateTransformer.UpdateResult.Recreate;
         if (oldParams.t === newParams.t) return StateTransformer.UpdateResult.Unchanged;
         const unitTransforms = b.data.state.unitTransforms!;
-        unwindStructureAssebmly(structure, unitTransforms, newParams.t);
+        unwindStructureAssembly(structure, unitTransforms, newParams.t);
         b.label = `Unwind T = ${newParams.t.toFixed(2)}`;
         b.data.source = a;
         return StateTransformer.UpdateResult.Updated;
@@ -267,21 +267,28 @@ const ExplodeStructureRepresentation3D = PluginStateTransform.BuiltIn({
     name: 'explode-structure-representation-3d',
     display: 'Explode 3D Representation',
     from: SO.Molecule.Structure.Representation3D,
-    to: ExplodeRepresentation3D.Obj,
-    params: ExplodeRepresentation3D.Params
+    to: SO.Molecule.Structure.Representation3DState,
+    params: { t: PD.Numeric(0, { min: 0, max: 1, step: 0.01 }) }
 })({
     canAutoUpdate() {
         return true;
     },
-    apply({ params }, plugin: PluginContext) {
-        return new ExplodeRepresentation3D.Obj(new ExplodeRepresentation3D.Behavior(plugin, params), { label: `Explosion T = ${params.t.toFixed(2)}` });
+    apply({ a, params, spine }) {
+        const srcStructure = spine.getRootOfType(SO.Molecule.Structure)!.data;
+        const unitTransforms = new StructureUnitTransforms(srcStructure);
+        explodeStructure(srcStructure, unitTransforms, params.t);
+        return new SO.Molecule.Structure.Representation3DState({ state: { unitTransforms }, info: srcStructure, source: a }, { label: `Explode T = ${params.t.toFixed(2)}` });
     },
-    update({ b, newParams }) {
-        return Task.create('Update Explosion', async () => {
-            const updated = await b.data.update(newParams);
-            b.label = `Explosion T = ${newParams.t.toFixed(2)}`;
-            return updated ? StateTransformer.UpdateResult.Updated : StateTransformer.UpdateResult.Unchanged;
-        });
+    update({ a, b, newParams, oldParams, spine }) {
+        const srcStructure = spine.getRootOfType(SO.Molecule.Structure)!.data;
+        const structure = b.data.info as Structure;
+        if (srcStructure !== structure) return StateTransformer.UpdateResult.Recreate;
+        if (oldParams.t === newParams.t) return StateTransformer.UpdateResult.Unchanged;
+        const unitTransforms = b.data.state.unitTransforms!;
+        explodeStructure(structure, unitTransforms, newParams.t);
+        b.label = `Explode T = ${newParams.t.toFixed(2)}`;
+        b.data.source = a;
+        return StateTransformer.UpdateResult.Updated;
     }
 });