diff --git a/src/components/SketchPlane.tsx b/src/components/SketchPlane.tsx index 6f7709743..274453c99 100644 --- a/src/components/SketchPlane.tsx +++ b/src/components/SketchPlane.tsx @@ -1,19 +1,32 @@ -import { useStore } from '../useStore' +import { useState } from 'react' +import { Selections, useStore } from '../useStore' import { DoubleSide, Vector3, Quaternion } from 'three' import { Program } from '../lang/abstractSyntaxTree' import { addNewSketchLn } from '../lang/std/sketch' import { roundOff } from '../lib/utils' export const SketchPlane = () => { - const { ast, guiMode, updateAst, programMemory, updateAstAsync } = useStore( - (s) => ({ - guiMode: s.guiMode, - ast: s.ast, - updateAst: s.updateAst, - updateAstAsync: s.updateAstAsync, - programMemory: s.programMemory, - }) - ) + const { + ast, + guiMode, + programMemory, + updateAstAsync, + setSelectionRanges, + selectionRanges, + isShiftDown, + setCursor, + } = useStore((s) => ({ + guiMode: s.guiMode, + ast: s.ast, + updateAstAsync: s.updateAstAsync, + programMemory: s.programMemory, + setSelectionRanges: s.setSelectionRanges, + selectionRanges: s.selectionRanges, + isShiftDown: s.isShiftDown, + setCursor: s.setCursor, + })) + const [xHover, setXHover] = useState(false) + const [yHover, setYHover] = useState(false) if (guiMode.mode !== 'sketch') { return null } @@ -35,6 +48,32 @@ export const SketchPlane = () => { temp ) + const onAxisClick = (name: 'y-axis' | 'x-axis') => () => { + const _selectionRanges: Selections = isShiftDown + ? selectionRanges + : { + codeBasedSelections: [ + { + range: [0, 0], + type: 'default', + }, + ], + otherSelections: [], + } + if (!isShiftDown) { + setCursor({ + ..._selectionRanges, + otherSelections: [name], + }) + } + setTimeout(() => { + setSelectionRanges({ + ..._selectionRanges, + otherSelections: [name], + }) + }, 100) + } + return ( <> { /> + !isShiftDown && + setSelectionRanges({ + ...selectionRanges, + otherSelections: [], + }) + } /> + setXHover(true)} + onPointerOut={() => setXHover(false)} + onClick={onAxisClick('x-axis')} + > + + + + setYHover(true)} + onPointerOut={() => setYHover(false)} + onClick={onAxisClick('y-axis')} + > + + + ) } diff --git a/src/components/Toolbar/ConvertVariable.tsx b/src/components/Toolbar/ConvertVariable.tsx index 9baaaf7aa..c1e73c8df 100644 --- a/src/components/Toolbar/ConvertVariable.tsx +++ b/src/components/Toolbar/ConvertVariable.tsx @@ -23,7 +23,7 @@ export const ConvertToVariable = () => { const { isSafe, value } = isNodeSafeToReplace( ast, - selectionRanges.codeBasedSelections[0].range + selectionRanges.codeBasedSelections?.[0]?.range || [] ) const canReplace = isSafe && value.type !== 'Identifier' const isOnlyOneSelection = selectionRanges.codeBasedSelections.length === 1 diff --git a/src/components/Toolbar/SetAngleLength.tsx b/src/components/Toolbar/SetAngleLength.tsx index e538b1bbc..479332768 100644 --- a/src/components/Toolbar/SetAngleLength.tsx +++ b/src/components/Toolbar/SetAngleLength.tsx @@ -12,8 +12,13 @@ import { transformAstSketchLines, } from '../../lang/std/sketchcombos' import { SetAngleLengthModal } from '../SetAngleLengthModal' -import { createVariableDeclaration } from '../../lang/modifyAst' +import { + createBinaryExpressionWithUnary, + createIdentifier, + createVariableDeclaration, +} from '../../lang/modifyAst' import { removeDoubleNegatives } from '../AvailableVarsHelpers' +import { normaliseAngle } from '../../lib/utils' const getModalInfo = create(SetAngleLengthModal as any) @@ -68,16 +73,47 @@ export const SetAngleLength = ({ referenceSegName: '', }) try { + const isReferencingYAxis = + selectionRanges.otherSelections.length === 1 && + selectionRanges.otherSelections[0] === 'y-axis' + const isReferencingYAxisAngle = + isReferencingYAxis && angleOrLength === 'setAngle' + + const isReferencingXAxis = + selectionRanges.otherSelections.length === 1 && + selectionRanges.otherSelections[0] === 'x-axis' + const isReferencingXAxisAngle = + isReferencingXAxis && angleOrLength === 'setAngle' + + let forceVal = valueUsedInTransform || 0 + let calcIdentifier = createIdentifier('_0') + if (isReferencingYAxisAngle) { + calcIdentifier = createIdentifier(forceVal < 0 ? '_270' : '_90') + forceVal = normaliseAngle(forceVal + (forceVal < 0 ? 90 : -90)) + } else if (isReferencingXAxisAngle) { + calcIdentifier = createIdentifier( + Math.abs(forceVal) > 90 ? '_180' : '_0' + ) + forceVal = + Math.abs(forceVal) > 90 + ? normaliseAngle(forceVal - 180) + : forceVal + } const { valueNode, variableName, newVariableInsertIndex, sign } = await getModalInfo({ - value: valueUsedInTransform, + value: forceVal, valueName: angleOrLength === 'setAngle' ? 'angle' : 'length', } as any) - const finalValue = removeDoubleNegatives( - valueNode, - sign, - variableName - ) + let finalValue = removeDoubleNegatives(valueNode, sign, variableName) + if ( + isReferencingYAxisAngle || + (isReferencingXAxisAngle && calcIdentifier.name !== '_0') + ) { + finalValue = createBinaryExpressionWithUnary([ + calcIdentifier, + finalValue, + ]) + } const { modifiedAst: _modifiedAst } = transformAstSketchLines({ ast: JSON.parse(JSON.stringify(ast)), diff --git a/src/lib/utils.ts b/src/lib/utils.ts index f98d49256..5cc87ac19 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -20,6 +20,10 @@ export function getLength(a: [number, number], b: [number, number]): number { export function getAngle(a: [number, number], b: [number, number]): number { const x = b[0] - a[0] const y = b[1] - a[1] - const result = ((Math.atan2(y, x) * 180) / Math.PI + 360) % 360 + return normaliseAngle((Math.atan2(y, x) * 180) / Math.PI) +} + +export function normaliseAngle(angle: number): number { + const result = ((angle % 360) + 360) % 360 return result > 180 ? result - 360 : result }