diff --git a/modules/ui/components/controls/FormSection.jsx b/modules/ui/components/controls/FormSection.jsx
index 37bc5739..10db5333 100644
--- a/modules/ui/components/controls/FormSection.jsx
+++ b/modules/ui/components/controls/FormSection.jsx
@@ -1,14 +1,19 @@
-import React from 'react';
+import React, {useState} from 'react';
import {Title} from '../Folder';
-export class StackSection extends React.Component {
-
- render() {
- const {title, children, isClosed, onTitleClick} = this.props;
- return
- {title}
- {!isClosed && children}
- ;
+export function StackSection(props) {
+ let {title, initialCollapse, collapsible, children} = props;
+
+ if (collapsible === undefined) {
+ collapsible = true;
}
-
+
+ const [visible, setVisible] = useState(!initialCollapse);
+
+ const onTitleClick = collapsible ? () => setVisible(visible => !visible) : undefined;
+
+ return
+ {title}
+ {visible && children}
+ ;
}
\ No newline at end of file
diff --git a/modules/ui/components/controls/InputControl.jsx b/modules/ui/components/controls/InputControl.jsx
index cca42838..88beae75 100644
--- a/modules/ui/components/controls/InputControl.jsx
+++ b/modules/ui/components/controls/InputControl.jsx
@@ -1,19 +1,30 @@
-import React from 'react';
+import React, {useEffect, useRef} from 'react';
import PropTypes from 'prop-types';
-export default class InputControl extends React.Component {
+export default function InputControl(inprops) {
- render() {
- let {type, inputRef, ...props} = this.props;
-
- return
-
+ let {type, inputRef, width, onWheel, ...props} = inprops;
+
+ const style = width&&{
+ width
+ }
+
+ const divRef = useRef()
+
+ useEffect(() => {
+ if (onWheel && divRef.current) {
+ divRef.current.addEventListener('wheel', e => e.preventDefault(), {passive:false})
+ }
+ }, [divRef.current])
+
+ return
+
;
- }
+
}
InputControl.propTypes = {
- type: PropTypes.oneOf(['number', 'text']),
+ type: PropTypes.oneOf(['number', 'text']),
};
InputControl.defaultProps = {
diff --git a/modules/ui/components/controls/NumberControl.jsx b/modules/ui/components/controls/NumberControl.jsx
index 91226655..4490e622 100644
--- a/modules/ui/components/controls/NumberControl.jsx
+++ b/modules/ui/components/controls/NumberControl.jsx
@@ -4,46 +4,36 @@ import InputControl from './InputControl';
export default function NumberControl(props) {
- let {onChange, onFocus, value} = props;
+ let {onChange, onFocus, value, width, baseStep, round, min, max, accelerator, cycle} = props;
const onChangeFromTarget = e => {
onChange(e.target.value);
};
- const attachWheelListener = useCallback((input) => {
- if (!input) {
- return;
+ const onWheel = (e) => {
+ let delta = e.shiftKey ? e.deltaX : e.deltaY;
+ let step = baseStep * (e.shiftKey ? accelerator : 1);
+ let val = parseFloat(e.target.value);
+ if (isNaN(val)) val = 0;
+ val = val + (delta < 0 ? -step : step);
+ if (min !== undefined && val < min) {
+ val = cycle ? max : min;
}
- const onWheel = (e) => {
- let {baseStep, round, min, max, onChange, accelerator} = props;
- let delta = e.shiftKey ? e.deltaX : e.deltaY;
- let step = baseStep * (e.shiftKey ? accelerator : 1);
- let val = parseFloat(e.target.value);
- if (isNaN(val)) val = 0;
- val = val + (delta < 0 ? -step : step);
- if (min !== undefined && val < min) {
- val = min;
- }
- if (max !== undefined && val > max) {
- val = max;
- }
- if (round !== 0) {
- val = val.toFixed(round);
- }
- input.value = val;
- onChange(val);
- e.preventDefault();
- e.stopPropagation();
- };
- input.addEventListener('wheel', onWheel, {passive: false});
- }, []);
+ if (max !== undefined && val > max) {
+ val = cycle ? min : max;
+ }
+ if (round !== 0) {
+ val = val.toFixed(round);
+ }
+ onChange(val);
+ };
return
-
+ width={width}
+ onWheel={onWheel}/>
}
diff --git a/modules/ui/styles/global/form.less b/modules/ui/styles/global/form.less
index f3a8b133..878e8e79 100644
--- a/modules/ui/styles/global/form.less
+++ b/modules/ui/styles/global/form.less
@@ -7,11 +7,15 @@ button {
padding: 6px 10px;
border: 0;
background-color: @bg-color-9;
- font-weight: bold;
+ //font-weight: bold;
color: @font-color;
white-space: nowrap;
border-radius: 1px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+
&.icon-button {
display: inline-flex;
diff --git a/web/app/cad/craft/craftPlugin.ts b/web/app/cad/craft/craftPlugin.ts
index ddc1a9a9..87b99554 100644
--- a/web/app/cad/craft/craftPlugin.ts
+++ b/web/app/cad/craft/craftPlugin.ts
@@ -146,7 +146,10 @@ export function activate(ctx: CoreContext) {
promise.then(({consumed, created}) => {
consumed.forEach(m => models.delete(m));
- created.forEach(m => models.add(m));
+ created.forEach(m => {
+ m.originatingOperation = i;
+ models.add(m)
+ });
models$.next(Array.from(models).sort((m1, m2) => (m1.id||'').localeCompare(m2.id)));
runPromise(i + 1);
diff --git a/web/app/cad/craft/datum/create/CreateDatumWizard.jsx b/web/app/cad/craft/datum/create/CreateDatumWizard.jsx
index 7b55737b..10bee9b8 100644
--- a/web/app/cad/craft/datum/create/CreateDatumWizard.jsx
+++ b/web/app/cad/craft/datum/create/CreateDatumWizard.jsx
@@ -1,7 +1,14 @@
import React from 'react';
-import {Group} from '../../wizard/components/form/Form';
+import {attachToForm, Group} from '../../wizard/components/form/Form';
import {NumberField} from '../../wizard/components/form/Fields';
import EntityList from '../../wizard/components/form/EntityList';
+import {StackSection} from "ui/components/controls/FormSection";
+import Button from "ui/components/controls/Button";
+import {IoAddCircleOutline, IoIosRemoveCircleOutline} from "react-icons/all";
+import ls from './CreateDatumWizard.less'
+import ComboBoxControl, {ComboBoxOption} from "ui/components/controls/ComboBoxControl";
+import NumberControl from "ui/components/controls/NumberControl";
+import produce from "immer";
export default function CreateDatumWizard() {
return
@@ -9,5 +16,60 @@ export default function CreateDatumWizard() {
+
;
+}
+
+const Rotations = attachToForm(RotationsImpl);
+
+function RotationsImpl({value, onChange}) {
+
+ value = value || [];
+
+ function add() {
+
+ onChange([
+ ...value,
+ {
+ axis: 'X',
+ angle: 0
+ }
+ ]);
+
+ }
+
+ return
+
+ {value.map((rot, i) =>
+
+ axis:
+ {
+ onChange(produce(value, value => {
+ value[i].axis = axis
+ }));
+ }} value={rot.axis}>
+ X
+ Y
+ Z
+
+ degree:
+ {
+ onChange(produce(value, value => {
+ value[i].angle = angle
+ }));
+ }} value={rot.angle} />
+
+
+
+
+
)}
+
+
+
+
+
+
+
}
\ No newline at end of file
diff --git a/web/app/cad/craft/datum/create/CreateDatumWizard.less b/web/app/cad/craft/datum/create/CreateDatumWizard.less
new file mode 100644
index 00000000..f2019114
--- /dev/null
+++ b/web/app/cad/craft/datum/create/CreateDatumWizard.less
@@ -0,0 +1,14 @@
+.rot {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.rotControls {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ & > * {
+ margin-right: 5px;
+ }
+}
\ No newline at end of file
diff --git a/web/app/cad/craft/datum/create/createDatumOpSchema.js b/web/app/cad/craft/datum/create/createDatumOpSchema.js
index 2675626e..a9f67327 100644
--- a/web/app/cad/craft/datum/create/createDatumOpSchema.js
+++ b/web/app/cad/craft/datum/create/createDatumOpSchema.js
@@ -16,4 +16,22 @@ export default {
type: 'number',
defaultValue: 0
},
+ rotations: {
+ type: 'array',
+ defaultValue: [],
+ items: {
+ type: 'object',
+ schema: {
+ axis: {
+ type: 'string',
+ enum: ['X', 'Y', 'Z']
+ },
+ angle: {
+ type: 'number',
+ min: 0,
+ max: 360
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/web/app/cad/craft/datum/create/createDatumOperation.js b/web/app/cad/craft/datum/create/createDatumOperation.js
index 904137c6..d0d60c2e 100644
--- a/web/app/cad/craft/datum/create/createDatumOperation.js
+++ b/web/app/cad/craft/datum/create/createDatumOperation.js
@@ -7,6 +7,7 @@ import {MDatum} from '../../../model/mdatum';
import {roundInteractiveInput} from '../../wizard/roundUtils';
import {DatumParamsRenderer} from '../DatumParamsRenderer';
import {pointAsText} from 'renders';
+import {applyRotation} from "cad/craft/datum/rotate/rotateDatumOperation";
function updateCSys(csys, params, findFace) {
csys.copy(CSys.ORIGIN);
@@ -17,6 +18,12 @@ function updateCSys(csys, params, findFace) {
}
}
+ params.rotations.forEach(r => {
+ let axis = csys[r.axis.toLowerCase()];
+ applyRotation(csys, csys, r.angle, axis);
+ });
+
+
csys.origin.x += params.x;
csys.origin.y += params.y;
csys.origin.z += params.z;
@@ -33,7 +40,7 @@ function create(params, {cadRegistry}) {
}
function previewer(ctx, initialParams, updateParams) {
-
+
let datum3D = new DatumObject3D(CSys.origin(), ctx.services.viewer);
datum3D.onMove = (begin, end, delta) => {
@@ -55,7 +62,7 @@ function previewer(ctx, initialParams, updateParams) {
params.z = roundInteractiveInput(z);
})
};
-
+
function update(params) {
updateCSys(datum3D.csys, params, ctx.services.cadRegistry.findFace);
}
@@ -68,6 +75,23 @@ function previewer(ctx, initialParams, updateParams) {
update(initialParams);
SceneGraph.addToGroup(ctx.services.cadScene.workGroup, datum3D);
+ const modifications = ctx.craftService.modifications$.value;
+ const preDrag = modifications.hints?.preDrag;
+ if (preDrag) {
+ let axis;
+ if ('X' === preDrag.axis) {
+ axis = datum3D.csysObj.xAxis;
+ } else if ('Y' === preDrag.axis) {
+ axis = datum3D.csysObj.yAxis;
+ } else if ('Z' === preDrag.axis) {
+ axis = datum3D.csysObj.zAxis;
+ }
+
+ if (axis) {
+ ctx.services.modelMouseEventSystem.dispatchMousedown(preDrag.event, [{object: axis.handle}]);
+ }
+ }
+
return {
update, dispose
}
diff --git a/web/app/cad/craft/datum/csysObject.js b/web/app/cad/craft/datum/csysObject.js
index dae11e0a..3fcb5651 100644
--- a/web/app/cad/craft/datum/csysObject.js
+++ b/web/app/cad/craft/datum/csysObject.js
@@ -11,7 +11,7 @@ export default class CSysObject3D extends Object3D {
this.csys = csys;
this.sceneSetup = sceneSetup;
- function createBasisArrow(axis, color) {
+ function createBasisArrow(name, axis, color) {
let meshArrow = new MeshArrow({
dir: axis,
color,
@@ -22,12 +22,13 @@ export default class CSysObject3D extends Object3D {
materialCreate: p => new MeshLambertMaterial(p),
...arrowParams
});
+ meshArrow.name = name;
return meshArrow;
}
- this.xAxis = createBasisArrow(AXIS.X, 0xFF0000);
- this.yAxis = createBasisArrow(AXIS.Y, 0x00FF00);
- this.zAxis = createBasisArrow(AXIS.Z, 0x0000FF);
+ this.xAxis = createBasisArrow('X', AXIS.X, 0xFF0000);
+ this.yAxis = createBasisArrow('Y', AXIS.Y, 0x00FF00);
+ this.zAxis = createBasisArrow('Z', AXIS.Z, 0x0000FF);
this.add(this.xAxis);
this.add(this.yAxis);
diff --git a/web/app/cad/craft/datum/rotate/rotateDatumOperation.js b/web/app/cad/craft/datum/rotate/rotateDatumOperation.js
index 8698b609..f2383b8d 100644
--- a/web/app/cad/craft/datum/rotate/rotateDatumOperation.js
+++ b/web/app/cad/craft/datum/rotate/rotateDatumOperation.js
@@ -57,7 +57,7 @@ function previewer(ctx, initialParams) {
}
}
-function applyRotation(origCsys, csys, angle, axis) {
+export function applyRotation(origCsys, csys, angle, axis) {
auxMatrix.rotate(angle * DEG_RAD, axis, ORIGIN);
auxMatrix.__apply(origCsys.x, csys.x);
auxMatrix.__apply(origCsys.y, csys.y);
diff --git a/web/app/cad/mdf/ui/SectionWidget.tsx b/web/app/cad/mdf/ui/SectionWidget.tsx
index b42a5801..1097dbff 100644
--- a/web/app/cad/mdf/ui/SectionWidget.tsx
+++ b/web/app/cad/mdf/ui/SectionWidget.tsx
@@ -18,12 +18,8 @@ export interface SectionWidgetProps extends ContainerBasicProps {
}
export function SectionWidget(props: SectionWidgetProps) {
- const [visible, setVisible] = useState(!props.initialCollapse);
-
- const onTitleClick = props.collapsible ? () => setVisible(visible => !visible) : undefined;
-
- return
- {visible && }
+ return
+
}
diff --git a/web/app/cad/model/mobject.ts b/web/app/cad/model/mobject.ts
index e684cdce..c5f038ff 100644
--- a/web/app/cad/model/mobject.ts
+++ b/web/app/cad/model/mobject.ts
@@ -9,6 +9,7 @@ export abstract class MObject {
TYPE: EntityKind;
id: string;
+ originatingOperation: number = -1;
ext: any = {};
protected constructor(TYPE, id) {
diff --git a/web/app/cad/scene/views/datumView.js b/web/app/cad/scene/views/datumView.js
index 2573b084..493b0fa1 100644
--- a/web/app/cad/scene/views/datumView.js
+++ b/web/app/cad/scene/views/datumView.js
@@ -105,12 +105,18 @@ export default class DatumView extends View {
this.csysObj.add(this.menuButton);
}
- dragStart(e, axis) {
- if (!isReadOnly() && !this.operationStarted) {
- selectDatum(datum);
- beginOperation('DATUM_MOVE');
- }
- super.dragStart(e, axis);
+ dragStart(event, axis) {
+ ctx.craftService.historyTravel.setPointer(datum.originatingOperation - 1, {
+ preDrag: {
+ event, axis: axis.name
+ }
+ });
+ // if (!isReadOnly() && !this.operationStarted) {
+ // const history = ctx.craftService.modifications$.value.history;
+ // selectDatum(datum);
+ // beginOperation('DATUM_MOVE');
+ // }
+ // super.dragStart(event, axis);
}
beginOperation(freezeDragging = false) {