feat: maintain Part Design body tip

This commit is contained in:
2026-08-02 21:40:44 -04:00
parent 2a0b14b26d
commit 10921a086e
4 changed files with 16 additions and 3 deletions

View File

@@ -112,7 +112,7 @@ const featureProperties = (item: ModelTreeItem): ObjectPropertySnapshot[] => {
{ name: 'ConstraintStatus', label: 'Solver state', group: 'Constraints', scope: 'data', type: 'App::PropertyString', value: 'Fully constrained', readOnly: true },
]
if (item.type === 'body') return [
{ name: 'Tip', label: 'Tip', group: 'Part Design', scope: 'data', type: 'App::PropertyLink', value: 'fillet', recompute: true },
{ name: 'Tip', label: 'Tip', group: 'Part Design', scope: 'data', type: 'App::PropertyLink', value: 'fillet', readOnly: true, recompute: true },
]
return []
}
@@ -325,10 +325,14 @@ export function createMockFacade(): BitBybitWebCadFacade {
tree.push(item)
}
const objectSnapshot = createObjectSnapshot(item)
const sourceId = typeof draft.source === 'string' && document.objects.some((object) => object.id === draft.source) ? draft.source : ''
const sourceObject = sourceId ? document.objects.find((object) => object.id === sourceId) : undefined
objectSnapshot.properties = objectSnapshot.properties.map((property) => {
if (!property.recompute) return property
const candidate = draft[property.name.toLowerCase()]
if (property.type === 'App::PropertyLink' && typeof candidate === 'string' && candidate.length > 0) return { ...property, value: candidate }
if (property.type === 'App::PropertyLink' && sourceObject && property.name === 'Profile' && sourceObject.typeId === 'Sketcher::SketchObject') return { ...property, value: sourceObject.id }
if (property.type === 'App::PropertyLink' && sourceObject && property.name === 'Base' && shapeTypeIds.has(sourceObject.typeId)) return { ...property, value: sourceObject.id }
if (property.type === 'App::PropertyBool' && typeof candidate === 'boolean') return { ...property, value: candidate }
if ((property.type === 'App::PropertyLength' || property.type === 'App::PropertyAngle' || property.type === 'App::PropertyPercent' || property.type === 'App::PropertyFloat') && typeof candidate === 'number' && Number.isFinite(candidate)) return { ...property, value: candidate }
if (property.type === 'App::PropertyEnumeration' && typeof candidate === 'string' && property.options?.includes(candidate)) return { ...property, value: candidate }
@@ -338,10 +342,15 @@ export function createMockFacade(): BitBybitWebCadFacade {
objectSnapshot.properties = objectSnapshot.properties.map((property) => property.name === 'Base' && typeof draft.base !== 'string' && state.selectedObjectId ? { ...property, value: state.selectedObjectId } : property)
}
const objects = [...document.objects.map((object) => ({ ...object, properties: object.properties.map((property) => ({ ...property })), sketch: object.sketch ? cloneSketch(object.sketch) : undefined })), objectSnapshot]
const tipObject = type === 'feature' && partDesignCommands.has(commandId) && commandId !== 'create-sketch' ? objects.find((object) => object.id === 'body') : undefined
if (tipObject) {
const tip = tipObject.properties.find((property) => property.name === 'Tip')
if (tip) tip.value = objectId
}
const nextDocument: DocumentSnapshot = { ...document, version: document.version + 1, dirty: true, tree, objects }
nextDocument.dependencies = collectDependencyEdges(nextDocument)
nextDocument.recompute = createRecomputeSnapshot(objects.map((object) => object.id), document.recompute?.generation ?? 0)
markDocumentTouched(nextDocument, [objectId])
markDocumentTouched(nextDocument, tipObject ? [objectId, tipObject.id] : [objectId])
return { document: nextDocument, objectId }
}
const setProperty = ({ objectId, propertyName, value }: SetPropertyInput) => {