2023-09-16 01:23:11 -04:00
|
|
|
import { useStore, toolTips, ToolTip } from './useStore'
|
2023-01-09 13:19:14 +11:00
|
|
|
import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst'
|
2023-03-03 20:35:48 +11:00
|
|
|
import { getNodePathFromSourceRange } from './lang/queryAst'
|
2023-02-21 10:50:45 +11:00
|
|
|
import { HorzVert } from './components/Toolbar/HorzVert'
|
2023-03-22 03:02:37 +11:00
|
|
|
import { RemoveConstrainingValues } from './components/Toolbar/RemoveConstrainingValues'
|
2023-03-17 21:15:46 +11:00
|
|
|
import { EqualLength } from './components/Toolbar/EqualLength'
|
|
|
|
import { EqualAngle } from './components/Toolbar/EqualAngle'
|
2023-03-19 18:46:39 +11:00
|
|
|
import { Intersect } from './components/Toolbar/Intersect'
|
2023-04-05 15:08:46 +10:00
|
|
|
import { SetHorzVertDistance } from './components/Toolbar/SetHorzVertDistance'
|
2023-04-08 14:16:49 +10:00
|
|
|
import { SetAngleLength } from './components/Toolbar/setAngleLength'
|
2023-04-05 15:08:46 +10:00
|
|
|
import { SetAbsDistance } from './components/Toolbar/SetAbsDistance'
|
2023-04-08 14:16:49 +10:00
|
|
|
import { SetAngleBetween } from './components/Toolbar/SetAngleBetween'
|
2023-08-31 09:47:59 -04:00
|
|
|
import { Fragment, useEffect } from 'react'
|
|
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
|
|
import { faSearch, faX } from '@fortawesome/free-solid-svg-icons'
|
|
|
|
import { Popover, Transition } from '@headlessui/react'
|
|
|
|
import styles from './Toolbar.module.css'
|
2023-09-13 08:36:47 +10:00
|
|
|
import { v4 as uuidv4 } from 'uuid'
|
|
|
|
import { useAppMode } from 'hooks/useAppMode'
|
2023-09-16 01:23:11 -04:00
|
|
|
import { ActionIcon } from 'components/ActionIcon'
|
|
|
|
|
|
|
|
export const sketchButtonClassnames = {
|
|
|
|
background:
|
|
|
|
'bg-chalkboard-100 group-hover:bg-chalkboard-90 hover:bg-chalkboard-90 dark:bg-fern-20 dark:group-hover:bg-fern-10 dark:hover:bg-fern-10 group-disabled:bg-chalkboard-50 dark:group-disabled:bg-chalkboard-60 group-hover:group-disabled:bg-chalkboard-50 dark:group-hover:group-disabled:bg-chalkboard-50',
|
|
|
|
icon: 'text-fern-20 h-auto group-hover:text-fern-10 hover:text-fern-10 dark:text-chalkboard-100 dark:group-hover:text-chalkboard-100 dark:hover:text-chalkboard-100 group-disabled:bg-chalkboard-60 hover:group-disabled:text-inherit',
|
|
|
|
}
|
|
|
|
|
|
|
|
const sketchFnLabels: Record<ToolTip | 'sketch_line' | 'move', string> = {
|
|
|
|
sketch_line: 'Line',
|
|
|
|
line: 'Line',
|
|
|
|
move: 'Move',
|
|
|
|
angledLine: 'Angled Line',
|
|
|
|
angledLineThatIntersects: 'Angled Line That Intersects',
|
|
|
|
angledLineOfXLength: 'Angled Line Of X Length',
|
|
|
|
angledLineOfYLength: 'Angled Line Of Y Length',
|
|
|
|
angledLineToX: 'Angled Line To X',
|
|
|
|
angledLineToY: 'Angled Line To Y',
|
|
|
|
lineTo: 'Line to Point',
|
|
|
|
xLine: 'Horizontal Line',
|
|
|
|
yLine: 'Vertical Line',
|
|
|
|
xLineTo: 'Horizontal Line to Point',
|
|
|
|
yLineTo: 'Vertical Line to Point',
|
|
|
|
}
|
2022-11-27 14:06:33 +11:00
|
|
|
|
|
|
|
export const Toolbar = () => {
|
2023-02-21 10:28:34 +11:00
|
|
|
const {
|
|
|
|
setGuiMode,
|
|
|
|
guiMode,
|
|
|
|
selectionRanges,
|
|
|
|
ast,
|
|
|
|
updateAst,
|
|
|
|
programMemory,
|
2023-09-13 08:36:47 +10:00
|
|
|
engineCommandManager,
|
2023-09-15 04:35:48 -07:00
|
|
|
executeAst,
|
2023-02-21 10:28:34 +11:00
|
|
|
} = useStore((s) => ({
|
|
|
|
guiMode: s.guiMode,
|
|
|
|
setGuiMode: s.setGuiMode,
|
|
|
|
selectionRanges: s.selectionRanges,
|
|
|
|
ast: s.ast,
|
|
|
|
updateAst: s.updateAst,
|
|
|
|
programMemory: s.programMemory,
|
2023-09-13 08:36:47 +10:00
|
|
|
engineCommandManager: s.engineCommandManager,
|
2023-09-15 04:35:48 -07:00
|
|
|
executeAst: s.executeAst,
|
2023-02-21 10:28:34 +11:00
|
|
|
}))
|
2023-09-13 08:36:47 +10:00
|
|
|
useAppMode()
|
2023-02-12 10:56:45 +11:00
|
|
|
|
2023-09-16 01:23:11 -04:00
|
|
|
function ToolbarButtons({ className }: React.HTMLAttributes<HTMLElement>) {
|
2023-08-31 09:47:59 -04:00
|
|
|
return (
|
2023-09-16 01:23:11 -04:00
|
|
|
<span className={styles.toolbarButtons + ' ' + className}>
|
2023-08-31 09:47:59 -04:00
|
|
|
{guiMode.mode === 'default' && (
|
2023-01-06 12:45:34 +11:00
|
|
|
<button
|
|
|
|
onClick={() => {
|
2023-08-31 09:47:59 -04:00
|
|
|
setGuiMode({
|
|
|
|
mode: 'sketch',
|
|
|
|
sketchMode: 'selectFace',
|
|
|
|
})
|
2023-01-06 12:45:34 +11:00
|
|
|
}}
|
2023-09-16 01:23:11 -04:00
|
|
|
className="group"
|
2023-01-06 12:45:34 +11:00
|
|
|
>
|
2023-09-16 01:23:11 -04:00
|
|
|
<ActionIcon icon="sketch" className="!p-0.5" size="md" />
|
2023-08-31 09:47:59 -04:00
|
|
|
Start Sketch
|
2023-01-06 12:45:34 +11:00
|
|
|
</button>
|
2023-08-31 09:47:59 -04:00
|
|
|
)}
|
|
|
|
{guiMode.mode === 'canEditExtrude' && (
|
2023-01-06 12:45:34 +11:00
|
|
|
<button
|
|
|
|
onClick={() => {
|
|
|
|
if (!ast) return
|
2023-02-21 10:28:34 +11:00
|
|
|
const pathToNode = getNodePathFromSourceRange(
|
|
|
|
ast,
|
2023-04-03 16:05:25 +10:00
|
|
|
selectionRanges.codeBasedSelections[0].range
|
2023-02-21 10:28:34 +11:00
|
|
|
)
|
2023-08-31 09:47:59 -04:00
|
|
|
const { modifiedAst } = sketchOnExtrudedFace(
|
2023-01-13 17:58:37 +11:00
|
|
|
ast,
|
|
|
|
pathToNode,
|
2023-08-31 09:47:59 -04:00
|
|
|
programMemory
|
2023-01-13 17:58:37 +11:00
|
|
|
)
|
2023-09-15 04:35:48 -07:00
|
|
|
updateAst(modifiedAst, true)
|
2023-01-06 12:45:34 +11:00
|
|
|
}}
|
2023-09-16 01:23:11 -04:00
|
|
|
className="group"
|
2023-01-06 12:45:34 +11:00
|
|
|
>
|
2023-09-16 01:23:11 -04:00
|
|
|
<ActionIcon icon="sketch" className="!p-0.5" size="md" />
|
|
|
|
Sketch on Face
|
2023-01-06 12:45:34 +11:00
|
|
|
</button>
|
2023-08-31 09:47:59 -04:00
|
|
|
)}
|
2023-09-13 08:36:47 +10:00
|
|
|
{guiMode.mode === 'canEditSketch' && (
|
2023-08-31 09:47:59 -04:00
|
|
|
<button
|
|
|
|
onClick={() => {
|
2023-09-17 21:57:43 -07:00
|
|
|
const pathToNode = getNodePathFromSourceRange(
|
|
|
|
ast,
|
|
|
|
selectionRanges.codeBasedSelections[0].range
|
|
|
|
)
|
2023-08-31 09:47:59 -04:00
|
|
|
setGuiMode({
|
|
|
|
mode: 'sketch',
|
2023-09-17 21:57:43 -07:00
|
|
|
sketchMode: 'enterSketchEdit',
|
|
|
|
pathToNode: pathToNode,
|
|
|
|
rotation: [0, 0, 0, 1],
|
|
|
|
position: [0, 0, 0],
|
|
|
|
pathId: guiMode.pathId,
|
2023-08-31 09:47:59 -04:00
|
|
|
})
|
|
|
|
}}
|
2023-09-16 01:23:11 -04:00
|
|
|
className="group"
|
2023-08-31 09:47:59 -04:00
|
|
|
>
|
2023-09-16 01:23:11 -04:00
|
|
|
<ActionIcon icon="sketch" className="!p-0.5" size="md" />
|
2023-08-31 09:47:59 -04:00
|
|
|
Edit Sketch
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
{guiMode.mode === 'canEditSketch' && (
|
|
|
|
<>
|
|
|
|
<button
|
|
|
|
onClick={() => {
|
|
|
|
if (!ast) return
|
|
|
|
const pathToNode = getNodePathFromSourceRange(
|
|
|
|
ast,
|
|
|
|
selectionRanges.codeBasedSelections[0].range
|
|
|
|
)
|
|
|
|
const { modifiedAst, pathToExtrudeArg } = extrudeSketch(
|
|
|
|
ast,
|
|
|
|
pathToNode
|
|
|
|
)
|
2023-09-15 04:35:48 -07:00
|
|
|
updateAst(modifiedAst, true, { focusPath: pathToExtrudeArg })
|
2023-08-31 09:47:59 -04:00
|
|
|
}}
|
2023-09-16 01:23:11 -04:00
|
|
|
className="group"
|
2023-08-31 09:47:59 -04:00
|
|
|
>
|
2023-09-16 01:23:11 -04:00
|
|
|
<ActionIcon icon="extrude" className="!p-0.5" size="md" />
|
|
|
|
Extrude
|
2023-08-31 09:47:59 -04:00
|
|
|
</button>
|
2023-03-19 18:46:39 +11:00
|
|
|
<button
|
2023-08-31 09:47:59 -04:00
|
|
|
onClick={() => {
|
|
|
|
if (!ast) return
|
|
|
|
const pathToNode = getNodePathFromSourceRange(
|
|
|
|
ast,
|
|
|
|
selectionRanges.codeBasedSelections[0].range
|
|
|
|
)
|
|
|
|
const { modifiedAst, pathToExtrudeArg } = extrudeSketch(
|
|
|
|
ast,
|
|
|
|
pathToNode,
|
|
|
|
false
|
|
|
|
)
|
2023-09-15 04:35:48 -07:00
|
|
|
updateAst(modifiedAst, true, { focusPath: pathToExtrudeArg })
|
2023-08-31 09:47:59 -04:00
|
|
|
}}
|
2023-09-16 01:23:11 -04:00
|
|
|
className="group"
|
2023-03-19 18:46:39 +11:00
|
|
|
>
|
2023-09-16 01:23:11 -04:00
|
|
|
<ActionIcon icon="extrude" className="!p-0.5" size="md" />
|
|
|
|
Extrude as new
|
2023-03-19 18:46:39 +11:00
|
|
|
</button>
|
2023-08-31 09:47:59 -04:00
|
|
|
</>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{guiMode.mode === 'sketch' && (
|
2023-09-13 08:36:47 +10:00
|
|
|
<button
|
|
|
|
onClick={() => {
|
|
|
|
engineCommandManager?.sendSceneCommand({
|
|
|
|
type: 'modeling_cmd_req',
|
|
|
|
cmd_id: uuidv4(),
|
|
|
|
cmd: { type: 'edit_mode_exit' },
|
|
|
|
})
|
2023-09-15 04:35:48 -07:00
|
|
|
engineCommandManager?.sendSceneCommand({
|
|
|
|
type: 'modeling_cmd_req',
|
|
|
|
cmd_id: uuidv4(),
|
|
|
|
cmd: { type: 'default_camera_disable_sketch_mode' },
|
|
|
|
})
|
|
|
|
|
2023-09-13 08:36:47 +10:00
|
|
|
setGuiMode({ mode: 'default' })
|
2023-09-15 04:35:48 -07:00
|
|
|
executeAst()
|
2023-09-13 08:36:47 +10:00
|
|
|
}}
|
2023-09-16 01:23:11 -04:00
|
|
|
className="group"
|
2023-09-13 08:36:47 +10:00
|
|
|
>
|
2023-09-16 01:23:11 -04:00
|
|
|
<ActionIcon
|
|
|
|
icon="exit"
|
|
|
|
className="!p-0.5"
|
|
|
|
bgClassName={sketchButtonClassnames.background}
|
|
|
|
iconClassName={sketchButtonClassnames.icon}
|
|
|
|
size="md"
|
|
|
|
/>
|
2023-08-31 09:47:59 -04:00
|
|
|
Exit sketch
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
{toolTips
|
|
|
|
.filter(
|
|
|
|
// (sketchFnName) => !['angledLineThatIntersects'].includes(sketchFnName)
|
2023-09-13 08:36:47 +10:00
|
|
|
(sketchFnName) => ['sketch_line', 'move'].includes(sketchFnName)
|
2023-03-19 18:46:39 +11:00
|
|
|
)
|
2023-08-31 09:47:59 -04:00
|
|
|
.map((sketchFnName) => {
|
|
|
|
if (
|
|
|
|
guiMode.mode !== 'sketch' ||
|
|
|
|
!('isTooltip' in guiMode || guiMode.sketchMode === 'sketchEdit')
|
|
|
|
)
|
|
|
|
return null
|
|
|
|
return (
|
|
|
|
<button
|
|
|
|
key={sketchFnName}
|
2023-09-13 08:36:47 +10:00
|
|
|
onClick={() => {
|
|
|
|
engineCommandManager?.sendSceneCommand({
|
|
|
|
type: 'modeling_cmd_req',
|
|
|
|
cmd_id: uuidv4(),
|
|
|
|
cmd: {
|
|
|
|
type: 'set_tool',
|
|
|
|
tool:
|
|
|
|
guiMode.sketchMode === sketchFnName
|
|
|
|
? 'select'
|
|
|
|
: (sketchFnName as any),
|
|
|
|
},
|
|
|
|
})
|
2023-08-31 09:47:59 -04:00
|
|
|
setGuiMode({
|
|
|
|
...guiMode,
|
|
|
|
...(guiMode.sketchMode === sketchFnName
|
|
|
|
? {
|
|
|
|
sketchMode: 'sketchEdit',
|
|
|
|
// todo: ...guiMod is adding isTooltip: true, will probably just fix with xstate migtaion
|
|
|
|
}
|
|
|
|
: {
|
|
|
|
sketchMode: sketchFnName,
|
2023-09-13 08:36:47 +10:00
|
|
|
waitingFirstClick: true,
|
2023-08-31 09:47:59 -04:00
|
|
|
isTooltip: true,
|
2023-09-17 21:57:43 -07:00
|
|
|
pathId: guiMode.pathId,
|
2023-08-31 09:47:59 -04:00
|
|
|
}),
|
|
|
|
})
|
2023-09-13 08:36:47 +10:00
|
|
|
}}
|
2023-09-16 01:23:11 -04:00
|
|
|
className={
|
|
|
|
'group ' +
|
|
|
|
(guiMode.sketchMode === sketchFnName
|
|
|
|
? '!text-fern-70 !bg-fern-10 !dark:text-fern-20 !border-fern-50'
|
|
|
|
: '')
|
|
|
|
}
|
2023-08-31 09:47:59 -04:00
|
|
|
>
|
2023-09-16 01:23:11 -04:00
|
|
|
<ActionIcon
|
|
|
|
icon={sketchFnName.includes('line') ? 'line' : 'move'}
|
|
|
|
className="!p-0.5"
|
|
|
|
bgClassName={sketchButtonClassnames.background}
|
|
|
|
iconClassName={sketchButtonClassnames.icon}
|
|
|
|
size="md"
|
|
|
|
/>
|
|
|
|
{sketchFnLabels[sketchFnName]}
|
2023-08-31 09:47:59 -04:00
|
|
|
</button>
|
|
|
|
)
|
|
|
|
})}
|
|
|
|
<HorzVert horOrVert="horizontal" />
|
|
|
|
<HorzVert horOrVert="vertical" />
|
|
|
|
<EqualLength />
|
|
|
|
<EqualAngle />
|
|
|
|
<SetHorzVertDistance buttonType="alignEndsVertically" />
|
|
|
|
<SetHorzVertDistance buttonType="setHorzDistance" />
|
|
|
|
<SetAbsDistance buttonType="snapToYAxis" />
|
|
|
|
<SetAbsDistance buttonType="xAbs" />
|
|
|
|
<SetHorzVertDistance buttonType="alignEndsHorizontally" />
|
|
|
|
<SetAbsDistance buttonType="snapToXAxis" />
|
|
|
|
<SetHorzVertDistance buttonType="setVertDistance" />
|
|
|
|
<SetAbsDistance buttonType="yAbs" />
|
|
|
|
<SetAngleLength angleOrLength="setAngle" />
|
|
|
|
<SetAngleLength angleOrLength="setLength" />
|
|
|
|
<Intersect />
|
|
|
|
<RemoveConstrainingValues />
|
|
|
|
<SetAngleBetween />
|
2023-09-13 08:36:47 +10:00
|
|
|
</span>
|
2023-08-31 09:47:59 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Popover className={styles.toolbarWrapper + ' ' + guiMode.mode}>
|
|
|
|
<div className={styles.toolbar}>
|
|
|
|
<span className={styles.toolbarCap + ' ' + styles.label}>
|
|
|
|
{guiMode.mode === 'sketch' ? '2D' : '3D'}
|
|
|
|
</span>
|
2023-09-16 01:23:11 -04:00
|
|
|
<menu className="flex-1 gap-2 py-0.5 overflow-hidden whitespace-nowrap">
|
2023-08-31 09:47:59 -04:00
|
|
|
<ToolbarButtons />
|
|
|
|
</menu>
|
|
|
|
<Popover.Button
|
|
|
|
className={styles.toolbarCap + ' ' + styles.popoverToggle}
|
|
|
|
>
|
|
|
|
<FontAwesomeIcon icon={faSearch} />
|
|
|
|
</Popover.Button>
|
|
|
|
</div>
|
|
|
|
<Transition
|
|
|
|
as={Fragment}
|
|
|
|
enter="transition ease-out duration-200"
|
|
|
|
enterFrom="opacity-0"
|
|
|
|
enterTo="opacity-100"
|
|
|
|
leave="transition ease-out duration-100"
|
|
|
|
leaveFrom="opacity-100"
|
|
|
|
leaveTo="opacity-0"
|
|
|
|
>
|
|
|
|
<Popover.Overlay className="fixed inset-0 bg-chalkboard-110/20 dark:bg-chalkboard-110/50" />
|
|
|
|
</Transition>
|
|
|
|
<Transition
|
|
|
|
as={Fragment}
|
|
|
|
enter="transition ease-out duration-100"
|
|
|
|
enterFrom="opacity-0 translate-y-1 scale-95"
|
|
|
|
enterTo="opacity-100 translate-y-0 scale-100"
|
|
|
|
leave="transition ease-out duration-75"
|
|
|
|
leaveFrom="opacity-100 translate-y-0"
|
|
|
|
leaveTo="opacity-0 translate-y-2"
|
|
|
|
>
|
|
|
|
<Popover.Panel className="absolute top-0 w-screen max-w-xl left-1/2 -translate-x-1/2 flex flex-col gap-8 bg-chalkboard-10 dark:bg-chalkboard-100 p-5 rounded border border-chalkboard-20/30 dark:border-chalkboard-70/50">
|
|
|
|
<section className="flex justify-between items-center">
|
|
|
|
<p
|
|
|
|
className={`${styles.toolbarCap} ${styles.label} !self-center rounded-r-full w-fit`}
|
|
|
|
>
|
|
|
|
You're in {guiMode.mode === 'sketch' ? '2D' : '3D'}
|
|
|
|
</p>
|
|
|
|
<Popover.Button className="p-2 flex items-center justify-center rounded-sm bg-chalkboard-20 text-chalkboard-110 dark:bg-chalkboard-70 dark:text-chalkboard-20 border-none hover:bg-chalkboard-30 dark:hover:bg-chalkboard-60">
|
|
|
|
<FontAwesomeIcon icon={faX} className="w-4 h-4" />
|
|
|
|
</Popover.Button>
|
|
|
|
</section>
|
|
|
|
<section>
|
2023-09-16 01:23:11 -04:00
|
|
|
<ToolbarButtons className="flex-wrap" />
|
2023-08-31 09:47:59 -04:00
|
|
|
</section>
|
|
|
|
</Popover.Panel>
|
|
|
|
</Transition>
|
|
|
|
</Popover>
|
2022-11-27 14:06:33 +11:00
|
|
|
)
|
|
|
|
}
|