molstar
Version:
A comprehensive macromolecular library.
396 lines (395 loc) • 17.4 kB
JavaScript
/**
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { __awaiter, __generator } from "tslib";
import { ParamDefinition as PD } from '../mol-util/param-definition';
import { ColorTheme } from '../mol-theme/color';
import { SizeTheme } from '../mol-theme/size';
import { Theme } from '../mol-theme/theme';
import { Subject } from 'rxjs';
import { Task } from '../mol-task';
import { MarkerActions } from '../mol-util/marker-action';
import { Loci as ModelLoci, EmptyLoci, isEmptyLoci } from '../mol-model/loci';
import { Overpaint } from '../mol-theme/overpaint';
import { Transparency } from '../mol-theme/transparency';
import { Mat4 } from '../mol-math/linear-algebra';
import { getQualityProps } from './util';
import { BaseGeometry } from '../mol-geo/geometry/base';
import { Visual } from './visual';
import { Clipping } from '../mol-theme/clipping';
import { SetUtils } from '../mol-util/set';
import { cantorPairing } from '../mol-data/util';
import { Substance } from '../mol-theme/substance';
export var RepresentationProvider;
(function (RepresentationProvider) {
function getDetaultParams(r, ctx, data) {
return PD.getDefaultValues(r.getParams(ctx, data));
}
RepresentationProvider.getDetaultParams = getDetaultParams;
})(RepresentationProvider || (RepresentationProvider = {}));
export var EmptyRepresentationProvider = {
name: '',
label: '',
description: '',
factory: function () { return Representation.Empty; },
getParams: function () { return ({}); },
defaultValues: {},
defaultColorTheme: ColorTheme.EmptyProvider,
defaultSizeTheme: SizeTheme.EmptyProvider,
isApplicable: function () { return true; }
};
function getTypes(list) {
return list.map(function (e) { return [e.name, e.provider.label]; });
}
var RepresentationRegistry = /** @class */ (function () {
function RepresentationRegistry() {
this._list = [];
this._map = new Map();
this._name = new Map();
}
Object.defineProperty(RepresentationRegistry.prototype, "default", {
get: function () { return this._list[0]; },
enumerable: false,
configurable: true
});
Object.defineProperty(RepresentationRegistry.prototype, "types", {
get: function () { return getTypes(this._list); },
enumerable: false,
configurable: true
});
;
RepresentationRegistry.prototype.add = function (provider) {
if (this._map.has(provider.name)) {
throw new Error("".concat(provider.name, " already registered."));
}
this._list.push({ name: provider.name, provider: provider });
this._map.set(provider.name, provider);
this._name.set(provider, provider.name);
};
RepresentationRegistry.prototype.getName = function (provider) {
if (!this._name.has(provider))
throw new Error("'".concat(provider.label, "' is not a registered represenatation provider."));
return this._name.get(provider);
};
RepresentationRegistry.prototype.remove = function (provider) {
var name = provider.name;
this._list.splice(this._list.findIndex(function (e) { return e.name === name; }), 1);
var p = this._map.get(name);
if (p) {
this._map.delete(name);
this._name.delete(p);
}
};
RepresentationRegistry.prototype.get = function (name) {
return this._map.get(name) || EmptyRepresentationProvider;
};
Object.defineProperty(RepresentationRegistry.prototype, "list", {
get: function () {
return this._list;
},
enumerable: false,
configurable: true
});
RepresentationRegistry.prototype.getApplicableList = function (data) {
return this._list.filter(function (e) { return e.provider.isApplicable(data); });
};
RepresentationRegistry.prototype.getApplicableTypes = function (data) {
return getTypes(this.getApplicableList(data));
};
return RepresentationRegistry;
}());
export { RepresentationRegistry };
//
export { Representation };
var Representation;
(function (Representation) {
var Loci;
(function (Loci) {
function areEqual(a, b) {
return a.repr === b.repr && ModelLoci.areEqual(a.loci, b.loci);
}
Loci.areEqual = areEqual;
function isEmpty(a) {
return ModelLoci.isEmpty(a.loci);
}
Loci.isEmpty = isEmpty;
Loci.Empty = { loci: EmptyLoci };
})(Loci = Representation.Loci || (Representation.Loci = {}));
function createState() {
return { visible: true, alphaFactor: 1, pickable: true, colorOnly: false, syncManually: false, transform: Mat4.identity(), overpaint: Overpaint.Empty, transparency: Transparency.Empty, substance: Substance.Empty, clipping: Clipping.Empty, markerActions: MarkerActions.All };
}
Representation.createState = createState;
function updateState(state, update) {
if (update.visible !== undefined)
state.visible = update.visible;
if (update.alphaFactor !== undefined)
state.alphaFactor = update.alphaFactor;
if (update.pickable !== undefined)
state.pickable = update.pickable;
if (update.colorOnly !== undefined)
state.colorOnly = update.colorOnly;
if (update.overpaint !== undefined)
state.overpaint = update.overpaint;
if (update.transparency !== undefined)
state.transparency = update.transparency;
if (update.substance !== undefined)
state.substance = update.substance;
if (update.clipping !== undefined)
state.clipping = update.clipping;
if (update.syncManually !== undefined)
state.syncManually = update.syncManually;
if (update.transform !== undefined)
Mat4.copy(state.transform, update.transform);
if (update.markerActions !== undefined)
state.markerActions = update.markerActions;
}
Representation.updateState = updateState;
Representation.StateBuilder = { create: createState, update: updateState };
Representation.Empty = {
label: '', groupCount: 0, renderObjects: [], geometryVersion: -1, props: {}, params: {}, updated: new Subject(), state: createState(), theme: Theme.createEmpty(),
createOrUpdate: function () { return Task.constant('', undefined); },
setState: function () { },
setTheme: function () { },
getLoci: function () { return EmptyLoci; },
getAllLoci: function () { return []; },
mark: function () { return false; },
destroy: function () { }
};
var GeometryState = /** @class */ (function () {
function GeometryState() {
this.curr = new Set();
this.next = new Set();
this._version = -1;
}
Object.defineProperty(GeometryState.prototype, "version", {
get: function () {
return this._version;
},
enumerable: false,
configurable: true
});
GeometryState.prototype.add = function (id, version) {
this.next.add(cantorPairing(id, version));
};
GeometryState.prototype.snapshot = function () {
var _a;
if (!SetUtils.areEqual(this.curr, this.next)) {
this._version += 1;
}
_a = [this.next, this.curr], this.curr = _a[0], this.next = _a[1];
this.next.clear();
};
return GeometryState;
}());
Representation.GeometryState = GeometryState;
function createMulti(label, ctx, getParams, stateBuilder, reprDefs) {
var _this = this;
var version = 0;
var updated = new Subject();
var geometryState = new GeometryState();
var currentState = stateBuilder.create();
var currentTheme = Theme.createEmpty();
var currentParams;
var currentProps;
var currentData;
var reprMap = {};
var reprList = Object.keys(reprDefs).map(function (name, i) {
reprMap[i] = name;
var repr = reprDefs[name](ctx, getParams);
repr.setState(currentState);
return repr;
});
return {
label: label,
updated: updated,
get groupCount() {
var groupCount = 0;
if (currentProps) {
var visuals = currentProps.visuals;
for (var i = 0, il = reprList.length; i < il; ++i) {
if (!visuals || visuals.includes(reprMap[i])) {
groupCount += reprList[i].groupCount;
}
}
}
return groupCount;
},
get renderObjects() {
var renderObjects = [];
if (currentProps) {
var visuals = currentProps.visuals;
for (var i = 0, il = reprList.length; i < il; ++i) {
if (!visuals || visuals.includes(reprMap[i])) {
renderObjects.push.apply(renderObjects, reprList[i].renderObjects);
}
}
}
return renderObjects;
},
get geometryVersion() { return geometryState.version; },
get props() { return currentProps; },
get params() { return currentParams; },
createOrUpdate: function (props, data) {
if (props === void 0) { props = {}; }
if (data && data !== currentData) {
currentParams = getParams(ctx, data);
currentData = data;
if (!currentProps)
currentProps = PD.getDefaultValues(currentParams);
}
var qualityProps = getQualityProps(Object.assign({}, currentProps, props), currentData);
Object.assign(currentProps, props, qualityProps);
var visuals = currentProps.visuals;
return Task.create("Creating or updating '".concat(label, "' representation"), function (runtime) { return __awaiter(_this, void 0, void 0, function () {
var i, il;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
i = 0, il = reprList.length;
_a.label = 1;
case 1:
if (!(i < il)) return [3 /*break*/, 5];
if (!(!visuals || visuals.includes(reprMap[i]))) return [3 /*break*/, 3];
return [4 /*yield*/, reprList[i].createOrUpdate(currentProps, currentData).runInContext(runtime)];
case 2:
_a.sent();
_a.label = 3;
case 3:
geometryState.add(i, reprList[i].geometryVersion);
_a.label = 4;
case 4:
++i;
return [3 /*break*/, 1];
case 5:
geometryState.snapshot();
updated.next(version++);
return [2 /*return*/];
}
});
}); });
},
get state() { return currentState; },
get theme() { return currentTheme; },
getLoci: function (pickingId) {
var visuals = currentProps.visuals;
for (var i = 0, il = reprList.length; i < il; ++i) {
if (!visuals || visuals.includes(reprMap[i])) {
var loci = reprList[i].getLoci(pickingId);
if (!isEmptyLoci(loci))
return loci;
}
}
return EmptyLoci;
},
getAllLoci: function () {
var loci = [];
var visuals = currentProps.visuals;
for (var i = 0, il = reprList.length; i < il; ++i) {
if (!visuals || visuals.includes(reprMap[i])) {
loci.push.apply(loci, reprList[i].getAllLoci());
}
}
return loci;
},
mark: function (loci, action) {
var marked = false;
for (var i = 0, il = reprList.length; i < il; ++i) {
marked = reprList[i].mark(loci, action) || marked;
}
return marked;
},
setState: function (state) {
stateBuilder.update(currentState, state);
for (var i = 0, il = reprList.length; i < il; ++i) {
reprList[i].setState(state); // only set the new (partial) state
}
},
setTheme: function (theme) {
currentTheme = theme;
for (var i = 0, il = reprList.length; i < il; ++i) {
reprList[i].setTheme(theme);
}
},
destroy: function () {
for (var i = 0, il = reprList.length; i < il; ++i) {
reprList[i].destroy();
}
}
};
}
Representation.createMulti = createMulti;
function fromRenderObject(label, renderObject) {
var _this = this;
var version = 0;
var updated = new Subject();
var geometryState = new GeometryState();
var currentState = Representation.createState();
var currentTheme = Theme.createEmpty();
var currentParams = PD.clone(BaseGeometry.Params);
var currentProps = PD.getDefaultValues(BaseGeometry.Params);
return {
label: label,
updated: updated,
get groupCount() { return renderObject.values.uGroupCount.ref.value; },
get renderObjects() { return [renderObject]; },
get geometryVersion() { return geometryState.version; },
get props() { return currentProps; },
get params() { return currentParams; },
createOrUpdate: function (props) {
if (props === void 0) { props = {}; }
var qualityProps = getQualityProps(Object.assign({}, currentProps, props));
Object.assign(currentProps, props, qualityProps);
return Task.create("Updating '".concat(label, "' representation"), function (runtime) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
// TODO
geometryState.add(0, renderObject.id);
geometryState.snapshot();
updated.next(version++);
return [2 /*return*/];
});
}); });
},
get state() { return currentState; },
get theme() { return currentTheme; },
getLoci: function () {
// TODO
return EmptyLoci;
},
getAllLoci: function () {
// TODO
return [];
},
mark: function (loci, action) {
// TODO
return false;
},
setState: function (state) {
if (state.visible !== undefined)
Visual.setVisibility(renderObject, state.visible);
if (state.alphaFactor !== undefined)
Visual.setAlphaFactor(renderObject, state.alphaFactor);
if (state.pickable !== undefined)
Visual.setPickable(renderObject, state.pickable);
if (state.colorOnly !== undefined)
Visual.setColorOnly(renderObject, state.colorOnly);
if (state.overpaint !== undefined) {
// TODO
}
if (state.transparency !== undefined) {
// TODO
}
if (state.substance !== undefined) {
// TODO
}
if (state.transform !== undefined)
Visual.setTransform(renderObject, state.transform);
Representation.updateState(currentState, state);
},
setTheme: function () { },
destroy: function () { }
};
}
Representation.fromRenderObject = fromRenderObject;
})(Representation || (Representation = {}));