Skip to content
Snippets Groups Projects
Commit 0e3f6d8c authored by Alexander Rose's avatar Alexander Rose
Browse files

ui, spacefill visibility and structure center

parent 914e4d35
No related branches found
No related tags found
No related merge requests found
......@@ -88,7 +88,7 @@ export function isEnter(e: React.KeyboardEvent<HTMLInputElement>) {
export function TextBoxGroup(props: {
value: string,
onChange: (v: string) => void,
placeholder?:string,
placeholder?: string,
label: string,
onEnter?: (e: React.KeyboardEvent<HTMLInputElement>) => void
title?: string
......
......@@ -13,7 +13,7 @@ import { View } from '../view';
import { EntityTreeController } from '../../controller/entity/tree';
import { Controller } from '../../controller/controller';
import { AnyEntity, RootEntity } from 'mol-view/state/entity';
import { AnyTransform, SpacefillUpdate, UrlToData, DataToCif, FileToData, CifToMmcif, MmcifToModel, ModelToStructure, StructureToSpacefill, MmcifFileToSpacefill } from 'mol-view/state/transform';
import { AnyTransform, SpacefillUpdate, UrlToData, DataToCif, FileToData, CifToMmcif, MmcifToModel, ModelToStructure, StructureToSpacefill, MmcifFileToSpacefill, StructureCenter } from 'mol-view/state/transform';
function getTransforms(entity: AnyEntity): AnyTransform[] {
const transforms: AnyTransform[] = []
......@@ -40,7 +40,7 @@ function getTransforms(entity: AnyEntity): AnyTransform[] {
transforms.push(ModelToStructure)
break;
case 'structure':
transforms.push(StructureToSpacefill)
transforms.push(StructureToSpacefill, StructureCenter)
break;
case 'spacefill':
transforms.push(SpacefillUpdate)
......
......@@ -17,6 +17,7 @@ import { Spacefill } from './spacefill';
import { AnyEntity } from 'mol-view/state/entity';
import { FileLoader } from './file-loader';
import { ModelToStructure } from './model';
import { StructureCenter } from './structure';
function getTransformComponent(controller: TransformListController, entity: AnyEntity, transform: AnyTransform) {
switch (transform.kind) {
......@@ -24,6 +25,8 @@ function getTransformComponent(controller: TransformListController, entity: AnyE
return <FileLoader controller={controller} ctx={controller.context.stage.ctx}></FileLoader>
case 'model-to-structure':
return <ModelToStructure controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></ModelToStructure>
case 'structure-center':
return <StructureCenter controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></StructureCenter>
case 'spacefill-update':
return <Spacefill controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></Spacefill>
}
......
......@@ -11,11 +11,14 @@ import * as React from 'react'
import { View } from '../view';
import { Controller } from '../../controller/controller';
import { Toggle } from '../controls/common';
import { SpacefillEntity } from 'mol-view/state/entity';
import { SpacefillUpdate } from 'mol-view/state/transform'
import { StateContext } from 'mol-view/state/context';
import { ColorTheme } from 'mol-geo/theme';
import { Color, ColorNames } from 'mol-util/color';
import { Query, Queries as Q } from 'mol-model/structure';
import { Slider } from '../controls/slider';
export const ColorThemeInfo = {
'atom-index': {},
......@@ -31,6 +34,8 @@ interface SpacefillState {
detail: number
colorTheme: ColorTheme
colorValue: Color
visible: boolean
alpha: number
}
export class Spacefill extends View<Controller<any>, SpacefillState, { transform: SpacefillUpdate, entity: SpacefillEntity, ctx: StateContext }> {
......@@ -38,7 +43,9 @@ export class Spacefill extends View<Controller<any>, SpacefillState, { transform
doubleSided: true,
detail: 2,
colorTheme: { name: 'element-symbol' } as ColorTheme,
colorValue: 0x000000
colorValue: 0x000000,
visible: true,
alpha: 1
}
update(state?: Partial<SpacefillState>) {
......@@ -135,6 +142,27 @@ export class Spacefill extends View<Controller<any>, SpacefillState, { transform
</select>
</div>
</div>
<div className='molstar-control-row molstar-options-group'>
<div>
<Toggle
value={this.state.visible}
label='Visibility'
onChange={value => this.update({ visible: value })}
/>
</div>
</div>
{/* <div className='molstar-control-row molstar-options-group'>
<div>
<Slider
value={this.state.alpha}
label='Opacity'
min={0}
max={1}
step={0.01}
onChange={value => this.update({ alpha: value })}
/>
</div>
</div> */}
</div>
</div>
</div>
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* Adapted from LiteMol
* Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import * as React from 'react'
import { View } from '../view';
import { Controller } from '../../controller/controller';
import { Button } from '../controls/common';
import { StructureEntity } from 'mol-view/state/entity';
import { StructureCenter as StructureCenterTransform } from 'mol-view/state/transform'
import { StateContext } from 'mol-view/state/context';
export const ColorThemeInfo = {
'atom-index': {},
'chain-id': {},
'element-symbol': {},
'instance-index': {},
'uniform': {}
}
export type ColorThemeInfo = keyof typeof ColorThemeInfo
export class StructureCenter extends View<Controller<any>, {}, { transform: StructureCenterTransform, entity: StructureEntity, ctx: StateContext }> {
center() {
const { ctx, entity, transform } = this.props
transform.apply(ctx, entity)
}
render() {
const { transform } = this.props
return <div className='molstar-transformer-wrapper'>
<div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'>
<div className='molstar-panel-header'>
<button
className='molstar-btn molstar-btn-link molstar-panel-expander'
onClick={() => {}}
>
<span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span>
</button>
</div>
<div className='molstar-panel-body'>
<div>
<div className='molstar-control-row molstar-options-group'>
<div>
<Button onClick={value => this.center()}>
Center
</Button>
</div>
</div>
</div>
</div>
</div>
</div>;
}
}
\ No newline at end of file
......@@ -9,8 +9,7 @@ import { Structure, StructureSymmetry, Unit } from 'mol-model/structure';
import { Task } from 'mol-task'
import { RenderObject } from 'mol-gl/scene';
import { Representation, RepresentationProps } from '..';
// import { Mat4, EPSILON } from 'mol-math/linear-algebra';
import { ColorTheme } from '../../theme';
export interface UnitsRepresentation<P> {
renderObjects: ReadonlyArray<RenderObject>
......@@ -29,14 +28,29 @@ interface GroupRepresentation<T> {
group: Unit.SymmetryGroup
}
export function StructureRepresentation<P>(reprCtor: () => UnitsRepresentation<P>): StructureRepresentation<P> {
export const DefaultStructureProps = {
colorTheme: { name: 'instance-index' } as ColorTheme,
alpha: 1,
visible: true,
doubleSided: false
}
export type StructureProps = Partial<typeof DefaultStructureProps>
export function StructureRepresentation<P extends StructureProps>(reprCtor: () => UnitsRepresentation<P>): StructureRepresentation<P> {
const renderObjects: RenderObject[] = []
const groupReprs: GroupRepresentation<P>[] = []
// let currentProps: typeof DefaultStructureProps
return {
renderObjects,
create(structure: Structure, props: P = {} as P) {
// currentProps = Object.assign({}, DefaultStructureProps, props)
return Task.create('StructureRepresentation.create', async ctx => {
// const { query } = currentProps
// const qs = await query(structure).runAsChild(ctx)
// const subStructure = Selection.unionStructure(qs)
const groups = StructureSymmetry.getTransformGroups(structure);
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
......@@ -49,8 +63,8 @@ export function StructureRepresentation<P>(reprCtor: () => UnitsRepresentation<P
},
update(props: P) {
return Task.create('StructureRepresentation.update', async ctx => {
// TODO check model.id, conformation.id, unit.id, elementGroup(.hashCode/.areEqual)
renderObjects.length = 0 // clear
for (let i = 0, il = groupReprs.length; i < il; ++i) {
const groupRepr = groupReprs[i]
const { repr, group } = groupRepr
......
......@@ -11,20 +11,16 @@ import { RenderObject, createMeshRenderObject, MeshRenderObject } from 'mol-gl/s
// import { createColorTexture } from 'mol-gl/util';
import { Vec3, Mat4 } from 'mol-math/linear-algebra'
import { Unit, Element, Queries } from 'mol-model/structure';
import { UnitsRepresentation } from './index';
import { UnitsRepresentation, DefaultStructureProps } from './index';
import { Task } from 'mol-task'
import { MeshBuilder } from '../../shape/mesh-builder';
import { createTransforms, createColors } from './utils';
import { ColorTheme } from '../../theme';
import VertexMap from '../../shape/vertex-map';
import { icosahedronVertexCount } from '../../primitive/icosahedron';
export const DefaultSpacefillProps = {
...DefaultStructureProps,
detail: 0,
colorTheme: { name: 'instance-index' } as ColorTheme,
alpha: 1,
visible: true,
doubleSided: false
}
export type SpacefillProps = Partial<typeof DefaultSpacefillProps>
......@@ -74,10 +70,13 @@ function createSpacefillMesh(unit: Unit, detail: number) {
export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
const renderObjects: RenderObject[] = []
let spheres: MeshRenderObject
let currentProps: typeof DefaultSpacefillProps
return {
renderObjects,
create(group: Unit.SymmetryGroup, props: SpacefillProps = {}) {
currentProps = Object.assign({}, DefaultSpacefillProps, props)
return Task.create('Spacefill.create', async ctx => {
renderObjects.length = 0 // clear
......@@ -116,10 +115,20 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
})
},
update(props: SpacefillProps) {
const newProps = Object.assign({}, currentProps, props)
return Task.create('Spacefill.update', async ctx => {
if (!spheres) return false
if (props.detail !== currentProps.detail) return false
if (props.colorTheme !== currentProps.colorTheme) return false
if (props.detail !== currentProps.detail) return false
spheres.props.alpha = newProps.alpha
spheres.props.visible = newProps.visible
spheres.props.doubleSided = newProps.doubleSided
return false
currentProps = newProps
return true
})
}
}
......
......@@ -15,6 +15,7 @@ import InputObserver, { DragInput, WheelInput, ButtonsFlag, PinchInput } from 'm
export const DefaultTrackballControlsProps = {
noScroll: true,
target: [0, 0, 0] as Vec3,
rotateSpeed: 3.0,
zoomSpeed: 4.0,
......@@ -36,6 +37,7 @@ interface Object {
interface TrackballControls {
viewport: Viewport
target: Vec3
dynamicDampingFactor: number
rotateSpeed: number
......@@ -52,6 +54,7 @@ namespace TrackballControls {
const p = { ...DefaultTrackballControlsProps, ...props }
const viewport: Viewport = { x: 0, y: 0, width: 0, height: 0 }
const target: Vec3 = Vec3.clone(p.target)
let { rotateSpeed, zoomSpeed, panSpeed } = p
let { staticMoving, dynamicDampingFactor } = p
......@@ -64,7 +67,6 @@ namespace TrackballControls {
const pinchSub = input.pinch.subscribe(onPinch)
// For internal use
const target = Vec3.zero()
const lastPosition = Vec3.zero()
const _eye = Vec3.zero()
......@@ -297,6 +299,7 @@ namespace TrackballControls {
return {
viewport,
target,
get dynamicDampingFactor() { return dynamicDampingFactor },
set dynamicDampingFactor(value: number ) { dynamicDampingFactor = value },
......
......@@ -31,7 +31,9 @@ export namespace StateEntity {
}
export type AnyEntity = StateEntity<any, any>
export type NullEntity = StateEntity<null, 'null'>
export const NullEntity: NullEntity = { id: -1, kind: 'null', value: null }
export const RootEntity: StateEntity<null, 'root'> = { id: 0, kind: 'root', value: null }
export interface UrlProps {
......
......@@ -5,7 +5,7 @@
*/
import CIF from 'mol-io/reader/cif'
import { FileEntity, DataEntity, UrlEntity, CifEntity, MmcifEntity, ModelEntity, StructureEntity, SpacefillEntity, AnyEntity } from './entity';
import { FileEntity, DataEntity, UrlEntity, CifEntity, MmcifEntity, ModelEntity, StructureEntity, SpacefillEntity, AnyEntity, NullEntity } from './entity';
import { Model, Structure } from 'mol-model/structure';
import { StateContext } from './context';
......@@ -80,9 +80,17 @@ export const ModelToStructure: ModelToStructure = StateTransform.create('model',
} else {
structure = Structure.ofModel(model)
}
console.log('center', structure.boundary.sphere.center)
return StructureEntity.ofStructure(ctx, structure)
})
export type StructureCenter = StateTransform<StructureEntity, NullEntity, {}>
export const StructureCenter: StructureCenter = StateTransform.create('structure', 'null', 'structure-center',
async function (ctx: StateContext, structureEntity: StructureEntity) {
ctx.viewer.center(structureEntity.value.boundary.sphere.center)
return NullEntity
})
export type StructureToSpacefill = StateTransform<StructureEntity, SpacefillEntity, SpacefillProps>
export const StructureToSpacefill: StructureToSpacefill = StateTransform.create('structure', 'spacefill', 'structure-to-spacefill',
async function (ctx: StateContext, structureEntity: StructureEntity, props: SpacefillProps = {}) {
......@@ -90,21 +98,29 @@ export const StructureToSpacefill: StructureToSpacefill = StateTransform.create(
await spacefillRepr.create(structureEntity.value, props).run(ctx.log)
ctx.viewer.add(spacefillRepr)
ctx.viewer.requestDraw()
console.log(ctx.viewer.stats)
console.log(ctx.viewer.stats, props)
// ctx.viewer.input.drag.subscribe(async () => {
// console.log('drag')
// console.time('spacefill update')
// await spacefillRepr.update(props).run(ctx.log)
// console.timeEnd('spacefill update')
// ctx.viewer.add(spacefillRepr)
// ctx.viewer.update()
// ctx.viewer.requestDraw()
// })
return SpacefillEntity.ofRepr(ctx, spacefillRepr)
})
export type SpacefillUpdate = StateTransform<SpacefillEntity, SpacefillEntity, SpacefillProps>
export const SpacefillUpdate: SpacefillUpdate = StateTransform.create('spacefill', 'spacefill', 'spacefill-update',
export type SpacefillUpdate = StateTransform<SpacefillEntity, NullEntity, SpacefillProps>
export const SpacefillUpdate: SpacefillUpdate = StateTransform.create('spacefill', 'null', 'spacefill-update',
async function (ctx: StateContext, spacefillEntity: SpacefillEntity, props: SpacefillProps = {}) {
console.log('fopbar')
const spacefillRepr = spacefillEntity.value
await spacefillRepr.update(props).run(ctx.log)
ctx.viewer.add(spacefillRepr)
ctx.viewer.update()
ctx.viewer.requestDraw()
console.log(ctx.viewer.stats)
return spacefillEntity
console.log(ctx.viewer.stats, props)
return NullEntity
})
// composed
......
......@@ -20,6 +20,8 @@ import { createContext } from 'mol-gl/webgl/context';
import { Representation } from 'mol-geo/representation';
interface Viewer {
center: (p: Vec3) => void
hide: (repr: Representation<any>) => void
show: (repr: Representation<any>) => void
......@@ -37,6 +39,7 @@ interface Viewer {
resetCamera: () => void
downloadScreenshot: () => void
input: InputObserver
stats: RendererStats
dispose: () => void
}
......@@ -110,6 +113,10 @@ namespace Viewer {
handleResize()
return {
center: (p: Vec3) => {
Vec3.set(controls.target, p[0], p[1], p[2])
},
hide: (repr: Representation<any>) => {
const renderObjectSet = reprMap.get(repr)
if (renderObjectSet) renderObjectSet.forEach(o => o.props.visible = false)
......@@ -159,6 +166,9 @@ namespace Viewer {
},
reprCount,
get input() {
return input
},
get stats() {
return renderer.stats
},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment