diff --git a/src/mol-geo/geometry/color-data.ts b/src/mol-geo/geometry/color-data.ts index 59c2a16686bd0a4a97ee1e3877f51995965482c4..d9d798acc569fbbace36806b517015e0690e11fd 100644 --- a/src/mol-geo/geometry/color-data.ts +++ b/src/mol-geo/geometry/color-data.ts @@ -56,8 +56,7 @@ export function getColorThemeProps(props: ColorProps): ColorThemeProps { return p } -export function createColors(ctx: RuntimeContext, locationIt: LocationIterator, props: ColorProps, colorData?: ColorData): Promise<ColorData> { - const colorTheme = ColorTheme(getColorThemeProps(props)) +export function createColors(ctx: RuntimeContext, locationIt: LocationIterator, colorTheme: ColorTheme, colorData?: ColorData): Promise<ColorData> { switch (getGranularity(locationIt, colorTheme.granularity)) { case 'uniform': return createUniformColor(ctx, locationIt, colorTheme.color, colorData) case 'group': return createGroupColor(ctx, locationIt, colorTheme.color, colorData) diff --git a/src/mol-geo/geometry/direct-volume/direct-volume.ts b/src/mol-geo/geometry/direct-volume/direct-volume.ts index d0057084b5b420b0f566401997c5720349bfe551..3298b5844fcae22569416801ad6f9eb68b0a3a4b 100644 --- a/src/mol-geo/geometry/direct-volume/direct-volume.ts +++ b/src/mol-geo/geometry/direct-volume/direct-volume.ts @@ -17,7 +17,7 @@ import { LocationIterator } from 'mol-geo/util/location-iterator'; import { TransformData } from '../transform-data'; import { createColors } from '../color-data'; import { createMarkers } from '../marker-data'; -import { Geometry } from '../geometry'; +import { Geometry, Theme } from '../geometry'; const VolumeBox = Box() const RenderModeOptions = [['isosurface', 'Isosurface'], ['volume', 'Volume']] as [string, string][] @@ -75,11 +75,11 @@ export namespace DirectVolume { export const DefaultProps = paramDefaultValues(Params) export type Props = typeof DefaultProps - export async function createValues(ctx: RuntimeContext, directVolume: DirectVolume, transform: TransformData, locationIt: LocationIterator, props: Props): Promise<DirectVolumeValues> { + export async function createValues(ctx: RuntimeContext, directVolume: DirectVolume, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: Props): Promise<DirectVolumeValues> { const { gridTexture, gridTextureDim } = directVolume const { instanceCount, groupCount } = locationIt - const color = await createColors(ctx, locationIt, props) + const color = await createColors(ctx, locationIt, theme.color) const marker = createMarkers(instanceCount * groupCount) const counts = { drawCount: VolumeBox.indices.length, groupCount, instanceCount } diff --git a/src/mol-geo/geometry/geometry.ts b/src/mol-geo/geometry/geometry.ts index 57df5ab488d3f3c0d6f006ca8a4cf15223d8de6a..726559e397d5869675c6c05bf0b43209da7fdd8a 100644 --- a/src/mol-geo/geometry/geometry.ts +++ b/src/mol-geo/geometry/geometry.ts @@ -10,13 +10,14 @@ import { RenderableState } from 'mol-gl/renderable'; import { ValueCell } from 'mol-util'; import { BaseValues } from 'mol-gl/renderable/schema'; import { Color } from 'mol-util/color'; -import { ColorThemeOptions, ColorThemeName, ColorScaleOptions, ColorScaleName } from 'mol-theme/color'; +import { ColorThemeOptions, ColorThemeName, ColorScaleOptions, ColorScaleName, ColorTheme } from 'mol-theme/color'; import { LocationIterator } from '../util/location-iterator'; -import { ColorType } from './color-data'; -import { SizeType } from './size-data'; +import { ColorType, getColorThemeProps } from './color-data'; +import { SizeType, getSizeThemeProps } from './size-data'; import { Lines } from './lines/lines'; -import { paramDefaultValues, RangeParam, BooleanParam, SelectParam, ColorParam } from 'mol-util/parameter' +import { paramDefaultValues, RangeParam, BooleanParam, SelectParam, ColorParam, NumberParam } from 'mol-util/parameter' import { DirectVolume } from './direct-volume/direct-volume'; +import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; // @@ -35,6 +36,18 @@ export type VisualQuality = keyof typeof VisualQualityInfo export const VisualQualityNames = Object.keys(VisualQualityInfo) export const VisualQualityOptions = VisualQualityNames.map(n => [n, n] as [VisualQuality, string]) +export interface Theme { + color: ColorTheme + size: SizeTheme +} + +export function createTheme(props: Geometry.Props) { + return { + color: ColorTheme(getColorThemeProps(props)), + size: SizeTheme(getSizeThemeProps(props)) + } +} + // export type GeometryKindType = { @@ -64,9 +77,14 @@ export namespace Geometry { depthMask: BooleanParam('Depth Mask', '', true), useFog: BooleanParam('Use Fog', '', false), quality: SelectParam<VisualQuality>('Quality', '', 'auto', VisualQualityOptions), + colorTheme: SelectParam<ColorThemeName>('Color Theme', '', 'uniform', ColorThemeOptions), colorList: SelectParam<ColorScaleName>('Color Scale', '', 'default', ColorScaleOptions), colorValue: ColorParam('Color Value', '', Color(0xCCCCCC)), + + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1), } export const DefaultProps = paramDefaultValues(Params) export type Props = typeof DefaultProps diff --git a/src/mol-geo/geometry/lines/lines.ts b/src/mol-geo/geometry/lines/lines.ts index a6a7c83bdc6ee1dbe93029beb6c53dfc8800ded7..4df72d393ee0f53e8b380bedb955f4f6510cf8ed 100644 --- a/src/mol-geo/geometry/lines/lines.ts +++ b/src/mol-geo/geometry/lines/lines.ts @@ -7,18 +7,17 @@ import { ValueCell } from 'mol-util' import { Mat4 } from 'mol-math/linear-algebra' import { transformPositionArray/* , transformDirectionArray, getNormalMatrix */ } from '../../util'; -import { Geometry } from '../geometry'; +import { Geometry, Theme } from '../geometry'; import { RuntimeContext } from 'mol-task'; import { createColors } from '../color-data'; import { createMarkers } from '../marker-data'; import { createSizes } from '../size-data'; import { TransformData } from '../transform-data'; import { LocationIterator } from '../../util/location-iterator'; -import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; import { LinesValues } from 'mol-gl/renderable/lines'; import { Mesh } from '../mesh/mesh'; import { LinesBuilder } from './lines-builder'; -import { BooleanParam, SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter'; +import { BooleanParam, paramDefaultValues } from 'mol-util/parameter'; /** Wide line */ export interface Lines { @@ -94,17 +93,14 @@ export namespace Lines { export const Params = { ...Geometry.Params, lineSizeAttenuation: BooleanParam('Line Size Attenuation', '', false), - sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), - sizeValue: NumberParam('Size Value', '', 1, 0, 10, 0.1), - sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1), } export const DefaultProps = paramDefaultValues(Params) export type Props = typeof DefaultProps - export async function createValues(ctx: RuntimeContext, lines: Lines, transform: TransformData, locationIt: LocationIterator, props: Props): Promise<LinesValues> { + export async function createValues(ctx: RuntimeContext, lines: Lines, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: Props): Promise<LinesValues> { const { instanceCount, groupCount } = locationIt - const color = await createColors(ctx, locationIt, props) - const size = await createSizes(ctx, locationIt, props) + const color = await createColors(ctx, locationIt, theme.color) + const size = await createSizes(ctx, locationIt, theme.size) const marker = createMarkers(instanceCount * groupCount) const counts = { drawCount: lines.lineCount * 2 * 3, groupCount, instanceCount } diff --git a/src/mol-geo/geometry/mesh/mesh.ts b/src/mol-geo/geometry/mesh/mesh.ts index 14a204f9c3039dea431a09522aa3ebf47efe80cc..43a67d7aa38dcbed415f35cc370b63759677aca9 100644 --- a/src/mol-geo/geometry/mesh/mesh.ts +++ b/src/mol-geo/geometry/mesh/mesh.ts @@ -10,7 +10,7 @@ import { Vec3, Mat4 } from 'mol-math/linear-algebra' import { Sphere3D } from 'mol-math/geometry' import { transformPositionArray/* , transformDirectionArray, getNormalMatrix */ } from '../../util'; import { MeshValues } from 'mol-gl/renderable'; -import { Geometry } from '../geometry'; +import { Geometry, Theme } from '../geometry'; import { createMarkers } from '../marker-data'; import { TransformData } from '../transform-data'; import { LocationIterator } from '../../util/location-iterator'; @@ -346,9 +346,9 @@ export namespace Mesh { export const DefaultProps = paramDefaultValues(Params) export type Props = typeof DefaultProps - export async function createValues(ctx: RuntimeContext, mesh: Mesh, transform: TransformData, locationIt: LocationIterator, props: Props): Promise<MeshValues> { + export async function createValues(ctx: RuntimeContext, mesh: Mesh, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: Props): Promise<MeshValues> { const { instanceCount, groupCount } = locationIt - const color = await createColors(ctx, locationIt, props) + const color = await createColors(ctx, locationIt, theme.color) const marker = createMarkers(instanceCount * groupCount) const counts = { drawCount: mesh.triangleCount * 3, groupCount, instanceCount } diff --git a/src/mol-geo/geometry/points/points.ts b/src/mol-geo/geometry/points/points.ts index 277528b60d91f2134461ed0662461eab2ebf46d9..0378f0a10b9aee2a4ecdd7dfcbf135a0481dd12c 100644 --- a/src/mol-geo/geometry/points/points.ts +++ b/src/mol-geo/geometry/points/points.ts @@ -7,7 +7,7 @@ import { ValueCell } from 'mol-util' import { Mat4 } from 'mol-math/linear-algebra' import { transformPositionArray/* , transformDirectionArray, getNormalMatrix */ } from '../../util'; -import { Geometry } from '../geometry'; +import { Geometry, Theme } from '../geometry'; import { PointsValues } from 'mol-gl/renderable'; import { RuntimeContext } from 'mol-task'; import { createColors } from '../color-data'; @@ -15,8 +15,7 @@ import { createMarkers } from '../marker-data'; import { createSizes } from '../size-data'; import { TransformData } from '../transform-data'; import { LocationIterator } from '../../util/location-iterator'; -import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; -import { BooleanParam, NumberParam, SelectParam, paramDefaultValues } from 'mol-util/parameter'; +import { BooleanParam, NumberParam, paramDefaultValues } from 'mol-util/parameter'; /** Point cloud */ export interface Points { @@ -58,17 +57,14 @@ export namespace Points { pointSizeAttenuation: BooleanParam('Point Size Attenuation', '', false), pointFilledCircle: BooleanParam('Point Filled Circle', '', false), pointEdgeBleach: NumberParam('Point Edge Bleach', '', 0.2, 0, 1, 0.05), - sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), - sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), - sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1), } export const DefaultProps = paramDefaultValues(Params) export type Props = typeof DefaultProps - export async function createValues(ctx: RuntimeContext, points: Points, transform: TransformData, locationIt: LocationIterator, props: Props): Promise<PointsValues> { + export async function createValues(ctx: RuntimeContext, points: Points, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: Props): Promise<PointsValues> { const { instanceCount, groupCount } = locationIt - const color = await createColors(ctx, locationIt, props) - const size = await createSizes(ctx, locationIt, props) + const color = await createColors(ctx, locationIt, theme.color) + const size = await createSizes(ctx, locationIt, theme.size) const marker = createMarkers(instanceCount * groupCount) const counts = { drawCount: points.pointCount, groupCount, instanceCount } diff --git a/src/mol-geo/geometry/size-data.ts b/src/mol-geo/geometry/size-data.ts index 7c7ab279493648eb0aa05f5fa7ac184d31c4b387..06cdcef0c6d48ef6d47a333bf9fc58edb3eb14c1 100644 --- a/src/mol-geo/geometry/size-data.ts +++ b/src/mol-geo/geometry/size-data.ts @@ -40,8 +40,7 @@ export function getSizeThemeProps(props: SizeProps): SizeThemeProps { } } -export async function createSizes(ctx: RuntimeContext, locationIt: LocationIterator, props: SizeProps, sizeData?: SizeData): Promise<SizeData> { - const sizeTheme = SizeTheme(getSizeThemeProps(props)) +export async function createSizes(ctx: RuntimeContext, locationIt: LocationIterator, sizeTheme: SizeTheme, sizeData?: SizeData): Promise<SizeData> { switch (getGranularity(locationIt, sizeTheme.granularity)) { case 'uniform': return createUniformSize(ctx, locationIt, sizeTheme.size, sizeData) case 'group': return createGroupSize(ctx, locationIt, sizeTheme.size, sizeData) diff --git a/src/mol-repr/index.ts b/src/mol-repr/index.ts index a293cf595c352db3bd053bf82228a0e3080f8be6..d1489c425880512b642492275e0c42c974d78573 100644 --- a/src/mol-repr/index.ts +++ b/src/mol-repr/index.ts @@ -11,6 +11,8 @@ import { Loci, isEmptyLoci, EmptyLoci } from 'mol-model/loci'; import { MarkerAction } from '../mol-geo/geometry/marker-data'; import { Params, MultiSelectParam } from 'mol-util/parameter'; import { WebGLContext } from 'mol-gl/webgl/context'; +import { getQualityProps } from './util'; +import { Theme } from 'mol-geo/geometry/geometry'; // import { ColorTheme } from 'mol-theme/color'; // export interface RepresentationProps { @@ -68,9 +70,8 @@ export namespace Representation { }, createOrUpdate: (ctx: RepresentationContext, props: Partial<P> = {}, data?: D) => { if (data) currentData = data - // const qualityProps = getQualityProps(Object.assign({}, currentProps, props), structure) - // currentProps = Object.assign({}, DefaultCartoonProps, currentProps, props, qualityProps) - currentProps = Object.assign({}, defaultProps, currentProps, props) + const qualityProps = getQualityProps(Object.assign({}, currentProps, props), data) + currentProps = Object.assign({}, defaultProps, currentProps, props, qualityProps) const { visuals } = currentProps return Task.create(`Creating '${label}' representation`, async runtime => { @@ -108,13 +109,11 @@ export namespace Representation { export interface VisualContext extends RepresentationContext { runtime: RuntimeContext, - // TODO - // colorTheme: ColorTheme, } export interface Visual<D, P extends RepresentationProps> { readonly renderObject: RenderObject | undefined - createOrUpdate: (ctx: VisualContext, props?: Partial<P>, data?: D) => Promise<void> + createOrUpdate: (ctx: VisualContext, theme: Theme, props?: Partial<P>, data?: D) => Promise<void> getLoci: (pickingId: PickingId) => Loci mark: (loci: Loci, action: MarkerAction) => boolean destroy: () => void diff --git a/src/mol-repr/shape/index.ts b/src/mol-repr/shape/index.ts index 209f2b2aa6142cb2c2d2fda564ab3cee6ea346d8..6923e6dee64e2008f5080d82ec07edb6a94f7fb9 100644 --- a/src/mol-repr/shape/index.ts +++ b/src/mol-repr/shape/index.ts @@ -15,7 +15,7 @@ import { OrderedSet, Interval } from 'mol-data/int'; import { paramDefaultValues, SelectParam } from 'mol-util/parameter'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { createIdentityTransform } from 'mol-geo/geometry/transform-data'; -import { createRenderableState } from 'mol-geo/geometry/geometry'; +import { createRenderableState, createTheme } from 'mol-geo/geometry/geometry'; import { PickingId } from 'mol-geo/geometry/picking'; import { MarkerAction, applyMarkerAction } from 'mol-geo/geometry/marker-data'; import { LocationIterator } from 'mol-geo/util/location-iterator'; @@ -49,9 +49,10 @@ export function ShapeRepresentation<P extends ShapeProps>(): ShapeRepresentation const mesh = _shape.mesh const locationIt = ShapeGroupIterator.fromShape(_shape) + const theme = createTheme(currentProps) const transform = createIdentityTransform() - const values = await Mesh.createValues(runtime, mesh, transform, locationIt, currentProps) + const values = await Mesh.createValues(runtime, mesh, transform, locationIt, theme, currentProps) const state = createRenderableState(currentProps) _renderObject = createMeshRenderObject(values, state) diff --git a/src/mol-repr/structure/complex-representation.ts b/src/mol-repr/structure/complex-representation.ts index 62d828bb2c0d8b783c8c87dd58c21dd1eaefe374..58529f5dd1b6c43a45a5ace7b7f01a0544052ea2 100644 --- a/src/mol-repr/structure/complex-representation.ts +++ b/src/mol-repr/structure/complex-representation.ts @@ -13,17 +13,22 @@ import { ComplexVisual } from './complex-visual'; import { PickingId } from 'mol-geo/geometry/picking'; import { MarkerAction } from 'mol-geo/geometry/marker-data'; import { RepresentationContext } from 'mol-repr'; +import { createTheme, Theme } from 'mol-geo/geometry/geometry'; export function ComplexRepresentation<P extends StructureProps>(label: string, visualCtor: () => ComplexVisual<P>): StructureRepresentation<P> { let visual: ComplexVisual<P> | undefined + let _structure: Structure let _props: P + let _theme: Theme function createOrUpdate(ctx: RepresentationContext, props: Partial<P> = {}, structure?: Structure) { - _props = Object.assign({}, _props, props) + if (structure) _structure = structure + _props = Object.assign({}, _props, props, { structure: _structure }) + _theme = createTheme(_props) return Task.create('Creating or updating ComplexRepresentation', async runtime => { if (!visual) visual = visualCtor() - await visual.createOrUpdate({ ...ctx, runtime }, _props, structure) + await visual.createOrUpdate({ ...ctx, runtime }, _theme, _props, structure) }); } diff --git a/src/mol-repr/structure/complex-visual.ts b/src/mol-repr/structure/complex-visual.ts index 78856279772da9b6c2be60afd55140b69b9be298..740c4ddc32ee274ae5b00abeaa75bf4c55ebc947 100644 --- a/src/mol-repr/structure/complex-visual.ts +++ b/src/mol-repr/structure/complex-visual.ts @@ -15,7 +15,7 @@ import { Interval } from 'mol-data/int'; import { MultiSelectParam, paramDefaultValues } from 'mol-util/parameter'; import { RenderableValues } from 'mol-gl/renderable/schema'; import { createSizes } from 'mol-geo/geometry/size-data'; -import { Geometry, updateRenderableState } from 'mol-geo/geometry/geometry'; +import { Geometry, updateRenderableState, Theme } from 'mol-geo/geometry/geometry'; import { LocationIterator } from 'mol-geo/util/location-iterator'; import { PickingId } from 'mol-geo/geometry/picking'; import { createColors } from 'mol-geo/geometry/color-data'; @@ -36,7 +36,7 @@ type ComplexRenderObject = MeshRenderObject | LinesRenderObject | PointsRenderOb interface ComplexVisualBuilder<P extends ComplexProps, G extends Geometry> { defaultProps: P - createGeometry(ctx: VisualContext, structure: Structure, props: P, geometry?: G): Promise<G> + createGeometry(ctx: VisualContext, structure: Structure, theme: Theme, props: P, geometry?: G): Promise<G> createLocationIterator(structure: Structure): LocationIterator getLoci(pickingId: PickingId, structure: Structure, id: number): Loci mark(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean): boolean, @@ -45,7 +45,7 @@ interface ComplexVisualBuilder<P extends ComplexProps, G extends Geometry> { interface ComplexVisualGeometryBuilder<P extends ComplexProps, G extends Geometry> extends ComplexVisualBuilder<P, G> { createEmptyGeometry(geometry?: G): G - createRenderObject(ctx: VisualContext, structure: Structure, geometry: Geometry, locationIt: LocationIterator, currentProps: P): Promise<ComplexRenderObject> + createRenderObject(ctx: VisualContext, structure: Structure, geometry: Geometry, locationIt: LocationIterator, theme: Theme, currentProps: P): Promise<ComplexRenderObject> updateValues(values: RenderableValues, newProps: P): void } @@ -61,18 +61,18 @@ export function ComplexVisual<P extends ComplexMeshProps>(builder: ComplexVisual let locationIt: LocationIterator let conformationHash: number - async function create(ctx: VisualContext, structure: Structure, props: Partial<P> = {}) { - currentProps = Object.assign({}, defaultProps, props, { structure }) + async function create(ctx: VisualContext, structure: Structure, theme: Theme, props: Partial<P> = {}) { + currentProps = Object.assign({}, defaultProps, props) currentStructure = structure conformationHash = Structure.conformationHash(currentStructure) - geometry = await createGeometry(ctx, currentStructure, currentProps, geometry) + geometry = await createGeometry(ctx, currentStructure, theme, currentProps, geometry) locationIt = createLocationIterator(structure) - renderObject = await createRenderObject(ctx, structure, geometry, locationIt, currentProps) + renderObject = await createRenderObject(ctx, structure, geometry, locationIt, theme, currentProps) } - async function update(ctx: VisualContext, props: Partial<P>) { + async function update(ctx: VisualContext, theme: Theme, props: Partial<P>) { const newProps = Object.assign({}, currentProps, props, { structure: currentStructure }) if (!renderObject) return false @@ -93,7 +93,7 @@ export function ComplexVisual<P extends ComplexMeshProps>(builder: ComplexVisual // if (updateState.createGeometry) { - geometry = await createGeometry(ctx, currentStructure, newProps, geometry) + geometry = await createGeometry(ctx, currentStructure, theme, newProps, geometry) ValueCell.update(renderObject.values.drawCount, Geometry.getDrawCount(geometry)) updateState.updateColor = true } @@ -101,12 +101,12 @@ export function ComplexVisual<P extends ComplexMeshProps>(builder: ComplexVisual if (updateState.updateSize) { // not all geometries have size data, so check here if ('uSize' in renderObject.values) { - await createSizes(ctx.runtime, locationIt, newProps, renderObject.values) + await createSizes(ctx.runtime, locationIt, theme.size, renderObject.values) } } if (updateState.updateColor) { - await createColors(ctx.runtime, locationIt, newProps, renderObject.values) + await createColors(ctx.runtime, locationIt, theme.color, renderObject.values) } updateValues(renderObject.values, newProps) @@ -118,18 +118,18 @@ export function ComplexVisual<P extends ComplexMeshProps>(builder: ComplexVisual return { get renderObject () { return renderObject }, - async createOrUpdate(ctx: VisualContext, props: Partial<P> = {}, structure?: Structure) { + async createOrUpdate(ctx: VisualContext, theme: Theme, props: Partial<P> = {}, structure?: Structure) { if (!structure && !currentStructure) { throw new Error('missing structure') } else if (structure && (!currentStructure || !renderObject)) { - await create(ctx, structure, props) + await create(ctx, structure, theme, props) } else if (structure && structure.hashCode !== currentStructure.hashCode) { - await create(ctx, structure, props) + await create(ctx, structure, theme, props) } else { if (structure && Structure.conformationHash(structure) !== Structure.conformationHash(currentStructure)) { currentStructure = structure } - await update(ctx, props) + await update(ctx, theme, props) } }, getLoci(pickingId: PickingId) { diff --git a/src/mol-repr/structure/representation/cartoon.ts b/src/mol-repr/structure/representation/cartoon.ts index 6a4e48bb0ed2fb78aa0ff5397d36c414fd721389..56d577b86401e56ffa91146ba47496317934132b 100644 --- a/src/mol-repr/structure/representation/cartoon.ts +++ b/src/mol-repr/structure/representation/cartoon.ts @@ -12,17 +12,17 @@ import { paramDefaultValues, SelectParam, NumberParam } from 'mol-util/parameter import { UnitsRepresentation } from '../units-representation'; import { StructureRepresentation } from '../index'; import { Representation } from 'mol-repr'; -// import { PolymerDirectionVisual, DefaultPolymerDirectionProps } from '../visual/polymer-direction-wedge'; +import { PolymerDirectionVisual, PolymerDirectionParams } from '../visual/polymer-direction-wedge'; export const CartoonParams = { ...PolymerTraceParams, ...PolymerGapParams, ...NucleotideBlockParams, - // ...PolymerDirectionParams, + ...PolymerDirectionParams, sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), - sizeValue: NumberParam('Size Value', '', 0.6, 0, 10, 0.1), + sizeValue: NumberParam('Size Value', '', 0.2, 0, 10, 0.1), } -export const DefaultCartoonProps = paramDefaultValues(CartoonParams) +export const DefaultCartoonProps = { ...paramDefaultValues(CartoonParams), visuals: [ '0', '1', '2' ] } export type CartoonProps = typeof DefaultCartoonProps export type CartoonRepresentation = StructureRepresentation<CartoonProps> @@ -32,6 +32,6 @@ export function CartoonRepresentation(): CartoonRepresentation { UnitsRepresentation('Polymer trace mesh', PolymerTraceVisual), UnitsRepresentation('Polymer gap cylinder', PolymerGapVisual), UnitsRepresentation('Nucleotide block mesh', NucleotideBlockVisual), - // UnitsRepresentation('Polymer direction wedge', PolymerDirectionVisual) - ] as StructureRepresentation<CartoonProps>[]) + UnitsRepresentation('Polymer direction wedge', PolymerDirectionVisual) + ] as unknown as StructureRepresentation<CartoonProps>[]) // TODO avoid cast to unknown } \ No newline at end of file diff --git a/src/mol-repr/structure/units-representation.ts b/src/mol-repr/structure/units-representation.ts index 50e350f5cbef9a0c40fec28635278495f8fbc30e..0b419bc140e3a411bbc0c24c4aa5617ce4e4aaba 100644 --- a/src/mol-repr/structure/units-representation.ts +++ b/src/mol-repr/structure/units-representation.ts @@ -14,6 +14,7 @@ import { StructureGroup } from './units-visual'; import { StructureProps, StructureParams, StructureRepresentation } from './index'; import { PickingId } from 'mol-geo/geometry/picking'; import { MarkerAction } from 'mol-geo/geometry/marker-data'; +import { Theme, createTheme } from 'mol-geo/geometry/geometry'; export interface UnitsVisual<P extends RepresentationProps = {}> extends Visual<StructureGroup, P> { } @@ -21,11 +22,13 @@ export function UnitsRepresentation<P extends StructureProps>(label: string, vis let visuals = new Map<number, { group: Unit.SymmetryGroup, visual: UnitsVisual<P> }>() let _props: P + let _theme: Theme let _structure: Structure let _groups: ReadonlyArray<Unit.SymmetryGroup> function createOrUpdate(ctx: RepresentationContext, props: Partial<P> = {}, structure?: Structure) { - _props = Object.assign({}, _props, props) + _props = Object.assign({}, _props, props, { structure: structure || _structure }) + _theme = createTheme(_props) return Task.create('Creating or updating UnitsRepresentation', async runtime => { if (!_structure && !structure) { @@ -37,7 +40,7 @@ export function UnitsRepresentation<P extends StructureProps>(label: string, vis for (let i = 0; i < _groups.length; i++) { const group = _groups[i]; const visual = visualCtor() - await visual.createOrUpdate({ ...ctx, runtime }, _props, { group, structure }) + await visual.createOrUpdate({ ...ctx, runtime }, _theme, _props, { group, structure }) visuals.set(group.hashCode, { visual, group }) } } else if (structure && _structure.hashCode !== structure.hashCode) { @@ -53,13 +56,13 @@ export function UnitsRepresentation<P extends StructureProps>(label: string, vis const visualGroup = oldVisuals.get(group.hashCode) if (visualGroup) { const { visual } = visualGroup - await visual.createOrUpdate({ ...ctx, runtime }, _props, { group, structure }) + await visual.createOrUpdate({ ...ctx, runtime }, _theme, _props, { group, structure }) visuals.set(group.hashCode, { visual, group }) oldVisuals.delete(group.hashCode) } else { // newGroups.push(group) const visual = visualCtor() - await visual.createOrUpdate({ ...ctx, runtime }, _props, { group, structure }) + await visual.createOrUpdate({ ...ctx, runtime }, _theme, _props, { group, structure }) visuals.set(group.hashCode, { visual, group }) } } @@ -85,7 +88,7 @@ export function UnitsRepresentation<P extends StructureProps>(label: string, vis const group = _groups[i]; const visualGroup = visuals.get(group.hashCode) if (visualGroup) { - await visualGroup.visual.createOrUpdate({ ...ctx, runtime }, _props, { group, structure }) + await visualGroup.visual.createOrUpdate({ ...ctx, runtime }, _theme, _props, { group, structure }) visualGroup.group = group } else { throw new Error(`expected to find visual for hashCode ${group.hashCode}`) @@ -98,7 +101,7 @@ export function UnitsRepresentation<P extends StructureProps>(label: string, vis visuals.forEach(({ visual, group }) => visualsList.push([ visual, group ])) for (let i = 0, il = visualsList.length; i < il; ++i) { const [ visual, group ] = visualsList[i] - await visual.createOrUpdate({ ...ctx, runtime }, _props, { group, structure: _structure }) + await visual.createOrUpdate({ ...ctx, runtime }, _theme, _props, { group, structure: _structure }) } } if (structure) _structure = structure diff --git a/src/mol-repr/structure/units-visual.ts b/src/mol-repr/structure/units-visual.ts index 7f8ef19694e4f25bfb5362831550a9b2e8836a55..f2bbd9992343b2c8e7dec6fdac2e87946449df14 100644 --- a/src/mol-repr/structure/units-visual.ts +++ b/src/mol-repr/structure/units-visual.ts @@ -14,7 +14,7 @@ import { deepEqual, ValueCell, UUID } from 'mol-util'; import { Interval } from 'mol-data/int'; import { MultiSelectParam, paramDefaultValues } from 'mol-util/parameter'; import { RenderableValues } from 'mol-gl/renderable/schema'; -import { Geometry, updateRenderableState } from 'mol-geo/geometry/geometry'; +import { Geometry, updateRenderableState, Theme } from 'mol-geo/geometry/geometry'; import { LocationIterator } from 'mol-geo/util/location-iterator'; import { PickingId } from 'mol-geo/geometry/picking'; import { createMarkers, MarkerAction, applyMarkerAction } from 'mol-geo/geometry/marker-data'; @@ -48,7 +48,7 @@ type UnitsRenderObject = MeshRenderObject | LinesRenderObject | PointsRenderObje interface UnitsVisualBuilder<P extends UnitsProps, G extends Geometry> { defaultProps: P - createGeometry(ctx: VisualContext, unit: Unit, structure: Structure, props: P, geometry?: G): Promise<G> + createGeometry(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: P, geometry?: G): Promise<G> createLocationIterator(group: Unit.SymmetryGroup): LocationIterator getLoci(pickingId: PickingId, group: Unit.SymmetryGroup, id: number): Loci mark(loci: Loci, group: Unit.SymmetryGroup, apply: (interval: Interval) => boolean): boolean @@ -57,7 +57,7 @@ interface UnitsVisualBuilder<P extends UnitsProps, G extends Geometry> { interface UnitsVisualGeometryBuilder<P extends UnitsProps, G extends Geometry> extends UnitsVisualBuilder<P, G> { createEmptyGeometry(geometry?: G): G - createRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, geometry: Geometry, locationIt: LocationIterator, currentProps: P): Promise<UnitsRenderObject> + createRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, geometry: Geometry, locationIt: LocationIterator, theme: Theme, currentProps: P): Promise<UnitsRenderObject> updateValues(values: RenderableValues, newProps: P): void } @@ -74,22 +74,22 @@ export function UnitsVisual<P extends UnitsProps>(builder: UnitsVisualGeometryBu let locationIt: LocationIterator let currentConformationId: UUID - async function create(ctx: VisualContext, group: Unit.SymmetryGroup, props: Partial<P> = {}) { + async function create(ctx: VisualContext, group: Unit.SymmetryGroup, theme: Theme, props: Partial<P> = {}) { currentProps = Object.assign({}, defaultProps, props, { structure: currentStructure }) currentGroup = group const unit = group.units[0] currentConformationId = Unit.conformationId(unit) geometry = includesUnitKind(currentProps.unitKinds, unit) - ? await createGeometry(ctx, unit, currentStructure, currentProps, geometry) + ? await createGeometry(ctx, unit, currentStructure, theme, currentProps, geometry) : createEmptyGeometry(geometry) // TODO create empty location iterator when not in unitKinds locationIt = createLocationIterator(group) - renderObject = await createRenderObject(ctx, group, geometry, locationIt, currentProps) + renderObject = await createRenderObject(ctx, group, geometry, locationIt, theme, currentProps) } - async function update(ctx: VisualContext, props: Partial<P> = {}) { + async function update(ctx: VisualContext, theme: Theme, props: Partial<P> = {}) { if (!renderObject) return const newProps = Object.assign({}, currentProps, props, { structure: currentStructure }) @@ -122,7 +122,7 @@ export function UnitsVisual<P extends UnitsProps>(builder: UnitsVisualGeometryBu if (updateState.createGeometry) { geometry = includesUnitKind(newProps.unitKinds, unit) - ? await createGeometry(ctx, unit, currentStructure, newProps, geometry) + ? await createGeometry(ctx, unit, currentStructure, theme, newProps, geometry) : createEmptyGeometry(geometry) ValueCell.update(renderObject.values.drawCount, Geometry.getDrawCount(geometry)) updateState.updateColor = true @@ -131,12 +131,12 @@ export function UnitsVisual<P extends UnitsProps>(builder: UnitsVisualGeometryBu if (updateState.updateSize) { // not all geometries have size data, so check here if ('uSize' in renderObject.values) { - await createSizes(ctx.runtime, locationIt, newProps, renderObject.values) + await createSizes(ctx.runtime, locationIt, theme.size, renderObject.values) } } if (updateState.updateColor) { - await createColors(ctx.runtime, locationIt, newProps, renderObject.values) + await createColors(ctx.runtime, locationIt, theme.color, renderObject.values) } updateValues(renderObject.values, newProps) @@ -147,24 +147,24 @@ export function UnitsVisual<P extends UnitsProps>(builder: UnitsVisualGeometryBu return { get renderObject () { return renderObject }, - async createOrUpdate(ctx: VisualContext, props: Partial<P> = {}, structureGroup?: StructureGroup) { + async createOrUpdate(ctx: VisualContext, theme: Theme, props: Partial<P> = {}, structureGroup?: StructureGroup) { if (structureGroup) currentStructure = structureGroup.structure const group = structureGroup ? structureGroup.group : undefined if (!group && !currentGroup) { throw new Error('missing group') } else if (group && (!currentGroup || !renderObject)) { // console.log('unit-visual first create') - await create(ctx, group, props) + await create(ctx, group, theme, props) } else if (group && group.hashCode !== currentGroup.hashCode) { // console.log('unit-visual group.hashCode !== currentGroup.hashCode') - await create(ctx, group, props) + await create(ctx, group, theme, props) } else { // console.log('unit-visual update') if (group && !sameGroupConformation(group, currentGroup)) { // console.log('unit-visual new conformation') currentGroup = group } - await update(ctx, props) + await update(ctx, theme, props) } }, getLoci(pickingId: PickingId) { diff --git a/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts b/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts index 0b064012b8c56b7c9db6611e3f1524edf065a7b4..df2b2231846293b2d52a7e7071c4989bcadc1368 100644 --- a/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts +++ b/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts @@ -10,7 +10,7 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { createLinkCylinderMesh, LinkCylinderProps, LinkCylinderParams } from './util/link'; import { OrderedSet, Interval } from 'mol-data/int'; import { ComplexMeshVisual, ComplexVisual } from '../complex-visual'; -import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; +import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; import { LinkType } from 'mol-model/structure/model/types'; import { BitFlags } from 'mol-util'; import { UnitsMeshParams } from '../units-visual'; @@ -20,6 +20,7 @@ import { LocationIterator } from 'mol-geo/util/location-iterator'; import { PickingId } from 'mol-geo/geometry/picking'; import { VisualUpdateState } from '../../util'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; // TODO create seperate visual // for (let i = 0, il = carbohydrates.terminalLinks.length; i < il; ++i) { @@ -35,9 +36,8 @@ import { VisualContext } from 'mol-repr'; const radiusFactor = 0.3 -async function createCarbohydrateLinkCylinderMesh(ctx: VisualContext, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) { +async function createCarbohydrateLinkCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: LinkCylinderProps, mesh?: Mesh) { const { links, elements } = structure.carbohydrates - const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue }) const location = StructureElement.create() const builderProps = { @@ -54,7 +54,7 @@ async function createCarbohydrateLinkCylinderMesh(ctx: VisualContext, structure: const l = links[edgeIndex] location.unit = elements[l.carbohydrateIndexA].unit location.element = elements[l.carbohydrateIndexA].anomericCarbon - return sizeTheme.size(location) * radiusFactor + return theme.size.size(location) * radiusFactor } } diff --git a/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts b/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts index ddbd3215d3c7c9c4f9a9d30a9510b43d9bd572fa..d09c3693931aaad08da8b9bfdbb8b48c96ca4feb 100644 --- a/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts +++ b/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts @@ -13,7 +13,7 @@ import { DiamondPrism, PentagonalPrism, HexagonalPrism } from 'mol-geo/primitive import { Structure, StructureElement } from 'mol-model/structure'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder'; -import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; +import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; import { getSaccharideShape, SaccharideShapes } from 'mol-model/structure/structure/carbohydrates/constants'; import { addSphere } from 'mol-geo/geometry/mesh/builder/sphere'; import { ComplexMeshParams, ComplexMeshVisual } from '../complex-visual'; @@ -25,6 +25,7 @@ import { PickingId } from 'mol-geo/geometry/picking'; import { OrderedSet, Interval } from 'mol-data/int'; import { EmptyLoci, Loci } from 'mol-model/loci'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; const t = Mat4.identity() const sVec = Vec3.zero() @@ -44,10 +45,9 @@ const diamondPrism = DiamondPrism() const pentagonalPrism = PentagonalPrism() const hexagonalPrism = HexagonalPrism() -async function createCarbohydrateSymbolMesh(ctx: VisualContext, structure: Structure, props: CarbohydrateSymbolProps, mesh?: Mesh) { +async function createCarbohydrateSymbolMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: CarbohydrateSymbolProps, mesh?: Mesh) { const builder = MeshBuilder.create(256, 128, mesh) - const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue }) const { detail } = props const carbohydrates = structure.carbohydrates @@ -60,7 +60,7 @@ async function createCarbohydrateSymbolMesh(ctx: VisualContext, structure: Struc l.unit = c.unit l.element = c.unit.elements[c.anomericCarbon] - const size = sizeTheme.size(l) + const size = theme.size.size(l) const radius = size * radiusFactor const side = size * sideFactor diff --git a/src/mol-repr/structure/visual/cross-link-restraint-cylinder.ts b/src/mol-repr/structure/visual/cross-link-restraint-cylinder.ts index 190565acb8ecba70588c608fbaf1822fcf4d50c1..271f55210c7f82fb7d044b7449af079fe00e947f 100644 --- a/src/mol-repr/structure/visual/cross-link-restraint-cylinder.ts +++ b/src/mol-repr/structure/visual/cross-link-restraint-cylinder.ts @@ -12,7 +12,7 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { ComplexMeshVisual, ComplexMeshParams } from '../complex-visual'; import { Interval } from 'mol-data/int'; -import { SizeTheme, SizeThemeOptions, SizeThemeName } from 'mol-theme/size'; +import { SizeThemeOptions, SizeThemeName } from 'mol-theme/size'; import { BitFlags } from 'mol-util'; import { LinkType } from 'mol-model/structure/model/types'; import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter'; @@ -20,13 +20,13 @@ import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { LocationIterator } from 'mol-geo/util/location-iterator'; import { PickingId } from 'mol-geo/geometry/picking'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; -async function createCrossLinkRestraintCylinderMesh(ctx: VisualContext, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) { +async function createCrossLinkRestraintCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: LinkCylinderProps, mesh?: Mesh) { const crossLinks = structure.crossLinkRestraints if (!crossLinks.count) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue }) const location = StructureElement.create() const builderProps = { @@ -44,7 +44,7 @@ async function createCrossLinkRestraintCylinderMesh(ctx: VisualContext, structur const b = crossLinks.pairs[edgeIndex] location.unit = b.unitA location.element = b.unitA.elements[b.indexA] - return sizeTheme.size(location) + return theme.size.size(location) } } diff --git a/src/mol-repr/structure/visual/element-point.ts b/src/mol-repr/structure/visual/element-point.ts index c0b7ebb436024bd2cc0508021ebe0401d934e7a6..62798dc3eb3cb42284a798e13f6c66f06107e9fa 100644 --- a/src/mol-repr/structure/visual/element-point.ts +++ b/src/mol-repr/structure/visual/element-point.ts @@ -15,6 +15,7 @@ import { SelectParam, NumberParam, BooleanParam, paramDefaultValues } from 'mol- import { Points } from 'mol-geo/geometry/points/points'; import { PointsBuilder } from 'mol-geo/geometry/points/points-builder'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; export const ElementPointParams = { ...UnitsPointsParams, @@ -27,7 +28,7 @@ export type ElementPointProps = typeof DefaultElementPointProps // TODO size -export async function createElementPoint(ctx: VisualContext, unit: Unit, structure: Structure, props: ElementPointProps, points: Points) { +export async function createElementPoint(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: ElementPointProps, points: Points) { const elements = unit.elements const n = elements.length const builder = PointsBuilder.create(n, n / 10, points) diff --git a/src/mol-repr/structure/visual/gaussian-density-point.ts b/src/mol-repr/structure/visual/gaussian-density-point.ts index f14268e78eebe8ea5b51439a9b4746479d790310..eb2b9fdb07ff113e4b4012c5dfcf5b3cbeb9f07b 100644 --- a/src/mol-repr/structure/visual/gaussian-density-point.ts +++ b/src/mol-repr/structure/visual/gaussian-density-point.ts @@ -17,6 +17,7 @@ import { paramDefaultValues, SelectParam, NumberParam, BooleanParam } from 'mol- import { Points } from 'mol-geo/geometry/points/points'; import { PointsBuilder } from 'mol-geo/geometry/points/points-builder'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; export const GaussianDensityPointParams = { ...UnitsPointsParams, @@ -28,7 +29,7 @@ export const GaussianDensityPointParams = { export const DefaultGaussianDensityPointProps = paramDefaultValues(GaussianDensityPointParams) export type GaussianDensityPointProps = typeof DefaultGaussianDensityPointProps -export async function createGaussianDensityPoint(ctx: VisualContext, unit: Unit, structure: Structure, props: GaussianDensityProps, points?: Points) { +export async function createGaussianDensityPoint(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityProps, points?: Points) { const { transform, field: { space, data } } = await unit.computeGaussianDensity(props, ctx.runtime, ctx.webgl) const { dimensions, get } = space diff --git a/src/mol-repr/structure/visual/gaussian-density-volume.ts b/src/mol-repr/structure/visual/gaussian-density-volume.ts index e0b96b1f9c25c7cf092fa22d9e6284fddb5989c0..b61bf52712e0b19c860bfc2e4ccf46ee8bb91232 100644 --- a/src/mol-repr/structure/visual/gaussian-density-volume.ts +++ b/src/mol-repr/structure/visual/gaussian-density-volume.ts @@ -13,8 +13,9 @@ import { GaussianDensityProps, GaussianDensityParams, computeUnitGaussianDensity import { paramDefaultValues } from 'mol-util/parameter'; import { DirectVolume } from 'mol-geo/geometry/direct-volume/direct-volume'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; -async function createGaussianDensityVolume(ctx: VisualContext, unit: Unit, structure: Structure, props: GaussianDensityProps, directVolume?: DirectVolume): Promise<DirectVolume> { +async function createGaussianDensityVolume(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityProps, directVolume?: DirectVolume): Promise<DirectVolume> { const { runtime, webgl } = ctx if (webgl === undefined) throw new Error('createGaussianDensityVolume requires `webgl` object in VisualContext') diff --git a/src/mol-repr/structure/visual/gaussian-surface-mesh.ts b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts index 3e983cff2dc9e2d5657d932e98839e04a2b789af..c19f13f5ffcefd8c7c2fefeeaf720a500f3d444d 100644 --- a/src/mol-repr/structure/visual/gaussian-surface-mesh.ts +++ b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts @@ -14,8 +14,9 @@ import { paramDefaultValues } from 'mol-util/parameter'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { computeMarchingCubesMesh } from 'mol-geo/util/marching-cubes/algorithm'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; -async function createGaussianSurfaceMesh(ctx: VisualContext, unit: Unit, structure: Structure, props: GaussianDensityProps, mesh?: Mesh): Promise<Mesh> { +async function createGaussianSurfaceMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityProps, mesh?: Mesh): Promise<Mesh> { const { smoothness } = props const { transform, field, idField } = await unit.computeGaussianDensity(props, ctx.runtime, ctx.webgl) diff --git a/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts b/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts index 1b3e3033144751186ca6637b197f7048ff6d9822..1bb596a95c9b45f1e3eceb85cad5c560d355f323 100644 --- a/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts +++ b/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts @@ -15,8 +15,9 @@ import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; import { Lines } from 'mol-geo/geometry/lines/lines'; import { computeMarchingCubesLines } from 'mol-geo/util/marching-cubes/algorithm'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; -async function createGaussianWireframe(ctx: VisualContext, unit: Unit, structure: Structure, props: GaussianDensityProps, lines?: Lines): Promise<Lines> { +async function createGaussianWireframe(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityProps, lines?: Lines): Promise<Lines> { const { smoothness } = props const { transform, field, idField } = await unit.computeGaussianDensity(props, ctx.runtime) diff --git a/src/mol-repr/structure/visual/inter-unit-link-cylinder.ts b/src/mol-repr/structure/visual/inter-unit-link-cylinder.ts index 76a51d6805d4d925a91c2f2d2fa3e20356d02f83..d478bef27bb8c223cc7aae419268460f63455486 100644 --- a/src/mol-repr/structure/visual/inter-unit-link-cylinder.ts +++ b/src/mol-repr/structure/visual/inter-unit-link-cylinder.ts @@ -12,20 +12,19 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { ComplexMeshVisual, ComplexMeshParams } from '../complex-visual'; import { Interval } from 'mol-data/int'; -import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; import { BitFlags } from 'mol-util'; -import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter'; +import { paramDefaultValues } from 'mol-util/parameter'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { PickingId } from 'mol-geo/geometry/picking'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; -async function createInterUnitLinkCylinderMesh(ctx: VisualContext, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) { +async function createInterUnitLinkCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: LinkCylinderProps, mesh?: Mesh) { const links = structure.links const { bondCount, bonds } = links if (!bondCount) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue, factor: props.sizeFactor }) const location = StructureElement.create() const builderProps = { @@ -43,7 +42,7 @@ async function createInterUnitLinkCylinderMesh(ctx: VisualContext, structure: St const b = bonds[edgeIndex] location.unit = b.unitA location.element = b.unitA.elements[b.indexA] - return sizeTheme.size(location) + return theme.size.size(location) } } @@ -53,9 +52,6 @@ async function createInterUnitLinkCylinderMesh(ctx: VisualContext, structure: St export const InterUnitLinkParams = { ...ComplexMeshParams, ...LinkCylinderParams, - sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions), - sizeValue: NumberParam('Size Value', '', 0.2, 0, 10, 0.1), - sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1), } export const DefaultInterUnitLinkProps = paramDefaultValues(InterUnitLinkParams) export type InterUnitLinkProps = typeof DefaultInterUnitLinkProps diff --git a/src/mol-repr/structure/visual/intra-unit-link-cylinder.ts b/src/mol-repr/structure/visual/intra-unit-link-cylinder.ts index b4239034cf5e80e3c974b7cf5db1655b9fbd6bd3..7625e106d0c581baa3066cf959f30e3d8072da89 100644 --- a/src/mol-repr/structure/visual/intra-unit-link-cylinder.ts +++ b/src/mol-repr/structure/visual/intra-unit-link-cylinder.ts @@ -13,17 +13,17 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; import { Interval } from 'mol-data/int'; -import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; +import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; import { BitFlags } from 'mol-util'; import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { PickingId } from 'mol-geo/geometry/picking'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; -async function createIntraUnitLinkCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) { +async function createIntraUnitLinkCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: LinkCylinderProps, mesh?: Mesh) { if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue, factor: props.sizeFactor }) const location = StructureElement.create(unit) const elements = unit.elements; @@ -57,7 +57,7 @@ async function createIntraUnitLinkCylinderMesh(ctx: VisualContext, unit: Unit, s flags: (edgeIndex: number) => BitFlags.create(_flags[edgeIndex]), radius: (edgeIndex: number) => { location.element = elements[a[edgeIndex]] - return sizeTheme.size(location) + return theme.size.size(location) } } diff --git a/src/mol-repr/structure/visual/nucleotide-block-mesh.ts b/src/mol-repr/structure/visual/nucleotide-block-mesh.ts index 9a2e8372608dbd3bcfbba7806545b127096e5e3b..fef1b64a2245371fc3697e7c7ea8d0c4aab251e8 100644 --- a/src/mol-repr/structure/visual/nucleotide-block-mesh.ts +++ b/src/mol-repr/structure/visual/nucleotide-block-mesh.ts @@ -18,6 +18,7 @@ import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder'; import { addCylinder } from 'mol-geo/geometry/mesh/builder/cylinder'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; const p1 = Vec3.zero() const p2 = Vec3.zero() @@ -34,7 +35,7 @@ const sVec = Vec3.zero() const box = Box() // TODO define props, should be scalable -async function createNucleotideBlockMesh(ctx: VisualContext, unit: Unit, structure: Structure, props: {}, mesh?: Mesh) { +async function createNucleotideBlockMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: {}, mesh?: Mesh) { if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh) // TODO better vertex count estimate diff --git a/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts b/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts index 6968ac9b53c676171198f5e113cec87672f3f51c..1837c11538853ee4a415ecf2a8f6ade05ddaa25b 100644 --- a/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts +++ b/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts @@ -11,28 +11,25 @@ import { PolymerBackboneIterator } from './util/polymer'; import { getElementLoci, markElement, StructureElementIterator } from './util/element'; import { Vec3 } from 'mol-math/linear-algebra'; import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; -import { SizeTheme, SizeThemeOptions, SizeThemeName } from 'mol-theme/size'; import { OrderedSet } from 'mol-data/int'; -import { paramDefaultValues, NumberParam, SelectParam } from 'mol-util/parameter'; +import { paramDefaultValues, NumberParam } from 'mol-util/parameter'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder'; import { CylinderProps } from 'mol-geo/primitive/cylinder'; import { addCylinder } from 'mol-geo/geometry/mesh/builder/cylinder'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; export const PolymerBackboneCylinderParams = { - sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), - sizeValue: NumberParam('Size Value', '', 1, 0, 10, 0.1), radialSegments: NumberParam('Radial Segments', '', 16, 3, 56, 1), } export const DefaultPolymerBackboneCylinderProps = paramDefaultValues(PolymerBackboneCylinderParams) export type PolymerBackboneCylinderProps = typeof DefaultPolymerBackboneCylinderProps -async function createPolymerBackboneCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, props: PolymerBackboneCylinderProps, mesh?: Mesh) { +async function createPolymerBackboneCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PolymerBackboneCylinderProps, mesh?: Mesh) { const polymerElementCount = unit.polymerElements.length if (!polymerElementCount) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue }) const { radialSegments } = props const vertexCountEstimate = radialSegments * 2 * polymerElementCount * 2 @@ -51,11 +48,11 @@ async function createPolymerBackboneCylinderMesh(ctx: VisualContext, unit: Unit, pos(centerA.element, pA) pos(centerB.element, pB) - cylinderProps.radiusTop = cylinderProps.radiusBottom = sizeTheme.size(centerA) + cylinderProps.radiusTop = cylinderProps.radiusBottom = theme.size.size(centerA) builder.setGroup(OrderedSet.indexOf(elements, centerA.element)) addCylinder(builder, pA, pB, 0.5, cylinderProps) - cylinderProps.radiusTop = cylinderProps.radiusBottom = sizeTheme.size(centerB) + cylinderProps.radiusTop = cylinderProps.radiusBottom = theme.size.size(centerB) builder.setGroup(OrderedSet.indexOf(elements, centerB.element)) addCylinder(builder, pB, pA, 0.5, cylinderProps) diff --git a/src/mol-repr/structure/visual/polymer-direction-wedge.ts b/src/mol-repr/structure/visual/polymer-direction-wedge.ts index 461df57daff267d3d244e8f1aff061a0dd8df159..7c8c2398cbaf8084891f9c40a58ed2dc64ddab21 100644 --- a/src/mol-repr/structure/visual/polymer-direction-wedge.ts +++ b/src/mol-repr/structure/visual/polymer-direction-wedge.ts @@ -10,12 +10,13 @@ import { PolymerTraceIterator, createCurveSegmentState, interpolateCurveSegment, import { Vec3, Mat4 } from 'mol-math/linear-algebra'; import { SecondaryStructureType, isNucleic } from 'mol-model/structure/model/types'; import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; -import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; +import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter'; import { Wedge } from 'mol-geo/primitive/wedge'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; const t = Mat4.identity() const sVec = Vec3.zero() @@ -36,12 +37,10 @@ export const PolymerDirectionWedgeParams = { export const DefaultPolymerDirectionWedgeProps = paramDefaultValues(PolymerDirectionWedgeParams) export type PolymerDirectionWedgeProps = typeof DefaultPolymerDirectionWedgeProps -async function createPolymerDirectionWedgeMesh(ctx: VisualContext, unit: Unit, structure: Structure, props: PolymerDirectionWedgeProps, mesh?: Mesh) { +async function createPolymerDirectionWedgeMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PolymerDirectionWedgeProps, mesh?: Mesh) { const polymerElementCount = unit.polymerElements.length if (!polymerElementCount) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue }) - const vertexCount = polymerElementCount * 24 const builder = MeshBuilder.create(vertexCount, vertexCount / 10, mesh) const linearSegments = 1 @@ -63,7 +62,7 @@ async function createPolymerDirectionWedgeMesh(ctx: VisualContext, unit: Unit, s interpolateCurveSegment(state, v, tension, shift) if ((isSheet && !v.secStrucChange) || !isSheet) { - const size = sizeTheme.size(v.center) + const size = theme.size.size(v.center) const depth = depthFactor * size const width = widthFactor * size const height = heightFactor * size diff --git a/src/mol-repr/structure/visual/polymer-gap-cylinder.ts b/src/mol-repr/structure/visual/polymer-gap-cylinder.ts index c00559b244db6e1efc308e05c9cdb641d79c5769..d7ae6fc57ecb002653f29a2f8f0b381c057774aa 100644 --- a/src/mol-repr/structure/visual/polymer-gap-cylinder.ts +++ b/src/mol-repr/structure/visual/polymer-gap-cylinder.ts @@ -10,7 +10,7 @@ import { VisualUpdateState } from '../../util'; import { PolymerGapIterator, PolymerGapLocationIterator, markPolymerGapElement, getPolymerGapElementLoci } from './util/polymer'; import { Vec3 } from 'mol-math/linear-algebra'; import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; -import { SizeTheme, SizeThemeOptions, SizeThemeName } from 'mol-theme/size'; +import { SizeThemeOptions, SizeThemeName } from 'mol-theme/size'; import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter'; import { LinkCylinderParams } from './util/link'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; @@ -19,23 +19,20 @@ import { CylinderProps } from 'mol-geo/primitive/cylinder'; import { addSphere } from 'mol-geo/geometry/mesh/builder/sphere'; import { addFixedCountDashedCylinder } from 'mol-geo/geometry/mesh/builder/cylinder'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; const segmentCount = 10 export const PolymerGapCylinderParams = { - sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions), - sizeValue: NumberParam('Size Value', '', 1, 0, 10, 0.1), - sizeFactor: NumberParam('Size Factor', '', 0.3, 0, 10, 0.1), radialSegments: NumberParam('Radial Segments', '', 16, 3, 56, 1), } export const DefaultPolymerGapCylinderProps = paramDefaultValues(PolymerGapCylinderParams) export type PolymerGapCylinderProps = typeof DefaultPolymerGapCylinderProps -async function createPolymerGapCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, props: PolymerGapCylinderProps, mesh?: Mesh) { +async function createPolymerGapCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PolymerGapCylinderProps, mesh?: Mesh) { const polymerGapCount = unit.gapElements.length if (!polymerGapCount) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue, factor: props.sizeValue }) const { radialSegments } = props const vertexCountEstimate = segmentCount * radialSegments * 2 * polymerGapCount * 2 @@ -60,11 +57,11 @@ async function createPolymerGapCylinderMesh(ctx: VisualContext, unit: Unit, stru pos(centerA.element, pA) pos(centerB.element, pB) - cylinderProps.radiusTop = cylinderProps.radiusBottom = sizeTheme.size(centerA) + cylinderProps.radiusTop = cylinderProps.radiusBottom = theme.size.size(centerA) builder.setGroup(i) addFixedCountDashedCylinder(builder, pA, pB, 0.5, segmentCount, cylinderProps) - cylinderProps.radiusTop = cylinderProps.radiusBottom = sizeTheme.size(centerB) + cylinderProps.radiusTop = cylinderProps.radiusBottom = theme.size.size(centerB) builder.setGroup(i + 1) addFixedCountDashedCylinder(builder, pB, pA, 0.5, segmentCount, cylinderProps) } diff --git a/src/mol-repr/structure/visual/polymer-trace-mesh.ts b/src/mol-repr/structure/visual/polymer-trace-mesh.ts index 941d9d65148863cbe615120c238e0534f8ff75ee..6187a494f57759ef95c53b402020c9dbf709210e 100644 --- a/src/mol-repr/structure/visual/polymer-trace-mesh.ts +++ b/src/mol-repr/structure/visual/polymer-trace-mesh.ts @@ -10,18 +10,15 @@ import { VisualUpdateState } from '../../util'; import { PolymerTraceIterator, createCurveSegmentState, interpolateCurveSegment, PolymerLocationIterator, getPolymerElementLoci, markPolymerElement } from './util/polymer'; import { SecondaryStructureType, isNucleic } from 'mol-model/structure/model/types'; import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; -import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; -import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter'; +import { NumberParam, paramDefaultValues } from 'mol-util/parameter'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder'; import { addSheet } from 'mol-geo/geometry/mesh/builder/sheet'; import { addTube } from 'mol-geo/geometry/mesh/builder/tube'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; export const PolymerTraceMeshParams = { - sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions), - sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), - sizeFactor: NumberParam('Size Factor', '', 0.3, 0, 10, 0.1), linearSegments: NumberParam('Linear Segments', '', 8, 1, 48, 1), radialSegments: NumberParam('Radial Segments', '', 16, 3, 56, 1), aspectRatio: NumberParam('Aspect Ratio', '', 5, 0.1, 5, 0.1), @@ -32,11 +29,10 @@ export type PolymerTraceMeshProps = typeof DefaultPolymerTraceMeshProps // TODO handle polymer ends properly -async function createPolymerTraceMesh(ctx: VisualContext, unit: Unit, structure: Structure, props: PolymerTraceMeshProps, mesh?: Mesh) { +async function createPolymerTraceMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PolymerTraceMeshProps, mesh?: Mesh) { const polymerElementCount = unit.polymerElements.length if (!polymerElementCount) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue, factor: props.sizeFactor }) const { linearSegments, radialSegments, aspectRatio, arrowFactor } = props const vertexCount = linearSegments * radialSegments * polymerElementCount + (radialSegments + 1) * polymerElementCount * 2 @@ -60,7 +56,7 @@ async function createPolymerTraceMesh(ctx: VisualContext, unit: Unit, structure: interpolateCurveSegment(state, v, tension, shift) - let width = sizeTheme.size(v.center) + let width = theme.size.size(v.center) if (isCoarse) width *= aspectRatio / 2 if (isSheet) { diff --git a/src/mol-repr/structure/visual/util/common.ts b/src/mol-repr/structure/visual/util/common.ts index a0cff0c67bd20c61ab0626bfa00bc8dbdd48f064..25598d6e34efc0d16031ab5984b1b25f4548f2a8 100644 --- a/src/mol-repr/structure/visual/util/common.ts +++ b/src/mol-repr/structure/visual/util/common.ts @@ -11,7 +11,7 @@ import { Mat4 } from 'mol-math/linear-algebra'; import { TransformData, createTransform, createIdentityTransform } from 'mol-geo/geometry/transform-data'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { LocationIterator } from 'mol-geo/util/location-iterator'; -import { createRenderableState } from 'mol-geo/geometry/geometry'; +import { createRenderableState, Theme } from 'mol-geo/geometry/geometry'; import { Points } from 'mol-geo/geometry/points/points'; import { Lines } from 'mol-geo/geometry/lines/lines'; import { DirectVolume } from 'mol-geo/geometry/direct-volume/direct-volume'; @@ -49,16 +49,16 @@ export function includesUnitKind(unitKinds: UnitKind[], unit: Unit) { type StructureMeshProps = Mesh.Props & StructureProps -export async function createComplexMeshRenderObject(ctx: VisualContext, structure: Structure, mesh: Mesh, locationIt: LocationIterator, props: StructureMeshProps) { +export async function createComplexMeshRenderObject(ctx: VisualContext, structure: Structure, mesh: Mesh, locationIt: LocationIterator, theme: Theme, props: StructureMeshProps) { const transform = createIdentityTransform() - const values = await Mesh.createValues(ctx.runtime, mesh, transform, locationIt, props) + const values = await Mesh.createValues(ctx.runtime, mesh, transform, locationIt, theme, props) const state = createRenderableState(props) return createMeshRenderObject(values, state) } -export async function createUnitsMeshRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, mesh: Mesh, locationIt: LocationIterator, props: StructureMeshProps) { +export async function createUnitsMeshRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, mesh: Mesh, locationIt: LocationIterator, theme: Theme, props: StructureMeshProps) { const transform = createUnitsTransform(group) - const values = await Mesh.createValues(ctx.runtime, mesh, transform, locationIt, props) + const values = await Mesh.createValues(ctx.runtime, mesh, transform, locationIt, theme, props) const state = createRenderableState(props) return createMeshRenderObject(values, state) } @@ -67,9 +67,9 @@ export async function createUnitsMeshRenderObject(ctx: VisualContext, group: Uni type StructurePointsProps = Points.Props & StructureProps -export async function createUnitsPointsRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, points: Points, locationIt: LocationIterator, props: StructurePointsProps) { +export async function createUnitsPointsRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, points: Points, locationIt: LocationIterator, theme: Theme, props: StructurePointsProps) { const transform = createUnitsTransform(group) - const values = await Points.createValues(ctx.runtime, points, transform, locationIt, props) + const values = await Points.createValues(ctx.runtime, points, transform, locationIt, theme, props) const state = createRenderableState(props) return createPointsRenderObject(values, state) } @@ -78,9 +78,9 @@ export async function createUnitsPointsRenderObject(ctx: VisualContext, group: U type StructureLinesProps = Lines.Props & StructureProps -export async function createUnitsLinesRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, lines: Lines, locationIt: LocationIterator, props: StructureLinesProps) { +export async function createUnitsLinesRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, lines: Lines, locationIt: LocationIterator, theme: Theme, props: StructureLinesProps) { const transform = createUnitsTransform(group) - const values = await Lines.createValues(ctx.runtime, lines, transform, locationIt, props) + const values = await Lines.createValues(ctx.runtime, lines, transform, locationIt, theme, props) const state = createRenderableState(props) return createLinesRenderObject(values, state) } @@ -89,9 +89,9 @@ export async function createUnitsLinesRenderObject(ctx: VisualContext, group: Un type StructureDirectVolumeProps = DirectVolume.Props & StructureProps -export async function createUnitsDirectVolumeRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, directVolume: DirectVolume, locationIt: LocationIterator, props: StructureDirectVolumeProps) { +export async function createUnitsDirectVolumeRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, directVolume: DirectVolume, locationIt: LocationIterator, theme: Theme, props: StructureDirectVolumeProps) { const transform = createUnitsTransform(group) - const values = await DirectVolume.createValues(ctx.runtime, directVolume, transform, locationIt, props) + const values = await DirectVolume.createValues(ctx.runtime, directVolume, transform, locationIt, theme, props) const state = createRenderableState(props) return createDirectVolumeRenderObject(values, state) } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/util/element.ts b/src/mol-repr/structure/visual/util/element.ts index 909bce22aa260a8a8491c31d1cc015d4c7f90dac..e1ccb69774b2497ffd08b7a936f497d67c1ca5e8 100644 --- a/src/mol-repr/structure/visual/util/element.ts +++ b/src/mol-repr/structure/visual/util/element.ts @@ -8,7 +8,6 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { Unit, StructureElement, Structure } from 'mol-model/structure'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { Interval, OrderedSet } from 'mol-data/int'; -import { SizeTheme, SizeThemeName } from 'mol-theme/size'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { sphereVertexCount } from 'mol-geo/primitive/sphere'; import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder'; @@ -16,18 +15,16 @@ import { addSphere } from 'mol-geo/geometry/mesh/builder/sphere'; import { PickingId } from 'mol-geo/geometry/picking'; import { LocationIterator } from 'mol-geo/util/location-iterator'; import { VisualContext } from 'mol-repr'; +import { Theme } from 'mol-geo/geometry/geometry'; export interface ElementSphereMeshProps { - sizeTheme: SizeThemeName, - sizeValue: number, detail: number, } -export async function createElementSphereMesh(ctx: VisualContext, unit: Unit, structure: Structure, props: ElementSphereMeshProps, mesh?: Mesh) { +export async function createElementSphereMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: ElementSphereMeshProps, mesh?: Mesh) { const { detail } = props const { elements } = unit; - const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue }) const elementCount = elements.length; const vertexCount = elementCount * sphereVertexCount(detail) const meshBuilder = MeshBuilder.create(vertexCount, vertexCount / 2, mesh) @@ -42,7 +39,7 @@ export async function createElementSphereMesh(ctx: VisualContext, unit: Unit, st pos(elements[i], v) meshBuilder.setGroup(i) - addSphere(meshBuilder, v, sizeTheme.size(l), detail) + addSphere(meshBuilder, v, theme.size.size(l), detail) if (i % 10000 === 0 && ctx.runtime.shouldUpdate) { await ctx.runtime.update({ message: 'Sphere mesh', current: i, max: elementCount }); diff --git a/src/mol-repr/structure/visual/util/link.ts b/src/mol-repr/structure/visual/util/link.ts index 4f3931f480ddf07a77f3dc13c3830542ff8b4a32..422b4216bad4ed823ff4822bf638ad1c077d953e 100644 --- a/src/mol-repr/structure/visual/util/link.ts +++ b/src/mol-repr/structure/visual/util/link.ts @@ -6,9 +6,8 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { LinkType } from 'mol-model/structure/model/types'; -import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size'; import { Unit, StructureElement, Structure, Link } from 'mol-model/structure'; -import { SelectParam, RangeParam, NumberParam, paramDefaultValues } from 'mol-util/parameter'; +import { RangeParam, NumberParam, paramDefaultValues } from 'mol-util/parameter'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder'; import { CylinderProps } from 'mol-geo/primitive/cylinder'; @@ -17,9 +16,6 @@ import { LocationIterator } from 'mol-geo/util/location-iterator'; import { VisualContext } from 'mol-repr'; export const LinkCylinderParams = { - sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), - sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), - sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1), linkScale: RangeParam('Link Scale', '', 0.4, 0, 1, 0.1), linkSpacing: RangeParam('Link Spacing', '', 1, 0, 2, 0.01), linkRadius: RangeParam('Link Radius', '', 0.25, 0, 10, 0.05), diff --git a/src/mol-repr/util.ts b/src/mol-repr/util.ts index 0b71cd247d96592ae3dc676a30a4fd54b88cb27b..4db8e0cee7c100f8650074fb216192c9bec3379b 100644 --- a/src/mol-repr/util.ts +++ b/src/mol-repr/util.ts @@ -61,16 +61,16 @@ export interface QualityProps { resolution: number } -export function getQualityProps(props: Partial<QualityProps>, structure?: Structure) { +export function getQualityProps(props: Partial<QualityProps>, data?: any) { let quality = defaults(props.quality, 'auto' as VisualQuality) let detail = defaults(props.detail, 1) let radialSegments = defaults(props.radialSegments, 12) let linearSegments = defaults(props.linearSegments, 8) let resolution = defaults(props.resolution, 2) - if (quality === 'auto' && structure) { - let score = structure.elementCount - if (structure.isCoarse) score *= 10 + if (quality === 'auto' && data instanceof Structure) { + let score = data.elementCount + if (data.isCoarse) score *= 10 if (score > 500_000) { quality = 'lowest' } else if (score > 300_000) { diff --git a/src/mol-repr/volume/direct-volume.ts b/src/mol-repr/volume/direct-volume.ts index ce412b099d4f6a811e62e9481cd05c2a1130a146..504316adf6f42cf3352a0735c0c948168717f69e 100644 --- a/src/mol-repr/volume/direct-volume.ts +++ b/src/mol-repr/volume/direct-volume.ts @@ -17,7 +17,7 @@ import { createTexture } from 'mol-gl/webgl/texture'; import { LocationIterator } from 'mol-geo/util/location-iterator'; import { createIdentityTransform } from 'mol-geo/geometry/transform-data'; import { DirectVolume } from 'mol-geo/geometry/direct-volume/direct-volume'; -import { Geometry, createRenderableState } from 'mol-geo/geometry/geometry'; +import { Geometry, createRenderableState, Theme } from 'mol-geo/geometry/geometry'; import { PickingId } from 'mol-geo/geometry/picking'; import { MarkerAction } from 'mol-geo/geometry/marker-data'; import { VisualUpdateState } from 'mol-repr/util'; @@ -198,9 +198,9 @@ export function DirectVolumeVisual(): VolumeVisual<DirectVolumeProps> { mark: () => false, setUpdateState: (state: VisualUpdateState, newProps: DirectVolumeProps, currentProps: DirectVolumeProps) => { }, - createRenderObject: async (ctx: VisualContext, geometry: DirectVolume, locationIt: LocationIterator, props: DirectVolumeProps) => { + createRenderObject: async (ctx: VisualContext, geometry: DirectVolume, locationIt: LocationIterator, theme: Theme, props: DirectVolumeProps) => { const transform = createIdentityTransform() - const values = await DirectVolume.createValues(ctx.runtime, geometry, transform, locationIt, props) + const values = await DirectVolume.createValues(ctx.runtime, geometry, transform, locationIt, theme, props) const state = createRenderableState(props) return createDirectVolumeRenderObject(values, state) }, diff --git a/src/mol-repr/volume/index.ts b/src/mol-repr/volume/index.ts index f7d0ddded2558081b882009f0301a535cdbaa51f..d168f36d4a67b928d8ae95e18b6cadc6658a340e 100644 --- a/src/mol-repr/volume/index.ts +++ b/src/mol-repr/volume/index.ts @@ -9,7 +9,7 @@ import { RepresentationProps, Representation, Visual, RepresentationContext, Vis import { VolumeData, VolumeIsoValue } from 'mol-model/volume'; import { Loci, EmptyLoci, isEveryLoci } from 'mol-model/loci'; import { paramDefaultValues, RangeParam } from 'mol-util/parameter'; -import { Geometry, updateRenderableState } from 'mol-geo/geometry/geometry'; +import { Geometry, updateRenderableState, Theme, createTheme } from 'mol-geo/geometry/geometry'; import { PickingId } from 'mol-geo/geometry/picking'; import { MarkerAction, applyMarkerAction } from 'mol-geo/geometry/marker-data'; import { DirectVolumeRenderObject, PointsRenderObject, LinesRenderObject, MeshRenderObject } from 'mol-gl/render-object'; @@ -33,7 +33,7 @@ interface VolumeVisualBuilder<P extends VolumeProps, G extends Geometry> { } interface VolumeVisualGeometryBuilder<P extends VolumeProps, G extends Geometry> extends VolumeVisualBuilder<P, G> { - createRenderObject(ctx: VisualContext, geometry: G, locationIt: LocationIterator, currentProps: P): Promise<VolumeRenderObject> + createRenderObject(ctx: VisualContext, geometry: G, locationIt: LocationIterator, theme: Theme, currentProps: P): Promise<VolumeRenderObject> updateValues(values: RenderableValues, newProps: P): void } @@ -48,25 +48,25 @@ export function VolumeVisual<P extends VolumeProps>(builder: VolumeVisualGeometr let geometry: Geometry let locationIt: LocationIterator - async function create(ctx: VisualContext, volume: VolumeData, props: Partial<VolumeProps> = {}) { + async function create(ctx: VisualContext, volume: VolumeData, theme: Theme, props: Partial<VolumeProps> = {}) { currentProps = Object.assign({}, defaultProps, props) if (props.isoValueRelative) { currentProps.isoValueAbsolute = VolumeIsoValue.calcAbsolute(currentVolume.dataStats, props.isoValueRelative) - console.log('create props.isoValueRelative', props.isoValueRelative, currentProps.isoValueAbsolute, currentVolume.dataStats) + // console.log('create props.isoValueRelative', props.isoValueRelative, currentProps.isoValueAbsolute, currentVolume.dataStats) } geometry = await createGeometry(ctx, volume, currentProps, geometry) locationIt = LocationIterator(1, 1, () => NullLocation) - renderObject = await createRenderObject(ctx, geometry, locationIt, currentProps) + renderObject = await createRenderObject(ctx, geometry, locationIt, theme, currentProps) } - async function update(ctx: VisualContext, props: Partial<VolumeProps> = {}) { + async function update(ctx: VisualContext, theme: Theme, props: Partial<VolumeProps> = {}) { if (!renderObject) return const newProps = Object.assign({}, currentProps, props) if (props.isoValueRelative) { newProps.isoValueAbsolute = VolumeIsoValue.calcAbsolute(currentVolume.dataStats, props.isoValueRelative) - console.log('update props.isoValueRelative', props.isoValueRelative, newProps.isoValueAbsolute, currentVolume.dataStats) + // console.log('update props.isoValueRelative', props.isoValueRelative, newProps.isoValueAbsolute, currentVolume.dataStats) } VisualUpdateState.reset(updateState) @@ -85,17 +85,17 @@ export function VolumeVisual<P extends VolumeProps>(builder: VolumeVisualGeometr return { get renderObject () { return renderObject }, - async createOrUpdate(ctx: VisualContext, props: Partial<VolumeProps> = {}, volume?: VolumeData) { + async createOrUpdate(ctx: VisualContext, theme: Theme, props: Partial<VolumeProps> = {}, volume?: VolumeData) { if (!volume && !currentVolume) { throw new Error('missing volume') } else if (volume && (!currentVolume || !renderObject)) { currentVolume = volume - await create(ctx, volume, props) + await create(ctx, volume, theme, props) } else if (volume && volume !== currentVolume) { currentVolume = volume - await create(ctx, volume, props) + await create(ctx, volume, theme, props) } else { - await update(ctx, props) + await update(ctx, theme, props) } currentProps = Object.assign({}, defaultProps, props) @@ -145,10 +145,13 @@ export type VolumeProps = typeof DefaultVolumeProps export function VolumeRepresentation<P extends VolumeProps>(visualCtor: (volumeData: VolumeData) => VolumeVisual<P>): VolumeRepresentation<P> { let visual: VolumeVisual<any> let _props: P + let _theme: Theme let busy = false function createOrUpdate(ctx: RepresentationContext, props: Partial<P> = {}, volumeData?: VolumeData) { _props = Object.assign({}, DefaultVolumeProps, _props, props) + _theme = createTheme(_props) + return Task.create('VolumeRepresentation.create', async runtime => { // TODO queue it somehow if (busy) return @@ -158,11 +161,11 @@ export function VolumeRepresentation<P extends VolumeProps>(visualCtor: (volumeD } else if (volumeData && !visual) { busy = true visual = visualCtor(volumeData) - await visual.createOrUpdate({ ...ctx, runtime } , props, volumeData) + await visual.createOrUpdate({ ...ctx, runtime }, _theme, _props, volumeData) busy = false } else { busy = true - await visual.createOrUpdate({ ...ctx, runtime }, props, volumeData) + await visual.createOrUpdate({ ...ctx, runtime }, _theme, _props, volumeData) busy = false } }); diff --git a/src/mol-repr/volume/isosurface-mesh.ts b/src/mol-repr/volume/isosurface-mesh.ts index 1f81989e83bab70631a943033fe36d39a466d790..1586550078e88129c385190f6f301ea50755e3d8 100644 --- a/src/mol-repr/volume/isosurface-mesh.ts +++ b/src/mol-repr/volume/isosurface-mesh.ts @@ -14,7 +14,7 @@ import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { computeMarchingCubesMesh } from 'mol-geo/util/marching-cubes/algorithm'; import { LocationIterator } from 'mol-geo/util/location-iterator'; import { createIdentityTransform } from 'mol-geo/geometry/transform-data'; -import { createRenderableState } from 'mol-geo/geometry/geometry'; +import { createRenderableState, Theme } from 'mol-geo/geometry/geometry'; import { PickingId } from 'mol-geo/geometry/picking'; import { MarkerAction } from 'mol-geo/geometry/marker-data'; import { VisualUpdateState } from 'mol-repr/util'; @@ -57,9 +57,9 @@ export function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> { setUpdateState: (state: VisualUpdateState, newProps: IsosurfaceProps, currentProps: IsosurfaceProps) => { if (newProps.isoValueAbsolute !== currentProps.isoValueAbsolute) state.createGeometry = true }, - createRenderObject: async (ctx: VisualContext, geometry: Mesh, locationIt: LocationIterator, props: IsosurfaceProps) => { + createRenderObject: async (ctx: VisualContext, geometry: Mesh, locationIt: LocationIterator, theme: Theme, props: IsosurfaceProps) => { const transform = createIdentityTransform() - const values = await Mesh.createValues(ctx.runtime, geometry, transform, locationIt, props) + const values = await Mesh.createValues(ctx.runtime, geometry, transform, locationIt, theme, props) const state = createRenderableState(props) return createMeshRenderObject(values, state) }, diff --git a/src/mol-theme/color/chain-id.ts b/src/mol-theme/color/chain-id.ts index 0fd9e3955a12238e72496d5e527a8a7e71741944..c91825e4729d16b1777eceb17796f75906109baf 100644 --- a/src/mol-theme/color/chain-id.ts +++ b/src/mol-theme/color/chain-id.ts @@ -25,7 +25,7 @@ function getAsymId(unit: Unit): StructureElement.Property<string> { export function ChainIdColorTheme(props: ColorThemeProps): ColorTheme { let color: LocationColor - let scale: ColorScale | undefined = undefined + const scale = ColorScale.create({ list: props.list, minLabel: 'Start', maxLabel: 'End' }) // const table: [string, Color][] = [] if (props.structure) { @@ -41,7 +41,7 @@ export function ChainIdColorTheme(props: ColorThemeProps): ColorTheme { } }) } - scale = ColorScale.create({ domain: [ 0, asymIdSerialMap.size - 1 ] }) + scale.setDomain(0, asymIdSerialMap.size - 1) const scaleColor = scale.color // asymIdSerialMap.forEach((v, k) => table.push([k, scaleColor(v)])) @@ -63,7 +63,7 @@ export function ChainIdColorTheme(props: ColorThemeProps): ColorTheme { } return { - features: {}, + features: { structure: true, list: true }, granularity: 'group', color, description: Description, diff --git a/src/mol-theme/color/cross-link.ts b/src/mol-theme/color/cross-link.ts index bb3cf176c4f5a5c8fdbc330b63e7c69e5436c089..d24b79e4a92b4e45f7f887df5e333066f0be69c0 100644 --- a/src/mol-theme/color/cross-link.ts +++ b/src/mol-theme/color/cross-link.ts @@ -49,7 +49,7 @@ export function CrossLinkColorTheme(props: ColorThemeProps): ColorTheme { } return { - features: { list: true, domain: true }, + features: { list: true, domain: true, structure: true }, granularity: 'group', color, description: Description, diff --git a/src/mol-theme/color/element-index.ts b/src/mol-theme/color/element-index.ts index ecce0a1c1bc0804043f2c9ee4c5f8aaabbc69882..2ba30ce687307d87d5caa9fb34a9db98c71c4e91 100644 --- a/src/mol-theme/color/element-index.ts +++ b/src/mol-theme/color/element-index.ts @@ -15,7 +15,7 @@ const Description = 'Gives every element (atom or coarse sphere/gaussian) a uniq export function ElementIndexColorTheme(props: ColorThemeProps): ColorTheme { let color: LocationColor - let scale: ColorScale | undefined = undefined + let scale = ColorScale.create({ list: props.list, minLabel: 'Start', maxLabel: 'End' }) if (props.structure) { const { units } = props.structure @@ -29,7 +29,7 @@ export function ElementIndexColorTheme(props: ColorThemeProps): ColorTheme { elementCount += units[i].elements.length unitIdIndex.set(units[i].id, i) } - scale = ColorScale.create({ domain: [ 0, elementCount - 1 ], list: props.list }) + scale.setDomain(0, elementCount - 1) const scaleColor = scale.color color = (location: Location): Color => { @@ -48,7 +48,7 @@ export function ElementIndexColorTheme(props: ColorThemeProps): ColorTheme { } return { - features: { list: true }, + features: { structure: true, list: true }, granularity: 'groupInstance', color, description: Description, diff --git a/src/mol-theme/color/polymer-index.ts b/src/mol-theme/color/polymer-index.ts index b32fa80cbaa1649bbdf2b0aed8d2ace1f6f9b3e8..b17a57dfe8a526c52dc1de93d0e5cee1ba558c0f 100644 --- a/src/mol-theme/color/polymer-index.ts +++ b/src/mol-theme/color/polymer-index.ts @@ -14,7 +14,7 @@ const Description = 'Gives every polymer a unique color based on the position (i export function PolymerIndexColorTheme(props: ColorThemeProps): ColorTheme { let color: LocationColor - let scale: ColorScale | undefined = undefined + const scale = ColorScale.create({ list: props.list, minLabel: 'Start', maxLabel: 'End' }) if (props.structure) { const { units } = props.structure @@ -22,7 +22,7 @@ export function PolymerIndexColorTheme(props: ColorThemeProps): ColorTheme { for (let i = 0, il = units.length; i <il; ++i) { if (units[i].polymerElements.length > 0) ++polymerCount } - scale = ColorScale.create({ list: props.list, domain: [ 0, polymerCount - 1 ] }) + scale.setDomain(0, polymerCount - 1) const unitIdColor = new Map<number, Color>() for (let i = 0, j = 0, il = units.length; i <il; ++i) { if (units[i].polymerElements.length > 0) { diff --git a/src/mol-theme/color/unit-index.ts b/src/mol-theme/color/unit-index.ts index f41b29199a01f064b84b4c3155fd64b06da9c4cd..a17dc82b6e40a5c7ac2782a970d248b682e0fd7b 100644 --- a/src/mol-theme/color/unit-index.ts +++ b/src/mol-theme/color/unit-index.ts @@ -14,11 +14,11 @@ const Description = 'Gives every unit (single chain or collection of single elem export function UnitIndexColorTheme(props: ColorThemeProps): ColorTheme { let color: LocationColor - let scale: ColorScale | undefined = undefined + const scale = ColorScale.create({ list: props.list, minLabel: 'Start', maxLabel: 'End' }) if (props.structure) { const { units } = props.structure - scale = ColorScale.create({ domain: [ 0, units.length - 1 ] }) + scale.setDomain(0, units.length - 1) const unitIdColor = new Map<number, Color>() for (let i = 0, il = units.length; i <il; ++i) { unitIdColor.set(units[i].id, scale.color(i)) @@ -37,7 +37,7 @@ export function UnitIndexColorTheme(props: ColorThemeProps): ColorTheme { } return { - features: {}, + features: { structure: true, list: true }, granularity: 'instance', color, description: Description,