index.ts 3.8 KB

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