initial implementation of sketching on extrude face
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
import { useStore } from './useStore'
|
import { useStore } from './useStore'
|
||||||
import { extrudeSketch } from './lang/modifyAst'
|
import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst'
|
||||||
import { getNodePathFromSourceRange } from './lang/abstractSyntaxTree'
|
import { getNodePathFromSourceRange } from './lang/abstractSyntaxTree'
|
||||||
|
|
||||||
export const Toolbar = () => {
|
export const Toolbar = () => {
|
||||||
@ -27,8 +27,21 @@ export const Toolbar = () => {
|
|||||||
Start sketch
|
Start sketch
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{guiMode.mode === 'canEditSketch' && (
|
{guiMode.mode === 'canEditExtrude' && (
|
||||||
<button
|
<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={() => {
|
onClick={() => {
|
||||||
setGuiMode({
|
setGuiMode({
|
||||||
mode: 'sketch',
|
mode: 'sketch',
|
||||||
@ -48,8 +61,8 @@ export const Toolbar = () => {
|
|||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!ast) return
|
if (!ast) return
|
||||||
const pathToNote = getNodePathFromSourceRange(ast, selectionRange)
|
const pathToNode = getNodePathFromSourceRange(ast, selectionRange)
|
||||||
const { modifiedAst } = extrudeSketch(ast, pathToNote)
|
const { modifiedAst } = extrudeSketch(ast, pathToNode)
|
||||||
updateAst(modifiedAst)
|
updateAst(modifiedAst)
|
||||||
}}
|
}}
|
||||||
className="border m-1 px-1 rounded"
|
className="border m-1 px-1 rounded"
|
||||||
@ -59,8 +72,8 @@ export const Toolbar = () => {
|
|||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!ast) return
|
if (!ast) return
|
||||||
const pathToNote = getNodePathFromSourceRange(ast, selectionRange)
|
const pathToNode = getNodePathFromSourceRange(ast, selectionRange)
|
||||||
const { modifiedAst } = extrudeSketch(ast, pathToNote, false)
|
const { modifiedAst } = extrudeSketch(ast, pathToNode, false)
|
||||||
updateAst(modifiedAst)
|
updateAst(modifiedAst)
|
||||||
}}
|
}}
|
||||||
className="border m-1 px-1 rounded"
|
className="border m-1 px-1 rounded"
|
||||||
@ -70,7 +83,7 @@ export const Toolbar = () => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{guiMode.mode !== 'default' && (
|
{guiMode.mode === 'sketch' && (
|
||||||
<button
|
<button
|
||||||
onClick={() => setGuiMode({ mode: 'default' })}
|
onClick={() => setGuiMode({ mode: 'default' })}
|
||||||
className="border m-1 px-1 rounded"
|
className="border m-1 px-1 rounded"
|
||||||
|
@ -216,7 +216,7 @@ function RenderViewerArtifact({
|
|||||||
const [editorCursor, setEditorCursor] = useState(false)
|
const [editorCursor, setEditorCursor] = useState(false)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const shouldHighlight = isOverlapping(
|
const shouldHighlight = isOverlapping(
|
||||||
artifact.__meta.slice(-1)[0].sourceRange,
|
artifact.__meta[0].sourceRange,
|
||||||
selectionRange
|
selectionRange
|
||||||
)
|
)
|
||||||
setEditorCursor(shouldHighlight)
|
setEditorCursor(shouldHighlight)
|
||||||
@ -238,10 +238,22 @@ function RenderViewerArtifact({
|
|||||||
)
|
)
|
||||||
const { rotation, position } = artifact
|
const { rotation, position } = artifact
|
||||||
setGuiMode({ mode: 'canEditSketch', pathToNode, rotation, position })
|
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 (
|
} else if (
|
||||||
!shouldHighlight &&
|
!shouldHighlight &&
|
||||||
guiMode.mode === 'canEditSketch' &&
|
(guiMode.mode === 'canEditSketch' || guiMode.mode === 'canEditExtrude') &&
|
||||||
artifact.type === 'sketchGroup'
|
(artifact.type === 'sketchGroup' || artifact.type === 'extrudeGroup')
|
||||||
) {
|
) {
|
||||||
setGuiMode({ mode: 'default' })
|
setGuiMode({ mode: 'default' })
|
||||||
}
|
}
|
||||||
|
@ -98,6 +98,10 @@ show(mySketch001)`
|
|||||||
sourceRange: [89, 102],
|
sourceRange: [89, 102],
|
||||||
pathToNode: [],
|
pathToNode: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
sourceRange: [20, 68],
|
||||||
|
pathToNode: ['body', 0, 'declarations', 0, 'init', 0],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
@ -176,6 +180,10 @@ show(theExtrude, sk2)`
|
|||||||
sourceRange: [138, 166],
|
sourceRange: [138, 166],
|
||||||
pathToNode: [],
|
pathToNode: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
sourceRange: [12, 75],
|
||||||
|
pathToNode: ['body', 0, 'declarations', 0, 'init', 0],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -224,6 +232,10 @@ show(theExtrude, sk2)`
|
|||||||
sourceRange: [334, 347],
|
sourceRange: [334, 347],
|
||||||
pathToNode: [],
|
pathToNode: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
sourceRange: [237, 299],
|
||||||
|
pathToNode: ['body', 3, 'declarations', 0, 'init', 0],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
getNodeFromPath,
|
getNodeFromPath,
|
||||||
VariableDeclarator,
|
VariableDeclarator,
|
||||||
} from './abstractSyntaxTree'
|
} from './abstractSyntaxTree'
|
||||||
|
import { PathToNode } from './executor'
|
||||||
|
|
||||||
export function addSketchTo(
|
export function addSketchTo(
|
||||||
node: Program,
|
node: Program,
|
||||||
@ -107,6 +108,7 @@ export function addSketchTo(
|
|||||||
function findUniqueName(
|
function findUniqueName(
|
||||||
ast: Program | string,
|
ast: Program | string,
|
||||||
name: string,
|
name: string,
|
||||||
|
pad = 3,
|
||||||
index = 1
|
index = 1
|
||||||
): string {
|
): string {
|
||||||
let searchStr = ''
|
let searchStr = ''
|
||||||
@ -115,13 +117,13 @@ function findUniqueName(
|
|||||||
} else {
|
} else {
|
||||||
searchStr = JSON.stringify(ast)
|
searchStr = JSON.stringify(ast)
|
||||||
}
|
}
|
||||||
const indexStr = `${index}`.padStart(3, '0')
|
const indexStr = `${index}`.padStart(pad, '0')
|
||||||
const newName = `${name}${indexStr}`
|
const newName = `${name}${indexStr}`
|
||||||
const isInString = searchStr.includes(newName)
|
const isInString = searchStr.includes(newName)
|
||||||
if (!isInString) {
|
if (!isInString) {
|
||||||
return newName
|
return newName
|
||||||
}
|
}
|
||||||
return findUniqueName(searchStr, name, index + 1)
|
return findUniqueName(searchStr, name, pad, index + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
function addToShow(node: Program, name: string): Program {
|
function addToShow(node: Program, name: string): Program {
|
||||||
@ -375,3 +377,136 @@ export function extrudeSketch(
|
|||||||
pathToNode: [...pathToNode.slice(0, -1), showCallIndex],
|
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))
|
||||||
|
}
|
||||||
|
@ -228,6 +228,10 @@ export const sketchFns = {
|
|||||||
sourceRange,
|
sourceRange,
|
||||||
pathToNode: [], // TODO
|
pathToNode: [], // TODO
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
sourceRange: sketchVal.__meta[0].sourceRange,
|
||||||
|
pathToNode: sketchVal.__meta[0].pathToNode,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -36,6 +36,12 @@ type GuiModes =
|
|||||||
rotation: Rotation
|
rotation: Rotation
|
||||||
position: Position
|
position: Position
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
mode: 'canEditExtrude'
|
||||||
|
pathToNode: PathToNode
|
||||||
|
rotation: Rotation
|
||||||
|
position: Position
|
||||||
|
}
|
||||||
|
|
||||||
interface StoreState {
|
interface StoreState {
|
||||||
editorView: EditorView | null
|
editorView: EditorView | null
|
||||||
|
Reference in New Issue
Block a user