diff --git a/src/components/SketchLine.tsx b/src/components/SketchLine.tsx
index 71ce0c5f1..87a445b59 100644
--- a/src/components/SketchLine.tsx
+++ b/src/components/SketchLine.tsx
@@ -12,6 +12,8 @@ import {
Path,
Rotation,
Position,
+ PathToNode,
+ SourceRange,
} from '../lang/executor'
import { BufferGeometry } from 'three'
import { useStore } from '../useStore'
@@ -191,9 +193,10 @@ export function RenderViewerArtifacts({
}: {
artifacts: (ExtrudeGroup | SketchGroup)[]
}) {
+ useSetAppModeFromCursorLocation(artifacts)
return (
<>
- {artifacts.map((artifact, i) => (
+ {artifacts?.map((artifact, i) => (
))}
>
@@ -205,59 +208,22 @@ function RenderViewerArtifact({
}: {
artifact: ExtrudeGroup | SketchGroup
}) {
- const { selectionRange, guiMode, ast, setGuiMode } = useStore(
- ({ selectionRange, guiMode, ast, setGuiMode }) => ({
- selectionRange,
- guiMode,
- ast,
- setGuiMode,
- })
- )
- const [editorCursor, setEditorCursor] = useState(false)
- useEffect(() => {
- const shouldHighlight = isOverlapping(
- artifact.__meta[0].sourceRange,
- selectionRange
- )
- setEditorCursor(shouldHighlight)
- }, [selectionRange, artifact.__meta])
-
- useEffect(() => {
- const shouldHighlight = artifact.__meta.some((aMeta) =>
- isOverlapping(aMeta.sourceRange, selectionRange)
- )
- if (
- shouldHighlight &&
- (guiMode.mode === 'default' || guiMode.mode === 'canEditSketch') &&
- ast &&
- artifact.type === 'sketchGroup'
- ) {
- const pathToNode = getNodePathFromSourceRange(
- ast,
- artifact.__meta[0].sourceRange
- )
- const { rotation, position } = artifact
- setGuiMode({ mode: 'canEditSketch', pathToNode, rotation, position })
- } else if (
- shouldHighlight &&
- (guiMode.mode === 'default' || guiMode.mode === 'canEditSketch') &&
- ast &&
- artifact.type === 'extrudeGroup'
- ) {
- const pathToNode = getNodePathFromSourceRange(
- ast,
- artifact.__meta[0].sourceRange
- )
- const { rotation, position } = artifact
- setGuiMode({ mode: 'canEditExtrude', pathToNode, rotation, position })
- } else if (
- !shouldHighlight &&
- (guiMode.mode === 'canEditSketch' || guiMode.mode === 'canEditExtrude') &&
- (artifact.type === 'sketchGroup' || artifact.type === 'extrudeGroup')
- ) {
- setGuiMode({ mode: 'default' })
- }
- }, [selectionRange, artifact, ast, guiMode.mode, setGuiMode])
+ // const { selectionRange, guiMode, ast, setGuiMode } = useStore(
+ // ({ selectionRange, guiMode, ast, setGuiMode }) => ({
+ // selectionRange,
+ // guiMode,
+ // ast,
+ // setGuiMode,
+ // })
+ // )
+ // const [editorCursor, setEditorCursor] = useState(false)
+ // useEffect(() => {
+ // const shouldHighlight = isOverlapping(
+ // artifact.__meta.slice(-1)[0].sourceRange,
+ // selectionRange
+ // )
+ // setEditorCursor(shouldHighlight)
+ // }, [selectionRange, artifact.__meta])
if (artifact.type === 'sketchGroup') {
return (
@@ -266,7 +232,7 @@ function RenderViewerArtifact({
@@ -281,7 +247,7 @@ function RenderViewerArtifact({
@@ -454,3 +420,91 @@ function LineRender({
>
)
}
+
+type Boop = ExtrudeGroup | SketchGroup
+
+function useSetAppModeFromCursorLocation(artifacts: Boop[]) {
+ const { selectionRange, guiMode, setGuiMode, ast } = useStore(
+ ({ selectionRange, guiMode, setGuiMode, ast }) => ({
+ selectionRange,
+ guiMode,
+ setGuiMode,
+ ast,
+ })
+ )
+ useEffect(() => {
+ const artifactsWithinCursorRange: (
+ | {
+ parentType: Boop['type']
+ isParent: true
+ pathToNode: PathToNode
+ sourceRange: SourceRange
+ rotation: Rotation
+ position: Position
+ }
+ | {
+ parentType: Boop['type']
+ isParent: false
+ pathToNode: PathToNode
+ sourceRange: SourceRange
+ }
+ )[] = []
+ artifacts.forEach((artifact) => {
+ artifact.value.forEach((geo) => {
+ if (isOverlapping(geo.__geoMeta.sourceRange, selectionRange)) {
+ artifactsWithinCursorRange.push({
+ parentType: artifact.type,
+ isParent: false,
+ pathToNode: geo.__geoMeta.pathToNode,
+ sourceRange: geo.__geoMeta.sourceRange,
+ })
+ }
+ })
+ artifact.__meta.forEach((meta) => {
+ if (isOverlapping(meta.sourceRange, selectionRange)) {
+ artifactsWithinCursorRange.push({
+ parentType: artifact.type,
+ isParent: true,
+ pathToNode: meta.pathToNode,
+ sourceRange: meta.sourceRange,
+ rotation: artifact.rotation,
+ position: artifact.position,
+ })
+ }
+ })
+ })
+ const parentArtifacts = artifactsWithinCursorRange.filter((a) => a.isParent)
+ if (parentArtifacts.length > 1) {
+ console.log('multiple parents, might be an issue?', parentArtifacts)
+ }
+ const artifact = parentArtifacts[0]
+ const shouldHighlight = !!artifact
+ if (
+ shouldHighlight &&
+ (guiMode.mode === 'default' || guiMode.mode === 'canEditSketch') &&
+ ast &&
+ artifact.parentType === 'sketchGroup' &&
+ artifact.isParent
+ ) {
+ const pathToNode = getNodePathFromSourceRange(ast, artifact.sourceRange)
+ const { rotation, position } = artifact
+ setGuiMode({ mode: 'canEditSketch', pathToNode, rotation, position })
+ } else if (
+ shouldHighlight &&
+ (guiMode.mode === 'default' || guiMode.mode === 'canEditSketch') &&
+ ast &&
+ artifact.parentType === 'extrudeGroup' &&
+ artifact.isParent
+ ) {
+ const pathToNode = getNodePathFromSourceRange(ast, artifact.sourceRange)
+ const { rotation, position } = artifact
+ setGuiMode({ mode: 'canEditExtrude', pathToNode, rotation, position })
+ } else if (
+ !shouldHighlight &&
+ (guiMode.mode === 'canEditSketch' || guiMode.mode === 'canEditExtrude')
+ // (artifact.parentType === 'extrudeGroup' || artifact.type === 'extrudeGroup')
+ ) {
+ setGuiMode({ mode: 'default' })
+ }
+ }, [artifacts, selectionRange])
+}
diff --git a/src/lang/abstractSyntaxTree.ts b/src/lang/abstractSyntaxTree.ts
index d773d4eae..748c3bd42 100644
--- a/src/lang/abstractSyntaxTree.ts
+++ b/src/lang/abstractSyntaxTree.ts
@@ -1348,7 +1348,8 @@ function debuggerr(tokens: Token[], indexes: number[], msg = ''): string {
export function getNodeFromPath(
node: Program,
path: (string | number)[],
- stopAt: string = ''
+ stopAt: string = '',
+ returnEarly = false
) {
let currentNode = node as any
let stopAtNode = null
@@ -1363,6 +1364,9 @@ export function getNodeFromPath(
// it will match the deepest node of the type
// instead of returning at the first match
stopAtNode = currentNode
+ if (returnEarly) {
+ return stopAtNode
+ }
}
} catch (e) {
throw new Error(
diff --git a/src/lang/artifact.test.ts b/src/lang/artifact.test.ts
index b447b4183..3a4410868 100644
--- a/src/lang/artifact.test.ts
+++ b/src/lang/artifact.test.ts
@@ -74,6 +74,19 @@ show(mySketch001)`
{
type: 'extrudeGroup',
value: [
+ {
+ type: 'extrudePlane',
+ position: [-0.795, -0.5444722215136415, -0.5444722215136416],
+ rotation: [
+ 0.35471170441873584, 0.3467252481708758, -0.14361830020955396,
+ 0.8563498075401887,
+ ],
+ __geoMeta: {
+ geo: 'PlaneGeometry',
+ sourceRange: [24, 44],
+ pathToNode: [],
+ },
+ },
{
type: 'extrudePlane',
position: [
@@ -137,6 +150,19 @@ show(theExtrude, sk2)`
{
type: 'extrudeGroup',
value: [
+ {
+ type: 'extrudePlane',
+ position: [-0.1618929317752782, 0, 1.01798363377866],
+ rotation: [
+ 0.3823192025331841, -0.04029905920751535, -0.016692416874629204,
+ 0.9230002039112793,
+ ],
+ __geoMeta: {
+ geo: 'PlaneGeometry',
+ sourceRange: [16, 31],
+ pathToNode: [],
+ },
+ },
{
type: 'extrudePlane',
position: [
@@ -189,6 +215,21 @@ show(theExtrude, sk2)`
{
type: 'extrudeGroup',
value: [
+ {
+ type: 'extrudePlane',
+ position: [
+ 0.5230004643466108, 4.393026831645281, 5.367870706359959,
+ ],
+ rotation: [
+ -0.5548685410139091, 0.7377864971619333, 0.3261466075583827,
+ -0.20351996751370383,
+ ],
+ __geoMeta: {
+ geo: 'PlaneGeometry',
+ sourceRange: [241, 256],
+ pathToNode: [],
+ },
+ },
{
type: 'extrudePlane',
position: [
diff --git a/src/lang/engine.tsx b/src/lang/engine.tsx
index 54f06ffb0..3037783fb 100644
--- a/src/lang/engine.tsx
+++ b/src/lang/engine.tsx
@@ -98,10 +98,12 @@ export function extrudeGeo({
from,
to,
length,
+ extrusionDirection = 1,
}: {
from: [number, number, number]
to: [number, number, number]
length: number
+ extrusionDirection?: number
}): {
geo: BufferGeometry
position: Position
@@ -124,7 +126,13 @@ export function extrudeGeo({
face.translate(to[0], to[1], to[2])
const quat = new Quaternion()
- const euler = new Euler(-Math.PI / 2, ry, rz * sign, 'XYZ')
+ const otherSign = ry === 0 ? 1 : -1 // don't ask questions, it works okay
+ const euler = new Euler(
+ (Math.PI * otherSign * extrusionDirection) / 2,
+ ry,
+ rz * sign * -otherSign,
+ 'XYZ'
+ )
quat.setFromEuler(euler)
return {
diff --git a/src/lang/modifyAst.ts b/src/lang/modifyAst.ts
index 662da5a51..fbe530433 100644
--- a/src/lang/modifyAst.ts
+++ b/src/lang/modifyAst.ts
@@ -385,8 +385,12 @@ export function sketchOnExtrudedFace(
const _node = { ...node }
const dumbyStartend = { start: 0, end: 0 }
const newSketchName = findUniqueName(node, 'part')
- const oldSketchName = getNodeFromPath(_node, pathToNode, 'VariableDeclarator')
- .id.name
+ const oldSketchName = getNodeFromPath(
+ _node,
+ pathToNode,
+ 'VariableDeclarator',
+ true
+ ).id.name
const expression = getNodeFromPath(_node, pathToNode, 'CallExpression') as
| VariableDeclarator
| CallExpression
diff --git a/src/lang/sketch.ts b/src/lang/sketch.ts
index 21ee77826..ee22cadbb 100644
--- a/src/lang/sketch.ts
+++ b/src/lang/sketch.ts
@@ -173,13 +173,12 @@ export const sketchFns = {
const { position, rotation } = sketchVal
const extrudeSurfaces: ExtrudeSurface[] = []
+ const extrusionDirection = clockwiseSign(
+ sketch.value.map((line) => line.to)
+ )
sketch.value.map((line, index) => {
- if (line.type === 'toPoint' && index !== 0) {
- const lastPoint = sketch.value[index - 1]
- let from: [number, number] = [0, 0]
- if (lastPoint.type === 'toPoint') {
- from = lastPoint.to
- }
+ if (line.type === 'toPoint') {
+ let from: [number, number] = line.from
const to = line.to
const {
geo,
@@ -189,6 +188,7 @@ export const sketchFns = {
from: [from[0], from[1], 0],
to: [to[0], to[1], 0],
length,
+ extrusionDirection,
})
const groupQuaternion = new Quaternion(...rotation)
const currentWallQuat = new Quaternion(...faceRotation)
@@ -344,3 +344,13 @@ function getExtrudeWallTransform(
quaternion: path.rotation,
}
}
+
+function clockwiseSign(points: [number, number][]): number {
+ let sum = 0
+ for (let i = 0; i < points.length; i++) {
+ const currentPoint = points[i]
+ const nextPoint = points[(i + 1) % points.length]
+ sum += (nextPoint[0] - currentPoint[0]) * (nextPoint[1] + currentPoint[1])
+ }
+ return sum >= 0 ? 1 : -1
+}