Browse Source

simple PD.Mat4

Alexander Rose 5 years ago
parent
commit
ba89d5ec1e

+ 1 - 0
src/apps/state-docs/pd-to-md.ts

@@ -21,6 +21,7 @@ function paramInfo(param: PD.Any, offset: number): string {
         case 'color': return 'Color as 0xrrggbb';
         case 'color-list': return `A list of colors as 0xrrggbb`;
         case 'vec3': return `3D vector [x, y, z]`;
+        case 'mat4': return `4x4 transformation matrix`;
         case 'file': return `JavaScript File Handle`;
         case 'file-list': return `JavaScript FileList Handle`;
         case 'select': return `One of ${oToS(param.options)}`;

+ 2 - 2
src/mol-plugin-state/transforms/model.ts

@@ -310,7 +310,7 @@ const StructureCoordinateSystem = PluginStateTransform.BuiltIn({
                 angle: PD.Numeric(0, { min: -180, max: 180, step: 0.1 }),
                 translation: PD.Vec3(Vec3.create(0, 0, 0)),
             }, { isFlat: true }),
-            matrix: PD.Value(Mat4.identity(), { isHidden: true })
+            matrix: PD.Mat4(Mat4.identity())
         }, { label: 'Kind' })
     }
 })({
@@ -353,7 +353,7 @@ const TransformStructureConformation = PluginStateTransform.BuiltIn({
                 angle: PD.Numeric(0, { min: -180, max: 180, step: 0.1 }),
                 translation: PD.Vec3(Vec3.create(0, 0, 0)),
             }, { isFlat: true }),
-            matrix: PD.Value(Mat4.identity(), { isHidden: true })
+            matrix: PD.Mat4(Mat4.identity())
         }, { label: 'Kind' })
     }
 })({

+ 51 - 1
src/mol-plugin-ui/controls/parameters.tsx

@@ -6,7 +6,7 @@
  */
 
 import * as React from 'react';
-import { Vec2, Vec3 } from '../../mol-math/linear-algebra';
+import { Vec2, Vec3, Mat4 } from '../../mol-math/linear-algebra';
 import { PluginContext } from '../../mol-plugin/context';
 import { Color } from '../../mol-util/color';
 import { ColorListOptions, ColorListOptionsScale, ColorListOptionsSet, getColorListFromName, ColorListName } from '../../mol-util/color/lists';
@@ -178,6 +178,7 @@ function controlFor(param: PD.Any): ParamControl | undefined {
         case 'color': return CombinedColorControl;
         case 'color-list': return ColorListControl;
         case 'vec3': return Vec3Control;
+        case 'mat4': return Mat4Control;
         case 'file': return FileControl;
         case 'file-list': return FileListControl;
         case 'select': return SelectControl;
@@ -719,6 +720,55 @@ export class Vec3Control extends React.PureComponent<ParamProps<PD.Vec3>, { isEx
     }
 }
 
+export class Mat4Control extends React.PureComponent<ParamProps<PD.Mat4>, { isExpanded: boolean }> {
+    state = { isExpanded: false }
+
+    components = {
+        0: PD.Numeric(0),
+        1: PD.Numeric(0),
+        2: PD.Numeric(0),
+        3: PD.Numeric(0),
+        4: PD.Numeric(0),
+        5: PD.Numeric(0),
+        6: PD.Numeric(0),
+        7: PD.Numeric(0),
+        8: PD.Numeric(0),
+        9: PD.Numeric(0),
+        10: PD.Numeric(0),
+        11: PD.Numeric(0),
+        12: PD.Numeric(0),
+        13: PD.Numeric(0),
+        14: PD.Numeric(0),
+        15: PD.Numeric(0),
+    }
+
+    change(value: PD.MultiSelect<any>['defaultValue']) {
+        this.props.onChange({ name: this.props.name, param: this.props.param, value });
+    }
+
+    componentChange: ParamOnChange = ({ name, value }) => {
+        const v = Mat4.copy(Mat4.zero(), this.props.value);
+        v[+name] = value;
+        this.change(v);
+    }
+
+    toggleExpanded = (e: React.MouseEvent<HTMLButtonElement>) => {
+        this.setState({ isExpanded: !this.state.isExpanded });
+        e.currentTarget.blur();
+    }
+
+    render() {
+        const v = this.props.value;
+        const label = this.props.param.label || camelCaseToWords(this.props.name);
+        return <>
+            <ControlRow label={label} control={<button onClick={this.toggleExpanded} disabled={this.props.isDisabled}>{'4\u00D74 Matrix'}</button>} />
+            {this.state.isExpanded && <div className='msp-control-offset'>
+                <ParameterControls params={this.components} values={v} onChange={this.componentChange} onEnter={this.props.onEnter} />
+            </div>}
+        </>;
+    }
+}
+
 export class FileControl extends React.PureComponent<ParamProps<PD.FileParam>> {
     change(value: File) {
         this.props.onChange({ name: this.props.name, param: this.props.param, value });

+ 12 - 3
src/mol-util/param-definition.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  * @author David Sehnal <david.sehnal@gmail.com>
@@ -7,7 +7,7 @@
 
 import { Color as ColorData } from './color';
 import { shallowEqualObjects } from './index';
-import { Vec2 as Vec2Data, Vec3 as Vec3Data } from '../mol-math/linear-algebra';
+import { Vec2 as Vec2Data, Vec3 as Vec3Data, Mat4 as Mat4Data, EPSILON } from '../mol-math/linear-algebra';
 import { deepClone } from './object';
 import { Script as ScriptData } from '../mol-script/script';
 import { Legend } from './legend';
@@ -140,6 +140,13 @@ export namespace ParamDefinition {
         return setInfo<Vec3>(setRange({ type: 'vec3', defaultValue }, range), info)
     }
 
+    export interface Mat4 extends Base<Mat4Data> {
+        type: 'mat4'
+    }
+    export function Mat4(defaultValue: Mat4Data, info?: Info): Mat4 {
+        return setInfo<Mat4>({ type: 'mat4', defaultValue }, info)
+    }
+
     export interface FileParam extends Base<File> {
         type: 'file'
         accept?: string
@@ -290,7 +297,7 @@ export namespace ParamDefinition {
     }
 
     export type Any =
-        | Value<any> | Select<any> | MultiSelect<any> | BooleanParam | Text | Color | Vec3 | Numeric | FileParam | FileListParam | Interval | LineGraph
+        | Value<any> | Select<any> | MultiSelect<any> | BooleanParam | Text | Color | Vec3 | Mat4 | Numeric | FileParam | FileListParam | Interval | LineGraph
         | ColorList | Group<any> | Mapped<any> | Converted<any, any> | Conditioned<any, any, any> | Script | ObjectList
 
     export type Params = { [k: string]: Any }
@@ -385,6 +392,8 @@ export namespace ParamDefinition {
             return true;
         } else if (p.type === 'vec3') {
             return Vec3Data.equals(a, b);
+        } else if (p.type === 'mat4') {
+            return Mat4Data.areEqual(a, b, EPSILON);
         } else if (p.type === 'script') {
             const u = a as Script['defaultValue'], v = b as Script['defaultValue'];
             return u.language === v.language && u.expression === v.expression;