Skip to content
Snippets Groups Projects
Commit 061bf7c7 authored by David Sehnal's avatar David Sehnal
Browse files

implemented bounded interval control, camera fog/clip as interval

parent fafc56d8
No related branches found
No related tags found
No related merge requests found
......@@ -97,6 +97,7 @@ class Camera implements Object3D {
Vec3.setMagnitude(this.deltaDirection, this.state.direction, deltaDistance)
if (currentDistance < targetDistance) Vec3.negate(this.deltaDirection, this.deltaDirection)
Vec3.add(this.newPosition, this.state.position, this.deltaDirection)
this.setState({ target, position: this.newPosition })
}
......
......@@ -35,11 +35,8 @@ export const Canvas3DParams = {
cameraMode: PD.Select('perspective', [['perspective', 'Perspective'], ['orthographic', 'Orthographic']]),
backgroundColor: PD.Color(Color(0x000000)),
// TODO: make this an interval?
clipNear: PD.Numeric(1, { min: 1, max: 100, step: 1 }),
clipFar: PD.Numeric(100, { min: 1, max: 100, step: 1 }),
// TODO: make this an interval?
fogNear: PD.Numeric(50, { min: 1, max: 100, step: 1 }),
fogFar: PD.Numeric(100, { min: 1, max: 100, step: 1 }),
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.' }),
showBoundingSpheres: PD.Boolean(false, { description: 'Show bounding spheres of render objects.' }),
// debug: PD.Group({
......@@ -168,13 +165,13 @@ namespace Canvas3D {
const cDist = Vec3.distance(camera.state.position, camera.state.target)
const bRadius = Math.max(10, scene.boundingSphere.radius)
const nearFactor = (50 - p.clipNear) / 50
const farFactor = -(50 - p.clipFar) / 50
const nearFactor = (50 - p.clip[0]) / 50
const farFactor = -(50 - p.clip[1]) / 50
const near = cDist - (bRadius * nearFactor)
const far = cDist + (bRadius * farFactor)
const fogNearFactor = (50 - p.fogNear) / 50
const fogFarFactor = -(50 - p.fogFar) / 50
const fogNearFactor = (50 - p.fog[0]) / 50
const fogFarFactor = -(50 - p.fog[1]) / 50
const fogNear = cDist - (bRadius * fogNearFactor)
const fogFar = cDist + (bRadius * fogFarFactor)
......@@ -378,10 +375,8 @@ namespace Canvas3D {
renderer.setClearColor(props.backgroundColor)
}
if (props.clipNear !== undefined) p.clipNear = props.clipNear
if (props.clipFar !== undefined) p.clipFar = props.clipFar
if (props.fogNear !== undefined) p.fogNear = props.fogNear
if (props.fogFar !== undefined) p.fogFar = props.fogFar
if (props.clip !== undefined) p.clip = [props.clip[0], props.clip[1]]
if (props.fog !== undefined) p.fog = [props.fog[0], props.fog[1]]
if (props.pickingAlphaThreshold !== undefined && props.pickingAlphaThreshold !== renderer.props.pickingAlphaThreshold) {
renderer.setPickingAlphaThreshold(props.pickingAlphaThreshold)
......@@ -396,10 +391,8 @@ namespace Canvas3D {
return {
cameraMode: camera.state.mode,
backgroundColor: renderer.props.clearColor,
clipNear: p.clipNear,
clipFar: p.clipFar,
fogNear: p.fogNear,
fogFar: p.fogFar,
clip: p.clip,
fog: p.fog,
pickingAlphaThreshold: renderer.props.pickingAlphaThreshold,
showBoundingSpheres: boundingSphereHelper.visible
}
......
......@@ -110,6 +110,57 @@
// }
}
.msp-slider2 {
> div:first-child {
position: absolute;
height: $row-height;
line-height: $row-height;
text-align: center;
left: 0;
width: 25px;
top: 0;
bottom: 0;
font-size: 80%;
}
> div:nth-child(2) {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 25px;
width: 100%;
padding-left: 20px;
padding-right: 25px;
display: table;
> div {
height: $row-height;
display: table-cell;
vertical-align: middle;
padding: 0 ($control-spacing + 4px);
}
}
> div:last-child {
position: absolute;
height: $row-height;
line-height: $row-height;
text-align: center;
right: 0;
width: 25px;
top: 0;
bottom: 0;
font-size: 80%;
}
// input[type=text] {
// text-align: right;
// }
// input[type=range] {
// width: 100%;
// }
}
.msp-toggle-color-picker {
button {
border: $control-spacing solid $msp-form-control-background !important;
......
......@@ -10,7 +10,7 @@ import { ParamDefinition as PD } from 'mol-util/param-definition';
import { camelCaseToWords } from 'mol-util/string';
import { ColorNames } from 'mol-util/color/tables';
import { Color } from 'mol-util/color';
import { Slider } from './slider';
import { Slider, Slider2 } from './slider';
export interface ParameterControlsProps<P extends PD.Params = PD.Params> {
params: P,
......@@ -49,7 +49,8 @@ function controlFor(param: PD.Any): ParamControl | undefined {
case 'file': return FileControl;
case 'select': return SelectControl;
case 'text': return TextControl;
case 'interval': return IntervalControl;
case 'interval': return typeof param.min !== 'undefined' && typeof param.max !== 'undefined'
? BoundedIntervalControl : IntervalControl;
case 'group': return GroupControl;
case 'mapped': return MappedControl;
case 'line-graph': return void 0;
......@@ -146,16 +147,20 @@ export class SelectControl extends SimpleParam<PD.Select<any>> {
}
export class IntervalControl extends SimpleParam<PD.Interval> {
// onChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
// this.setState({ value: e.target.value });
// this.props.onChange(e.target.value);
// }
onChange = (v: [number, number]) => { this.update(v); }
renderControl() {
return <span>interval TODO</span>;
}
}
export class BoundedIntervalControl extends SimpleParam<PD.Interval> {
onChange = (v: [number, number]) => { this.update(v); }
renderControl() {
return <Slider2 value={this.props.value} min={this.props.param.min!} max={this.props.param.max!}
step={this.props.param.step} onChange={this.onChange} disabled={this.props.isDisabled} />;
}
}
export class ColorControl extends SimpleParam<PD.Color> {
onChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
this.update(Color(parseInt(e.target.value)));
......
......@@ -52,6 +52,54 @@ export class Slider extends React.Component<{
}
}
export class Slider2 extends React.Component<{
min: number,
max: number,
value: [number, number],
step?: number,
onChange: (v: [number, number]) => void,
disabled?: boolean
}, { isChanging: boolean, current: [number, number] }> {
state = { isChanging: false, current: [0, 1] as [number, number] }
static getDerivedStateFromProps(props: { value: [number, number] }, state: { isChanging: boolean, current: [number, number] }) {
if (state.isChanging || (props.value[0] === state.current[0]) && (props.value[1] === state.current[1])) return null;
return { current: props.value };
}
begin = () => {
this.setState({ isChanging: true });
}
end = (v: [number, number]) => {
this.setState({ isChanging: false });
this.props.onChange(v);
}
updateCurrent = (current: [number, number]) => {
this.setState({ current });
}
render() {
let step = this.props.step;
if (step === void 0) step = 1;
return <div className='msp-slider2'>
<div>
{`${Math.round(100 * this.state.current[0]) / 100}`}
</div>
<div>
<div>
<SliderBase min={this.props.min} max={this.props.max} step={step} value={this.state.current} disabled={this.props.disabled}
onBeforeChange={this.begin} onChange={this.updateCurrent as any} onAfterChange={this.end as any} range={true} pushable={true} />
</div></div>
<div>
{`${Math.round(100 * this.state.current[1]) / 100}`}
</div>
</div>;
}
}
/**
* The following code was adapted from react-components/slider library.
*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment