diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts index b9bbb639ef126489123bab6d076ea25823188055..3c97dcd0acfde1ee9eb7de153f1eef3ad644084b 100644 --- a/src/mol-canvas3d/canvas3d.ts +++ b/src/mol-canvas3d/canvas3d.ts @@ -13,7 +13,7 @@ import * as SetUtils from 'mol-util/set' import Renderer, { RendererStats } from 'mol-gl/renderer' import { RenderObject } from 'mol-gl/render-object' -import TrackballControls from './controls/trackball' +import { TrackballControls, TrackballControlsParams } from './controls/trackball' import { Viewport } from './camera/util' import { resizeCanvas } from './util'; import { createContext, getGLContext, WebGLContext } from 'mol-gl/webgl/context'; @@ -37,9 +37,10 @@ export const Canvas3DParams = { clip: PD.Interval([1, 100], { min: 1, max: 100, step: 1 }), fog: PD.Interval([50, 100], { min: 1, max: 100, step: 1 }), pickingAlphaThreshold: PD.Numeric(0.5, { min: 0.0, max: 1.0, step: 0.01 }, { description: 'The minimum opacity value needed for an object to be pickable.' }), + trackball: PD.Group(TrackballControlsParams), debug: PD.Group(DebugHelperParams) } -export type Canvas3DParams = PD.Values<typeof Canvas3DParams> +export type Canvas3DProps = PD.Values<typeof Canvas3DParams> export { Canvas3D } @@ -67,17 +68,17 @@ interface Canvas3D { readonly camera: Camera downloadScreenshot: () => void getImageData: (variant: RenderVariant) => ImageData - setProps: (props: Partial<Canvas3DParams>) => void + setProps: (props: Partial<Canvas3DProps>) => void /** Returns a copy of the current Canvas3D instance props */ - readonly props: Canvas3DParams + readonly props: Canvas3DProps readonly input: InputObserver readonly stats: RendererStats dispose: () => void } namespace Canvas3D { - export function create(canvas: HTMLCanvasElement, container: Element, props: Partial<Canvas3DParams> = {}): Canvas3D { + export function create(canvas: HTMLCanvasElement, container: Element, props: Partial<Canvas3DProps> = {}): Canvas3D { const p = { ...PD.getDefaultValues(Canvas3DParams), ...props } const reprRenderObjects = new Map<Representation.Any, Set<RenderObject>>() @@ -107,7 +108,7 @@ namespace Canvas3D { const webgl = createContext(gl) const scene = Scene.create(webgl) - const controls = TrackballControls.create(input, camera, {}) + const controls = TrackballControls.create(input, camera, p.trackball) const renderer = Renderer.create(webgl, camera, { clearColor: p.backgroundColor }) let pickScale = 0.25 / webgl.pixelRatio @@ -362,7 +363,7 @@ namespace Canvas3D { } }, didDraw, - setProps: (props: Partial<Canvas3DParams>) => { + setProps: (props: Partial<Canvas3DProps>) => { if (props.cameraMode !== undefined && props.cameraMode !== camera.state.mode) { camera.setState({ mode: props.cameraMode }) } @@ -376,9 +377,8 @@ namespace Canvas3D { if (props.pickingAlphaThreshold !== undefined && props.pickingAlphaThreshold !== renderer.props.pickingAlphaThreshold) { renderer.setPickingAlphaThreshold(props.pickingAlphaThreshold) } - if (props.debug) { - debugHelper.setProps(props.debug) - } + if (props.trackball) controls.setProps(props.trackball) + if (props.debug) debugHelper.setProps(props.debug) requestDraw(true) }, @@ -389,6 +389,7 @@ namespace Canvas3D { clip: p.clip, fog: p.fog, pickingAlphaThreshold: renderer.props.pickingAlphaThreshold, + trackball: { ...controls.props }, debug: { ...debugHelper.props } } }, diff --git a/src/mol-canvas3d/controls/trackball.ts b/src/mol-canvas3d/controls/trackball.ts index 9703eac2d106fba7c1e787fd46cf3ab27c625be8..269c5819cc3f8530f8f9fd631a0eb29e116276c6 100644 --- a/src/mol-canvas3d/controls/trackball.ts +++ b/src/mol-canvas3d/controls/trackball.ts @@ -3,9 +3,7 @@ * * @author Alexander Rose <alexander.rose@weirdbyte.de> * @author David Sehnal <david.sehnal@gmail.com> - */ - -/* + * * This code has been modified from https://github.com/mrdoob/three.js/, * copyright (c) 2010-2018 three.js authors. MIT License */ @@ -14,46 +12,41 @@ import { Quat, Vec2, Vec3, EPSILON } from 'mol-math/linear-algebra'; import { cameraLookAt, Viewport } from '../camera/util'; import InputObserver, { DragInput, WheelInput, ButtonsType, PinchInput } from 'mol-util/input/input-observer'; import { Object3D } from 'mol-gl/object3d'; +import { ParamDefinition as PD } from 'mol-util/param-definition'; -export const DefaultTrackballControlsProps = { - noScroll: true, +export const TrackballControlsParams = { + noScroll: PD.Boolean(true, { isHidden: true }), - rotateSpeed: 3.0, - zoomSpeed: 4.0, - panSpeed: 0.8, + rotateSpeed: PD.Numeric(5.0, { min: 0.1, max: 10, step: 0.1 }), + zoomSpeed: PD.Numeric(6.0, { min: 0.1, max: 10, step: 0.1 }), + panSpeed: PD.Numeric(0.8, { min: 0.1, max: 5, step: 0.1 }), - staticMoving: true, - dynamicDampingFactor: 0.2, + staticMoving: PD.Boolean(true, { isHidden: true }), + dynamicDampingFactor: PD.Numeric(0.2, {}, { isHidden: true }), - minDistance: 0.01, - maxDistance: Infinity + minDistance: PD.Numeric(0.01, {}, { isHidden: true }), + maxDistance: PD.Numeric(Infinity, {}, { isHidden: true }) } -export type TrackballControlsProps = Partial<typeof DefaultTrackballControlsProps> +export type TrackballControlsProps = PD.Values<typeof TrackballControlsParams> +export { TrackballControls } interface TrackballControls { viewport: Viewport - dynamicDampingFactor: number - rotateSpeed: number - zoomSpeed: number - panSpeed: number + readonly props: Readonly<TrackballControlsProps> + setProps: (props: Partial<TrackballControlsProps>) => void update: () => void reset: () => void dispose: () => void } - namespace TrackballControls { - export function create (input: InputObserver, object: Object3D & { target: Vec3 }, props: TrackballControlsProps = {}): TrackballControls { - const p = { ...DefaultTrackballControlsProps, ...props } + export function create (input: InputObserver, object: Object3D & { target: Vec3 }, props: Partial<TrackballControlsProps> = {}): TrackballControls { + const p = { ...PD.getDefaultValues(TrackballControlsParams), ...props } const viewport: Viewport = { x: 0, y: 0, width: 0, height: 0 } const target: Vec3 = object.target - let { rotateSpeed, zoomSpeed, panSpeed } = p - let { staticMoving, dynamicDampingFactor } = p - let { minDistance, maxDistance } = p - let disposed = false const dragSub = input.drag.subscribe(onDrag) @@ -131,7 +124,7 @@ namespace TrackballControls { Vec3.normalize(rotAxis, Vec3.cross(rotAxis, rotMoveDir, _eye)) - angle *= rotateSpeed; + angle *= p.rotateSpeed; Quat.setAxisAngle(rotQuat, rotAxis, angle ) Vec3.transformQuat(_eye, _eye, rotQuat) @@ -139,8 +132,8 @@ namespace TrackballControls { Vec3.copy(_lastAxis, rotAxis) _lastAngle = angle; - } else if (!staticMoving && _lastAngle) { - _lastAngle *= Math.sqrt(1.0 - dynamicDampingFactor); + } else if (!p.staticMoving && _lastAngle) { + _lastAngle *= Math.sqrt(1.0 - p.dynamicDampingFactor); Vec3.sub(_eye, Vec3.copy(_eye, object.position), target) Quat.setAxisAngle(rotQuat, _lastAxis, _lastAngle) @@ -152,15 +145,15 @@ namespace TrackballControls { } function zoomCamera () { - const factor = 1.0 + (_zoomEnd[1] - _zoomStart[1]) * zoomSpeed + const factor = 1.0 + (_zoomEnd[1] - _zoomStart[1]) * p.zoomSpeed if (factor !== 1.0 && factor > 0.0) { Vec3.scale(_eye, _eye, factor) } - if (staticMoving) { + if (p.staticMoving) { Vec2.copy(_zoomStart, _zoomEnd) } else { - _zoomStart[1] += (_zoomEnd[1] - _zoomStart[1]) * dynamicDampingFactor + _zoomStart[1] += (_zoomEnd[1] - _zoomStart[1]) * p.dynamicDampingFactor } } @@ -172,7 +165,7 @@ namespace TrackballControls { Vec2.sub(panMouseChange, Vec2.copy(panMouseChange, _panEnd), _panStart) if (Vec2.squaredMagnitude(panMouseChange)) { - Vec2.scale(panMouseChange, panMouseChange, Vec3.magnitude(_eye) * panSpeed) + Vec2.scale(panMouseChange, panMouseChange, Vec3.magnitude(_eye) * p.panSpeed) Vec3.cross(panOffset, Vec3.copy(panOffset, _eye), object.up) Vec3.setMagnitude(panOffset, panOffset, panMouseChange[0]) @@ -183,11 +176,11 @@ namespace TrackballControls { Vec3.add(object.position, object.position, panOffset) Vec3.add(target, target, panOffset) - if (staticMoving) { + if (p.staticMoving) { Vec2.copy(_panStart, _panEnd) } else { Vec2.sub(panMouseChange, _panEnd, _panStart) - Vec2.scale(panMouseChange, panMouseChange, dynamicDampingFactor) + Vec2.scale(panMouseChange, panMouseChange, p.dynamicDampingFactor) Vec2.add(_panStart, _panStart, panMouseChange) } } @@ -195,14 +188,14 @@ namespace TrackballControls { /** Ensure the distance between object and target is within the min/max distance */ function checkDistances() { - if (Vec3.squaredMagnitude(_eye) > maxDistance * maxDistance) { - Vec3.setMagnitude(_eye, _eye, maxDistance) + if (Vec3.squaredMagnitude(_eye) > p.maxDistance * p.maxDistance) { + Vec3.setMagnitude(_eye, _eye, p.maxDistance) Vec3.add(object.position, target, _eye) Vec2.copy(_zoomStart, _zoomEnd) } - if (Vec3.squaredMagnitude(_eye) < minDistance * minDistance) { - Vec3.setMagnitude(_eye, _eye, minDistance) + if (Vec3.squaredMagnitude(_eye) < p.minDistance * p.minDistance) { + Vec3.setMagnitude(_eye, _eye, p.minDistance) Vec3.add(object.position, target, _eye) Vec2.copy(_zoomStart, _zoomEnd) } @@ -274,7 +267,7 @@ namespace TrackballControls { } _touchZoomDistanceEnd = distance - const factor = (_touchZoomDistanceStart / _touchZoomDistanceEnd) * zoomSpeed + const factor = (_touchZoomDistanceStart / _touchZoomDistanceEnd) * p.zoomSpeed _touchZoomDistanceStart = _touchZoomDistanceEnd; Vec3.scale(_eye, _eye, factor) } @@ -294,20 +287,12 @@ namespace TrackballControls { return { viewport, - get dynamicDampingFactor() { return dynamicDampingFactor }, - set dynamicDampingFactor(value: number ) { dynamicDampingFactor = value }, - get rotateSpeed() { return rotateSpeed }, - set rotateSpeed(value: number ) { rotateSpeed = value }, - get zoomSpeed() { return zoomSpeed }, - set zoomSpeed(value: number ) { zoomSpeed = value }, - get panSpeed() { return panSpeed }, - set panSpeed(value: number ) { panSpeed = value }, + get props() { return p as Readonly<TrackballControlsProps> }, + setProps: (props: Partial<TrackballControlsProps>) => { Object.assign(p, props) }, update, reset, dispose } } -} - -export default TrackballControls \ No newline at end of file +} \ No newline at end of file