Compare commits

...

2 Commits

Author SHA1 Message Date
f34c23d203 Cut release v0.24.5 (#3191) 2024-07-30 15:28:07 -04:00
5295f0ae7d Fix rectangle tool flakiness (#3190)
* Refactor line tool and rectangle tool to share same "no points" code path

* Remove console.log

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* Re-run CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-30 18:16:53 +00:00
7 changed files with 69 additions and 67 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -1,6 +1,6 @@
{ {
"name": "untitled-app", "name": "untitled-app",
"version": "0.24.4", "version": "0.24.5",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.17.0", "@codemirror/autocomplete": "^6.17.0",

View File

@ -80,5 +80,5 @@
} }
}, },
"productName": "Zoo Modeling App", "productName": "Zoo Modeling App",
"version": "0.24.4" "version": "0.24.5"
} }

View File

@ -27,6 +27,7 @@ import {
defaultPlaneColor, defaultPlaneColor,
getSceneScale, getSceneScale,
INTERSECTION_PLANE_LAYER, INTERSECTION_PLANE_LAYER,
OnClickCallbackArgs,
OnMouseEnterLeaveArgs, OnMouseEnterLeaveArgs,
RAYCASTABLE_PLANE, RAYCASTABLE_PLANE,
SEGMENT_LENGTH_LABEL, SEGMENT_LENGTH_LABEL,
@ -78,6 +79,7 @@ import {
} from 'lang/std/sketch' } from 'lang/std/sketch'
import { isOverlap, normaliseAngle, roundOff, throttle } from 'lib/utils' import { isOverlap, normaliseAngle, roundOff, throttle } from 'lib/utils'
import { import {
addStartProfileAt,
createArrayExpression, createArrayExpression,
createCallExpressionStdLib, createCallExpressionStdLib,
createLiteral, createLiteral,
@ -296,6 +298,51 @@ export class SceneEntities {
if (intersectionPlane) this.scene.remove(intersectionPlane) if (intersectionPlane) this.scene.remove(intersectionPlane)
} }
setupNoPointsListener({
sketchDetails,
afterClick,
}: {
sketchDetails: SketchDetails
afterClick: (args: OnClickCallbackArgs) => void
}) {
// Create a THREEjs plane to raycast clicks onto
this.createIntersectionPlane()
const quaternion = quaternionFromUpNForward(
new Vector3(...sketchDetails.yAxis),
new Vector3(...sketchDetails.zAxis)
)
// Position the click raycast plane
if (this.intersectionPlane) {
this.intersectionPlane.setRotationFromQuaternion(quaternion)
this.intersectionPlane.position.copy(
new Vector3(...(sketchDetails?.origin || [0, 0, 0]))
)
}
sceneInfra.setCallbacks({
onClick: async (args) => {
if (!args) return
if (args.mouseEvent.which !== 1) return
const { intersectionPoint } = args
if (!intersectionPoint?.twoD || !sketchDetails?.sketchPathToNode) return
const addStartProfileAtRes = addStartProfileAt(
kclManager.ast,
sketchDetails.sketchPathToNode,
[intersectionPoint.twoD.x, intersectionPoint.twoD.y]
)
if (trap(addStartProfileAtRes)) return
const { modifiedAst } = addStartProfileAtRes
await kclManager.updateAst(modifiedAst, false)
this.removeIntersectionPlane()
// Now perform the caller-specified action
afterClick(args)
},
})
}
async setupSketch({ async setupSketch({
sketchPathToNode, sketchPathToNode,
forward, forward,
@ -672,21 +719,6 @@ export class SceneEntities {
...this.mouseEnterLeaveCallbacks(), ...this.mouseEnterLeaveCallbacks(),
}) })
} }
setupRectangleOriginListener = () => {
sceneInfra.setCallbacks({
onClick: (args) => {
const twoD = args.intersectionPoint?.twoD
if (!twoD) {
console.warn(`This click didn't have a 2D intersection`, args)
return
}
sceneInfra.modelingSend({
type: 'Add rectangle origin',
data: [twoD.x, twoD.y],
})
},
})
}
setupDraftRectangle = async ( setupDraftRectangle = async (
sketchPathToNode: PathToNode, sketchPathToNode: PathToNode,
forward: [number, number, number], forward: [number, number, number],
@ -704,6 +736,8 @@ export class SceneEntities {
if (trap(_node1)) return Promise.reject(_node1) if (trap(_node1)) return Promise.reject(_node1)
const variableDeclarationName = const variableDeclarationName =
_node1.node?.declarations?.[0]?.id?.name || '' _node1.node?.declarations?.[0]?.id?.name || ''
const startSketchOn = _node1.node?.declarations
const startSketchOnInit = startSketchOn?.[0]?.init
const tags: [string, string, string] = [ const tags: [string, string, string] = [
findUniqueName(_ast, 'rectangleSegmentA'), findUniqueName(_ast, 'rectangleSegmentA'),
@ -711,15 +745,6 @@ export class SceneEntities {
findUniqueName(_ast, 'rectangleSegmentC'), findUniqueName(_ast, 'rectangleSegmentC'),
] ]
const _node2 = getNodeFromPath<VariableDeclaration>(
_ast,
sketchPathToNode || [],
'VariableDeclaration'
)
if (trap(_node2)) return Promise.reject(_node2)
const startSketchOn = _node2.node?.declarations
const startSketchOnInit = startSketchOn?.[0]?.init
startSketchOn[0].init = createPipeExpression([ startSketchOn[0].init = createPipeExpression([
startSketchOnInit, startSketchOnInit,
...getRectangleCallExpressions(rectangleOrigin, tags), ...getRectangleCallExpressions(rectangleOrigin, tags),

View File

@ -72,7 +72,7 @@ interface OnDragCallbackArgs extends OnMouseEnterLeaveArgs {
} }
intersects: Intersection<Object3D<Object3DEventMap>>[] intersects: Intersection<Object3D<Object3DEventMap>>[]
} }
interface OnClickCallbackArgs { export interface OnClickCallbackArgs {
mouseEvent: MouseEvent mouseEvent: MouseEvent
intersectionPoint?: { intersectionPoint?: {
twoD: Vector2 twoD: Vector2

View File

@ -24,13 +24,6 @@ export const getRectangleCallExpressions = (
rectangleOrigin: [number, number], rectangleOrigin: [number, number],
tags: [string, string, string] tags: [string, string, string]
) => [ ) => [
createCallExpressionStdLib('startProfileAt', [
createArrayExpression([
createLiteral(roundOff(rectangleOrigin[0])),
createLiteral(roundOff(rectangleOrigin[1])),
]),
createPipeSubstitution(),
]),
createCallExpressionStdLib('angledLine', [ createCallExpressionStdLib('angledLine', [
createArrayExpression([ createArrayExpression([
createLiteral(0), // 0 deg createLiteral(0), // 0 deg

View File

@ -1238,7 +1238,20 @@ export const modelingMachine = createMachine(
}, },
'listen for rectangle origin': ({ sketchDetails }) => { 'listen for rectangle origin': ({ sketchDetails }) => {
if (!sketchDetails) return if (!sketchDetails) return
sceneEntitiesManager.setupRectangleOriginListener() sceneEntitiesManager.setupNoPointsListener({
sketchDetails,
afterClick: (args) => {
const twoD = args.intersectionPoint?.twoD
if (twoD) {
sceneInfra.modelingSend({
type: 'Add rectangle origin',
data: [twoD.x, twoD.y],
})
} else {
console.error('No intersection point found')
}
},
})
}, },
'set up draft rectangle': ({ sketchDetails }, { data }) => { 'set up draft rectangle': ({ sketchDetails }, { data }) => {
if (!sketchDetails || !data) return if (!sketchDetails || !data) return
@ -1268,39 +1281,10 @@ export const modelingMachine = createMachine(
}, },
'setup noPoints onClick listener': ({ sketchDetails }) => { 'setup noPoints onClick listener': ({ sketchDetails }) => {
if (!sketchDetails) return if (!sketchDetails) return
sceneEntitiesManager.createIntersectionPlane()
const quaternion = quaternionFromUpNForward(
new Vector3(...sketchDetails.yAxis),
new Vector3(...sketchDetails.zAxis)
)
sceneEntitiesManager.intersectionPlane &&
sceneEntitiesManager.intersectionPlane.setRotationFromQuaternion(
quaternion
)
sceneEntitiesManager.intersectionPlane &&
sceneEntitiesManager.intersectionPlane.position.copy(
new Vector3(...(sketchDetails?.origin || [0, 0, 0]))
)
sceneInfra.setCallbacks({
onClick: async (args) => {
if (!args) return
if (args.mouseEvent.which !== 1) return
const { intersectionPoint } = args
if (!intersectionPoint?.twoD || !sketchDetails?.sketchPathToNode)
return
const addStartProfileAtRes = addStartProfileAt(
kclManager.ast,
sketchDetails.sketchPathToNode,
[intersectionPoint.twoD.x, intersectionPoint.twoD.y]
)
if (trap(addStartProfileAtRes)) return sceneEntitiesManager.setupNoPointsListener({
const { modifiedAst } = addStartProfileAtRes sketchDetails,
afterClick: () => sceneInfra.modelingSend('Add start point'),
await kclManager.updateAst(modifiedAst, false)
sceneEntitiesManager.removeIntersectionPlane()
sceneInfra.modelingSend('Add start point')
},
}) })
}, },
'add axis n grid': ({ sketchDetails }) => { 'add axis n grid': ({ sketchDetails }) => {