molstar
Version:
A comprehensive macromolecular library.
180 lines (179 loc) • 8.37 kB
JavaScript
/**
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { __awaiter, __generator } from "tslib";
import { ParamDefinition as PD } from '../../mol-util/param-definition';
import { StructureRepresentationStateBuilder } from './representation';
import { Representation } from '../representation';
import { Structure, StructureElement, Bond } from '../../mol-model/structure';
import { Subject } from 'rxjs';
import { getNextMaterialId } from '../../mol-gl/render-object';
import { Theme } from '../../mol-theme/theme';
import { Task } from '../../mol-task';
import { EmptyLoci, Loci, isEveryLoci, isDataLoci, EveryLoci } from '../../mol-model/loci';
import { MarkerActions } from '../../mol-util/marker-action';
import { Overpaint } from '../../mol-theme/overpaint';
import { Clipping } from '../../mol-theme/clipping';
import { Transparency } from '../../mol-theme/transparency';
import { Substance } from '../../mol-theme/substance';
export function ComplexRepresentation(label, ctx, getParams, visualCtor) {
var version = 0;
var webgl = ctx.webgl;
var updated = new Subject();
var geometryState = new Representation.GeometryState();
var materialId = getNextMaterialId();
var renderObjects = [];
var _state = StructureRepresentationStateBuilder.create();
var visual;
var _structure;
var _params;
var _props;
var _theme = Theme.createEmpty();
function createOrUpdate(props, structure) {
var _this = this;
if (props === void 0) { props = {}; }
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', function (runtime) { return __awaiter(_this, void 0, void 0, function () {
var newVisual, promise;
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
newVisual = false;
if (!visual) {
visual = visualCtor(materialId, _structure, _props, webgl);
newVisual = true;
}
else if ((_a = visual.mustRecreate) === null || _a === void 0 ? void 0 : _a.call(visual, _structure, _props, webgl)) {
visual.destroy();
visual = visualCtor(materialId, _structure, _props, webgl);
newVisual = true;
}
promise = visual.createOrUpdate({ webgl: webgl, runtime: runtime }, _theme, _props, structure);
if (!promise) return [3 /*break*/, 2];
return [4 /*yield*/, promise];
case 1:
_b.sent();
_b.label = 2;
case 2:
if (newVisual)
setState(_state); // current state for new visual
// update list of renderObjects
renderObjects.length = 0;
if (visual && visual.renderObject) {
renderObjects.push(visual.renderObject);
geometryState.add(visual.renderObject.id, visual.geometryVersion);
}
geometryState.snapshot();
// increment version
version += 1;
updated.next(version);
return [2 /*return*/];
}
});
}); });
}
function getLoci(pickingId) {
return visual ? visual.getLoci(pickingId) : EmptyLoci;
}
function getAllLoci() {
return [Structure.Loci(_structure.target)];
}
function mark(loci, action) {
if (!_structure)
return false;
if (!MarkerActions.is(_state.markerActions, action))
return false;
if (Structure.isLoci(loci) || StructureElement.Loci.is(loci) || Bond.isLoci(loci)) {
if (!Structure.areRootsEquivalent(loci.structure, _structure))
return false;
// Remap `loci` from equivalent structure to the current `_structure`
loci = Loci.remap(loci, _structure);
if (Structure.isLoci(loci) || (StructureElement.Loci.is(loci) && StructureElement.Loci.isWholeStructure(loci))) {
// Change to `EveryLoci` to allow for downstream optimizations
loci = EveryLoci;
}
}
else if (!isEveryLoci(loci) && !isDataLoci(loci)) {
return false;
}
if (Loci.isEmpty(loci))
return false;
return visual ? visual.mark(loci, action) : false;
}
function setState(state) {
StructureRepresentationStateBuilder.update(_state, state);
if (state.visible !== undefined && visual) {
// hide visual when _unitTransforms is set and not the identity
visual.setVisibility(state.visible && (_state.unitTransforms === null || _state.unitTransforms.isIdentity));
}
if (state.alphaFactor !== undefined && visual)
visual.setAlphaFactor(state.alphaFactor);
if (state.pickable !== undefined && visual)
visual.setPickable(state.pickable);
if (state.overpaint !== undefined && visual) {
// Remap loci from equivalent structure to the current structure
var remappedOverpaint = Overpaint.remap(state.overpaint, _structure);
visual.setOverpaint(remappedOverpaint, webgl);
}
if (state.transparency !== undefined && visual) {
// Remap loci from equivalent structure to the current structure
var remappedTransparency = Transparency.remap(state.transparency, _structure);
visual.setTransparency(remappedTransparency, webgl);
}
if (state.substance !== undefined && visual) {
// Remap loci from equivalent structure to the current structure
var remappedSubstance = Substance.remap(state.substance, _structure);
visual.setSubstance(remappedSubstance, webgl);
}
if (state.clipping !== undefined && visual) {
// Remap loci from equivalent structure to the current structure
var remappedClipping = Clipping.remap(state.clipping, _structure);
visual.setClipping(remappedClipping);
}
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 here and not the identity,
// it is ignored and sets the visual's visibility to `false`.
visual.setVisibility(_state.visible && (state.unitTransforms === null || state.unitTransforms.isIdentity));
}
}
function setTheme(theme) {
_theme = theme;
}
function destroy() {
if (visual)
visual.destroy();
}
return {
label: label,
get groupCount() {
return visual ? visual.groupCount : 0;
},
get props() { return _props; },
get params() { return _params; },
get state() { return _state; },
get theme() { return _theme; },
get geometryVersion() { return geometryState.version; },
renderObjects: renderObjects,
updated: updated,
createOrUpdate: createOrUpdate,
setState: setState,
setTheme: setTheme,
getLoci: getLoci,
getAllLoci: getAllLoci,
mark: mark,
destroy: destroy
};
}