|
@@ -5,65 +5,75 @@
|
|
|
*/
|
|
|
|
|
|
import { Task } from 'mol-task'
|
|
|
-import { RenderObject, createRenderObject, MeshRenderObject } from 'mol-gl/render-object';
|
|
|
-import { Representation, RepresentationContext } from '../representation';
|
|
|
+import { createRenderObject, GraphicsRenderObject } from 'mol-gl/render-object';
|
|
|
+import { Representation } from '../representation';
|
|
|
import { Loci, EmptyLoci, isEveryLoci } from 'mol-model/loci';
|
|
|
import { ValueCell } from 'mol-util';
|
|
|
import { Shape } from 'mol-model/shape';
|
|
|
import { OrderedSet, Interval } from 'mol-data/int';
|
|
|
import { ParamDefinition as PD } from 'mol-util/param-definition';
|
|
|
-import { Mesh } from 'mol-geo/geometry/mesh/mesh';
|
|
|
import { createIdentityTransform } from 'mol-geo/geometry/transform-data';
|
|
|
import { PickingId } from 'mol-geo/geometry/picking';
|
|
|
import { MarkerAction, applyMarkerAction } from 'mol-geo/geometry/marker-data';
|
|
|
import { LocationIterator } from 'mol-geo/util/location-iterator';
|
|
|
import { createEmptyTheme, Theme } from 'mol-theme/theme';
|
|
|
import { Subject } from 'rxjs';
|
|
|
+import { Geometry, GeometryUtils } from 'mol-geo/geometry/geometry';
|
|
|
+import { ShapeGroupColorTheme } from 'mol-theme/color/shape-group';
|
|
|
|
|
|
-export interface ShapeRepresentation<P extends ShapeParams> extends Representation<Shape, P> { }
|
|
|
+export interface ShapeRepresentation<D, G extends Geometry, P extends Geometry.Params<G>> extends Representation<D, P> { }
|
|
|
|
|
|
-export const ShapeParams = {
|
|
|
- ...Mesh.Params,
|
|
|
- // TODO
|
|
|
- // colorTheme: PD.Select<ColorThemeName>('Color Theme', '', 'shape-group', ColorThemeOptions)
|
|
|
-}
|
|
|
-export type ShapeParams = typeof ShapeParams
|
|
|
-
|
|
|
-export function ShapeRepresentation<P extends ShapeParams>(ctx: RepresentationContext): ShapeRepresentation<P> {
|
|
|
+export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Params<G>>(getShape: (data: D, props: PD.Values<P>, shape?: Shape<G>) => Shape<G>, geometryUtils: GeometryUtils<G>): ShapeRepresentation<D, G, P> {
|
|
|
let version = 0
|
|
|
const updated = new Subject<number>()
|
|
|
const _state = Representation.createState()
|
|
|
- const renderObjects: RenderObject[] = []
|
|
|
- let _renderObject: MeshRenderObject | undefined
|
|
|
- let _shape: Shape
|
|
|
+ const renderObjects: GraphicsRenderObject[] = []
|
|
|
+ let _renderObject: GraphicsRenderObject | undefined
|
|
|
+ let _shape: Shape<G>
|
|
|
let _theme = createEmptyTheme()
|
|
|
- let currentProps: PD.Values<P> = PD.getDefaultValues(ShapeParams) as PD.Values<P>
|
|
|
+ let currentProps: PD.Values<P> = PD.getDefaultValues(geometryUtils.Params as P) // TODO avoid casting
|
|
|
let currentParams: P
|
|
|
let locationIt: LocationIterator
|
|
|
|
|
|
- function createOrUpdate(props: Partial<PD.Values<P>> = {}, shape?: Shape) {
|
|
|
- currentProps = Object.assign({}, currentProps, props)
|
|
|
- if (shape) _shape = shape
|
|
|
+ function createOrUpdate(props: Partial<PD.Values<P>> = {}, data?: D) {
|
|
|
+ currentProps = Object.assign(currentProps, props)
|
|
|
+ const shape = data ? getShape(data, currentProps, _shape) : undefined
|
|
|
|
|
|
return Task.create('ShapeRepresentation.create', async runtime => {
|
|
|
- renderObjects.length = 0
|
|
|
+ if (!shape && !_shape) {
|
|
|
+ console.error('no shape given')
|
|
|
+ return
|
|
|
+ } else if (shape && !_shape) {
|
|
|
+ console.log('first shape')
|
|
|
+
|
|
|
+ } else if (shape && _shape && shape.id === _shape.id) {
|
|
|
+ console.log('same shape')
|
|
|
+
|
|
|
+ } else if (shape && _shape && shape.id !== _shape.id) {
|
|
|
+ console.log('new shape')
|
|
|
|
|
|
- if (!_shape) return
|
|
|
+ } else {
|
|
|
+ console.log('only props')
|
|
|
|
|
|
+ }
|
|
|
+
|
|
|
+ if (shape) _shape = shape
|
|
|
+ renderObjects.length = 0
|
|
|
locationIt = ShapeGroupIterator.fromShape(_shape)
|
|
|
- const transform = createIdentityTransform()
|
|
|
+ _theme.color = ShapeGroupColorTheme({ shape: _shape }, {})
|
|
|
|
|
|
- const values = Mesh.Utils.createValues(_shape.mesh, transform, locationIt, _theme, currentProps)
|
|
|
- const state = Mesh.Utils.createRenderableState(currentProps)
|
|
|
+ const transform = createIdentityTransform()
|
|
|
+ const values = geometryUtils.createValues(_shape.geometry, transform, locationIt, _theme, currentProps)
|
|
|
+ const state = geometryUtils.createRenderableState(currentProps)
|
|
|
|
|
|
- _renderObject = createRenderObject('mesh', values, state)
|
|
|
- renderObjects.push(_renderObject)
|
|
|
+ _renderObject = createRenderObject(_shape.geometry.kind, values, state)
|
|
|
+ if (_renderObject) renderObjects.push(_renderObject)
|
|
|
updated.next(version++)
|
|
|
});
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
- label: 'Shape mesh',
|
|
|
+ label: 'Shape geometry',
|
|
|
get groupCount () { return locationIt ? locationIt.count : 0 },
|
|
|
get renderObjects () { return renderObjects },
|
|
|
get props () { return currentProps },
|
|
@@ -84,7 +94,7 @@ export function ShapeRepresentation<P extends ShapeParams>(ctx: RepresentationCo
|
|
|
const { tMarker } = _renderObject.values
|
|
|
let changed = false
|
|
|
if (isEveryLoci(loci)) {
|
|
|
- if (applyMarkerAction(tMarker.ref.value.array, 0, _shape.mesh.triangleCount, action)) changed = true
|
|
|
+ if (applyMarkerAction(tMarker.ref.value.array, 0, _shape.groupCount, action)) changed = true
|
|
|
} else if (Shape.isLoci(loci)) {
|
|
|
for (const g of loci.groups) {
|
|
|
if (Interval.is(g.ids)) {
|
|
@@ -105,8 +115,8 @@ export function ShapeRepresentation<P extends ShapeParams>(ctx: RepresentationCo
|
|
|
return changed
|
|
|
},
|
|
|
setState(state: Partial<Representation.State>) {
|
|
|
- if (state.visible !== undefined) renderObjects.forEach(ro => ro.state.visible = state.visible!)
|
|
|
- if (state.pickable !== undefined) renderObjects.forEach(ro => ro.state.pickable = state.pickable!)
|
|
|
+ if (state.visible !== undefined) renderObjects.forEach(ro => ro.state.visible = !!state.visible)
|
|
|
+ if (state.pickable !== undefined) renderObjects.forEach(ro => ro.state.pickable = !!state.pickable)
|
|
|
// TODO state.transform
|
|
|
|
|
|
Representation.updateState(_state, state)
|
|
@@ -124,13 +134,12 @@ export function ShapeRepresentation<P extends ShapeParams>(ctx: RepresentationCo
|
|
|
|
|
|
export namespace ShapeGroupIterator {
|
|
|
export function fromShape(shape: Shape): LocationIterator {
|
|
|
- const { groupCount } = shape
|
|
|
const instanceCount = 1
|
|
|
const location = Shape.Location(shape)
|
|
|
const getLocation = (groupIndex: number) => {
|
|
|
location.group = groupIndex
|
|
|
return location
|
|
|
}
|
|
|
- return LocationIterator(groupCount, instanceCount, getLocation)
|
|
|
+ return LocationIterator(shape.groupCount, instanceCount, getLocation)
|
|
|
}
|
|
|
}
|