feat: close ordered pairs and property codec batches
This commit is contained in:
110
scripts/generate-freecad-property-direction-inventory.mjs
Normal file
110
scripts/generate-freecad-property-direction-inventory.mjs
Normal file
@@ -0,0 +1,110 @@
|
||||
import { createHash } from 'node:crypto'
|
||||
import { readFile, writeFile } from 'node:fs/promises'
|
||||
import { resolve } from 'node:path'
|
||||
|
||||
const root = resolve(new URL('..', import.meta.url).pathname)
|
||||
const runtimePath = resolve(root, '.cache/freecad/reference-desktop.json')
|
||||
const sourcePaths = [
|
||||
'.cache/freecad/FreeCAD/src/App/PropertyGeo.h',
|
||||
'.cache/freecad/FreeCAD/src/App/PropertyGeo.cpp',
|
||||
'.cache/freecad/FreeCAD/src/Gui/propertyeditor/PropertyItem.h',
|
||||
'.cache/freecad/FreeCAD/src/Gui/propertyeditor/PropertyItem.cpp',
|
||||
'.cache/freecad/FreeCAD/src/Mod/Part/App/FeatureMirroring.h',
|
||||
'.cache/freecad/FreeCAD/src/Mod/Part/App/FeatureMirroring.cpp',
|
||||
'.cache/freecad/FreeCAD/src/Mod/Part/App/FeatureProjectOnSurface.h',
|
||||
'.cache/freecad/FreeCAD/src/Mod/Part/App/FeatureProjectOnSurface.cpp',
|
||||
]
|
||||
const outputPath = resolve(root, 'config/freecad-property-direction-inventory.json')
|
||||
const runtimeContent = await readFile(runtimePath)
|
||||
const runtime = JSON.parse(runtimeContent)
|
||||
const sourceContents = await Promise.all(sourcePaths.map((path) => readFile(resolve(root, path))))
|
||||
const fail = (message) => { throw new Error(`FreeCAD PropertyDirection inventory generation failed: ${message}`) }
|
||||
const vector = (value) => {
|
||||
const match = /^Vector \(([-+0-9.eE]+), ([-+0-9.eE]+), ([-+0-9.eE]+)\)$/.exec(value)
|
||||
if (!match) fail(`unexpected native vector value: ${value}`)
|
||||
return match.slice(1).map(Number)
|
||||
}
|
||||
|
||||
if (runtime.schemaVersion !== 1 || runtime.freecadVersion !== '1.1.1' || runtime.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d') fail('desktop oracle is not the locked FreeCAD baseline')
|
||||
const hostContracts = {
|
||||
'Part::Mirroring.Normal': {
|
||||
dependencies: [
|
||||
{ propertyName: 'Source', role: 'shape-source', requiredForExecution: true },
|
||||
{ propertyName: 'Base', role: 'plane-origin', requiredForExecution: true },
|
||||
{ propertyName: 'MirrorPlane', role: 'optional-plane-override', requiredForExecution: false, overrides: ['Base', 'Normal'], overriddenStatus: 'ReadOnly' },
|
||||
],
|
||||
consumer: 'gp_Ax2(gp_Pnt(Base), gp_Dir(Normal))',
|
||||
},
|
||||
'Part::ProjectOnSurface.Direction': {
|
||||
dependencies: [
|
||||
{ propertyName: 'SupportFace', role: 'single-support-face', requiredForExecution: true },
|
||||
{ propertyName: 'Projection', role: 'projected-shape-list', requiredForExecution: true },
|
||||
],
|
||||
consumer: 'gp_Dir(Direction)',
|
||||
},
|
||||
}
|
||||
const records = []
|
||||
for (const objectType of runtime.runtimeObjects?.types ?? []) {
|
||||
for (const property of objectType.properties ?? []) {
|
||||
if (property.typeId !== 'App::PropertyDirection') continue
|
||||
const contract = hostContracts[`${objectType.typeId}.${property.name}`]
|
||||
if (!contract) fail(`missing host contract for ${objectType.typeId}.${property.name}`)
|
||||
records.push({
|
||||
objectTypeId: objectType.typeId,
|
||||
objectAvailable: objectType.available === true,
|
||||
probeStatus: objectType.probeStatus,
|
||||
propertyName: property.name,
|
||||
group: property.group,
|
||||
status: property.status,
|
||||
defaultDisplayValue: property.default,
|
||||
defaultValue: vector(property.default),
|
||||
valueModel: {
|
||||
kind: 'three-component-direction-vector',
|
||||
representation: 'Base::Vector3d',
|
||||
normalizationAtPropertyBoundary: 'none',
|
||||
unit: 'Length',
|
||||
writable: property.status.length === 0,
|
||||
},
|
||||
inputs: {
|
||||
accepted: ['Base.Vector', 'tuple-of-three-float-or-integer-components'],
|
||||
listAccepted: false,
|
||||
componentPaths: ['x', 'y', 'z'],
|
||||
},
|
||||
editor: 'Gui::PropertyEditor::PropertyDirectionItem',
|
||||
dependencies: contract.dependencies,
|
||||
applicability: {
|
||||
requiredObjectTypeId: objectType.typeId,
|
||||
source: 'Document.supportedTypes runtime inventory',
|
||||
propertyWriteRequiresShape: false,
|
||||
hostExecutionRequiresShapeInputs: true,
|
||||
nonZeroRequiredByConsumer: true,
|
||||
consumer: contract.consumer,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
records.sort((left, right) => `${left.objectTypeId}.${left.propertyName}`.localeCompare(`${right.objectTypeId}.${right.propertyName}`))
|
||||
if (records.length !== 2) fail(`expected two native App::PropertyDirection records, found ${records.length}`)
|
||||
const report = {
|
||||
schemaVersion: 1,
|
||||
status: 'pass',
|
||||
baseline: { freecadVersion: runtime.freecadVersion, commit: runtime.gitCommit },
|
||||
propertyType: 'App::PropertyDirection',
|
||||
recordCount: records.length,
|
||||
records,
|
||||
storage: {
|
||||
inheritedFrom: 'App::PropertyVector',
|
||||
xmlElement: 'PropertyVector',
|
||||
attributes: ['valueX', 'valueY', 'valueZ'],
|
||||
scalarEncoding: 'decimal-double',
|
||||
externalResource: false,
|
||||
},
|
||||
provenance: {
|
||||
runtime: { path: '.cache/freecad/reference-desktop.json', bytes: runtimeContent.length, sha256: createHash('sha256').update(runtimeContent).digest('hex') },
|
||||
sources: sourcePaths.map((path, index) => ({ path, bytes: sourceContents[index].length, sha256: createHash('sha256').update(sourceContents[index]).digest('hex') })),
|
||||
},
|
||||
classification: 'opaque-fcstd-proxy',
|
||||
nextPhases: ['B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'],
|
||||
}
|
||||
await writeFile(outputPath, `${JSON.stringify(report, null, 2)}\n`)
|
||||
console.log(JSON.stringify({ status: 'freecad-property-direction-inventory-generated', output: 'config/freecad-property-direction-inventory.json', propertyType: report.propertyType, recordCount: report.recordCount }, null, 2))
|
||||
Reference in New Issue
Block a user