/** * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose * @author David Sehnal */ import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { StructureParams, ComplexVisual, StructureRepresentation, StructureRepresentationStateBuilder, StructureRepresentationState } from './representation'; import { RepresentationContext, RepresentationParamsGetter } from '../representation'; import { Structure } from '../../mol-model/structure'; import { Subject } from 'rxjs'; import { getNextMaterialId, GraphicsRenderObject } from '../../mol-gl/render-object'; import { createEmptyTheme, Theme } from '../../mol-theme/theme'; import { Task } from '../../mol-task'; import { PickingId } from '../../mol-geo/geometry/picking'; import { EmptyLoci, Loci } from '../../mol-model/loci'; import { MarkerAction } from '../../mol-util/marker-action'; export function ComplexRepresentation

(label: string, ctx: RepresentationContext, getParams: RepresentationParamsGetter, visualCtor: (materialId: number) => ComplexVisual

): StructureRepresentation

{ let version = 0 const updated = new Subject() const materialId = getNextMaterialId() const renderObjects: GraphicsRenderObject[] = [] const _state = StructureRepresentationStateBuilder.create() let visual: ComplexVisual

| undefined let _structure: Structure let _params: P let _props: PD.Values

let _theme = createEmptyTheme() function createOrUpdate(props: Partial> = {}, structure?: Structure) { if (structure && structure !== _structure) { _params = getParams(ctx, structure) _structure = structure if (!_props) _props = PD.getDefaultValues(_params) } _props = Object.assign({}, _props, props) return Task.create('Creating or updating ComplexRepresentation', async runtime => { if (!visual) visual = visualCtor(materialId) const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, structure) if (promise) await promise // update list of renderObjects renderObjects.length = 0 if (visual && visual.renderObject) renderObjects.push(visual.renderObject) // increment version updated.next(version++) }); } function getLoci(pickingId: PickingId) { return visual ? visual.getLoci(pickingId) : EmptyLoci } function mark(loci: Loci, action: MarkerAction) { return visual ? visual.mark(loci, action) : false } function setState(state: Partial) { StructureRepresentationStateBuilder.update(_state, state) if (state.visible !== undefined && visual) { // hide visual when _unitTransforms is set visual.setVisibility(state.visible && _state.unitTransforms === null) } if (state.alphaFactor !== undefined && visual) visual.setAlphaFactor(state.alphaFactor) if (state.pickable !== undefined && visual) visual.setPickable(state.pickable) if (state.overpaint !== undefined && visual) visual.setOverpaint(state.overpaint) if (state.transparency !== undefined && visual) visual.setTransparency(state.transparency) if (state.transform !== undefined && visual) visual.setTransform(state.transform) if (state.unitTransforms !== undefined && visual) { // Since ComplexVisuals always renders geometries between units the application of `unitTransforms` // does not make sense. When given it is ignored here and sets the visual's visibility to `false`. visual.setVisibility(_state.visible && state.unitTransforms === null) } } function setTheme(theme: Theme) { _theme = theme } function destroy() { if (visual) visual.destroy() } return { label, get groupCount() { return visual ? visual.groupCount : 0 }, get props() { return _props }, get params() { return _params }, get state() { return _state }, get theme() { return _theme }, renderObjects, updated, createOrUpdate, setState, setTheme, getLoci, mark, destroy } }