diff --git a/package-lock.json b/package-lock.json index 0c5435164cb9db0db058b6d24f59968aa026e390..149b28965084d40054210f8b62733c5b4979ef5e 100644 Binary files a/package-lock.json and b/package-lock.json differ diff --git a/src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts b/src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts index 74ad78176fbe224b5a801082b41eb281bb1c1502..42f8ea7d1c69186576313c53ea87e96e4bba6172 100644 --- a/src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts +++ b/src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts @@ -39,7 +39,8 @@ const StructureFocusRepresentationParams = (plugin: PluginContext) => { size: SizeTheme.BuiltIn.uniform }) }), - components: PD.MultiSelect(FocusComponents, PD.arrayToOptions(FocusComponents)) + components: PD.MultiSelect(FocusComponents, PD.arrayToOptions(FocusComponents)), + excludeTargetFromSurroundings: PD.Boolean(false, { label: 'Exclude Target', description: 'Exclude the focus "target" from the surroudings component.' }) }; }; @@ -106,6 +107,7 @@ class StructureFocusRepresentationBehavior extends PluginBehavior.WithSubscriber private clear(root: StateTransform.Ref) { const state = this.plugin.state.data; + this.currentSource = void 0; const foci = state.select(StateSelection.Generators.byRef(root).subtree().withTag(StructureFocusRepresentationTags.TargetSel)); const surrs = state.select(StateSelection.Generators.byRef(root).subtree().withTag(StructureFocusRepresentationTags.SurrSel)); @@ -125,21 +127,31 @@ class StructureFocusRepresentationBehavior extends PluginBehavior.WithSubscriber return PluginCommands.State.Update(this.plugin, { state, tree: update, options: { doNotLogTiming: true, doNotUpdateCurrent: true } }); } + private currentSource: StructureElement.Loci | undefined = void 0; private async focus(sourceLoci: StructureElement.Loci) { const parent = this.plugin.helpers.substructureParent.get(sourceLoci.structure); if (!parent || !parent.obj) return; + this.currentSource = sourceLoci; const loci = StructureElement.Loci.remap(sourceLoci, parent.obj!.data); const residueLoci = StructureElement.Loci.extendToWholeResidues(loci); const residueBundle = StructureElement.Bundle.fromLoci(residueLoci); - const surroundings = MS.struct.modifier.includeSurroundings({ - 0: StructureElement.Bundle.toExpression(residueBundle), + const target = StructureElement.Bundle.toExpression(residueBundle); + let surroundings = MS.struct.modifier.includeSurroundings({ + 0: target, radius: this.params.expandRadius, 'as-whole-residues': true }); + if (this.params.excludeTargetFromSurroundings) { + surroundings = MS.struct.modifier.exceptBy({ + 0: surroundings, + by: target + }); + } + const { state, builder, refs } = this.ensureShape(parent); builder.to(refs[StructureFocusRepresentationTags.TargetSel]!).update(StateTransforms.Model.StructureSelectionFromBundle, old => ({ ...old, bundle: residueBundle })); @@ -159,6 +171,13 @@ class StructureFocusRepresentationBehavior extends PluginBehavior.WithSubscriber const old = this.params; this.params = params; + if (old.excludeTargetFromSurroundings !== params.excludeTargetFromSurroundings) { + if (this.currentSource) { + this.focus(this.currentSource); + } + return true; + } + const state = this.plugin.state.data; const builder = state.build(); @@ -187,8 +206,12 @@ class StructureFocusRepresentationBehavior extends PluginBehavior.WithSubscriber await PluginCommands.State.Update(this.plugin, { state, tree: builder, options: { doNotLogTiming: true, doNotUpdateCurrent: true } }); - // TODO: update properly - if (params.expandRadius !== old.expandRadius) await this.clear(StateTransform.RootRef); + if (params.expandRadius !== old.expandRadius) { + if (this.currentSource) { + this.focus(this.currentSource); + } + return true; + } return true; }