structure-transparency.ts 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. /**
  2. * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. * @author David Sehnal <david.sehnal@gmail.com>
  6. */
  7. import { Structure, StructureElement } from '../../mol-model/structure';
  8. import { PluginStateObject } from '../../mol-plugin-state/objects';
  9. import { StateTransforms } from '../../mol-plugin-state/transforms';
  10. import { PluginContext } from '../../mol-plugin/context';
  11. import { StateBuilder, StateObjectCell, StateSelection, StateTransform } from '../../mol-state';
  12. import { StructureComponentRef } from '../manager/structure/hierarchy-state';
  13. import { EmptyLoci, Loci } from '../../mol-model/loci';
  14. import { Transparency } from '../../mol-theme/transparency';
  15. type TransparencyEachReprCallback = (update: StateBuilder.Root, repr: StateObjectCell<PluginStateObject.Molecule.Structure.Representation3D, StateTransform<typeof StateTransforms.Representation.StructureRepresentation3D>>, transparency?: StateObjectCell<any, StateTransform<typeof StateTransforms.Representation.TransparencyStructureRepresentation3DFromBundle>>) => Promise<void>
  16. const TransparencyManagerTag = 'transparency-controls';
  17. export async function setStructureTransparency(plugin: PluginContext, components: StructureComponentRef[], value: number, lociGetter: (structure: Structure) => Promise<StructureElement.Loci | EmptyLoci>, types?: string[]) {
  18. await eachRepr(plugin, components, async (update, repr, transparencyCell) => {
  19. if (types && types.length > 0 && !types.includes(repr.params!.values.type.name)) return;
  20. const structure = repr.obj!.data.sourceData;
  21. // always use the root structure to get the loci so the transparency
  22. // stays applicable as long as the root structure does not change
  23. const loci = await lociGetter(structure.root);
  24. if (Loci.isEmpty(loci)) return;
  25. const layer = {
  26. bundle: StructureElement.Bundle.fromLoci(loci),
  27. value,
  28. };
  29. if (transparencyCell) {
  30. const bundleLayers = [...transparencyCell.params!.values.layers, layer];
  31. const filtered = getFilteredBundle(bundleLayers, structure);
  32. update.to(transparencyCell).update(Transparency.toBundle(filtered));
  33. } else {
  34. const filtered = getFilteredBundle([layer], structure);
  35. update.to(repr.transform.ref)
  36. .apply(StateTransforms.Representation.TransparencyStructureRepresentation3DFromBundle, Transparency.toBundle(filtered), { tags: TransparencyManagerTag });
  37. }
  38. });
  39. }
  40. export async function clearStructureTransparency(plugin: PluginContext, components: StructureComponentRef[], types?: string[]) {
  41. await eachRepr(plugin, components, async (update, repr, transparencyCell) => {
  42. if (types && types.length > 0 && !types.includes(repr.params!.values.type.name)) return;
  43. if (transparencyCell) {
  44. update.delete(transparencyCell.transform.ref);
  45. }
  46. });
  47. }
  48. async function eachRepr(plugin: PluginContext, components: StructureComponentRef[], callback: TransparencyEachReprCallback) {
  49. const state = plugin.state.data;
  50. const update = state.build();
  51. for (const c of components) {
  52. for (const r of c.representations) {
  53. const transparency = state.select(StateSelection.Generators.ofTransformer(StateTransforms.Representation.TransparencyStructureRepresentation3DFromBundle, r.cell.transform.ref).withTag(TransparencyManagerTag));
  54. await callback(update, r.cell, transparency[0]);
  55. }
  56. }
  57. return update.commit({ doNotUpdateCurrent: true });
  58. }
  59. /** filter transparency layers for given structure */
  60. function getFilteredBundle(layers: Transparency.BundleLayer[], structure: Structure) {
  61. const transparency = Transparency.ofBundle(layers, structure.root);
  62. const merged = Transparency.merge(transparency);
  63. return Transparency.filter(merged, structure);
  64. }