From 42e59ac068f0fb3be6141a4f2e17969af303e798 Mon Sep 17 00:00:00 2001 From: wangdequan Date: Sun, 2 Aug 2026 19:25:37 -0400 Subject: [PATCH] feat: add Part primitive task selection --- src/App.tsx | 4 +++- src/facade/mockFacade.ts | 9 +++++---- tests/facade.test.ts | 7 ++++--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 7e0b2ff..6ffab90 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -345,7 +345,9 @@ function TreeItem({ item, level, expanded, onToggle, itemsById, selectedObject, function TaskPanel({ workbench, facade, showNotice }: { workbench: Workbench; facade: BitBybitWebCadFacade; showNotice: (message: string) => void }) { const definition = workbenchDefinitions[workbench] const isSketch = workbench === 'Sketcher' - return
Active command

{isSketch ? 'Edit Sketch' : definition.taskTitle}

Preview
1
{isSketch ? 'Geometry and constraints' : definition.objectType}{definition.taskSummary}
Changes remain local until the document is recomputed.
+ const activeTask = facade.task.getActive() + const primitiveType = activeTask?.commandId === 'primitive' && typeof activeTask.draft.primitiveType === 'string' ? activeTask.draft.primitiveType : 'Box' + return
Active command

{isSketch ? 'Edit Sketch' : definition.taskTitle}

Preview
1
{isSketch ? 'Geometry and constraints' : definition.objectType}{definition.taskSummary}
{activeTask?.commandId === 'primitive' && }
Changes remain local until the document is recomputed.
} function PropertyPanel({ facade, objectId, scope, showNotice }: { facade: BitBybitWebCadFacade; objectId: string; scope: 'data' | 'view'; showNotice: (message: string) => void }) { diff --git a/src/facade/mockFacade.ts b/src/facade/mockFacade.ts index 0b0f743..0bf2440 100644 --- a/src/facade/mockFacade.ts +++ b/src/facade/mockFacade.ts @@ -287,8 +287,9 @@ export function createMockFacade(): BitBybitWebCadFacade { const existing = state.document.tree.filter((item) => item.label.toLowerCase().startsWith(base)).length return existing === 0 ? base : `${base}${String(existing).padStart(3, '0')}` } - const appendFeature = (document: DocumentSnapshot, commandId: string): { document: DocumentSnapshot; objectId: string } => { - const definition = featureCommands[commandId] + const appendFeature = (document: DocumentSnapshot, commandId: string, draft: Record = {}): { document: DocumentSnapshot; objectId: string } => { + const primitiveType = commandId === 'primitive' && ['Box', 'Cylinder', 'Sphere', 'Cone'].includes(String(draft.primitiveType)) ? String(draft.primitiveType) : 'Box' + const definition = commandId === 'primitive' ? { label: primitiveType, detail: primitiveType === 'Box' ? '10 × 10 × 10 mm' : `${primitiveType} primitive` } : featureCommands[commandId] if (!definition) return { document, objectId: '' } const objectId = nextFeatureId(definition.label) const type = commandId === 'create-sketch' ? 'sketch' : commandId === 'create-body' ? 'body' : 'feature' @@ -472,14 +473,14 @@ export function createMockFacade(): BitBybitWebCadFacade { const applyTask = () => { const task = state.task if (!task || task.status !== 'preview') return - const result = appendFeature(state.document, task.commandId) + const result = appendFeature(state.document, task.commandId, task.draft) if (!result.objectId) { state = { ...state, task: { ...task, status: 'completed' } } emitState() return } commit({ ...state, document: result.document, selectedObjectId: result.objectId, task: { ...task, status: 'completed' } }) - notify(`${featureCommands[task.commandId].label} created`) + notify(`${result.document.tree.find((item) => item.id === result.objectId)?.label || featureCommands[task.commandId]?.label || task.commandId} created`) } const execute = ({ commandId, payload }: ExecuteCommandInput) => { const requestId = `req-${++requestSequence}` diff --git a/tests/facade.test.ts b/tests/facade.test.ts index a923bd4..5685203 100644 --- a/tests/facade.test.ts +++ b/tests/facade.test.ts @@ -791,14 +791,15 @@ test('Part workbench commands create primitive and boolean document objects', () facade.task.apply() assert.equal(facade.app.document.getObject('box')?.typeId, 'Part::Box') facade.gui.command.execute({ commandId: 'primitive' }) + facade.task.update({ primitiveType: 'Cylinder' }) facade.task.apply() - assert.equal(facade.app.document.getObject('box001')?.typeId, 'Part::Box') + assert.equal(facade.app.document.getObject('cylinder')?.typeId, 'Part::Cylinder') assert.equal(facade.gui.command.getState('union').status, 'enabled') facade.gui.command.execute({ commandId: 'union' }) facade.task.apply() assert.equal(facade.app.document.getObject('union')?.typeId, 'Part::Fuse') facade.app.document.setProperty({ objectId: 'union', propertyName: 'Base', value: 'box' }) - facade.app.document.setProperty({ objectId: 'union', propertyName: 'Tool', value: 'box001' }) - assert.deepEqual(facade.app.document.getDependencies().filter((edge) => edge.sourceId === 'union').map((edge) => edge.targetId).sort(), ['box', 'box001']) + facade.app.document.setProperty({ objectId: 'union', propertyName: 'Tool', value: 'cylinder' }) + assert.deepEqual(facade.app.document.getDependencies().filter((edge) => edge.sourceId === 'union').map((edge) => edge.targetId).sort(), ['box', 'cylinder']) })