initial implementation of sketching on extrude face

This commit is contained in:
Kurt Hutten IrevDev
2023-01-09 13:19:14 +11:00
parent 2e007ae288
commit ed686e5e69
6 changed files with 194 additions and 12 deletions

View File

@ -1,5 +1,5 @@
import { useStore } from './useStore'
import { extrudeSketch } from './lang/modifyAst'
import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst'
import { getNodePathFromSourceRange } from './lang/abstractSyntaxTree'
export const Toolbar = () => {
@ -27,8 +27,21 @@ export const Toolbar = () => {
Start sketch
</button>
)}
{guiMode.mode === 'canEditSketch' && (
{guiMode.mode === 'canEditExtrude' && (
<button
onClick={() => {
if (!ast) return
const pathToNode = getNodePathFromSourceRange(ast, selectionRange)
const { modifiedAst } = sketchOnExtrudedFace(ast, pathToNode)
updateAst(modifiedAst)
}}
className="border m-1 px-1 rounded"
>
SketchOnFace
</button>
)}
{(guiMode.mode === 'canEditSketch' || false) && (
/*guiMode.mode === 'canEditExtrude'*/ <button
onClick={() => {
setGuiMode({
mode: 'sketch',
@ -48,8 +61,8 @@ export const Toolbar = () => {
<button
onClick={() => {
if (!ast) return
const pathToNote = getNodePathFromSourceRange(ast, selectionRange)
const { modifiedAst } = extrudeSketch(ast, pathToNote)
const pathToNode = getNodePathFromSourceRange(ast, selectionRange)
const { modifiedAst } = extrudeSketch(ast, pathToNode)
updateAst(modifiedAst)
}}
className="border m-1 px-1 rounded"
@ -59,8 +72,8 @@ export const Toolbar = () => {
<button
onClick={() => {
if (!ast) return
const pathToNote = getNodePathFromSourceRange(ast, selectionRange)
const { modifiedAst } = extrudeSketch(ast, pathToNote, false)
const pathToNode = getNodePathFromSourceRange(ast, selectionRange)
const { modifiedAst } = extrudeSketch(ast, pathToNode, false)
updateAst(modifiedAst)
}}
className="border m-1 px-1 rounded"
@ -70,7 +83,7 @@ export const Toolbar = () => {
</>
)}
{guiMode.mode !== 'default' && (
{guiMode.mode === 'sketch' && (
<button
onClick={() => setGuiMode({ mode: 'default' })}
className="border m-1 px-1 rounded"

View File

@ -216,7 +216,7 @@ function RenderViewerArtifact({
const [editorCursor, setEditorCursor] = useState(false)
useEffect(() => {
const shouldHighlight = isOverlapping(
artifact.__meta.slice(-1)[0].sourceRange,
artifact.__meta[0].sourceRange,
selectionRange
)
setEditorCursor(shouldHighlight)
@ -238,10 +238,22 @@ function RenderViewerArtifact({
)
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' &&
artifact.type === 'sketchGroup'
(guiMode.mode === 'canEditSketch' || guiMode.mode === 'canEditExtrude') &&
(artifact.type === 'sketchGroup' || artifact.type === 'extrudeGroup')
) {
setGuiMode({ mode: 'default' })
}

View File

@ -98,6 +98,10 @@ show(mySketch001)`
sourceRange: [89, 102],
pathToNode: [],
},
{
sourceRange: [20, 68],
pathToNode: ['body', 0, 'declarations', 0, 'init', 0],
},
],
},
])
@ -176,6 +180,10 @@ show(theExtrude, sk2)`
sourceRange: [138, 166],
pathToNode: [],
},
{
sourceRange: [12, 75],
pathToNode: ['body', 0, 'declarations', 0, 'init', 0],
},
],
},
{
@ -224,6 +232,10 @@ show(theExtrude, sk2)`
sourceRange: [334, 347],
pathToNode: [],
},
{
sourceRange: [237, 299],
pathToNode: ['body', 3, 'declarations', 0, 'init', 0],
},
],
},
])

View File

@ -10,6 +10,7 @@ import {
getNodeFromPath,
VariableDeclarator,
} from './abstractSyntaxTree'
import { PathToNode } from './executor'
export function addSketchTo(
node: Program,
@ -107,6 +108,7 @@ export function addSketchTo(
function findUniqueName(
ast: Program | string,
name: string,
pad = 3,
index = 1
): string {
let searchStr = ''
@ -115,13 +117,13 @@ function findUniqueName(
} else {
searchStr = JSON.stringify(ast)
}
const indexStr = `${index}`.padStart(3, '0')
const indexStr = `${index}`.padStart(pad, '0')
const newName = `${name}${indexStr}`
const isInString = searchStr.includes(newName)
if (!isInString) {
return newName
}
return findUniqueName(searchStr, name, index + 1)
return findUniqueName(searchStr, name, pad, index + 1)
}
function addToShow(node: Program, name: string): Program {
@ -375,3 +377,136 @@ export function extrudeSketch(
pathToNode: [...pathToNode.slice(0, -1), showCallIndex],
}
}
export function sketchOnExtrudedFace(
node: Program,
pathToNode: (string | number)[]
): { modifiedAst: Program; pathToNode: (string | number)[] } {
const _node = { ...node }
const dumbyStartend = { start: 0, end: 0 }
const newSketchName = findUniqueName(node, 'part')
const oldSketchName = getNodeFromPath(_node, pathToNode, 'VariableDeclarator')
.id.name
const expression = getNodeFromPath(_node, pathToNode, 'CallExpression') as
| VariableDeclarator
| CallExpression
const pathName =
expression.type === 'VariableDeclarator'
? expression.id.name
: findUniqueName(node, 'path', 2)
if (expression.type === 'CallExpression') {
const block = getNodeFromPath(_node, pathToNode, 'BlockStatement')
const expressionIndex = getLastIndex(pathToNode)
if (expression.callee.name !== 'lineTo')
throw new Error('expected a lineTo call')
const newExpression: VariableDeclaration = {
type: 'VariableDeclaration',
...dumbyStartend,
declarations: [
{
type: 'VariableDeclarator',
...dumbyStartend,
id: {
type: 'Identifier',
...dumbyStartend,
name: pathName,
},
init: expression,
},
],
kind: 'path',
}
block.body.splice(expressionIndex, 1, newExpression)
}
// create pipe expression with a sketch block piped into a transform function
const sketchPipe: PipeExpression = {
type: 'PipeExpression',
...dumbyStartend,
body: [
{
type: 'SketchExpression',
...dumbyStartend,
body: {
type: 'BlockStatement',
...dumbyStartend,
body: [],
},
},
{
type: 'CallExpression',
...dumbyStartend,
callee: {
type: 'Identifier',
...dumbyStartend,
name: 'transform',
},
optional: false,
arguments: [
{
type: 'CallExpression',
...dumbyStartend,
callee: {
type: 'Identifier',
...dumbyStartend,
name: 'getExtrudeWallTransform',
},
optional: false,
arguments: [
{
type: 'Literal',
...dumbyStartend,
value: pathName,
raw: `'${pathName}'`,
},
{
type: 'Identifier',
...dumbyStartend,
name: oldSketchName,
},
],
},
{
type: 'PipeSubstitution',
...dumbyStartend,
},
],
},
],
}
const variableDec: VariableDeclaration = {
type: 'VariableDeclaration',
...dumbyStartend,
declarations: [
{
type: 'VariableDeclarator',
...dumbyStartend,
id: {
type: 'Identifier',
...dumbyStartend,
name: newSketchName,
},
init: sketchPipe,
},
],
kind: 'sketch',
}
const showIndex = getShowIndex(_node)
_node.body.splice(showIndex, 0, variableDec)
return {
modifiedAst: addToShow(_node, newSketchName),
pathToNode,
}
}
const getLastIndex = (pathToNode: PathToNode): number => {
const last = pathToNode[pathToNode.length - 1]
if (typeof last === 'number') {
return last
}
return getLastIndex(pathToNode.slice(0, -1))
}

View File

@ -228,6 +228,10 @@ export const sketchFns = {
sourceRange,
pathToNode: [], // TODO
},
{
sourceRange: sketchVal.__meta[0].sourceRange,
pathToNode: sketchVal.__meta[0].pathToNode,
},
],
}
},

View File

@ -36,6 +36,12 @@ type GuiModes =
rotation: Rotation
position: Position
}
| {
mode: 'canEditExtrude'
pathToNode: PathToNode
rotation: Rotation
position: Position
}
interface StoreState {
editorView: EditorView | null