Files
modeling-app/src/lib/commandBarConfigs/modelingCommandConfig.ts
2024-10-18 10:25:54 -04:00

326 lines
9.1 KiB
TypeScript

import { Models } from '@kittycad/lib'
import { StateMachineCommandSetConfig, KclCommandValue } from 'lib/commandTypes'
import { KCL_DEFAULT_LENGTH, KCL_DEFAULT_DEGREE } from 'lib/constants'
import { components } from 'lib/machine-api'
import { Selections } from 'lib/selections'
import { machineManager } from 'lib/machineManager'
import { modelingMachine, SketchTool } from 'machines/modelingMachine'
type OutputFormat = Models['OutputFormat_type']
type OutputTypeKey = OutputFormat['type']
type ExtractStorageTypes<T> = T extends { storage: infer U } ? U : never
type StorageUnion = ExtractStorageTypes<OutputFormat>
export const EXTRUSION_RESULTS = [
'new',
'add',
'subtract',
'intersect',
] as const
export type ModelingCommandSchema = {
'Enter sketch': {}
Export: {
type: OutputTypeKey
storage?: StorageUnion
}
Make: {
machine: components['schemas']['MachineInfoResponse']
}
Extrude: {
selection: Selections // & { type: 'face' } would be cool to lock that down
// result: (typeof EXTRUSION_RESULTS)[number]
distance: KclCommandValue
}
Revolve: {
selection: Selections
angle: KclCommandValue
}
Fillet: {
// todo
selection: Selections
radius: KclCommandValue
}
'change tool': {
tool: SketchTool
}
'Text-to-CAD': {
prompt: string
}
}
export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
typeof modelingMachine,
ModelingCommandSchema
> = {
'Enter sketch': {
description: 'Enter sketch mode.',
icon: 'sketch',
},
'change tool': [
{
description: 'Start drawing straight lines.',
icon: 'line',
displayName: 'Line',
args: {
tool: {
defaultValue: 'line',
required: true,
skip: true,
inputType: 'string',
},
},
},
{
description: 'Start drawing an arc tangent to the current segment.',
icon: 'arc',
displayName: 'Tangential Arc',
args: {
tool: {
defaultValue: 'tangentialArc',
required: true,
skip: true,
inputType: 'string',
},
},
},
{
description: 'Start drawing a rectangle.',
icon: 'rectangle',
displayName: 'Rectangle',
args: {
tool: {
defaultValue: 'rectangle',
required: true,
skip: true,
inputType: 'string',
},
},
},
],
Export: {
description: 'Export the current model.',
icon: 'floppyDiskArrow',
needsReview: true,
args: {
type: {
inputType: 'options',
defaultValue: 'gltf',
required: true,
options: [
{ name: 'glTF', isCurrent: true, value: 'gltf' },
{ name: 'OBJ', isCurrent: false, value: 'obj' },
{ name: 'STL', isCurrent: false, value: 'stl' },
{ name: 'STEP', isCurrent: false, value: 'step' },
{ name: 'PLY', isCurrent: false, value: 'ply' },
],
},
storage: {
inputType: 'options',
defaultValue: (c) => {
switch (c.argumentsToSubmit.type) {
case 'gltf':
return 'embedded'
case 'stl':
return 'ascii'
case 'ply':
return 'ascii'
default:
return undefined
}
},
skip: true,
required: (commandContext) =>
['gltf', 'stl', 'ply'].includes(
commandContext.argumentsToSubmit.type as string
),
options: (commandContext) => {
const type = commandContext.argumentsToSubmit.type as
| OutputTypeKey
| undefined
switch (type) {
case 'gltf':
return [
{ name: 'embedded', isCurrent: true, value: 'embedded' },
{ name: 'binary', isCurrent: false, value: 'binary' },
{ name: 'standard', isCurrent: false, value: 'standard' },
]
case 'stl':
return [
{ name: 'binary', isCurrent: false, value: 'binary' },
{ name: 'ascii', isCurrent: true, value: 'ascii' },
]
case 'ply':
return [
{ name: 'ascii', isCurrent: true, value: 'ascii' },
{
name: 'binary_big_endian',
isCurrent: false,
value: 'binary_big_endian',
},
{
name: 'binary_little_endian',
isCurrent: false,
value: 'binary_little_endian',
},
]
default:
return []
}
},
},
},
},
Make: {
hide: 'web',
displayName: 'Make',
description:
'Export the current part and send to a 3D printer on the network.',
icon: 'printer3d',
needsReview: true,
args: {
machine: {
inputType: 'options',
required: true,
valueSummary: (machine: components['schemas']['MachineInfoResponse']) =>
machine.make_model.model ||
machine.make_model.manufacturer ||
'Unknown Machine',
options: () => {
return Object.entries(machineManager.machines).map(
([_, machine]) => ({
name:
`${machine.id} (${
machine.make_model.model || machine.make_model.manufacturer
}) (${machine.state.state})` +
(machine.hardware_configuration &&
machine.hardware_configuration.type !== 'none' &&
machine.hardware_configuration.config.nozzle_diameter
? ` - Nozzle Diameter: ${machine.hardware_configuration.config.nozzle_diameter}`
: '') +
(machine.hardware_configuration &&
machine.hardware_configuration.type !== 'none' &&
machine.hardware_configuration.config.filaments &&
machine.hardware_configuration.config.filaments[0]
? ` - ${
machine.hardware_configuration.config.filaments[0].name
} #${
machine.hardware_configuration.config &&
machine.hardware_configuration.config.filaments[0].color?.slice(
0,
6
)
}`
: ''),
isCurrent: false,
disabled: machine.state.state !== 'idle',
value: machine as components['schemas']['MachineInfoResponse'],
})
)
},
defaultValue: () => {
return Object.values(
machineManager.machines
)[0] as components['schemas']['MachineInfoResponse']
},
},
},
},
Extrude: {
description: 'Pull a sketch into 3D along its normal or perpendicular.',
icon: 'extrude',
needsReview: true,
args: {
selection: {
inputType: 'selection',
// TODO: These are products of an extrude
selectionTypes: ['extrude-wall', 'start-cap', 'end-cap'],
multiple: false, // TODO: multiple selection
required: true,
skip: true,
},
// result: {
// inputType: 'options',
// defaultValue: 'add',
// skip: true,
// required: true,
// options: EXTRUSION_RESULTS.map((r) => ({
// name: r,
// isCurrent: r === 'add',
// value: r,
// })),
// },
distance: {
inputType: 'kcl',
defaultValue: KCL_DEFAULT_LENGTH,
required: true,
},
},
},
// TODO: Update this configuration, copied from extrude for MVP of revolve, specifically the args.selection
Revolve: {
description: 'Create a 3D body by rotating a sketch region about an axis.',
icon: 'revolve',
needsReview: true,
args: {
selection: {
inputType: 'selection',
selectionTypes: ['extrude-wall', 'start-cap', 'end-cap'],
multiple: false, // TODO: multiple selection
required: true,
skip: true,
},
angle: {
inputType: 'kcl',
defaultValue: KCL_DEFAULT_DEGREE,
required: true,
},
},
},
Fillet: {
description: 'Fillet edge',
icon: 'fillet',
needsReview: true,
args: {
selection: {
inputType: 'selection',
selectionTypes: [
'default',
'line-end',
'line-mid',
'extrude-wall',
'solid2D',
'start-cap',
'end-cap',
'point',
'edge',
'line',
'arc',
'all',
],
multiple: true,
required: true,
skip: false,
warningMessage:
'Fillets cannot touch other fillets yet. This is under development.',
},
radius: {
inputType: 'kcl',
defaultValue: KCL_DEFAULT_LENGTH,
required: true,
},
},
},
'Text-to-CAD': {
description: 'Use the Zoo Text-to-CAD API to generate part starters.',
icon: 'chat',
args: {
prompt: {
inputType: 'text',
required: true,
},
},
},
}