2024-07-24 23:33:31 -04:00
import { CustomIconName } from 'components/CustomIcon'
import { DEV } from 'env'
2025-01-23 10:25:21 -05:00
import { commandBarActor , commandBarMachine } from 'machines/commandBarMachine'
2024-07-24 23:33:31 -04:00
import {
2024-12-16 10:34:11 -05:00
canRectangleOrCircleTool ,
isClosedSketch ,
2024-07-24 23:33:31 -04:00
isEditingExistingSketch ,
modelingMachine ,
2024-09-23 22:42:51 +10:00
pipeHasCircle ,
2024-07-24 23:33:31 -04:00
} from 'machines/modelingMachine'
2025-01-10 11:24:07 -05:00
import { IS_NIGHTLY_OR_DEBUG } from 'routes/Settings'
2024-07-24 23:33:31 -04:00
import { EventFrom , StateFrom } from 'xstate'
export type ToolbarModeName = 'modeling' | 'sketching'
type ToolbarMode = {
check : ( state : StateFrom < typeof modelingMachine > ) = > boolean
items : ( ToolbarItem | ToolbarItem [ ] | 'break' ) [ ]
}
export interface ToolbarItemCallbackProps {
2024-09-09 19:59:36 +03:00
modelingState : StateFrom < typeof modelingMachine >
2024-07-24 23:33:31 -04:00
modelingSend : ( event : EventFrom < typeof modelingMachine > ) = > void
sketchPathId : string | false
}
export type ToolbarItem = {
id : string
onClick : ( props : ToolbarItemCallbackProps ) = > void
icon? : CustomIconName
status : 'available' | 'unavailable' | 'kcl-only'
disabled ? : ( state : StateFrom < typeof modelingMachine > ) = > boolean
disableHotkey ? : ( state : StateFrom < typeof modelingMachine > ) = > boolean
title : string | ( ( props : ToolbarItemCallbackProps ) = > string )
showTitle? : boolean
hotkey ? :
| string
| ( ( state : StateFrom < typeof modelingMachine > ) = > string | string [ ] )
description : string
links : { label : string ; url : string } [ ]
isActive ? : ( state : StateFrom < typeof modelingMachine > ) = > boolean
2024-10-28 20:52:51 -04:00
disabledReason ? :
| string
| ( ( state : StateFrom < typeof modelingMachine > ) = > string | undefined )
2024-07-24 23:33:31 -04:00
}
export type ToolbarItemResolved = Omit <
ToolbarItem ,
'disabled' | 'disableHotkey' | 'hotkey' | 'isActive' | 'title'
> & {
title : string
disabled? : boolean
disableHotkey? : boolean
hotkey? : string | string [ ]
isActive? : boolean
}
export const toolbarConfig : Record < ToolbarModeName , ToolbarMode > = {
modeling : {
check : ( state ) = >
! ( state . matches ( 'Sketch' ) || state . matches ( 'Sketch no face' ) ) ,
items : [
{
id : 'sketch' ,
onClick : ( { modelingSend , sketchPathId } ) = >
! sketchPathId
? modelingSend ( {
type : 'Enter sketch' ,
data : { forceNewSketch : true } ,
} )
: modelingSend ( { type : 'Enter sketch' } ) ,
icon : 'sketch' ,
status : 'available' ,
title : ( { sketchPathId } ) = >
2024-12-16 10:34:11 -05:00
` ${ sketchPathId ? 'Edit' : 'Start' } Sketch ` ,
2024-07-24 23:33:31 -04:00
showTitle : true ,
hotkey : 'S' ,
description : 'Start drawing a 2D sketch' ,
links : [
{ label : 'KCL docs' , url : 'https://zoo.dev/docs/kcl/startSketchOn' } ,
] ,
} ,
'break' ,
{
id : 'extrude' ,
2025-01-23 10:25:21 -05:00
onClick : ( ) = >
commandBarActor . send ( {
2024-07-24 23:33:31 -04:00
type : 'Find and select command' ,
data : { name : 'Extrude' , groupId : 'modeling' } ,
} ) ,
icon : 'extrude' ,
status : 'available' ,
title : 'Extrude' ,
hotkey : 'E' ,
description : 'Pull a sketch into 3D along its normal or perpendicular.' ,
links : [ { label : 'KCL docs' , url : 'https://zoo.dev/docs/kcl/extrude' } ] ,
} ,
{
id : 'revolve' ,
2025-01-23 10:25:21 -05:00
onClick : ( ) = >
commandBarActor . send ( {
2024-09-17 08:29:52 -05:00
type : 'Find and select command' ,
data : { name : 'Revolve' , groupId : 'modeling' } ,
} ) ,
2024-07-24 23:33:31 -04:00
icon : 'revolve' ,
2025-02-01 06:02:43 -05:00
status : 'available' ,
2024-07-24 23:33:31 -04:00
title : 'Revolve' ,
hotkey : 'R' ,
description :
'Create a 3D body by rotating a sketch region about an axis.' ,
links : [
{ label : 'KCL docs' , url : 'https://zoo.dev/docs/kcl/revolve' } ,
{
label : 'KCL example' ,
url : 'https://zoo.dev/docs/kcl-samples/ball-bearing' ,
} ,
] ,
} ,
{
id : 'sweep' ,
2025-01-23 10:25:21 -05:00
onClick : ( ) = >
commandBarActor . send ( {
2025-01-11 08:20:49 -05:00
type : 'Find and select command' ,
data : { name : 'Sweep' , groupId : 'modeling' } ,
} ) ,
2024-07-24 23:33:31 -04:00
icon : 'sweep' ,
2025-02-01 05:21:25 -05:00
status : 'available' ,
2024-07-24 23:33:31 -04:00
title : 'Sweep' ,
hotkey : 'W' ,
description :
'Create a 3D body by moving a sketch region along an arbitrary path.' ,
links : [
{
2025-01-11 08:20:49 -05:00
label : 'KCL docs' ,
url : 'https://zoo.dev/docs/kcl/sweep' ,
2024-07-24 23:33:31 -04:00
} ,
] ,
} ,
{
id : 'loft' ,
2025-01-23 10:25:21 -05:00
onClick : ( ) = >
commandBarActor . send ( {
2024-12-04 17:24:16 -05:00
type : 'Find and select command' ,
data : { name : 'Loft' , groupId : 'modeling' } ,
} ) ,
2024-07-24 23:33:31 -04:00
icon : 'loft' ,
2024-12-04 17:24:16 -05:00
status : 'available' ,
2024-07-24 23:33:31 -04:00
title : 'Loft' ,
hotkey : 'L' ,
description :
'Create a 3D body by blending between two or more sketches.' ,
links : [
2024-09-05 16:48:03 -04:00
{
label : 'KCL docs' ,
url : 'https://zoo.dev/docs/kcl/loft' ,
} ,
2024-07-24 23:33:31 -04:00
] ,
} ,
'break' ,
{
id : 'fillet3d' ,
2025-01-23 10:25:21 -05:00
onClick : ( ) = >
commandBarActor . send ( {
2024-07-24 23:33:31 -04:00
type : 'Find and select command' ,
data : { name : 'Fillet' , groupId : 'modeling' } ,
} ) ,
icon : 'fillet3d' ,
2025-01-10 11:24:07 -05:00
status : DEV || IS_NIGHTLY_OR_DEBUG ? 'available' : 'kcl-only' ,
2024-07-24 23:33:31 -04:00
title : 'Fillet' ,
hotkey : 'F' ,
description : 'Round the edges of a 3D solid.' ,
links : [ { label : 'KCL docs' , url : 'https://zoo.dev/docs/kcl/fillet' } ] ,
} ,
{
2025-01-14 18:08:32 +01:00
id : 'chamfer3d' ,
2025-01-23 10:25:21 -05:00
onClick : ( ) = >
commandBarActor . send ( {
2025-01-14 18:08:32 +01:00
type : 'Find and select command' ,
data : { name : 'Chamfer' , groupId : 'modeling' } ,
} ) ,
2024-07-24 23:33:31 -04:00
icon : 'chamfer3d' ,
2025-01-14 18:08:32 +01:00
status : DEV || IS_NIGHTLY_OR_DEBUG ? 'available' : 'kcl-only' ,
2024-07-24 23:33:31 -04:00
title : 'Chamfer' ,
hotkey : 'C' ,
description : 'Bevel the edges of a 3D solid.' ,
links : [ { label : 'KCL docs' , url : 'https://zoo.dev/docs/kcl/chamfer' } ] ,
} ,
{
id : 'shell' ,
2025-01-23 10:25:21 -05:00
onClick : ( ) = > {
commandBarActor . send ( {
2024-12-09 15:20:48 -05:00
type : 'Find and select command' ,
data : { name : 'Shell' , groupId : 'modeling' } ,
} )
} ,
2024-07-24 23:33:31 -04:00
icon : 'shell' ,
2024-12-09 15:20:48 -05:00
status : 'available' ,
2024-07-24 23:33:31 -04:00
title : 'Shell' ,
description : 'Hollow out a 3D solid.' ,
links : [ { label : 'KCL docs' , url : 'https://zoo.dev/docs/kcl/shell' } ] ,
} ,
{
id : 'hole' ,
onClick : ( ) = > console . error ( 'Hole not yet implemented' ) ,
icon : 'hole' ,
status : 'unavailable' ,
title : 'Hole' ,
description : 'Create a hole in a 3D solid.' ,
links : [ ] ,
} ,
'break' ,
[
{
id : 'boolean-union' ,
onClick : ( ) = > console . error ( 'Boolean union not yet implemented' ) ,
icon : 'booleanUnion' ,
status : 'unavailable' ,
title : 'Union' ,
hotkey : 'Shift + B U' ,
description : 'Combine two or more solids into a single solid.' ,
links : [
{
label : 'GitHub discussion' ,
url : 'https://github.com/KittyCAD/modeling-app/discussions/509' ,
} ,
] ,
} ,
{
id : 'boolean-subtract' ,
onClick : ( ) = > console . error ( 'Boolean subtract not yet implemented' ) ,
icon : 'booleanSubtract' ,
status : 'unavailable' ,
title : 'Subtract' ,
hotkey : 'Shift + B S' ,
description : 'Subtract one solid from another.' ,
links : [
{
label : 'GitHub discussion' ,
url : 'https://github.com/KittyCAD/modeling-app/discussions/510' ,
} ,
] ,
} ,
{
id : 'boolean-intersect' ,
onClick : ( ) = > console . error ( 'Boolean intersect not yet implemented' ) ,
icon : 'booleanIntersect' ,
status : 'unavailable' ,
title : 'Intersect' ,
hotkey : 'Shift + B I' ,
description : 'Create a solid from the intersection of two solids.' ,
links : [
{
label : 'GitHub discussion' ,
url : 'https://github.com/KittyCAD/modeling-app/discussions/511' ,
} ,
] ,
} ,
] ,
2025-02-05 09:59:58 -05:00
'break' ,
2024-07-24 23:33:31 -04:00
[
{
id : 'plane-offset' ,
2025-01-23 10:25:21 -05:00
onClick : ( ) = > {
commandBarActor . send ( {
2024-11-26 11:36:14 -05:00
type : 'Find and select command' ,
data : { name : 'Offset plane' , groupId : 'modeling' } ,
} )
} ,
hotkey : 'O' ,
2024-07-24 23:33:31 -04:00
icon : 'plane' ,
2024-11-26 11:36:14 -05:00
status : 'available' ,
2024-07-24 23:33:31 -04:00
title : 'Offset plane' ,
description : 'Create a plane parallel to an existing plane.' ,
2025-01-21 18:32:56 -05:00
links : [
{
label : 'KCL docs' ,
url : 'https://zoo.dev/docs/kcl/offsetPlane' ,
} ,
] ,
2024-07-24 23:33:31 -04:00
} ,
{
id : 'plane-points' ,
onClick : ( ) = >
console . error ( 'Plane through points not yet implemented' ) ,
status : 'unavailable' ,
title : '3-point plane' ,
description : 'Create a plane from three points.' ,
links : [ ] ,
} ,
] ,
2025-02-05 09:59:58 -05:00
{
id : 'helix' ,
2025-02-07 10:16:36 -05:00
onClick : ( ) = > {
commandBarActor . send ( {
type : 'Find and select command' ,
data : { name : 'Helix' , groupId : 'modeling' } ,
} )
} ,
hotkey : 'H' ,
2025-02-05 09:59:58 -05:00
icon : 'helix' ,
2025-02-07 10:16:36 -05:00
status : DEV || IS_NIGHTLY_OR_DEBUG ? 'available' : 'kcl-only' ,
2025-02-05 09:59:58 -05:00
title : 'Helix' ,
description : 'Create a helix or spiral in 3D about an axis.' ,
links : [ { label : 'KCL docs' , url : 'https://zoo.dev/docs/kcl/helix' } ] ,
} ,
2025-01-07 11:45:30 -05:00
'break' ,
[
{
id : 'text-to-cad' ,
2025-01-23 10:25:21 -05:00
onClick : ( ) = >
commandBarActor . send ( {
2025-01-07 11:45:30 -05:00
type : 'Find and select command' ,
data : { name : 'Text-to-CAD' , groupId : 'modeling' } ,
} ) ,
icon : 'sparkles' ,
status : 'available' ,
title : 'Text-to-CAD' ,
description : 'Generate geometry from a text prompt.' ,
2025-01-21 18:32:56 -05:00
links : [
{
label : 'API docs' ,
url : 'https://zoo.dev/docs/api/ml/generate-a-cad-model-from-text' ,
} ,
] ,
2025-01-07 11:45:30 -05:00
} ,
{
id : 'prompt-to-edit' ,
2025-01-23 10:25:21 -05:00
onClick : ( ) = >
commandBarActor . send ( {
2025-01-07 11:45:30 -05:00
type : 'Find and select command' ,
data : { name : 'Prompt-to-edit' , groupId : 'modeling' } ,
} ) ,
icon : 'sparkles' ,
status : 'available' ,
title : 'Prompt-to-Edit' ,
description : 'Edit geometry based on a text prompt.' ,
links : [ ] ,
} ,
] ,
2024-07-24 23:33:31 -04:00
] ,
} ,
sketching : {
check : ( state ) = >
state . matches ( 'Sketch' ) || state . matches ( 'Sketch no face' ) ,
items : [
{
id : 'sketch-exit' ,
onClick : ( { modelingSend } ) = >
modelingSend ( {
type : 'Cancel' ,
} ) ,
disableHotkey : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) ||
2024-07-24 23:33:31 -04:00
state . matches ( 'Sketch no face' )
) ,
icon : 'arrowLeft' ,
status : 'available' ,
title : 'Exit sketch' ,
showTitle : true ,
hotkey : 'Esc' ,
description : 'Exit the current sketch' ,
links : [ ] ,
} ,
'break' ,
{
id : 'line' ,
2024-10-09 10:33:20 -04:00
onClick : ( { modelingState , modelingSend } ) = > {
2024-12-16 10:34:11 -05:00
if ( modelingState . matches ( { Sketch : { 'Line tool' : 'No Points' } } ) ) {
// Exit the sketch state if there are no points and they press ESC
modelingSend ( {
type : 'Cancel' ,
} )
} else {
// Exit the tool if there are points and they press ESC
modelingSend ( {
type : 'change tool' ,
data : {
tool : ! modelingState . matches ( { Sketch : 'Line tool' } )
? 'line'
: 'none' ,
} ,
} )
}
2024-10-09 10:33:20 -04:00
} ,
2024-07-24 23:33:31 -04:00
icon : 'line' ,
status : 'available' ,
disabled : ( state ) = >
state . matches ( 'Sketch no face' ) ||
2024-09-09 19:59:36 +03:00
state . matches ( {
Sketch : { 'Rectangle tool' : 'Awaiting second corner' } ,
2024-09-23 22:42:51 +10:00
} ) ||
state . matches ( {
Sketch : { 'Circle tool' : 'Awaiting Radius' } ,
2024-12-16 10:34:11 -05:00
} ) ||
isClosedSketch ( state . context ) ,
2024-07-24 23:33:31 -04:00
title : 'Line' ,
hotkey : ( state ) = >
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'Line tool' } ) ? [ 'Esc' , 'L' ] : 'L' ,
2024-07-24 23:33:31 -04:00
description : 'Start drawing straight lines' ,
links : [ ] ,
2024-09-09 19:59:36 +03:00
isActive : ( state ) = > state . matches ( { Sketch : 'Line tool' } ) ,
2024-07-24 23:33:31 -04:00
} ,
[
{
id : 'tangential-arc' ,
2024-09-09 19:59:36 +03:00
onClick : ( { modelingState , modelingSend } ) = >
2024-07-24 23:33:31 -04:00
modelingSend ( {
type : 'change tool' ,
data : {
2024-09-09 19:59:36 +03:00
tool : ! modelingState . matches ( { Sketch : 'Tangential arc to' } )
2024-07-24 23:33:31 -04:00
? 'tangentialArc'
: 'none' ,
} ,
} ) ,
icon : 'arc' ,
status : 'available' ,
disabled : ( state ) = >
2024-09-23 22:42:51 +10:00
( ! isEditingExistingSketch ( state . context ) &&
! state . matches ( { Sketch : 'Tangential arc to' } ) ) ||
pipeHasCircle ( state . context ) ,
2024-10-28 20:52:51 -04:00
disabledReason : ( state ) = >
! isEditingExistingSketch ( state . context ) &&
! state . matches ( { Sketch : 'Tangential arc to' } )
? "Cannot start a tangential arc because there's no previous line to be tangential to. Try drawing a line first or selecting an existing sketch to edit."
: undefined ,
2024-07-24 23:33:31 -04:00
title : 'Tangential Arc' ,
hotkey : ( state ) = >
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'Tangential arc to' } ) ? [ 'Esc' , 'A' ] : 'A' ,
2024-07-24 23:33:31 -04:00
description : 'Start drawing an arc tangent to the current segment' ,
links : [ ] ,
2024-09-09 19:59:36 +03:00
isActive : ( state ) = > state . matches ( { Sketch : 'Tangential arc to' } ) ,
2024-07-24 23:33:31 -04:00
} ,
{
id : 'three-point-arc' ,
onClick : ( ) = > console . error ( 'Three-point arc not yet implemented' ) ,
icon : 'arc' ,
status : 'unavailable' ,
title : 'Three-point Arc' ,
showTitle : false ,
description : 'Draw a circular arc defined by three points' ,
links : [
{
label : 'GitHub issue' ,
url : 'https://github.com/KittyCAD/modeling-app/issues/1659' ,
} ,
] ,
} ,
] ,
{
id : 'spline' ,
onClick : ( ) = > console . error ( 'Spline not yet implemented' ) ,
icon : 'spline' ,
status : 'unavailable' ,
title : 'Spline' ,
showTitle : false ,
description : 'Draw a spline curve through a series of points' ,
links : [ ] ,
} ,
'break' ,
[
{
id : 'circle-center' ,
2024-09-23 22:42:51 +10:00
onClick : ( { modelingState , modelingSend } ) = >
modelingSend ( {
type : 'change tool' ,
data : {
tool : ! modelingState . matches ( { Sketch : 'Circle tool' } )
? 'circle'
: 'none' ,
} ,
} ) ,
2024-07-24 23:33:31 -04:00
icon : 'circle' ,
2024-09-23 22:42:51 +10:00
status : 'available' ,
2024-07-24 23:33:31 -04:00
title : 'Center circle' ,
2024-12-16 10:34:11 -05:00
disabled : ( state ) = >
state . matches ( 'Sketch no face' ) ||
( ! canRectangleOrCircleTool ( state . context ) &&
2025-01-16 11:10:36 -05:00
! state . matches ( { Sketch : 'Circle tool' } ) &&
! state . matches ( { Sketch : 'circle3PointToolSelect' } ) ) ,
isActive : ( state ) = >
state . matches ( { Sketch : 'Circle tool' } ) ||
state . matches ( { Sketch : 'circle3PointToolSelect' } ) ,
2024-09-23 22:42:51 +10:00
hotkey : ( state ) = >
state . matches ( { Sketch : 'Circle tool' } ) ? [ 'Esc' , 'C' ] : 'C' ,
2024-07-24 23:33:31 -04:00
showTitle : false ,
description : 'Start drawing a circle from its center' ,
2025-01-16 11:10:36 -05:00
links : [ ] ,
2024-07-24 23:33:31 -04:00
} ,
{
id : 'circle-three-points' ,
2024-12-20 14:30:37 -05:00
onClick : ( { modelingState , modelingSend } ) = >
modelingSend ( {
type : 'change tool' ,
data : {
tool : ! modelingState . matches ( {
Sketch : 'circle3PointToolSelect' ,
} )
? 'circle3Points'
: 'none' ,
} ,
} ) ,
2024-07-24 23:33:31 -04:00
icon : 'circle' ,
2024-12-20 14:30:37 -05:00
status : 'available' ,
2025-01-16 11:10:36 -05:00
title : '3-point circle' ,
2024-07-24 23:33:31 -04:00
showTitle : false ,
description : 'Draw a circle defined by three points' ,
links : [ ] ,
} ,
] ,
[
{
id : 'corner-rectangle' ,
2024-09-09 19:59:36 +03:00
onClick : ( { modelingState , modelingSend } ) = >
2024-07-24 23:33:31 -04:00
modelingSend ( {
type : 'change tool' ,
data : {
2024-09-09 19:59:36 +03:00
tool : ! modelingState . matches ( { Sketch : 'Rectangle tool' } )
2024-07-24 23:33:31 -04:00
? 'rectangle'
: 'none' ,
} ,
} ) ,
icon : 'rectangle' ,
status : 'available' ,
2024-12-16 10:34:11 -05:00
disabled : ( state ) = >
state . matches ( 'Sketch no face' ) ||
( ! canRectangleOrCircleTool ( state . context ) &&
! state . matches ( { Sketch : 'Rectangle tool' } ) ) ,
2024-07-24 23:33:31 -04:00
title : 'Corner rectangle' ,
hotkey : ( state ) = >
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'Rectangle tool' } ) ? [ 'Esc' , 'R' ] : 'R' ,
2024-07-24 23:33:31 -04:00
description : 'Start drawing a rectangle' ,
links : [ ] ,
2024-09-09 19:59:36 +03:00
isActive : ( state ) = > state . matches ( { Sketch : 'Rectangle tool' } ) ,
2024-07-24 23:33:31 -04:00
} ,
{
id : 'center-rectangle' ,
2024-11-18 10:04:09 -05:00
onClick : ( { modelingState , modelingSend } ) = >
modelingSend ( {
type : 'change tool' ,
data : {
tool : ! modelingState . matches ( {
Sketch : 'Center Rectangle tool' ,
} )
? 'center rectangle'
: 'none' ,
} ,
} ) ,
icon : 'arc' ,
status : 'available' ,
2024-12-16 10:34:11 -05:00
disabled : ( state ) = >
state . matches ( 'Sketch no face' ) ||
( ! canRectangleOrCircleTool ( state . context ) &&
! state . matches ( { Sketch : 'Center Rectangle tool' } ) ) ,
2024-07-24 23:33:31 -04:00
title : 'Center rectangle' ,
2024-11-18 10:04:09 -05:00
hotkey : ( state ) = >
state . matches ( { Sketch : 'Center Rectangle tool' } )
? [ 'Esc' , 'C' ]
: 'C' ,
2024-07-24 23:33:31 -04:00
description : 'Start drawing a rectangle from its center' ,
links : [ ] ,
2024-11-18 10:04:09 -05:00
isActive : ( state ) = > {
return state . matches ( { Sketch : 'Center Rectangle tool' } )
} ,
2024-07-24 23:33:31 -04:00
} ,
] ,
{
id : 'polygon' ,
onClick : ( ) = > console . error ( 'Polygon not yet implemented' ) ,
icon : 'polygon' ,
status : 'unavailable' ,
title : 'Polygon' ,
showTitle : false ,
description : 'Draw a polygon with a specified number of sides' ,
links : [ ] ,
} ,
{
id : 'text' ,
onClick : ( ) = > console . error ( 'Text not yet implemented' ) ,
icon : 'text' ,
status : 'unavailable' ,
title : 'Text' ,
showTitle : false ,
description : 'Add text to your sketch as geometry.' ,
links : [ ] ,
} ,
'break' ,
{
id : 'mirror' ,
onClick : ( ) = > console . error ( 'Mirror not yet implemented' ) ,
icon : 'mirror' ,
status : 'unavailable' ,
title : 'Mirror' ,
showTitle : false ,
description : 'Mirror sketch entities about a line or axis' ,
links : [ ] ,
} ,
[
{
id : 'constraint-length' ,
2024-12-09 16:43:58 -05:00
disabled : ( state ) = > ! state . matches ( { Sketch : 'SketchIdle' } ) ,
2025-01-23 10:25:21 -05:00
onClick : ( ) = >
commandBarActor . send ( {
2024-12-09 16:43:58 -05:00
type : 'Find and select command' ,
data : {
name : 'Constrain length' ,
groupId : 'modeling' ,
} ,
} ) ,
2024-07-24 23:33:31 -04:00
icon : 'dimension' ,
status : 'available' ,
title : 'Length' ,
showTitle : false ,
description : 'Constrain the length of a straight segment' ,
links : [ ] ,
} ,
{
id : 'constraint-angle' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain angle' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain angle' } ) ,
status : 'available' ,
title : 'Angle' ,
showTitle : false ,
description : 'Constrain the angle between two segments' ,
links : [ ] ,
} ,
{
id : 'constraint-vertical' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Make segment vertical' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Make segment vertical' } ) ,
status : 'available' ,
title : 'Vertical' ,
showTitle : false ,
description :
'Constrain a straight segment to be vertical relative to the sketch' ,
links : [ ] ,
} ,
{
id : 'constraint-horizontal' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Make segment horizontal' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Make segment horizontal' } ) ,
status : 'available' ,
title : 'Horizontal' ,
showTitle : false ,
description :
'Constrain a straight segment to be horizontal relative to the sketch' ,
links : [ ] ,
} ,
{
id : 'constraint-parallel' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain parallel' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain parallel' } ) ,
status : 'available' ,
title : 'Parallel' ,
showTitle : false ,
description : 'Constrain two segments to be parallel' ,
links : [ ] ,
} ,
{
id : 'constraint-equal-length' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain equal length' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain equal length' } ) ,
status : 'available' ,
title : 'Equal length' ,
showTitle : false ,
description : 'Constrain two segments to be equal length' ,
links : [ ] ,
} ,
{
id : 'constraint-horizontal-distance' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain horizontal distance' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain horizontal distance' } ) ,
status : 'available' ,
title : 'Horizontal distance' ,
showTitle : false ,
description : 'Constrain the horizontal distance between two points' ,
links : [ ] ,
} ,
{
id : 'constraint-vertical-distance' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain vertical distance' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain vertical distance' } ) ,
status : 'available' ,
title : 'Vertical distance' ,
showTitle : false ,
description : 'Constrain the vertical distance between two points' ,
links : [ ] ,
} ,
{
id : 'constraint-absolute-x' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain ABS X' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain ABS X' } ) ,
status : 'available' ,
title : 'Absolute X' ,
showTitle : false ,
description : 'Constrain the x-coordinate of a point' ,
links : [ ] ,
} ,
{
id : 'constraint-absolute-y' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain ABS Y' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain ABS Y' } ) ,
status : 'available' ,
title : 'Absolute Y' ,
showTitle : false ,
description : 'Constrain the y-coordinate of a point' ,
links : [ ] ,
} ,
{
id : 'constraint-perpendicular-distance' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain perpendicular distance' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain perpendicular distance' } ) ,
status : 'available' ,
title : 'Perpendicular distance' ,
showTitle : false ,
description :
'Constrain the perpendicular distance between two segments' ,
links : [ ] ,
} ,
{
id : 'constraint-align-horizontal' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain horizontally align' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain horizontally align' } ) ,
status : 'available' ,
title : 'Horizontally align' ,
showTitle : false ,
description : 'Align the ends of two or more segments horizontally' ,
links : [ ] ,
} ,
{
id : 'constraint-align-vertical' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain vertically align' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain vertically align' } ) ,
status : 'available' ,
title : 'Vertically align' ,
showTitle : false ,
description : 'Align the ends of two or more segments vertically' ,
links : [ ] ,
} ,
{
id : 'snap-to-x' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain snap to X' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain snap to X' } ) ,
status : 'available' ,
title : 'Snap to X' ,
showTitle : false ,
description : 'Snap a point to an x-coordinate' ,
links : [ ] ,
} ,
{
id : 'snap-to-y' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain snap to Y' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain snap to Y' } ) ,
status : 'available' ,
title : 'Snap to Y' ,
showTitle : false ,
description : 'Snap a point to a y-coordinate' ,
links : [ ] ,
} ,
{
id : 'constraint-remove' ,
disabled : ( state ) = >
! (
2024-09-09 19:59:36 +03:00
state . matches ( { Sketch : 'SketchIdle' } ) &&
state . can ( { type : 'Constrain remove constraints' } )
2024-07-24 23:33:31 -04:00
) ,
onClick : ( { modelingSend } ) = >
modelingSend ( { type : 'Constrain remove constraints' } ) ,
status : 'available' ,
title : 'Remove constraints' ,
showTitle : false ,
description : 'Remove all constraints from the segment' ,
links : [ ] ,
} ,
] ,
] ,
} ,
}