updateSolveStatus() calls solve() when lastResult_.placements is empty,
but solve() calls updateSolveStatus() at the end. When an assembly has
zero constraints (all joints removed), the solver returns zero
placements, causing infinite recursion until stack overflow (segfault).
Add a static re-entrancy guard so the recursive solve() call is skipped
if updateSolveStatus() is already on the call stack.
When double-clicking a PartDesign Body inside an Assembly, the editing
context resolver failed to show PartDesign toolbars or a proper
breadcrumb. Three root causes:
1. Priority preemption: assembly.edit (priority 90) always matched
because the Assembly VP remained in edit mode, blocking all
PartDesign contexts (priorities 30-40).
2. Wrong active-object key: PartDesign matchers only queried the
"part" active object, but ViewProviderBody::toggleActiveBody()
sets "part" to the containing App::Part (which is the Assembly
itself). The Body is set under "pdbody", which was never queried.
3. Missing refresh trigger: ActiveObjectList::setObject() fires
Document::signalActivatedViewProvider, but EditingContextResolver
had no connection to it, so setActiveObject("pdbody", body) never
triggered a context re-resolve.
Changes:
- Forward signalActivatedViewProvider from Gui::Document to
Gui::Application (same pattern as signalInEdit/signalResetEdit)
- Connect EditingContextResolver to the new application-level signal
- Add getActivePdBodyObject() helper querying the "pdbody" key
- Add partdesign.in_assembly context (priority 95) that matches when
a Body is active pdbody while an Assembly is in edit
- Update partdesign.body and partdesign.feature matchers to check
pdbody before falling back to the part key
- Add Assembly > Body breadcrumb with Blue > Mauve coloring
- Update label resolution to prefer pdbody name
The kindred-solver addon imports networkx in its decompose module.
Without it, KindredSolver fails to import and solver registration
silently fails, leaving only the ondsel backend available.
Add a template system integrated with Silo new-item creation that lets
users create parts from pre-configured .kc templates and save existing
documents as reusable templates.
Changes:
- mods/silo: template discovery, picker UI, Save as Template command,
3-tier search paths (system, personal, org-shared)
- docs: template guide, SUMMARY.md entry, silo.md command reference
unique_ptr::reset() requires the complete type for its deleter, but
IKCSolver is only forward-declared in AssemblyObject.h. Move the
definition to AssemblyObject.cpp where the full header is included.
Expose AssemblyObject::getSolveContext() to Python and hook into the
.kc save flow so that silo/solver/context.json is packed into every
assembly archive. This lets server-side solver runners operate on
pre-extracted constraint graphs without a full FreeCAD installation.
Changes:
- Add public getSolveContext() to AssemblyObject (C++ and Python)
- Build Python dict via CPython C API matching kcsolve.SolveContext.to_dict()
- Register _solver_context_hook in kc_format.py pre-reinject hooks
- Add silo/solver/context.json to silo_tree.py _KNOWN_ENTRIES
The EditingContextResolver controls toolbar visibility via explicit
whitelists per editing context. Several contexts had incomplete lists,
causing workbench toolbars to be missing compared to base FreeCAD.
Changes:
partdesign.feature (priority 40):
- Add 'Sketcher' toolbar so users can create new sketches from an
active Body with features
partdesign.body (priority 30):
- Add Modeling, Dress-Up, and Transformation toolbars (previously
only showed Helper + Sketcher)
partdesign.workbench (priority 20):
- Add Modeling, Dress-Up, and Transformation toolbars (same as body)
sketcher.workbench (priority 20):
- Add Geometries, Constraints, B-Spline Tools, Visual Helpers
(previously only showed Sketcher + Sketcher Tools)
assembly.idle (priority 30):
- Add 'Assembly Joints' and 'Assembly Management' toolbars
assembly.workbench (priority 20):
- Add 'Assembly Joints' and 'Assembly Management' toolbars
No changes to sketcher.edit or assembly.edit contexts — those were
already correct.
Phase 3a of the solver server integration: add dict/JSON serialization
to all KCSolve pybind11 types so SolveContext and SolveResult can be
transported as JSON between the Create client, Silo server, and solver
runners.
Implementation:
- Constexpr enum string mapping tables for all 5 enums (BaseJointKind,
SolveStatus, DiagnosticKind, MotionKind, LimitKind) with template
bidirectional lookup helpers
- File-local to_dict/from_dict conversion functions for all 10 types
(Transform, Part, Constraint::Limit, Constraint, MotionDef,
SimulationParams, SolveContext, ConstraintDiagnostic,
SolveResult::PartResult, SolveResult)
- .def("to_dict") and .def_static("from_dict") on every py::class_<>
binding chain
Serialization details per SOLVER.md §3:
- SolveContext.to_dict() includes api_version field
- SolveContext.from_dict() validates api_version, raises ValueError on
mismatch
- Enums serialize as strings matching pybind11 .value() names
- Transform: {position: [x,y,z], quaternion: [w,x,y,z]}
- Optional simulation serializes as None/null
- Pure pybind11 py::dict construction, no new dependencies
Tests: 16 new tests in TestKCSolveSerialization covering round-trips for
all types, all 24 BaseJointKind values, all 4 SolveStatus values,
json.dumps/loads stdlib round-trip, and error cases (missing key,
invalid enum, bad array length, wrong api_version).
Add the kcsolve pybind11 module exposing the KCSolve C++ API to Python:
- PyIKCSolver trampoline enabling Python IKCSolver subclasses
- Bindings for all 5 enums, 10 structs, IKCSolver, and OndselAdapter
- Module functions wrapping SolverRegistry (available, load, joints_for,
set_default, get_default, register_solver)
- PySolverHolder class forwarding virtual calls with GIL acquisition
- register_solver() for runtime Python solver registration
IKCSolver constructor moved from protected to public for pybind11
trampoline access (class remains abstract via 3 pure virtuals).
Includes 16 Python tests covering module import, type bindings, enum
values, registry functions, Python solver subclassing, and full
register/load/solve round-trip.
Closes#288
Rewire AssemblyObject to call through KCSolve::IKCSolver instead of
directly manipulating OndselSolver ASMT types.
Key changes:
- Remove all 30+ #include <OndselSolver/*> from AssemblyObject.cpp
- Remove MbDPartData, objectPartMap, mbdAssembly members
- Add solver_ (IKCSolver), lastResult_ (SolveResult), partIdToObjs_ maps
- New buildSolveContext() builds SolveContext from FreeCAD document objects
with JointType/DistanceType -> BaseJointKind decomposition
- New computeMarkerTransform() replaces handleOneSideOfJoint()
- New computeRackPinionMarkers() replaces getRackPinionMarkers()
- Rewrite solve/preDrag/doDragStep/postDrag/generateSimulation to call
through IKCSolver interface
- Rewrite setNewPlacements/validateNewPlacements to use SolveResult
- Rewrite updateSolveStatus to use ConstraintDiagnostic
- Add export_native() to IKCSolver for ASMT export support
- Register OndselAdapter at Assembly module init in AppAssembly.cpp
- Remove OndselSolver from Assembly_LIBS (linked transitively via KCSolve)
Assembly module now has zero OndselSolver includes. All solver coupling
is confined to KCSolve/OndselAdapter.cpp.
Phase 1b of the pluggable solver system. Converts KCSolve from a
header-only INTERFACE target to a SHARED library and implements
the SolverRegistry with dynamic plugin discovery.
Changes:
- Add KCSolveGlobal.h export macro header (KCSolveExport)
- Move SolverRegistry method bodies from header to SolverRegistry.cpp
- Implement scan() with dlopen/LoadLibrary plugin loading
- Add scan_default_paths() for KCSOLVE_PLUGIN_PATH + system paths
- Plugin entry points: kcsolve_api_version() + kcsolve_create()
- API version checking (major version compatibility)
- Convert CMakeLists.txt from INTERFACE to SHARED library
- Link FreeCADBase (PRIVATE) for Console logging
- Link dl on POSIX for dynamic loading
- Fix -Wmissing-field-initializers warnings in IKCSolver.h defaults
The registry discovers plugins by scanning directories for shared
libraries that export the kcsolve C entry points. Plugins are
validated for API version compatibility before registration.
Manual registration via register_solver() remains available for
built-in solvers (e.g. OndselAdapter in Phase 1c).
Add the pluggable solver API as header-only files under
src/Mod/Assembly/Solver/. This is Phase 1a of the pluggable solver
system (INTER_SOLVER.md).
New files:
- Types.h: BaseJointKind enum (24 decomposed constraint types),
Transform, Part, Constraint, SolveContext, SolveResult, and
supporting types. Uses standalone types (no FreeCAD dependency)
for future server worker compatibility.
- IKCSolver.h: Abstract solver interface with solve(), drag protocol
(pre_drag/drag_step/post_drag), kinematic simulation
(run_kinematic/num_frames/update_for_frame), and diagnostics.
Only solve(), name(), and supported_joints() are pure virtual;
all other methods have default implementations.
- SolverRegistry.h: Thread-safe singleton registry for solver
backends with factory-based registration and default solver
selection.
- CMakeLists.txt: INTERFACE library target (header-only for now).
Modified:
- Assembly/CMakeLists.txt: add_subdirectory(Solver)
- Assembly/App/CMakeLists.txt: link KCSolve INTERFACE target
Add branch = main to mods/silo and mods/ztools in .gitmodules.
Enables 'git submodule update --remote' to auto-advance to latest main.
Third-party deps (GSL, googletest, AddonManager) remain pinned.
- Add Spreadsheet color preferences to KindredCreate.cfg using FCText
entries (TextColor, AliasedCellBackgroundColor, PositiveNumberColor,
NegativeNumberColor) matching the C++ GetASCII() reader in SheetModel.cpp
- Remove CatppuccinMocha install directive from CMakeLists.txt
- Update ztools submodule: theme.py deleted, CatppuccinMocha preference
pack removed, package.xml cleaned up
The previous apply_spreadsheet_colors() in ztools was a no-op: it called
SetUnsigned() but the Spreadsheet C++ reads GetASCII() — different param
types in FreeCAD's parameter system. Now properly fixed via preference pack.
Closes#278
Documentation updates:
- KNOWN_ISSUES.md: correct #6 (datum handling), resolve#10
(delete_bom_entry) and #11 (silo icons), fix stale formatDate
reference, mark completed next steps, add new next steps.
- INTEGRATION_PLAN.md: correct ztools SDK migration claim.
kc_format.py (#277):
- New _manifest_enrich_hook: populates part_uuid from SiloItemId and
silo_instance from Silo API URL on every .kc save.
- New update_manifest_fields(): public API to update manifest fields
in an already-saved .kc ZIP (used for post-upload revision_hash).
mods/silo submodule (#276):
- New bom_sync.py extraction engine.
- Post-commit hooks for BOM sync and manifest revision update.
- SSE bom_merged signal + Activity pane handler.
- merge_bom_json client method (forward-looking).
Refs: #276, #277