index.ts 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /**
  2. * Copyright (c) 2018 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, StructureSymmetry, Unit } from 'mol-model/structure';
  8. import { Task } from 'mol-task'
  9. import { RenderObject } from 'mol-gl/render-object';
  10. import { Representation, RepresentationProps } from '..';
  11. import { ColorTheme } from '../../theme';
  12. import { PickingId } from '../../util/picking';
  13. import { Loci, EmptyLoci, isEmptyLoci } from 'mol-model/loci';
  14. import { MarkerAction } from '../../util/marker-data';
  15. export interface UnitsRepresentation<P> {
  16. renderObjects: ReadonlyArray<RenderObject>
  17. create: (group: Unit.SymmetryGroup, props: P) => Task<void>
  18. update: (props: P) => Task<boolean>
  19. getLoci: (pickingId: PickingId) => Loci
  20. mark: (loci: Loci, action: MarkerAction) => void
  21. }
  22. export interface StructureRepresentation<P extends RepresentationProps = {}> extends Representation<Structure, P> { }
  23. interface GroupRepresentation<T> {
  24. repr: UnitsRepresentation<T>
  25. group: Unit.SymmetryGroup
  26. }
  27. export const DefaultStructureProps = {
  28. colorTheme: { name: 'instance-index' } as ColorTheme,
  29. alpha: 1,
  30. visible: true,
  31. doubleSided: false,
  32. depthMask: true,
  33. useFog: true,
  34. }
  35. export type StructureProps = Partial<typeof DefaultStructureProps>
  36. export function StructureRepresentation<P extends StructureProps>(reprCtor: () => UnitsRepresentation<P>): StructureRepresentation<P> {
  37. const renderObjects: RenderObject[] = []
  38. const groupReprs: GroupRepresentation<P>[] = []
  39. // let currentProps: typeof DefaultStructureProps
  40. function getLoci(pickingId: PickingId) {
  41. for (let i = 0, il = groupReprs.length; i < il; ++i) {
  42. const loc = groupReprs[i].repr.getLoci(pickingId)
  43. if (!isEmptyLoci(loc)) return loc
  44. }
  45. return EmptyLoci
  46. }
  47. return {
  48. renderObjects,
  49. create(structure: Structure, props: P = {} as P) {
  50. // currentProps = Object.assign({}, DefaultStructureProps, props)
  51. return Task.create('StructureRepresentation.create', async ctx => {
  52. // const { query } = currentProps
  53. // const qs = await query(structure).runAsChild(ctx)
  54. // const subStructure = Selection.unionStructure(qs)
  55. const groups = StructureSymmetry.getTransformGroups(structure);
  56. for (let i = 0; i < groups.length; i++) {
  57. const group = groups[i];
  58. const repr = reprCtor()
  59. groupReprs.push({ repr, group })
  60. await repr.create(group, props).runAsChild(ctx, { message: 'Building structure unit representations...', current: i, max: groups.length });
  61. renderObjects.push(...repr.renderObjects)
  62. }
  63. });
  64. },
  65. update(props: P) {
  66. return Task.create('StructureRepresentation.update', async ctx => {
  67. renderObjects.length = 0 // clear
  68. for (let i = 0, il = groupReprs.length; i < il; ++i) {
  69. const groupRepr = groupReprs[i]
  70. const { repr, group } = groupRepr
  71. const state = { message: 'Updating structure unit representations...', current: i, max: il };
  72. if (!await repr.update(props).runAsChild(ctx, state)) {
  73. console.log('update failed, need to rebuild')
  74. await repr.create(group, props).runAsChild(ctx, state)
  75. }
  76. renderObjects.push(...repr.renderObjects)
  77. }
  78. })
  79. },
  80. getLoci,
  81. mark(loci: Loci, action: MarkerAction) {
  82. for (let i = 0, il = groupReprs.length; i < il; ++i) {
  83. groupReprs[i].repr.mark(loci, action)
  84. }
  85. }
  86. }
  87. }