assembly-unwind.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /**
  2. * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { PluginStateAnimation } from '../model';
  7. import { PluginStateObject } from '../../objects';
  8. import { StateTransforms } from '../../transforms';
  9. import { StateSelection, StateTransform } from '../../../mol-state';
  10. import { PluginCommands } from '../../../mol-plugin/commands';
  11. import { ParamDefinition as PD } from '../../../mol-util/param-definition';
  12. import { PluginContext } from '../../../mol-plugin/context';
  13. export const AnimateAssemblyUnwind = PluginStateAnimation.create({
  14. name: 'built-in.animate-assembly-unwind',
  15. display: { name: 'Unwind Assembly' },
  16. isExportable: true,
  17. params: (plugin: PluginContext) => {
  18. const targets: [string, string][] = [['all', 'All']];
  19. const structures = plugin.state.data.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Structure));
  20. for (const s of structures) {
  21. targets.push([s.transform.ref, s.obj!.data.models[0].label]);
  22. }
  23. return {
  24. durationInMs: PD.Numeric(3000, { min: 100, max: 10000, step: 100}),
  25. playOnce: PD.Boolean(false),
  26. target: PD.Select(targets[0][0], targets)
  27. };
  28. },
  29. canApply(plugin) {
  30. const state = plugin.state.data;
  31. const root = StateTransform.RootRef;
  32. const reprs = state.select(StateSelection.Generators.ofType(PluginStateObject.Molecule.Structure.Representation3D, root));
  33. return { canApply: reprs.length > 0 };
  34. },
  35. getDuration: (params) => {
  36. return {
  37. kind: 'fixed',
  38. durationMs: params.durationInMs
  39. };
  40. },
  41. initialState: () => ({ t: 0 }),
  42. setup(params, _, plugin) {
  43. const state = plugin.state.data;
  44. const root = !params.target || params.target === 'all' ? StateTransform.RootRef : params.target;
  45. const reprs = state.select(StateSelection.Generators.ofType(PluginStateObject.Molecule.Structure.Representation3D, root));
  46. const update = state.build();
  47. let changed = false;
  48. for (const r of reprs) {
  49. const unwinds = state.select(StateSelection.Generators.ofTransformer(StateTransforms.Representation.UnwindStructureAssemblyRepresentation3D, r.transform.ref));
  50. if (unwinds.length > 0) continue;
  51. changed = true;
  52. update.to(r)
  53. .apply(StateTransforms.Representation.UnwindStructureAssemblyRepresentation3D, { t: 0 }, { tags: 'animate-assembly-unwind' });
  54. }
  55. if (!changed) return;
  56. return update.commit({ doNotUpdateCurrent: true });
  57. },
  58. teardown(_, __, plugin) {
  59. const state = plugin.state.data;
  60. const reprs = state.select(StateSelection.Generators.ofType(PluginStateObject.Molecule.Structure.Representation3DState)
  61. .withTag('animate-assembly-unwind'));
  62. if (reprs.length === 0) return;
  63. const update = state.build();
  64. for (const r of reprs) update.delete(r.transform.ref);
  65. return update.commit();
  66. },
  67. async apply(animState, t, ctx) {
  68. const state = ctx.plugin.state.data;
  69. const root = !ctx.params.target || ctx.params.target === 'all' ? StateTransform.RootRef : ctx.params.target;
  70. const anims = state.select(StateSelection.Generators.ofTransformer(StateTransforms.Representation.UnwindStructureAssemblyRepresentation3D, root));
  71. if (anims.length === 0) {
  72. return { kind: 'finished' };
  73. }
  74. const update = state.build();
  75. const d = (t.current - t.lastApplied) / ctx.params.durationInMs;
  76. let newTime = (animState.t + d), finished = false;
  77. if (ctx.params.playOnce && newTime >= 1) {
  78. finished = true;
  79. newTime = 1;
  80. } else {
  81. newTime = newTime % 1;
  82. }
  83. for (const m of anims) {
  84. update.to(m).update({ t: newTime });
  85. }
  86. await PluginCommands.State.Update(ctx.plugin, { state, tree: update, options: { doNotLogTiming: true } });
  87. if (finished) return { kind: 'finished' };
  88. return { kind: 'next', state: { t: newTime } };
  89. }
  90. });