UNPKG

molstar

Version:

A comprehensive macromolecular library.

387 lines (386 loc) 21 kB
"use strict"; /** * Copyright (c) 2018-2024 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.Visual = void 0; const loci_1 = require("../mol-model/loci"); const marker_action_1 = require("../mol-util/marker-action"); const linear_algebra_1 = require("../mol-math/linear-algebra"); const transform_data_1 = require("../mol-geo/geometry/transform-data"); const util_1 = require("../mol-gl/renderable/util"); const mol_util_1 = require("../mol-util"); const overpaint_data_1 = require("../mol-geo/geometry/overpaint-data"); const int_1 = require("../mol-data/int"); const transparency_data_1 = require("../mol-geo/geometry/transparency-data"); const clipping_data_1 = require("../mol-geo/geometry/clipping-data"); const marker_data_1 = require("../mol-geo/geometry/marker-data"); const base_1 = require("../mol-geo/geometry/base"); const color_smoothing_1 = require("../mol-geo/geometry/mesh/color-smoothing"); const color_smoothing_2 = require("../mol-geo/geometry/texture-mesh/color-smoothing"); const substance_data_1 = require("../mol-geo/geometry/substance-data"); const emissive_data_1 = require("../mol-geo/geometry/emissive-data"); var Visual; (function (Visual) { function setVisibility(renderObject, visible) { if (renderObject) renderObject.state.visible = visible; } Visual.setVisibility = setVisibility; function setAlphaFactor(renderObject, alphaFactor) { if (renderObject) renderObject.state.alphaFactor = alphaFactor; } Visual.setAlphaFactor = setAlphaFactor; function setPickable(renderObject, pickable) { if (renderObject) renderObject.state.pickable = pickable; } Visual.setPickable = setPickable; function setColorOnly(renderObject, colorOnly) { if (renderObject) renderObject.state.colorOnly = colorOnly; } Visual.setColorOnly = setColorOnly; function mark(renderObject, loci, action, lociApply, previous) { if (!renderObject || (0, loci_1.isEmptyLoci)(loci)) return false; const { tMarker, uMarker, markerAverage, markerStatus, uGroupCount, instanceCount, instanceGranularity: instanceGranularity } = renderObject.values; const count = instanceGranularity.ref.value ? instanceCount.ref.value : uGroupCount.ref.value * instanceCount.ref.value; const { array } = tMarker.ref.value; const currentStatus = markerStatus.ref.value; if (!(0, loci_1.isEveryLoci)(loci)) { // assume that all interval are non-overlapping let intervalSize = 0; lociApply(loci, interval => { intervalSize += int_1.Interval.size(interval); return true; }, true); if (intervalSize === 0) return false; if (intervalSize === count) loci = loci_1.EveryLoci; } let changed = false; let average = -1; let status = -1; if ((0, loci_1.isEveryLoci)(loci)) { const info = (0, marker_action_1.getMarkerInfo)(action, currentStatus); if (info.status !== -1) { changed = currentStatus !== info.status; if (changed) (0, marker_action_1.setMarkerValue)(array, info.status, count); } else { changed = (0, marker_action_1.applyMarkerAction)(array, int_1.Interval.ofLength(count), action); } average = info.average; status = info.status; } else { changed = lociApply(loci, interval => (0, marker_action_1.applyMarkerAction)(array, interval, action), true); if (changed) { average = (0, marker_action_1.getPartialMarkerAverage)(action, currentStatus); if (previous && previous.status !== -1 && average === -1 && marker_action_1.MarkerActions.isReverse(previous.action, action) && loci_1.Loci.areEqual(loci, previous.loci)) { status = previous.status; average = status === 0 ? 0 : 0.5; } } } if (changed) { if (average === -1) { average = (0, marker_data_1.getMarkersAverage)(array, count); if (average === 0) status = 0; } if (previous) { previous.action = action; previous.loci = loci; previous.status = currentStatus; } mol_util_1.ValueCell.updateIfChanged(uMarker, status); if (status === -1) mol_util_1.ValueCell.update(tMarker, tMarker.ref.value); mol_util_1.ValueCell.updateIfChanged(markerAverage, average); mol_util_1.ValueCell.updateIfChanged(markerStatus, status); } return changed; } Visual.mark = mark; function setOverpaint(renderObject, overpaint, lociApply, clear, smoothing) { if (!renderObject) return; const { tOverpaint, dOverpaintType, dOverpaint, uGroupCount, instanceCount, instanceGranularity: instanceGranularity } = renderObject.values; const count = instanceGranularity.ref.value ? instanceCount.ref.value : uGroupCount.ref.value * instanceCount.ref.value; // ensure texture has right size and type const type = instanceGranularity.ref.value ? 'instance' : 'groupInstance'; (0, overpaint_data_1.createOverpaint)(overpaint.layers.length ? count : 0, type, renderObject.values); const { array } = tOverpaint.ref.value; // clear all if requested if (clear) (0, overpaint_data_1.clearOverpaint)(array, 0, count); for (let i = 0, il = overpaint.layers.length; i < il; ++i) { const { loci, color, clear } = overpaint.layers[i]; const apply = (interval) => { const start = int_1.Interval.start(interval); const end = int_1.Interval.end(interval); return clear ? (0, overpaint_data_1.clearOverpaint)(array, start, end) : (0, overpaint_data_1.applyOverpaintColor)(array, start, end, color); }; lociApply(loci, apply, false); } mol_util_1.ValueCell.update(tOverpaint, tOverpaint.ref.value); mol_util_1.ValueCell.updateIfChanged(dOverpaintType, type); mol_util_1.ValueCell.updateIfChanged(dOverpaint, overpaint.layers.length > 0); if (overpaint.layers.length === 0) return; if (type === 'instance') return; if (smoothing && (0, base_1.hasColorSmoothingProp)(smoothing.props)) { const { geometry, props, webgl } = smoothing; if (geometry.kind === 'mesh') { const { resolution, overpaintTexture } = geometry.meta; const csp = (0, base_1.getColorSmoothingProps)(props.smoothColors, true, resolution); if (csp) { (0, color_smoothing_1.applyMeshOverpaintSmoothing)(renderObject.values, csp.resolution, csp.stride, webgl, overpaintTexture); geometry.meta.overpaintTexture = renderObject.values.tOverpaintGrid.ref.value; } } else if (webgl && geometry.kind === 'texture-mesh') { const { resolution, overpaintTexture } = geometry.meta; const csp = (0, base_1.getColorSmoothingProps)(props.smoothColors, true, resolution); if (csp) { (0, color_smoothing_2.applyTextureMeshOverpaintSmoothing)(renderObject.values, csp.resolution, csp.stride, webgl, overpaintTexture); geometry.meta.overpaintTexture = renderObject.values.tOverpaintGrid.ref.value; } } } } Visual.setOverpaint = setOverpaint; function setTransparency(renderObject, transparency, lociApply, clear, smoothing) { if (!renderObject) return; const { tTransparency, dTransparencyType, transparencyAverage, transparencyMin, dTransparency, uGroupCount, instanceCount, instanceGranularity: instanceGranularity } = renderObject.values; const count = instanceGranularity.ref.value ? instanceCount.ref.value : uGroupCount.ref.value * instanceCount.ref.value; // ensure texture has right size and type const type = instanceGranularity.ref.value ? 'instance' : 'groupInstance'; (0, transparency_data_1.createTransparency)(transparency.layers.length ? count : 0, type, renderObject.values); const { array } = tTransparency.ref.value; // clear if requested if (clear) (0, transparency_data_1.clearTransparency)(array, 0, count); for (let i = 0, il = transparency.layers.length; i < il; ++i) { const { loci, value } = transparency.layers[i]; const apply = (interval) => { const start = int_1.Interval.start(interval); const end = int_1.Interval.end(interval); return (0, transparency_data_1.applyTransparencyValue)(array, start, end, value); }; lociApply(loci, apply, false); } mol_util_1.ValueCell.update(tTransparency, tTransparency.ref.value); mol_util_1.ValueCell.updateIfChanged(transparencyAverage, (0, transparency_data_1.getTransparencyAverage)(array, count)); mol_util_1.ValueCell.updateIfChanged(transparencyMin, (0, transparency_data_1.getTransparencyMin)(array, count)); mol_util_1.ValueCell.updateIfChanged(dTransparencyType, type); mol_util_1.ValueCell.updateIfChanged(dTransparency, transparency.layers.length > 0); if (transparency.layers.length === 0) return; if (type === 'instance') return; if (smoothing && (0, base_1.hasColorSmoothingProp)(smoothing.props)) { const { geometry, props, webgl } = smoothing; if (geometry.kind === 'mesh') { const { resolution, transparencyTexture } = geometry.meta; const csp = (0, base_1.getColorSmoothingProps)(props.smoothColors, true, resolution); if (csp) { (0, color_smoothing_1.applyMeshTransparencySmoothing)(renderObject.values, csp.resolution, csp.stride, webgl, transparencyTexture); geometry.meta.transparencyTexture = renderObject.values.tTransparencyGrid.ref.value; } } else if (webgl && geometry.kind === 'texture-mesh') { const { resolution, transparencyTexture } = geometry.meta; const csp = (0, base_1.getColorSmoothingProps)(props.smoothColors, true, resolution); if (csp) { (0, color_smoothing_2.applyTextureMeshTransparencySmoothing)(renderObject.values, csp.resolution, csp.stride, webgl, transparencyTexture); geometry.meta.transparencyTexture = renderObject.values.tTransparencyGrid.ref.value; } } } } Visual.setTransparency = setTransparency; function setEmissive(renderObject, emissive, lociApply, clear, smoothing) { if (!renderObject) return; const { tEmissive, dEmissiveType, emissiveAverage, dEmissive, uGroupCount, instanceCount, instanceGranularity: instanceGranularity } = renderObject.values; const count = instanceGranularity.ref.value ? instanceCount.ref.value : uGroupCount.ref.value * instanceCount.ref.value; // ensure texture has right size and type const type = instanceGranularity.ref.value ? 'instance' : 'groupInstance'; (0, emissive_data_1.createEmissive)(emissive.layers.length ? count : 0, type, renderObject.values); const { array } = tEmissive.ref.value; // clear if requested if (clear) (0, emissive_data_1.clearEmissive)(array, 0, count); for (let i = 0, il = emissive.layers.length; i < il; ++i) { const { loci, value } = emissive.layers[i]; const apply = (interval) => { const start = int_1.Interval.start(interval); const end = int_1.Interval.end(interval); return (0, emissive_data_1.applyEmissiveValue)(array, start, end, value); }; lociApply(loci, apply, false); } mol_util_1.ValueCell.update(tEmissive, tEmissive.ref.value); mol_util_1.ValueCell.updateIfChanged(emissiveAverage, (0, emissive_data_1.getEmissiveAverage)(array, count)); mol_util_1.ValueCell.updateIfChanged(dEmissiveType, type); mol_util_1.ValueCell.updateIfChanged(dEmissive, emissive.layers.length > 0); if (emissive.layers.length === 0) return; if (type === 'instance') return; if (smoothing && (0, base_1.hasColorSmoothingProp)(smoothing.props)) { const { geometry, props, webgl } = smoothing; if (geometry.kind === 'mesh') { const { resolution, emissiveTexture } = geometry.meta; const csp = (0, base_1.getColorSmoothingProps)(props.smoothColors, true, resolution); if (csp) { (0, color_smoothing_1.applyMeshEmissiveSmoothing)(renderObject.values, csp.resolution, csp.stride, webgl, emissiveTexture); geometry.meta.emissiveTexture = renderObject.values.tEmissiveGrid.ref.value; } } else if (webgl && geometry.kind === 'texture-mesh') { const { resolution, emissiveTexture } = geometry.meta; const csp = (0, base_1.getColorSmoothingProps)(props.smoothColors, true, resolution); if (csp) { (0, color_smoothing_2.applyTextureMeshEmissiveSmoothing)(renderObject.values, csp.resolution, csp.stride, webgl, emissiveTexture); geometry.meta.emissiveTexture = renderObject.values.tEmissiveGrid.ref.value; } } } } Visual.setEmissive = setEmissive; function setSubstance(renderObject, substance, lociApply, clear, smoothing) { if (!renderObject) return; const { tSubstance, dSubstanceType, dSubstance, uGroupCount, instanceCount, instanceGranularity: instanceGranularity } = renderObject.values; const count = instanceGranularity.ref.value ? instanceCount.ref.value : uGroupCount.ref.value * instanceCount.ref.value; // ensure texture has right size and type const type = instanceGranularity.ref.value ? 'instance' : 'groupInstance'; (0, substance_data_1.createSubstance)(substance.layers.length ? count : 0, type, renderObject.values); const { array } = tSubstance.ref.value; // clear all if requested if (clear) (0, substance_data_1.clearSubstance)(array, 0, count); for (let i = 0, il = substance.layers.length; i < il; ++i) { const { loci, material, clear } = substance.layers[i]; const apply = (interval) => { const start = int_1.Interval.start(interval); const end = int_1.Interval.end(interval); return clear ? (0, substance_data_1.clearSubstance)(array, start, end) : (0, substance_data_1.applySubstanceMaterial)(array, start, end, material); }; lociApply(loci, apply, false); } mol_util_1.ValueCell.update(tSubstance, tSubstance.ref.value); mol_util_1.ValueCell.updateIfChanged(dSubstanceType, type); mol_util_1.ValueCell.updateIfChanged(dSubstance, substance.layers.length > 0); if (substance.layers.length === 0) return; if (type === 'instance') return; if (smoothing && (0, base_1.hasColorSmoothingProp)(smoothing.props)) { const { geometry, props, webgl } = smoothing; if (geometry.kind === 'mesh') { const { resolution, substanceTexture } = geometry.meta; const csp = (0, base_1.getColorSmoothingProps)(props.smoothColors, true, resolution); if (csp) { (0, color_smoothing_1.applyMeshSubstanceSmoothing)(renderObject.values, csp.resolution, csp.stride, webgl, substanceTexture); geometry.meta.substanceTexture = renderObject.values.tSubstanceGrid.ref.value; } } else if (webgl && geometry.kind === 'texture-mesh') { const { resolution, substanceTexture } = geometry.meta; const csp = (0, base_1.getColorSmoothingProps)(props.smoothColors, true, resolution); if (csp) { (0, color_smoothing_2.applyTextureMeshSubstanceSmoothing)(renderObject.values, csp.resolution, csp.stride, webgl, substanceTexture); geometry.meta.substanceTexture = renderObject.values.tSubstanceGrid.ref.value; } } } } Visual.setSubstance = setSubstance; function setClipping(renderObject, clipping, lociApply, clear) { if (!renderObject) return; const { tClipping, dClippingType, dClipping, uGroupCount, instanceCount, instanceGranularity: instanceGranularity } = renderObject.values; const count = instanceGranularity.ref.value ? instanceCount.ref.value : uGroupCount.ref.value * instanceCount.ref.value; const { layers } = clipping; // ensure texture has right size and type const type = instanceGranularity.ref.value ? 'instance' : 'groupInstance'; (0, clipping_data_1.createClipping)(layers.length ? count : 0, type, renderObject.values); const { array } = tClipping.ref.value; // clear if requested if (clear) (0, clipping_data_1.clearClipping)(array, 0, count); for (let i = 0, il = clipping.layers.length; i < il; ++i) { const { loci, groups } = clipping.layers[i]; const apply = (interval) => { const start = int_1.Interval.start(interval); const end = int_1.Interval.end(interval); return (0, clipping_data_1.applyClippingGroups)(array, start, end, groups); }; lociApply(loci, apply, false); } mol_util_1.ValueCell.update(tClipping, tClipping.ref.value); mol_util_1.ValueCell.updateIfChanged(dClippingType, type); mol_util_1.ValueCell.updateIfChanged(dClipping, clipping.layers.length > 0); } Visual.setClipping = setClipping; function setThemeStrength(renderObject, strength) { if (renderObject) { mol_util_1.ValueCell.updateIfChanged(renderObject.values.uOverpaintStrength, strength.overpaint); mol_util_1.ValueCell.updateIfChanged(renderObject.values.uTransparencyStrength, strength.transparency); mol_util_1.ValueCell.updateIfChanged(renderObject.values.uEmissiveStrength, strength.emissive); mol_util_1.ValueCell.updateIfChanged(renderObject.values.uSubstanceStrength, strength.substance); } } Visual.setThemeStrength = setThemeStrength; function setTransform(renderObject, transform, instanceTransforms) { if (!renderObject || (!transform && !instanceTransforms)) return; const { values } = renderObject; if (transform) { linear_algebra_1.Mat4.copy(values.matrix.ref.value, transform); mol_util_1.ValueCell.update(values.matrix, values.matrix.ref.value); } if (instanceTransforms) { values.extraTransform.ref.value.set(instanceTransforms); mol_util_1.ValueCell.update(values.extraTransform, values.extraTransform.ref.value); } else if (instanceTransforms === null) { (0, transform_data_1.fillIdentityTransform)(values.extraTransform.ref.value, values.instanceCount.ref.value); mol_util_1.ValueCell.update(values.extraTransform, values.extraTransform.ref.value); } (0, transform_data_1.updateTransformData)(values, values.invariantBoundingSphere.ref.value, values.instanceGrid.ref.value.cellSize, values.instanceGrid.ref.value.batchSize); const boundingSphere = (0, util_1.calculateTransformBoundingSphere)(values.invariantBoundingSphere.ref.value, values.transform.ref.value, values.instanceCount.ref.value, 0); mol_util_1.ValueCell.update(values.boundingSphere, boundingSphere); } Visual.setTransform = setTransform; })(Visual || (exports.Visual = Visual = {}));