-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathRotationInputPluginEuler.ts
99 lines (89 loc) · 3.59 KB
/
RotationInputPluginEuler.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { BindingTarget, InputBindingPlugin, PointNdConstraint, TpError, createPlugin, parseNumber, parsePickerLayout, parsePointDimensionParams, parseRecord } from '@tweakpane/core';
import { Euler } from './Euler.js';
import { RotationInputController } from './RotationInputController.js';
import { createAxisEuler } from './createAxisEuler.js';
import { createDimensionConstraint } from './createDimensionConstraint.js';
import { createEulerAssembly } from './createEulerAssembly.js';
import { parseEuler } from './parseEuler.js';
import { parseEulerOrder } from './parseEulerOrder.js';
import { parseEulerUnit } from './parseEulerUnit.js';
import type { RotationInputPluginEulerParams } from './RotationInputPluginEulerParams.js';
import type { ValueController } from '@tweakpane/core';
export const RotationInputPluginEuler: InputBindingPlugin<
Euler,
Euler,
RotationInputPluginEulerParams
> = createPlugin( {
id: 'rotation',
type: 'input',
accept( exValue: unknown, params: Record<string, unknown> ) {
// Parse parameters object
const result = parseRecord<RotationInputPluginEulerParams>( params, ( p ) => ( {
view: p.required.constant( 'rotation' ),
label: p.optional.string,
picker: p.optional.custom( parsePickerLayout ),
expanded: p.optional.boolean,
rotationMode: p.required.constant( 'euler' ),
x: p.optional.custom( parsePointDimensionParams ),
y: p.optional.custom( parsePointDimensionParams ),
z: p.optional.custom( parsePointDimensionParams ),
order: p.optional.custom( parseEulerOrder ),
unit: p.optional.custom( parseEulerUnit ),
} ) );
return result ? {
initialValue: parseEuler( exValue, result.order ?? 'XYZ', result.unit ?? 'rad' ),
params: result,
} : null;
},
binding: {
reader( { params } ) {
return ( exValue: unknown ): Euler => {
return parseEuler( exValue, params.order ?? 'XYZ', params.unit ?? 'rad' );
};
},
constraint( { params } ) {
return new PointNdConstraint( {
assembly: createEulerAssembly( params.order ?? 'XYZ', params.unit ?? 'rad' ),
components: [
createDimensionConstraint( 'x' in params ? params.x : undefined ),
createDimensionConstraint( 'y' in params ? params.y : undefined ),
createDimensionConstraint( 'z' in params ? params.z : undefined ),
]
} );
},
writer( _args ) {
return ( target: BindingTarget, inValue: Euler ) => {
target.writeProperty( 'x', inValue.x );
target.writeProperty( 'y', inValue.y );
target.writeProperty( 'z', inValue.z );
};
},
},
controller( { document, value, constraint, params, viewProps } ) {
if ( !( constraint instanceof PointNdConstraint ) ) {
throw TpError.shouldNeverHappen();
}
const expanded = 'expanded' in params ? params.expanded : undefined;
const picker = 'picker' in params ? params.picker : undefined;
const unit = params.unit ?? 'rad';
const digits = {
rad: 2,
deg: 0,
turn: 2,
}[ unit ];
return new RotationInputController( document, {
axes: [
createAxisEuler( digits, constraint.components[ 0 ] ),
createAxisEuler( digits, constraint.components[ 1 ] ),
createAxisEuler( digits, constraint.components[ 2 ] ),
],
assembly: createEulerAssembly( params.order ?? 'XYZ', unit ),
rotationMode: 'euler',
expanded: expanded ?? false,
parser: parseNumber,
pickerLayout: picker ?? 'popup',
value,
viewProps: viewProps,
} ) as unknown as ValueController<Euler>; // TODO: resolve type puzzle
},
} );