326 lines
9.1 KiB
TypeScript
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,
|
|
},
|
|
},
|
|
},
|
|
}
|