Compare commits
21 Commits
fix/qss-th
...
fix/book-t
| Author | SHA1 | Date | |
|---|---|---|---|
| a0cff5102d | |||
| 539ab7cc51 | |||
| 40bf0e4ae6 | |||
| 9bd5a7def1 | |||
| ccc372b2d1 | |||
| 23fd2593af | |||
| c25f1b62b8 | |||
| 10ae616f08 | |||
| d6ad0fb43d | |||
| bbee39431d | |||
| 3c0b14b862 | |||
| 1f793a6b71 | |||
| 65a2bb98db | |||
| c47eb26312 | |||
| 769072fb9d | |||
| 64bde8d97a | |||
| a9de667914 | |||
|
|
353efe51e2 | ||
| 6d828a6459 | |||
|
|
b7374d7b1f | ||
| 7ef7ce1dfc |
39
.gitea/workflows/docs.yml
Normal file
39
.gitea/workflows/docs.yml
Normal file
@@ -0,0 +1,39 @@
|
||||
name: Deploy Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "docs/**"
|
||||
- ".gitea/workflows/docs.yml"
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: docs
|
||||
steps:
|
||||
- name: Checkout
|
||||
run: |
|
||||
REPO_URL="http://gitea:3000/kindred/create.git"
|
||||
if [ -d .git ]; then
|
||||
git fetch "$REPO_URL" main
|
||||
git checkout -f FETCH_HEAD
|
||||
else
|
||||
git clone --depth 1 --branch main "$REPO_URL" .
|
||||
fi
|
||||
|
||||
- name: Install mdBook
|
||||
run: |
|
||||
if ! command -v mdbook &>/dev/null; then
|
||||
MDBOOK_VERSION="v0.5.2"
|
||||
wget -q -O mdbook.tar.gz "https://github.com/rust-lang/mdBook/releases/download/${MDBOOK_VERSION}/mdbook-${MDBOOK_VERSION}-x86_64-unknown-linux-musl.tar.gz"
|
||||
tar -xzf mdbook.tar.gz -C /usr/local/bin
|
||||
rm mdbook.tar.gz
|
||||
fi
|
||||
|
||||
- name: Build mdBook
|
||||
run: mdbook build docs/
|
||||
|
||||
- name: Deploy
|
||||
run: |
|
||||
rm -rf /opt/git/docs/book/*
|
||||
cp -r docs/book/* /opt/git/docs/book/
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -71,3 +71,6 @@ files_to_translate.txt
|
||||
# pixi environments
|
||||
.pixi
|
||||
*.egg-info
|
||||
|
||||
# mdBook build output
|
||||
docs/book/
|
||||
|
||||
16
docs/book.toml
Normal file
16
docs/book.toml
Normal file
@@ -0,0 +1,16 @@
|
||||
[book]
|
||||
title = "Kindred Create Documentation"
|
||||
authors = ["Kindred Systems LLC"]
|
||||
language = "en"
|
||||
src = "src"
|
||||
|
||||
[build]
|
||||
build-dir = "book"
|
||||
|
||||
[output.html]
|
||||
default-theme = "coal"
|
||||
preferred-dark-theme = "coal"
|
||||
git-repository-url = "https://git.kindred-systems.com/kindred/create"
|
||||
git-repository-icon = "fa-code-branch"
|
||||
additional-css = ["theme/kindred.css"]
|
||||
no-section-label = false
|
||||
33
docs/src/SUMMARY.md
Normal file
33
docs/src/SUMMARY.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Summary
|
||||
|
||||
[Introduction](./introduction.md)
|
||||
|
||||
---
|
||||
|
||||
# User Guide
|
||||
|
||||
- [Getting Started](./guide/getting-started.md)
|
||||
- [Installation](./guide/installation.md)
|
||||
- [Building from Source](./guide/building.md)
|
||||
- [Workbenches](./guide/workbenches.md)
|
||||
- [ztools](./guide/ztools.md)
|
||||
- [Silo](./guide/silo.md)
|
||||
|
||||
# Architecture
|
||||
|
||||
- [Overview](./architecture/overview.md)
|
||||
- [Python as Source of Truth](./architecture/python-source-of-truth.md)
|
||||
- [Silo Server](./architecture/silo-server.md)
|
||||
- [OndselSolver](./architecture/ondsel-solver.md)
|
||||
|
||||
# Development
|
||||
|
||||
- [Contributing](./development/contributing.md)
|
||||
- [Code Quality](./development/code-quality.md)
|
||||
- [Repository Structure](./development/repo-structure.md)
|
||||
- [Build System](./development/build-system.md)
|
||||
|
||||
# Reference
|
||||
|
||||
- [Configuration](./reference/configuration.md)
|
||||
- [Glossary](./reference/glossary.md)
|
||||
27
docs/src/architecture/ondsel-solver.md
Normal file
27
docs/src/architecture/ondsel-solver.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# OndselSolver
|
||||
|
||||
OndselSolver is the assembly constraint solver used by FreeCAD's Assembly workbench. Kindred Create vendors a fork of the solver as a git submodule.
|
||||
|
||||
- **Path:** `src/3rdParty/OndselSolver/`
|
||||
- **Source:** `git.kindred-systems.com/kindred/solver` (Kindred fork)
|
||||
|
||||
## How it works
|
||||
|
||||
The solver uses a **Lagrangian constraint formulation** to resolve assembly constraints (mates, joints, fixed positions). Given a set of parts with geometric constraints between them, it computes positions and orientations that satisfy all constraints simultaneously.
|
||||
|
||||
The Assembly workbench (`src/Mod/Assembly/`) calls the solver whenever constraints are added or modified. Kindred Create has patches to `Assembly/` that extend `findPlacement()` for better datum and origin handling.
|
||||
|
||||
## Why a fork
|
||||
|
||||
The solver is forked from the upstream Ondsel project for:
|
||||
- **Pinned stability** — the submodule is pinned to a known-good commit
|
||||
- **Potential modifications** — the fork allows Kindred-specific patches if needed
|
||||
- **Availability** — hosted on Kindred's Gitea instance for reliable access
|
||||
|
||||
## Future: GNN solver
|
||||
|
||||
There are plans to explore a Graph Neural Network (GNN) approach to constraint solving that could complement or supplement the Lagrangian solver for specific use cases. This is not yet implemented.
|
||||
|
||||
## Related: GSL
|
||||
|
||||
The `src/3rdParty/GSL/` submodule is Microsoft's Guidelines Support Library (`github.com/microsoft/GSL`), providing C++ core guidelines utilities like `gsl::span` and `gsl::not_null`. It is a build dependency, not related to the constraint solver.
|
||||
78
docs/src/architecture/overview.md
Normal file
78
docs/src/architecture/overview.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Architecture Overview
|
||||
|
||||
Kindred Create is structured as a thin integration layer on top of FreeCAD. The design follows three principles:
|
||||
|
||||
1. **Minimal core modifications** — prefer submodule addons over patching FreeCAD internals
|
||||
2. **Graceful degradation** — Create runs without ztools or Silo if submodules are missing
|
||||
3. **Pure Python addons** — workbenches follow FreeCAD's standard addon pattern
|
||||
|
||||
## Three-layer model
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ FreeCAD Documents (.FCStd) │ Python source of truth
|
||||
│ Workbench logic (Python) │
|
||||
├─────────────────────────────────┤
|
||||
│ PostgreSQL │ Silo metadata, revisions, BOM
|
||||
├─────────────────────────────────┤
|
||||
│ MinIO (S3-compatible) │ Binary file storage cache
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
FreeCAD documents are the authoritative representation of CAD data. Silo's PostgreSQL database stores metadata (part numbers, revisions, BOM relationships) and MinIO stores the binary `.FCStd` files. The FreeCAD workbench synchronizes between local files and the server.
|
||||
|
||||
## Source layout
|
||||
|
||||
```
|
||||
create/
|
||||
├── src/App/ # Core application (C++)
|
||||
├── src/Base/ # Foundation classes (C++)
|
||||
├── src/Gui/ # GUI framework (C++ + Qt6 + QSS)
|
||||
│ ├── Stylesheets/ # KindredCreate.qss theme
|
||||
│ ├── PreferencePacks/ # Theme preference pack
|
||||
│ ├── Icons/ # silo-*.svg origin icons
|
||||
│ ├── FileOrigin.* # Abstract file origin interface
|
||||
│ └── OriginManager.* # Origin lifecycle management
|
||||
├── src/Mod/ # ~37 FreeCAD modules
|
||||
│ ├── Create/ # Kindred bootstrap module
|
||||
│ ├── Assembly/ # Assembly workbench (Kindred patches)
|
||||
│ ├── PartDesign/ # Part Design (stock + ztools injection)
|
||||
│ └── ... # Other stock FreeCAD modules
|
||||
├── mods/
|
||||
│ ├── ztools/ # Datum/pattern/pocket workbench (submodule)
|
||||
│ └── silo/ # Parts database workbench (submodule)
|
||||
└── src/3rdParty/
|
||||
├── OndselSolver/ # Assembly solver (submodule)
|
||||
└── GSL/ # Guidelines Support Library (submodule)
|
||||
```
|
||||
|
||||
## Bootstrap sequence
|
||||
|
||||
1. FreeCAD core initializes, discovers `src/Mod/Create/`
|
||||
2. `Init.py` runs `setup_kindred_addons()` — adds `mods/ztools/ztools` and `mods/silo/freecad` to `sys.path`, executes their `Init.py`
|
||||
3. GUI phase: `InitGui.py` runs `setup_kindred_workbenches()` — executes addon `InitGui.py` files to register workbenches
|
||||
4. Deferred QTimer cascade:
|
||||
- **1500ms** — Register Silo as a file origin
|
||||
- **2000ms** — Dock the Silo auth panel
|
||||
- **3000ms** — Check for Silo first-start configuration
|
||||
- **4000ms** — Dock the Silo activity panel
|
||||
- **10000ms** — Check for application updates
|
||||
|
||||
The QTimer cascade exists because FreeCAD's startup is not fully synchronous — Silo registration must wait for the GUI framework to be ready.
|
||||
|
||||
## Origin system
|
||||
|
||||
The origin system is Kindred's primary addition to FreeCAD's GUI layer:
|
||||
|
||||
- **`FileOrigin`** — abstract C++ interface for file backends
|
||||
- **`LocalFileOrigin`** — default implementation (local filesystem)
|
||||
- **`SiloOrigin`** — Silo database backend (registered by the Python addon)
|
||||
- **`OriginManager`** — manages origin lifecycle, switching, capability queries
|
||||
- **`OriginSelectorWidget`** — dropdown in the File toolbar
|
||||
- **`CommandOrigin.cpp`** — Commit / Pull / Push / Info / BOM commands that delegate to the active origin
|
||||
|
||||
## Module interaction
|
||||
|
||||
- **ztools** injects commands into PartDesign via `_ZToolsPartDesignManipulator`
|
||||
- **Silo** registers as a `FileOrigin` backend via `silo_origin.register_silo_origin()`
|
||||
- **Create module** is glue only — no feature code, just bootstrap and version management
|
||||
26
docs/src/architecture/python-source-of-truth.md
Normal file
26
docs/src/architecture/python-source-of-truth.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Python as Source of Truth
|
||||
|
||||
In Kindred Create's architecture, FreeCAD documents (`.FCStd` files) are the authoritative representation of all CAD data. The Silo database and MinIO storage are caches and metadata indexes — they do not define the model.
|
||||
|
||||
## How it works
|
||||
|
||||
An `.FCStd` file is a ZIP archive containing:
|
||||
- XML documents describing the parametric model tree
|
||||
- BREP geometry files for each shape
|
||||
- Thumbnail images
|
||||
- Embedded spreadsheets and metadata
|
||||
|
||||
When a user runs **Commit**, the workbench uploads the entire `.FCStd` file to MinIO and records metadata (part number, revision, timestamp, commit message) in PostgreSQL. When a user runs **Pull**, the workbench downloads the `.FCStd` from MinIO and opens it locally.
|
||||
|
||||
## Why this design
|
||||
|
||||
- **No data loss** — the complete model is always in the `.FCStd` file, never split across systems
|
||||
- **Offline capability** — engineers can work without a server connection
|
||||
- **FreeCAD compatibility** — files are standard FreeCAD documents, openable in stock FreeCAD
|
||||
- **Simple sync model** — the unit of transfer is always a whole file, avoiding merge conflicts in binary geometry
|
||||
|
||||
## Trade-offs
|
||||
|
||||
- **Large files** — `.FCStd` files can grow large with complex assemblies; every commit stores the full file
|
||||
- **No partial sync** — you cannot pull a single feature or component; it is all or nothing
|
||||
- **Conflict resolution** — two users editing the same file must resolve conflicts manually (last-commit-wins by default)
|
||||
50
docs/src/architecture/silo-server.md
Normal file
50
docs/src/architecture/silo-server.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Silo Server
|
||||
|
||||
The Silo server is a Go REST API that provides the backend for the Silo workbench. It manages part numbers, revisions, bills of materials, and file storage for engineering teams.
|
||||
|
||||
## Components
|
||||
|
||||
```
|
||||
silo/
|
||||
├── cmd/
|
||||
│ ├── silo/ # CLI tool
|
||||
│ └── silod/ # API server
|
||||
├── internal/
|
||||
│ ├── api/ # HTTP handlers, routes, templates
|
||||
│ ├── config/ # Configuration loading
|
||||
│ ├── db/ # PostgreSQL access
|
||||
│ ├── migration/ # Property migration utilities
|
||||
│ ├── partnum/ # Part number generation
|
||||
│ ├── schema/ # YAML schema parsing
|
||||
│ └── storage/ # MinIO file storage
|
||||
├── migrations/ # Database migration SQL scripts
|
||||
├── schemas/ # Part numbering schema definitions (YAML)
|
||||
└── deployments/ # Docker Compose and systemd configs
|
||||
```
|
||||
|
||||
## Stack
|
||||
|
||||
- **Go** REST API with 38+ routes
|
||||
- **PostgreSQL** for metadata, revisions, BOM relationships
|
||||
- **MinIO** (S3-compatible) for binary `.FCStd` file storage
|
||||
- **LDAP / OIDC** for authentication
|
||||
- **SSE** (Server-Sent Events) for real-time activity feed
|
||||
|
||||
## Key features
|
||||
|
||||
- **Configurable part number generation** via YAML schemas
|
||||
- **Revision tracking** with append-only history
|
||||
- **BOM management** with reference designators and alternates
|
||||
- **Physical inventory** tracking with hierarchical locations
|
||||
|
||||
## Database migrations
|
||||
|
||||
Migrations live in `migrations/` as numbered SQL scripts (e.g., `001_initial.sql`). Apply them sequentially against the database:
|
||||
|
||||
```bash
|
||||
psql -h psql.kindred.internal -U silo -d silo -f migrations/001_initial.sql
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
See `mods/silo/deployments/` for Docker Compose and systemd configurations. A typical deployment runs the Go server alongside PostgreSQL and MinIO containers.
|
||||
72
docs/src/development/build-system.md
Normal file
72
docs/src/development/build-system.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Build System
|
||||
|
||||
Kindred Create uses **CMake** for build configuration, **pixi** (conda-based) for dependency management and task running, and **ccache** for compilation caching.
|
||||
|
||||
## Overview
|
||||
|
||||
- **CMake** >= 3.22.0
|
||||
- **Ninja** generator (via conda presets)
|
||||
- **pixi** manages all dependencies — compilers, Qt6, OpenCASCADE, Python, etc.
|
||||
- **ccache** with 4 GB max, zlib compression level 6, sloppy mode
|
||||
- **mold** linker on Linux for faster link times
|
||||
|
||||
## CMake configuration
|
||||
|
||||
The root `CMakeLists.txt` defines:
|
||||
- **Kindred Create version:** `0.1.0` (via `KINDRED_CREATE_VERSION`)
|
||||
- **FreeCAD base version:** `1.0.0` (via `FREECAD_VERSION`)
|
||||
- CMake policy settings for compatibility
|
||||
- ccache auto-detection
|
||||
- Submodule dependency checks
|
||||
- Library setup: yaml-cpp, fmt, ICU
|
||||
|
||||
### Version injection
|
||||
|
||||
The version flows from CMake to Python via `configure_file()`:
|
||||
|
||||
```
|
||||
CMakeLists.txt (KINDRED_CREATE_VERSION = "0.1.0")
|
||||
→ src/Mod/Create/version.py.in (template)
|
||||
→ build/*/Mod/Create/version.py (generated)
|
||||
→ update_checker.py (imports VERSION)
|
||||
```
|
||||
|
||||
## CMake presets
|
||||
|
||||
Defined in `CMakePresets.json`:
|
||||
|
||||
| Preset | Platform | Build type |
|
||||
|--------|----------|------------|
|
||||
| `conda-linux-debug` | Linux | Debug |
|
||||
| `conda-linux-release` | Linux | Release |
|
||||
| `conda-macos-debug` | macOS | Debug |
|
||||
| `conda-macos-release` | macOS | Release |
|
||||
| `conda-windows-debug` | Windows | Debug |
|
||||
| `conda-windows-release` | Windows | Release |
|
||||
|
||||
All presets inherit from a hidden `common` base and a hidden `conda` base (Ninja generator, conda toolchain).
|
||||
|
||||
## cMake/ helper modules
|
||||
|
||||
The `cMake/` directory contains CMake helper macros inherited from FreeCAD:
|
||||
- **FreeCAD_Helpers** — macros for building FreeCAD modules
|
||||
- Platform detection modules
|
||||
- Dependency finding modules (Find*.cmake)
|
||||
|
||||
## Dependencies
|
||||
|
||||
Core dependencies managed by pixi (from `pixi.toml`):
|
||||
|
||||
| Category | Packages |
|
||||
|----------|----------|
|
||||
| Build | cmake, ninja, swig, compilers (clang/gcc) |
|
||||
| CAD kernel | occt 7.8, coin3d, opencamlib, pythonocc-core |
|
||||
| UI | Qt6 6.8, PySide6, pyside6 |
|
||||
| Math | eigen, numpy, scipy, sympy |
|
||||
| Data | hdf5, vtk, smesh, ifcopenshell |
|
||||
| Python | 3.11 (< 3.12), pip, freecad-stubs |
|
||||
|
||||
Platform-specific extras:
|
||||
- **Linux:** clang, kernel-headers, mesa, X11, libspnav
|
||||
- **macOS:** sed
|
||||
- **Windows:** pthreads-win32
|
||||
40
docs/src/development/code-quality.md
Normal file
40
docs/src/development/code-quality.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Code Quality
|
||||
|
||||
## Formatting and linting
|
||||
|
||||
### C/C++
|
||||
|
||||
- **Formatter:** clang-format (config in `.clang-format`)
|
||||
- **Static analysis:** clang-tidy (config in `.clang-tidy`)
|
||||
|
||||
### Python
|
||||
|
||||
- **Formatter:** black with 100-character line length
|
||||
- **Linter:** pylint (config in `.pylintrc`)
|
||||
|
||||
## Pre-commit hooks
|
||||
|
||||
The repository uses [pre-commit](https://pre-commit.com/) to run formatters and linters automatically on staged files:
|
||||
|
||||
```bash
|
||||
pip install pre-commit
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
Configured hooks (`.pre-commit-config.yaml`):
|
||||
- `trailing-whitespace` — remove trailing whitespace
|
||||
- `end-of-file-fixer` — ensure files end with a newline
|
||||
- `check-yaml` — validate YAML syntax
|
||||
- `check-added-large-files` — prevent accidental large file commits
|
||||
- `mixed-line-ending` — normalize line endings
|
||||
- `black` — Python formatting (100 char lines)
|
||||
- `clang-format` — C/C++ formatting
|
||||
|
||||
## Scope
|
||||
|
||||
Pre-commit hooks are configured to run on specific directories:
|
||||
- `src/Base/`, `src/Gui/`, `src/Main/`, `src/Tools/`
|
||||
- `src/Mod/Assembly/`, `src/Mod/BIM/`, `src/Mod/CAM/`, `src/Mod/Draft/`, `src/Mod/Fem/`, and other stock modules
|
||||
- `tests/src/`
|
||||
|
||||
Excluded: generated files, vendored libraries (`QSint/`, `Quarter/`, `3Dconnexion/navlib`), and binary formats.
|
||||
52
docs/src/development/contributing.md
Normal file
52
docs/src/development/contributing.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Contributing
|
||||
|
||||
Kindred Create is maintained at [git.kindred-systems.com/kindred/create](https://git.kindred-systems.com/kindred/create). Contributions are submitted as pull requests against the `main` branch.
|
||||
|
||||
## Getting started
|
||||
|
||||
```bash
|
||||
git clone --recursive ssh://git@git.kindred-systems.com:2222/kindred/create.git
|
||||
cd create
|
||||
pixi run configure
|
||||
pixi run build
|
||||
pixi run freecad
|
||||
```
|
||||
|
||||
See [Building from Source](../guide/building.md) for the full development setup.
|
||||
|
||||
## Branch and PR workflow
|
||||
|
||||
1. Create a feature branch from `main`:
|
||||
```bash
|
||||
git checkout -b feat/my-feature main
|
||||
```
|
||||
2. Make your changes, commit with conventional commit messages (see below).
|
||||
3. Push and open a pull request against `main`.
|
||||
4. CI builds and tests run automatically on all PRs.
|
||||
|
||||
## Commit messages
|
||||
|
||||
Use [Conventional Commits](https://www.conventionalcommits.org/):
|
||||
|
||||
| Prefix | Purpose |
|
||||
|--------|---------|
|
||||
| `feat:` | New feature |
|
||||
| `fix:` | Bug fix |
|
||||
| `chore:` | Maintenance, dependencies |
|
||||
| `docs:` | Documentation only |
|
||||
| `art:` | Icons, theme, visual assets |
|
||||
|
||||
Scope is optional but encouraged:
|
||||
- `feat(ztools): add datum point creation mode`
|
||||
- `fix(gui): correct menu icon size on Wayland`
|
||||
- `chore: update silo submodule`
|
||||
|
||||
## Reporting issues
|
||||
|
||||
Report issues at the [issue tracker](https://git.kindred-systems.com/kindred/create/issues). When reporting:
|
||||
|
||||
1. Note whether the issue involves Kindred Create additions (ztools, Silo, theme) or base FreeCAD
|
||||
2. Include version info from **Help > About FreeCAD > Copy to clipboard**
|
||||
3. Provide reproduction steps and attach example files (FCStd as ZIP) if applicable
|
||||
|
||||
For base FreeCAD issues, also check the [FreeCAD issue tracker](https://github.com/FreeCAD/FreeCAD/issues).
|
||||
73
docs/src/development/repo-structure.md
Normal file
73
docs/src/development/repo-structure.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Repository Structure
|
||||
|
||||
```
|
||||
create/
|
||||
├── src/
|
||||
│ ├── App/ # Core application (C++)
|
||||
│ ├── Base/ # Base classes (C++)
|
||||
│ ├── Gui/ # GUI framework and stylesheets (C++)
|
||||
│ ├── Main/ # Application entry points
|
||||
│ ├── Mod/ # FreeCAD modules (~37)
|
||||
│ │ ├── Create/ # Kindred bootstrap module
|
||||
│ │ ├── Assembly/ # Assembly workbench (Kindred patches)
|
||||
│ │ ├── PartDesign/ # Part Design workbench
|
||||
│ │ ├── Sketcher/ # Sketcher workbench
|
||||
│ │ ├── AddonManager/ # Addon manager (submodule)
|
||||
│ │ └── ... # Other stock FreeCAD modules
|
||||
│ └── 3rdParty/
|
||||
│ ├── OndselSolver/ # Assembly solver (submodule)
|
||||
│ └── GSL/ # Guidelines Support Library (submodule)
|
||||
├── mods/ # Kindred addon workbenches (submodules)
|
||||
│ ├── ztools/ # ztools workbench
|
||||
│ └── silo/ # Silo parts database
|
||||
├── kindred-icons/ # SVG icon library (~200 icons)
|
||||
├── resources/ # Branding, desktop integration
|
||||
│ ├── branding/ # Logo, splash, icon generation scripts
|
||||
│ └── icons/ # Platform icons (.ico, .icns, hicolor)
|
||||
├── package/ # Packaging scripts
|
||||
│ ├── debian/ # Debian package
|
||||
│ ├── ubuntu/ # Ubuntu-specific
|
||||
│ ├── fedora/ # RPM package
|
||||
│ ├── rattler-build/ # Cross-platform bundles (AppImage, DMG, NSIS)
|
||||
│ └── WindowsInstaller/ # NSIS installer definition
|
||||
├── .gitea/workflows/ # CI/CD pipelines
|
||||
│ ├── build.yml # Build + test on push/PR
|
||||
│ └── release.yml # Release on tag push
|
||||
├── tests/ # Test suite
|
||||
│ ├── src/ # C++ test sources
|
||||
│ └── lib/ # Google Test framework (submodule)
|
||||
├── cMake/ # CMake helper modules
|
||||
├── docs/ # Documentation (this book)
|
||||
├── tools/ # Dev utilities (build, lint, profile)
|
||||
├── contrib/ # IDE configs (VSCode, CLion, debugger)
|
||||
├── data/ # Example and test data
|
||||
├── CMakeLists.txt # Root build configuration
|
||||
├── CMakePresets.json # Platform build presets
|
||||
├── pixi.toml # Pixi environment and tasks
|
||||
├── CONTRIBUTING.md # Contribution guide
|
||||
├── README.md # Project overview
|
||||
├── LICENSE # LGPL-2.1-or-later
|
||||
└── .pre-commit-config.yaml # Code quality hooks
|
||||
```
|
||||
|
||||
## Git submodules
|
||||
|
||||
| Submodule | Path | Source | Purpose |
|
||||
|-----------|------|--------|---------|
|
||||
| ztools | `mods/ztools` | `git.kindred-systems.com/forbes/ztools` | Unified workbench |
|
||||
| silo-mod | `mods/silo` | `git.kindred-systems.com/kindred/silo-mod` | Parts database |
|
||||
| OndselSolver | `src/3rdParty/OndselSolver` | `git.kindred-systems.com/kindred/solver` | Assembly solver |
|
||||
| GSL | `src/3rdParty/GSL` | `github.com/microsoft/GSL` | C++ guidelines library |
|
||||
| AddonManager | `src/Mod/AddonManager` | `github.com/FreeCAD/AddonManager` | Extension manager |
|
||||
| googletest | `tests/lib` | `github.com/google/googletest` | Test framework |
|
||||
|
||||
## Key files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `src/Mod/Create/Init.py` | Console-phase bootstrap — loads addons |
|
||||
| `src/Mod/Create/InitGui.py` | GUI-phase bootstrap — registers workbenches, deferred setup |
|
||||
| `src/Gui/FileOrigin.h` | Abstract file origin interface (Kindred addition) |
|
||||
| `src/Gui/Stylesheets/KindredCreate.qss` | Catppuccin Mocha theme |
|
||||
| `pixi.toml` | Build tasks and dependencies |
|
||||
| `CMakeLists.txt` | Root CMake configuration |
|
||||
107
docs/src/guide/building.md
Normal file
107
docs/src/guide/building.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Building from Source
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **git** with submodule support
|
||||
- **[pixi](https://pixi.sh)** — conda-based dependency manager and task runner
|
||||
|
||||
Pixi handles all other dependencies (CMake, compilers, Qt6, OpenCASCADE, etc.).
|
||||
|
||||
## Clone
|
||||
|
||||
```bash
|
||||
git clone --recursive ssh://git@git.kindred-systems.com:2222/kindred/create.git
|
||||
cd create
|
||||
```
|
||||
|
||||
If cloned without `--recursive`:
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
The repository includes six submodules:
|
||||
|
||||
| Submodule | Path | Source |
|
||||
|-----------|------|--------|
|
||||
| ztools | `mods/ztools` | `git.kindred-systems.com/forbes/ztools` |
|
||||
| silo-mod | `mods/silo` | `git.kindred-systems.com/kindred/silo-mod` |
|
||||
| OndselSolver | `src/3rdParty/OndselSolver` | `git.kindred-systems.com/kindred/solver` |
|
||||
| GSL | `src/3rdParty/GSL` | `github.com/microsoft/GSL` |
|
||||
| AddonManager | `src/Mod/AddonManager` | `github.com/FreeCAD/AddonManager` |
|
||||
| googletest | `tests/lib` | `github.com/google/googletest` |
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
pixi run configure
|
||||
pixi run build
|
||||
pixi run install
|
||||
pixi run freecad
|
||||
```
|
||||
|
||||
By default these target the **debug** configuration. For release builds:
|
||||
|
||||
```bash
|
||||
pixi run configure-release
|
||||
pixi run build-release
|
||||
pixi run install-release
|
||||
pixi run freecad-release
|
||||
```
|
||||
|
||||
## All pixi tasks
|
||||
|
||||
| Task | Description |
|
||||
|------|-------------|
|
||||
| `initialize` | `git submodule update --init --recursive` |
|
||||
| `configure` | CMake configure (debug) |
|
||||
| `configure-debug` | CMake configure with debug preset |
|
||||
| `configure-release` | CMake configure with release preset |
|
||||
| `build` | Build (debug) |
|
||||
| `build-debug` | `cmake --build build/debug` |
|
||||
| `build-release` | `cmake --build build/release` |
|
||||
| `install` | Install (debug) |
|
||||
| `install-debug` | `cmake --install build/debug` |
|
||||
| `install-release` | `cmake --install build/release` |
|
||||
| `test` | Run tests (debug) |
|
||||
| `test-debug` | `ctest --test-dir build/debug` |
|
||||
| `test-release` | `ctest --test-dir build/release` |
|
||||
| `freecad` | Launch FreeCAD (debug) |
|
||||
| `freecad-debug` | `build/debug/bin/FreeCAD` |
|
||||
| `freecad-release` | `build/release/bin/FreeCAD` |
|
||||
|
||||
## CMake presets
|
||||
|
||||
The project provides presets in `CMakePresets.json` for each platform and build type:
|
||||
|
||||
- `conda-linux-debug` / `conda-linux-release`
|
||||
- `conda-macos-debug` / `conda-macos-release`
|
||||
- `conda-windows-debug` / `conda-windows-release`
|
||||
|
||||
All presets inherit from a `common` base that enables `CMAKE_EXPORT_COMPILE_COMMANDS` and configures job pools. The `conda` presets use the Ninja generator and pick up compiler paths from the pixi environment.
|
||||
|
||||
## Platform notes
|
||||
|
||||
**Linux:** Uses clang from conda-forge. Requires kernel-headers, mesa, X11, and libspnav (all provided by pixi). Uses the mold linker for faster link times.
|
||||
|
||||
**macOS:** Minimal extra dependencies — pixi provides nearly everything. Tested on both Intel and Apple Silicon.
|
||||
|
||||
**Windows:** Requires pthreads-win32 and MSVC. The conda preset configures the MSVC toolchain automatically when run inside a pixi shell.
|
||||
|
||||
## Caching
|
||||
|
||||
The build uses **ccache** for compilation caching:
|
||||
- Maximum cache size: 4 GB
|
||||
- Compression: zlib level 6
|
||||
- Sloppiness mode enabled for faster cache hits
|
||||
|
||||
ccache is auto-detected by CMake at configure time.
|
||||
|
||||
## Common problems
|
||||
|
||||
**Submodules not initialized:** If you see missing file errors for ztools or Silo, run `pixi run initialize` or `git submodule update --init --recursive`.
|
||||
|
||||
**Pixi not found:** Install pixi from <https://pixi.sh>.
|
||||
|
||||
**ccache full:** Clear with `ccache -C` or increase the limit in your ccache config.
|
||||
|
||||
**Preset not found:** Ensure you are running CMake from within a pixi shell (`pixi shell`) so that conda environment variables are set.
|
||||
41
docs/src/guide/getting-started.md
Normal file
41
docs/src/guide/getting-started.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Getting Started
|
||||
|
||||
Kindred Create can be installed from prebuilt packages or built from source. This section covers both paths.
|
||||
|
||||
## Quick start (prebuilt)
|
||||
|
||||
Download the latest release from the [releases page](https://git.kindred-systems.com/kindred/create/releases).
|
||||
|
||||
**Debian/Ubuntu:**
|
||||
```bash
|
||||
sudo apt install ./kindred-create_*.deb
|
||||
```
|
||||
|
||||
**AppImage:**
|
||||
```bash
|
||||
chmod +x KindredCreate-*.AppImage
|
||||
./KindredCreate-*.AppImage
|
||||
```
|
||||
|
||||
## Quick start (from source)
|
||||
|
||||
```bash
|
||||
git clone --recursive ssh://git@git.kindred-systems.com:2222/kindred/create.git
|
||||
cd create
|
||||
pixi run configure
|
||||
pixi run build
|
||||
pixi run freecad
|
||||
```
|
||||
|
||||
See [Installation](./installation.md) for prebuilt package details and [Building from Source](./building.md) for the full development setup.
|
||||
|
||||
## First run
|
||||
|
||||
On first launch, Kindred Create:
|
||||
|
||||
1. Loads the **ztools** and **Silo** workbenches automatically via the Create bootstrap module
|
||||
2. Opens the **ZToolsWorkbench** as the default workbench
|
||||
3. Prompts for Silo server configuration if not yet set up
|
||||
4. Checks for application updates in the background (after ~10 seconds)
|
||||
|
||||
If the Silo server is not available, Kindred Create operates normally with local file operations. The Silo features activate once a server is configured.
|
||||
49
docs/src/guide/installation.md
Normal file
49
docs/src/guide/installation.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Installation
|
||||
|
||||
## Prebuilt packages
|
||||
|
||||
Download the latest release from the [releases page](https://git.kindred-systems.com/kindred/create/releases).
|
||||
|
||||
### Debian / Ubuntu
|
||||
|
||||
```bash
|
||||
sudo apt install ./kindred-create_*.deb
|
||||
```
|
||||
|
||||
### AppImage (any Linux)
|
||||
|
||||
```bash
|
||||
chmod +x KindredCreate-*.AppImage
|
||||
./KindredCreate-*.AppImage
|
||||
```
|
||||
|
||||
The AppImage is a self-contained bundle using squashfs with zstd compression. No installation required.
|
||||
|
||||
### macOS
|
||||
|
||||
> macOS builds are planned but not yet available in CI. Build from source for now.
|
||||
|
||||
### Windows
|
||||
|
||||
> Windows builds are planned but not yet available in CI. Build from source for now.
|
||||
|
||||
## Verifying your installation
|
||||
|
||||
Launch Kindred Create and check the console output (View > Report View) for:
|
||||
|
||||
```
|
||||
Create: Loaded ztools Init.py
|
||||
Create: Loaded silo Init.py
|
||||
Create module initialized
|
||||
```
|
||||
|
||||
This confirms the bootstrap module loaded both workbenches. If Silo is not configured, you will see a settings prompt on first launch.
|
||||
|
||||
## Uninstalling
|
||||
|
||||
**Debian/Ubuntu:**
|
||||
```bash
|
||||
sudo apt remove kindred-create
|
||||
```
|
||||
|
||||
**AppImage:** Delete the `.AppImage` file. No system files are modified.
|
||||
204
docs/src/guide/silo.md
Normal file
204
docs/src/guide/silo.md
Normal file
@@ -0,0 +1,204 @@
|
||||
# Silo
|
||||
|
||||
Silo is an item database and part management system for Kindred Create. It provides revision-controlled storage for CAD files, configurable part number generation, BOM management, and team collaboration.
|
||||
|
||||
- **Submodule path:** `mods/silo/`
|
||||
- **Source:** `git.kindred-systems.com/kindred/silo-mod`
|
||||
|
||||
## Architecture
|
||||
|
||||
Silo has three components:
|
||||
|
||||
```
|
||||
┌──────────────────────┐ ┌──────────────┐
|
||||
│ FreeCAD Workbench │────▶│ Go REST API │
|
||||
│ (Python commands) │ │ (silod) │
|
||||
└──────────────────────┘ └──────┬───────┘
|
||||
│ │
|
||||
│ silo-client │
|
||||
│ (shared API lib) │
|
||||
│ ┌─────┴─────┐
|
||||
│ │ │
|
||||
│ PostgreSQL MinIO
|
||||
│ (metadata) (files)
|
||||
│
|
||||
Local .FCStd files
|
||||
```
|
||||
|
||||
- **Go REST API server** (`cmd/silod/`) — 38+ routes, backed by PostgreSQL and MinIO
|
||||
- **FreeCAD workbench** (`freecad/`) — Python commands integrated into Kindred Create
|
||||
- **Shared API client** (`silo-client/`) — Python library used by the workbench (nested submodule)
|
||||
|
||||
The silo-mod repository was split from a monorepo into three repos: `silo-client` (shared Python API client), `silo-mod` (FreeCAD workbench), and `silo-calc` (LibreOffice Calc extension).
|
||||
|
||||
## Workbench commands
|
||||
|
||||
### Document lifecycle
|
||||
|
||||
| Command | Shortcut | Description |
|
||||
|---------|----------|-------------|
|
||||
| `Silo_New` | Ctrl+N | Register a new part — select category, generate part number from schema, optional project tagging |
|
||||
| `Silo_Open` | Ctrl+O | Search and open items — combined dialog querying both the database and local files |
|
||||
| `Silo_Save` | Ctrl+S | Save locally to canonical path, collect document properties, upload to MinIO as auto-revision |
|
||||
| `Silo_Commit` | Ctrl+Shift+S | Save as a new revision with a user-provided comment |
|
||||
| `Silo_Pull` | — | Download from MinIO with revision selection, conflict detection, and progress tracking |
|
||||
| `Silo_Push` | — | Batch upload — finds local files not yet synced to the server, compares timestamps |
|
||||
|
||||
### Information and management
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `Silo_Info` | Show item metadata, project tags, and revision history table with status and labels |
|
||||
| `Silo_BOM` | Two-tab view: BOM (children) and Where Used (parents). Add, edit, remove entries with quantity and unit tracking |
|
||||
| `Silo_TagProjects` | Multi-select dialog for assigning project tags to items |
|
||||
| `Silo_Rollback` | Select a previous revision and create a new revision from that point with optional comment |
|
||||
| `Silo_SetStatus` | Change revision lifecycle status: draft → review → released → obsolete |
|
||||
|
||||
### Administration
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `Silo_Settings` | Full settings UI — API URL, SSL verify, custom CA cert, API token management, authentication status |
|
||||
| `Silo_Auth` | Session-based login: `/login` → `/api/auth/me` → `/api/auth/tokens`; stores API token in preferences |
|
||||
| `Silo_ToggleMode` | Switch between Silo workbench and other workbenches (menu only) |
|
||||
|
||||
## Origin integration
|
||||
|
||||
Silo registers as a **file origin** via the `FileOrigin` interface in `src/Gui/`. The `SiloOrigin` class in `silo_origin.py` implements:
|
||||
|
||||
| Capability | Value |
|
||||
|------------|-------|
|
||||
| `id` | `"silo"` |
|
||||
| `name` | `"Kindred Silo"` |
|
||||
| `type` | PLM (1) |
|
||||
| `tracksExternally` | true |
|
||||
| `requiresAuthentication` | true |
|
||||
| `supportsRevisions` | true |
|
||||
| `supportsBOM` | true |
|
||||
| `supportsPartNumbers` | true |
|
||||
| `supportsAssemblies` | true |
|
||||
|
||||
The origin delegates to the workbench commands for all operations (new, open, save, commit, pull, push, info, BOM). Registration happens via a deferred QTimer (1500ms after startup) in `src/Mod/Create/InitGui.py`.
|
||||
|
||||
## Configuration
|
||||
|
||||
### FreeCAD parameters
|
||||
|
||||
Stored in `User parameter:BaseApp/Preferences/Mod/KindredSilo`:
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `ApiUrl` | String | (empty) | Silo server URL |
|
||||
| `SslVerify` | Bool | true | Verify SSL certificates |
|
||||
| `CaCertPath` | String | (empty) | Path to custom CA certificate |
|
||||
| `ApiToken` | String | (empty) | Stored authentication token |
|
||||
| `FirstStartChecked` | Bool | false | Whether first-start prompt has been shown |
|
||||
| `ProjectsDir` | String | `~/projects` | Local directory for checked-out files |
|
||||
|
||||
### Environment variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `SILO_API_URL` | `http://localhost:8080/api` | Override for server API endpoint |
|
||||
| `SILO_PROJECTS_DIR` | `~/projects` | Override for local projects directory |
|
||||
|
||||
## Server setup
|
||||
|
||||
### Quick start
|
||||
|
||||
```bash
|
||||
# Database setup (apply migrations sequentially)
|
||||
psql -h psql.kindred.internal -U silo -d silo -f migrations/001_initial.sql
|
||||
# ... through 010_item_extended_fields.sql
|
||||
|
||||
# Configure
|
||||
cp config.example.yaml config.yaml
|
||||
# Edit config.yaml with your database, MinIO, and auth settings
|
||||
|
||||
# Run server
|
||||
go run ./cmd/silod
|
||||
```
|
||||
|
||||
### Production deployment
|
||||
|
||||
Production configs live in `mods/silo/deployments/`:
|
||||
|
||||
```
|
||||
deployments/
|
||||
├── config.prod.yaml # Database, MinIO, auth settings
|
||||
├── docker-compose.prod.yaml # Production container orchestration
|
||||
├── docker-compose.yaml # Development Docker Compose
|
||||
└── systemd/
|
||||
├── silod.env.example # Service environment template
|
||||
└── silod.service # systemd unit file
|
||||
```
|
||||
|
||||
The systemd service runs as user `silo` with security hardening (`ProtectSystem=strict`, `NoNewPrivileges`, `PrivateTmp`). Config at `/etc/silo/config.yaml`, binary at `/opt/silo/bin/silod`.
|
||||
|
||||
### Server stack
|
||||
|
||||
- **Go** REST API with 38+ routes
|
||||
- **PostgreSQL** for metadata, revisions, BOM relationships
|
||||
- **MinIO** (S3-compatible) for binary `.FCStd` file storage
|
||||
- **LDAP / OIDC** for authentication
|
||||
- **SSE** (Server-Sent Events) for real-time activity feed
|
||||
|
||||
## Database migrations
|
||||
|
||||
Migrations live in `mods/silo/migrations/` as numbered SQL scripts:
|
||||
|
||||
| Migration | Purpose |
|
||||
|-----------|---------|
|
||||
| `001_initial.sql` | Core schema — items, revisions, properties |
|
||||
| `002_sequence_by_name.sql` | Part number sequence generation |
|
||||
| `003_remove_material.sql` | Property cleanup |
|
||||
| `004_cad_sync_state.sql` | CAD file sync tracking |
|
||||
| `005_property_schema_version.sql` | Schema versioning for properties |
|
||||
| `006_project_tags.sql` | Project-to-item relationships |
|
||||
| `007_revision_status.sql` | Revision lifecycle status tracking |
|
||||
| `008_odoo_integration.sql` | ERP integration preparation |
|
||||
| `009_auth.sql` | User authentication tables |
|
||||
| `010_item_extended_fields.sql` | Extended item metadata |
|
||||
|
||||
Apply sequentially: `psql -f migrations/001_initial.sql`, then `002`, etc. There is no automated migration runner — apply manually against the database.
|
||||
|
||||
## Part numbering schemas
|
||||
|
||||
Part number generation is configured via YAML schemas in `mods/silo/schemas/`:
|
||||
|
||||
- `kindred-rd.yaml` — Primary R&D part numbering schema with category codes, sequence segments, and validation rules
|
||||
- `kindred-locations.yaml` — Location hierarchy schema for physical inventory tracking
|
||||
|
||||
## Directory structure
|
||||
|
||||
```
|
||||
mods/silo/
|
||||
├── cmd/
|
||||
│ ├── silo/ # CLI tool
|
||||
│ └── silod/ # API server
|
||||
├── internal/
|
||||
│ ├── api/ # HTTP handlers, routes, templates
|
||||
│ ├── config/ # Configuration loading
|
||||
│ ├── db/ # PostgreSQL access
|
||||
│ ├── migration/ # Property migration utilities
|
||||
│ ├── partnum/ # Part number generation
|
||||
│ ├── schema/ # YAML schema parsing
|
||||
│ └── storage/ # MinIO file storage
|
||||
├── freecad/
|
||||
│ ├── InitGui.py # SiloWorkbench registration
|
||||
│ ├── silo_commands.py # 14 commands + dock widgets
|
||||
│ ├── silo_origin.py # FileOrigin backend
|
||||
│ └── resources/icons/ # 10 silo-*.svg icons
|
||||
├── silo-client/ # Shared Python API client (nested submodule)
|
||||
│ └── silo_client/
|
||||
│ ├── client.py # SiloClient HTTP wrapper
|
||||
│ └── settings.py # SiloSettings config management
|
||||
├── migrations/ # 10 numbered SQL scripts
|
||||
├── schemas/ # Part numbering YAML schemas
|
||||
└── deployments/ # Docker Compose + systemd configs
|
||||
```
|
||||
|
||||
## Further reading
|
||||
|
||||
- `mods/silo/README.md` — server quickstart and CLI usage
|
||||
- `mods/silo/ROADMAP.md` — strategic roadmap (6 phases, Q2 2026 → Q4 2027)
|
||||
23
docs/src/guide/workbenches.md
Normal file
23
docs/src/guide/workbenches.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Workbenches
|
||||
|
||||
Kindred Create ships two custom workbenches on top of FreeCAD's standard set.
|
||||
|
||||
## ztools
|
||||
|
||||
A unified workbench that consolidates part design, assembly, and sketcher tools into a single interface. It is the **default workbench** when Kindred Create launches.
|
||||
|
||||
ztools commands are also injected into the PartDesign workbench menus and toolbars via a manipulator mechanism, so they are accessible even when working in stock PartDesign.
|
||||
|
||||
See the [ztools guide](./ztools.md) for details.
|
||||
|
||||
## Silo
|
||||
|
||||
A parts database workbench for managing CAD files, part numbers, revisions, and bills of materials across teams. Silo commands (New, Open, Save, Commit, Pull, Push, Info, BOM) are integrated into the File menu and toolbar across **all** workbenches via the origin system.
|
||||
|
||||
Silo requires a running server instance. On first launch, Kindred Create prompts for server configuration.
|
||||
|
||||
See the [Silo guide](./silo.md) for details.
|
||||
|
||||
## Stock FreeCAD workbenches
|
||||
|
||||
All standard FreeCAD workbenches are available: PartDesign, Sketcher, Assembly, TechDraw, Draft, BIM, CAM, FEM, Mesh, Spreadsheet, and others. Kindred Create does not remove or disable any stock functionality.
|
||||
133
docs/src/guide/ztools.md
Normal file
133
docs/src/guide/ztools.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# ztools
|
||||
|
||||
ztools is a pure-Python FreeCAD workbench that consolidates part design, assembly, and sketcher tools into a single unified interface. It is the **default workbench** when Kindred Create launches.
|
||||
|
||||
- **Submodule path:** `mods/ztools/`
|
||||
- **Source:** `git.kindred-systems.com/forbes/ztools`
|
||||
- **Stats:** 6,400+ lines of code, 24+ command classes, 33 custom icons, 17 toolbars
|
||||
|
||||
## Commands
|
||||
|
||||
### Datum Creator (`ZTools_DatumCreator`)
|
||||
|
||||
Creates datum geometry (planes, axes, points) with 16 creation modes. The task panel auto-detects the geometry type from your selection and offers appropriate modes. Supports custom naming, spreadsheet linking, and body- or document-level creation.
|
||||
|
||||
### Datum Manager (`ZTools_DatumManager`)
|
||||
|
||||
Manages existing datums. (Stub — planned for Phase 1, Q1 2026.)
|
||||
|
||||
### Enhanced Pocket (`ZTools_EnhancedPocket`)
|
||||
|
||||
Extends FreeCAD's Pocket feature with **Flip Side to Cut** — a SOLIDWORKS-style feature that removes material *outside* the sketch profile rather than inside. Uses a Boolean Common operation internally. Supports all standard pocket types: Dimension, Through All, To First, Up To Face, Two Dimensions. Taper angle is supported for standard pockets (disabled for flipped).
|
||||
|
||||
### Rotated Linear Pattern (`ZTools_RotatedLinearPattern`)
|
||||
|
||||
Creates a linear pattern with incremental rotation per instance. Configure direction, spacing, number of occurrences, and cumulative or per-instance rotation. Source components are automatically hidden.
|
||||
|
||||
### Assembly Linear Pattern (`ZTools_AssemblyLinearPattern`)
|
||||
|
||||
Creates linear patterns of assembly components. Supports multi-component selection, direction vectors, total length or spacing modes, and creation as Links (recommended) or copies. Auto-detects the parent assembly.
|
||||
|
||||
### Assembly Polar Pattern (`ZTools_AssemblyPolarPattern`)
|
||||
|
||||
Creates polar (circular) patterns of assembly components. Supports custom or preset axes (X/Y/Z), full circle or custom angle, center point definition, and creation as Links or copies.
|
||||
|
||||
### Spreadsheet Formatting (9 commands)
|
||||
|
||||
| Command | Action |
|
||||
|---------|--------|
|
||||
| `ZTools_SpreadsheetStyleBold` | Toggle bold |
|
||||
| `ZTools_SpreadsheetStyleItalic` | Toggle italic |
|
||||
| `ZTools_SpreadsheetStyleUnderline` | Toggle underline |
|
||||
| `ZTools_SpreadsheetAlignLeft` | Left align |
|
||||
| `ZTools_SpreadsheetAlignCenter` | Center align |
|
||||
| `ZTools_SpreadsheetAlignRight` | Right align |
|
||||
| `ZTools_SpreadsheetBgColor` | Background color picker |
|
||||
| `ZTools_SpreadsheetTextColor` | Text color picker |
|
||||
| `ZTools_SpreadsheetQuickAlias` | Auto-create aliases from row/column labels |
|
||||
|
||||
## Datum creation modes
|
||||
|
||||
### Planes (7 modes)
|
||||
|
||||
| Mode | Description | Input |
|
||||
|------|-------------|-------|
|
||||
| Offset from Face | Offsets a planar face along its normal | Face + distance (mm) |
|
||||
| Offset from Plane | Offsets an existing datum plane | Datum plane + distance (mm) |
|
||||
| Midplane | Plane halfway between two parallel faces | Two parallel faces |
|
||||
| 3 Points | Plane through three non-collinear points | Three vertices |
|
||||
| Normal to Edge | Plane perpendicular to an edge at a parameter location | Edge + parameter (0.0–1.0) |
|
||||
| Angled | Rotates a plane about an edge by a specified angle | Face + edge + angle (degrees) |
|
||||
| Tangent to Cylinder | Plane tangent to a cylindrical face at an angular position | Cylindrical face + angle (degrees) |
|
||||
|
||||
### Axes (4 modes)
|
||||
|
||||
| Mode | Description | Input |
|
||||
|------|-------------|-------|
|
||||
| 2 Points | Axis through two points | Two vertices |
|
||||
| From Edge | Axis along a linear edge | Linear edge |
|
||||
| Cylinder Center | Axis along the centerline of a cylinder | Cylindrical face |
|
||||
| Plane Intersection | Axis at the intersection of two planes | Two non-parallel planes |
|
||||
|
||||
### Points (5 modes)
|
||||
|
||||
| Mode | Description | Input |
|
||||
|------|-------------|-------|
|
||||
| At Vertex | Point at a vertex location | Vertex |
|
||||
| XYZ Coordinates | Point at explicit coordinates | x, y, z (mm) |
|
||||
| On Edge | Point at a location along an edge | Edge + parameter (0.0–1.0) |
|
||||
| Face Center | Point at the center of mass of a face | Face |
|
||||
| Circle Center | Point at the center of a circular or arc edge | Circular edge |
|
||||
|
||||
## PartDesign injection
|
||||
|
||||
ztools registers a `_ZToolsPartDesignManipulator` that hooks into the PartDesign workbench at startup. This injects the following commands into PartDesign's toolbars and menus:
|
||||
|
||||
| PartDesign toolbar | Injected command |
|
||||
|--------------------|-----------------|
|
||||
| Part Design Helper Features | `ZTools_DatumCreator`, `ZTools_DatumManager` |
|
||||
| Part Design Modeling Features | `ZTools_EnhancedPocket` |
|
||||
| Part Design Transformation Features | `ZTools_RotatedLinearPattern` |
|
||||
|
||||
The manipulator is registered in `InitGui.py` when the Create bootstrap module loads addon workbenches.
|
||||
|
||||
## Directory structure
|
||||
|
||||
```
|
||||
mods/ztools/
|
||||
├── ztools/ztools/
|
||||
│ ├── InitGui.py # Workbench registration + manipulator
|
||||
│ ├── Init.py # Console initialization
|
||||
│ ├── commands/
|
||||
│ │ ├── datum_commands.py # DatumCreator + DatumManager
|
||||
│ │ ├── datum_viewprovider.py # ViewProvider + edit panel
|
||||
│ │ ├── pocket_commands.py # EnhancedPocket + FlippedPocket
|
||||
│ │ ├── pattern_commands.py # RotatedLinearPattern
|
||||
│ │ ├── assembly_pattern_commands.py # Linear + Polar assembly patterns
|
||||
│ │ └── spreadsheet_commands.py # 9 formatting commands
|
||||
│ ├── datums/
|
||||
│ │ └── core.py # 16 datum creation functions
|
||||
│ └── resources/ # Icons and theme
|
||||
└── CatppuccinMocha/ # Theme preference pack
|
||||
```
|
||||
|
||||
## Internal properties
|
||||
|
||||
ztools stores metadata on feature objects using these properties (preserved for backward compatibility):
|
||||
|
||||
| Property | Purpose |
|
||||
|----------|---------|
|
||||
| `ZTools_Type` | Feature type identifier |
|
||||
| `ZTools_Params` | JSON creation parameters |
|
||||
| `ZTools_SourceRefs` | JSON source geometry references |
|
||||
|
||||
## Known gaps
|
||||
|
||||
- Datum Manager is a stub — full implementation planned for Q1 2026
|
||||
- Datum parameter changes don't recalculate from source geometry yet
|
||||
- Enhanced Pocket taper angle is disabled for flipped pockets
|
||||
|
||||
## Further reading
|
||||
|
||||
- `mods/ztools/KINDRED_INTEGRATION.md` — integration architecture and migration options
|
||||
- `mods/ztools/ROADMAP.md` — phased development plan (Q1–Q4 2026)
|
||||
37
docs/src/introduction.md
Normal file
37
docs/src/introduction.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Kindred Create
|
||||
|
||||
Kindred Create is a fork of [FreeCAD](https://www.freecad.org) 1.0+ that adds integrated tooling for professional engineering workflows. It ships custom workbenches and a dark theme on top of FreeCAD's parametric modeling core.
|
||||
|
||||
- **License:** LGPL 2.1+
|
||||
- **Organization:** [Kindred Systems LLC](https://www.kindred-systems.com)
|
||||
- **Build system:** CMake + [pixi](https://pixi.sh)
|
||||
- **Current version:** Kindred Create v0.1.0 (FreeCAD base v1.0.0)
|
||||
|
||||
## Key features
|
||||
|
||||
**[ztools](./guide/ztools.md)** — A unified workbench that consolidates part design, assembly, and sketcher tools into a single interface. Adds custom datum creation (planes, axes, points with 16 creation modes), pattern tools for assemblies, an enhanced pocket with flip-side cutting, and spreadsheet formatting commands.
|
||||
|
||||
**[Silo](./guide/silo.md)** — A parts database system for managing CAD files, part numbers, revisions, and bills of materials across teams. Includes a Go REST API server backed by PostgreSQL and MinIO, with FreeCAD commands for opening, saving, and syncing files directly from the application.
|
||||
|
||||
**Catppuccin Mocha theme** — A dark theme applied across the entire application, including the 3D viewport, sketch editor, spreadsheet view, and tree view. Uses spanning-line branch indicators instead of disclosure arrows, with tuned preference defaults for document handling, selection behavior, and notifications.
|
||||
|
||||
**Origin system** — A pluggable file backend abstraction. The origin selector in the File toolbar lets you switch between local filesystem operations and Silo database operations. Silo commands (Commit, Pull, Push, Info, BOM) are available across all workbenches when Silo is the active origin.
|
||||
|
||||
**Update checker** — On startup, Kindred Create checks the Gitea releases API for newer versions and logs the result. Configurable check interval and skip-version preferences.
|
||||
|
||||
## How it relates to FreeCAD
|
||||
|
||||
Kindred Create is a fork/distribution of FreeCAD 1.0+. The design minimizes core modifications — custom functionality is delivered through submodule addons (ztools, Silo) that follow FreeCAD's standard workbench pattern. If the addon submodules are missing, Kindred Create still functions as a themed FreeCAD.
|
||||
|
||||
The primary additions to FreeCAD's core are:
|
||||
- The **origin system** (`FileOrigin` interface in `src/Gui/`) for pluggable file backends
|
||||
- The **Create bootstrap module** (`src/Mod/Create/`) that loads addons at startup
|
||||
- The **Catppuccin Mocha theme** (`KindredCreate.qss`) and preference pack
|
||||
- Patches to **Assembly** (`findPlacement()` datum/origin handling)
|
||||
|
||||
## Links
|
||||
|
||||
- **Source:** <https://git.kindred-systems.com/kindred/create>
|
||||
- **Downloads:** <https://git.kindred-systems.com/kindred/create/releases>
|
||||
- **Issue tracker:** <https://git.kindred-systems.com/kindred/create/issues>
|
||||
- **Website:** <https://www.kindred-systems.com/create>
|
||||
117
docs/src/reference/configuration.md
Normal file
117
docs/src/reference/configuration.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# Configuration
|
||||
|
||||
## Silo workbench
|
||||
|
||||
### FreeCAD parameters
|
||||
|
||||
Stored in `User parameter:BaseApp/Preferences/Mod/KindredSilo`:
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `ApiUrl` | String | (empty) | Silo server API endpoint URL |
|
||||
| `SslVerify` | Bool | true | Verify SSL certificates when connecting to server |
|
||||
| `CaCertPath` | String | (empty) | Path to custom CA certificate for self-signed certs |
|
||||
| `ApiToken` | String | (empty) | Stored authentication token (set by `Silo_Auth`) |
|
||||
| `FirstStartChecked` | Bool | false | Whether the first-start settings prompt has been shown |
|
||||
| `ProjectsDir` | String | `~/projects` | Local directory for checked-out CAD files |
|
||||
|
||||
### Environment variables
|
||||
|
||||
These override the FreeCAD parameter values when set:
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `SILO_API_URL` | `http://localhost:8080/api` | Silo server API endpoint |
|
||||
| `SILO_PROJECTS_DIR` | `~/projects` | Local directory for checked-out files |
|
||||
|
||||
### Keyboard shortcuts
|
||||
|
||||
Recommended shortcuts (prompted on first workbench activation):
|
||||
|
||||
| Shortcut | Command |
|
||||
|----------|---------|
|
||||
| Ctrl+O | `Silo_Open` — Search and open items |
|
||||
| Ctrl+N | `Silo_New` — Create new item |
|
||||
| Ctrl+S | `Silo_Save` — Save locally and upload |
|
||||
| Ctrl+Shift+S | `Silo_Commit` — Save with revision comment |
|
||||
|
||||
## Update checker
|
||||
|
||||
Stored in `User parameter:BaseApp/Preferences/Mod/KindredCreate/Update`:
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `CheckEnabled` | Bool | true | Enable or disable update checks |
|
||||
| `CheckIntervalDays` | Int | 1 | Minimum days between checks |
|
||||
| `LastCheckTimestamp` | String | (empty) | ISO 8601 timestamp of last successful check |
|
||||
| `SkippedVersion` | String | (empty) | Version the user chose to skip |
|
||||
|
||||
The checker queries:
|
||||
```
|
||||
https://git.kindred-systems.com/api/v1/repos/kindred/create/releases?limit=10
|
||||
```
|
||||
|
||||
It compares the current version (injected at build time via `version.py.in`) against the latest non-draft, non-prerelease tag. The `latest` rolling tag is ignored. Checks run 10 seconds after GUI startup.
|
||||
|
||||
To disable: set `CheckEnabled` to `false` in FreeCAD preferences, or set `CheckIntervalDays` to `0` for on-demand only.
|
||||
|
||||
## Theme
|
||||
|
||||
The default theme is **Catppuccin Mocha** applied via `KindredCreate.qss`.
|
||||
|
||||
| Setting | Location |
|
||||
|---------|----------|
|
||||
| Canonical stylesheet | `src/Gui/Stylesheets/KindredCreate.qss` |
|
||||
| Preference pack | `src/Gui/PreferencePacks/KindredCreate/` |
|
||||
| Default theme name | `coal` (in mdBook docs) / `KindredCreate` (in app) |
|
||||
|
||||
To switch themes: **Edit > Preferences > General > Stylesheet** and select a different `.qss` file.
|
||||
|
||||
The preference pack is synced from the canonical stylesheet at build time via CMake's `configure_file()`. Edits should be made to the canonical file, not the preference pack copy.
|
||||
|
||||
## Build configuration
|
||||
|
||||
### Version constants
|
||||
|
||||
Defined in the root `CMakeLists.txt`:
|
||||
|
||||
| Constant | Value | Description |
|
||||
|----------|-------|-------------|
|
||||
| `KINDRED_CREATE_VERSION` | `0.1.0` | Kindred Create version |
|
||||
| `FREECAD_VERSION` | `1.0.0` | FreeCAD base version |
|
||||
|
||||
These are injected into `src/Mod/Create/version.py` at build time via `version.py.in`.
|
||||
|
||||
### CMake presets
|
||||
|
||||
Defined in `CMakePresets.json`:
|
||||
|
||||
| Preset | Platform | Build type |
|
||||
|--------|----------|------------|
|
||||
| `conda-linux-debug` | Linux | Debug |
|
||||
| `conda-linux-release` | Linux | Release |
|
||||
| `conda-macos-debug` | macOS | Debug |
|
||||
| `conda-macos-release` | macOS | Release |
|
||||
| `conda-windows-debug` | Windows | Debug |
|
||||
| `conda-windows-release` | Windows | Release |
|
||||
|
||||
### ccache
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Max size | 4 GB |
|
||||
| Compression | zlib level 6 |
|
||||
| Sloppiness | `include_file_ctime,include_file_mtime,pch_defines,time_macros` |
|
||||
|
||||
ccache is auto-detected by CMake at configure time. Clear with `ccache -C`.
|
||||
|
||||
## Silo server
|
||||
|
||||
Server configuration is defined in YAML. See `mods/silo/deployments/config.prod.yaml` for production settings and `mods/silo/config.example.yaml` for all available options.
|
||||
|
||||
Key sections:
|
||||
- **database** — PostgreSQL connection string
|
||||
- **storage** — MinIO endpoint, bucket, access keys
|
||||
- **auth** — LDAP/OIDC provider settings
|
||||
- **server** — Listen address, TLS, CORS
|
||||
- **schemas** — Path to part numbering YAML schemas
|
||||
53
docs/src/reference/glossary.md
Normal file
53
docs/src/reference/glossary.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Glossary
|
||||
|
||||
## Terms
|
||||
|
||||
**BOM** — Bill of Materials. A structured list of components in an assembly with part numbers, quantities, and reference designators.
|
||||
|
||||
**Catppuccin Mocha** — A dark color palette used for Kindred Create's theme. Part of the [Catppuccin](https://github.com/catppuccin/catppuccin) color scheme family.
|
||||
|
||||
**Datum** — Reference geometry (plane, axis, or point) used as a construction aid for modeling. Not a physical shape — used to position features relative to abstract references.
|
||||
|
||||
**FCStd** — FreeCAD's standard document format. A ZIP archive containing XML model trees, BREP geometry, thumbnails, and embedded data.
|
||||
|
||||
**FileOrigin** — Abstract C++ interface in `src/Gui/` that defines a pluggable file backend. Implementations: `LocalFileOrigin` (filesystem) and `SiloOrigin` (database).
|
||||
|
||||
**FreeCAD** — Open-source parametric 3D CAD platform. Kindred Create is based on FreeCAD v1.0.0. Website: <https://www.freecad.org>
|
||||
|
||||
**Kindred Create** — The full application: a FreeCAD fork plus Kindred's addon workbenches, theme, and tooling.
|
||||
|
||||
**Manipulator** — FreeCAD mechanism for injecting commands from one workbench into another's menus and toolbars. Used by ztools to add commands to PartDesign.
|
||||
|
||||
**MinIO** — S3-compatible object storage server. Used by Silo to store binary `.FCStd` files.
|
||||
|
||||
**OndselSolver** — Lagrangian constraint solver for the Assembly workbench. Vendored as a submodule from a Kindred fork.
|
||||
|
||||
**Origin** — In Kindred Create context: the pluggable file backend system. In FreeCAD context: the coordinate system origin (X/Y/Z axes and planes) of a Part or Body.
|
||||
|
||||
**pixi** — Conda-based dependency manager and task runner. Used for all build operations. Website: <https://pixi.sh>
|
||||
|
||||
**Preference pack** — FreeCAD mechanism for bundling theme settings, preferences, and stylesheets into an installable package.
|
||||
|
||||
**QSS** — Qt Style Sheet. A CSS-like language for styling Qt widgets. Kindred Create's theme is defined in `KindredCreate.qss`.
|
||||
|
||||
**rattler-build** — Cross-platform package build tool from the conda ecosystem. Used to create AppImage, DMG, and NSIS installer bundles.
|
||||
|
||||
**Silo** — Kindred's parts database system. Consists of a Go server, FreeCAD workbench, and shared Python client library.
|
||||
|
||||
**SSE** — Server-Sent Events. HTTP-based protocol for real-time server-to-client notifications. Used by Silo for the activity feed.
|
||||
|
||||
**Workbench** — FreeCAD's plugin/module system. Each workbench provides a set of tools, menus, and toolbars for a specific task domain.
|
||||
|
||||
**ztools** — Kindred's unified workbench combining Part Design, Assembly, and Sketcher tools with custom datum creation and assembly patterns.
|
||||
|
||||
## Repository URLs
|
||||
|
||||
| Repository | URL |
|
||||
|------------|-----|
|
||||
| Kindred Create | <https://git.kindred-systems.com/kindred/create> |
|
||||
| ztools | <https://git.kindred-systems.com/forbes/ztools> |
|
||||
| silo-mod | <https://git.kindred-systems.com/kindred/silo-mod> |
|
||||
| OndselSolver | <https://git.kindred-systems.com/kindred/solver> |
|
||||
| GSL | <https://github.com/microsoft/GSL> |
|
||||
| AddonManager | <https://github.com/FreeCAD/AddonManager> |
|
||||
| googletest | <https://github.com/google/googletest> |
|
||||
8
docs/theme/kindred.css
vendored
Normal file
8
docs/theme/kindred.css
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/* Kindred Create docs - minor overrides for coal theme */
|
||||
:root {
|
||||
--sidebar-width: 280px;
|
||||
}
|
||||
|
||||
.sidebar .sidebar-scrollbox {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
Submodule mods/silo updated: 383eefce9c...c6e187a75c
@@ -49,7 +49,9 @@ def activePartOrAssembly():
|
||||
|
||||
def activeAssembly():
|
||||
active_assembly = activePartOrAssembly()
|
||||
if active_assembly is not None and active_assembly.isDerivedFrom("Assembly::AssemblyObject"):
|
||||
if active_assembly is not None and active_assembly.isDerivedFrom(
|
||||
"Assembly::AssemblyObject"
|
||||
):
|
||||
if active_assembly.ViewObject.isInEditMode():
|
||||
return active_assembly
|
||||
|
||||
@@ -59,7 +61,9 @@ def activeAssembly():
|
||||
def activePart():
|
||||
active_part = activePartOrAssembly()
|
||||
|
||||
if active_part is not None and not active_part.isDerivedFrom("Assembly::AssemblyObject"):
|
||||
if active_part is not None and not active_part.isDerivedFrom(
|
||||
"Assembly::AssemblyObject"
|
||||
):
|
||||
return active_part
|
||||
|
||||
return None
|
||||
@@ -120,7 +124,9 @@ def number_of_components_in(assembly):
|
||||
def isLink(obj):
|
||||
# If element count is not 0, then its a link group in which case the Link
|
||||
# is a container and it's the LinkElement that is linking to external doc.
|
||||
return (obj.TypeId == "App::Link" and obj.ElementCount == 0) or obj.TypeId == "App::LinkElement"
|
||||
return (
|
||||
obj.TypeId == "App::Link" and obj.ElementCount == 0
|
||||
) or obj.TypeId == "App::LinkElement"
|
||||
|
||||
|
||||
def isLinkGroup(obj):
|
||||
@@ -375,7 +381,9 @@ def getGlobalPlacement(ref, targetObj=None):
|
||||
if not isRefValid(ref, 1):
|
||||
return App.Placement()
|
||||
|
||||
if targetObj is None: # If no targetObj is given, we consider it's the getObject(ref)
|
||||
if (
|
||||
targetObj is None
|
||||
): # If no targetObj is given, we consider it's the getObject(ref)
|
||||
targetObj = getObject(ref)
|
||||
if targetObj is None:
|
||||
return App.Placement()
|
||||
@@ -520,11 +528,17 @@ def findElementClosestVertex(ref, mousePos):
|
||||
|
||||
for i, edge in enumerate(edges):
|
||||
curve = edge.Curve
|
||||
if curve.TypeId == "Part::GeomCircle" or curve.TypeId == "Part::GeomEllipse":
|
||||
if (
|
||||
curve.TypeId == "Part::GeomCircle"
|
||||
or curve.TypeId == "Part::GeomEllipse"
|
||||
):
|
||||
center_points.append(curve.Location)
|
||||
center_points_edge_indexes.append(i)
|
||||
|
||||
elif _type == "Part::GeomCylinder" and curve.TypeId == "Part::GeomBSplineCurve":
|
||||
elif (
|
||||
_type == "Part::GeomCylinder"
|
||||
and curve.TypeId == "Part::GeomBSplineCurve"
|
||||
):
|
||||
# handle special case of 2 cylinder intersecting.
|
||||
for j, facej in enumerate(obj.Shape.Faces):
|
||||
surfacej = facej.Surface
|
||||
@@ -553,7 +567,9 @@ def findElementClosestVertex(ref, mousePos):
|
||||
if _type == "Part::GeomCylinder" or _type == "Part::GeomCone":
|
||||
centerOfG = face.CenterOfGravity - surface.Center
|
||||
centerPoint = surface.Center + centerOfG
|
||||
centerPoint = centerPoint + App.Vector().projectToLine(centerOfG, surface.Axis)
|
||||
centerPoint = centerPoint + App.Vector().projectToLine(
|
||||
centerOfG, surface.Axis
|
||||
)
|
||||
face_points.append(centerPoint)
|
||||
else:
|
||||
face_points.append(face.CenterOfGravity)
|
||||
@@ -623,7 +639,8 @@ def color_from_unsigned(c):
|
||||
|
||||
def getJointsOfType(asm, jointTypes):
|
||||
if not (
|
||||
asm.isDerivedFrom("Assembly::AssemblyObject") or asm.isDerivedFrom("Assembly::AssemblyLink")
|
||||
asm.isDerivedFrom("Assembly::AssemblyObject")
|
||||
or asm.isDerivedFrom("Assembly::AssemblyLink")
|
||||
):
|
||||
return []
|
||||
|
||||
@@ -763,7 +780,9 @@ def getSubMovingParts(obj, partsAsSolid):
|
||||
|
||||
if isLink(obj):
|
||||
linked_obj = obj.getLinkedObject()
|
||||
if linked_obj.isDerivedFrom("App::Part") or linked_obj.isDerivedFrom("Part::Feature"):
|
||||
if linked_obj.isDerivedFrom("App::Part") or linked_obj.isDerivedFrom(
|
||||
"Part::Feature"
|
||||
):
|
||||
return [obj]
|
||||
|
||||
return []
|
||||
@@ -996,7 +1015,7 @@ def findPlacement(ref, ignoreVertex=False):
|
||||
vtx = getElementName(ref[1][1])
|
||||
|
||||
if not elt or not vtx:
|
||||
# case of whole parts such as PartDesign::Body or App/PartDesign::CordinateSystem/Point/Line/Plane.
|
||||
# Origin objects (App::Line, App::Plane, App::Point)
|
||||
if obj.TypeId == "App::Line":
|
||||
if obj.Role == "X_Axis":
|
||||
return App.Placement(App.Vector(), App.Rotation(0.5, 0.5, 0.5, 0.5))
|
||||
@@ -1005,9 +1024,25 @@ def findPlacement(ref, ignoreVertex=False):
|
||||
if obj.Role == "Z_Axis":
|
||||
return App.Placement(App.Vector(), App.Rotation(-0.5, 0.5, -0.5, 0.5))
|
||||
|
||||
# PartDesign datum planes (including ZTools datums like ZPlane_Mid, ZPlane_Offset)
|
||||
if obj.TypeId == "App::Plane":
|
||||
if obj.Role == "XY_Plane":
|
||||
return App.Placement()
|
||||
if obj.Role == "XZ_Plane":
|
||||
return App.Placement(
|
||||
App.Vector(), App.Rotation(App.Vector(1, 0, 0), -90)
|
||||
)
|
||||
if obj.Role == "YZ_Plane":
|
||||
return App.Placement(
|
||||
App.Vector(), App.Rotation(App.Vector(0, 1, 0), 90)
|
||||
)
|
||||
return App.Placement()
|
||||
|
||||
if obj.TypeId == "App::Point":
|
||||
return App.Placement()
|
||||
|
||||
# PartDesign datum planes
|
||||
if obj.isDerivedFrom("PartDesign::Plane"):
|
||||
if hasattr(obj, "Shape") and obj.Shape.Faces:
|
||||
if hasattr(obj, "Shape") and not obj.Shape.isNull() and obj.Shape.Faces:
|
||||
face = obj.Shape.Faces[0]
|
||||
surface = face.Surface
|
||||
plc = App.Placement()
|
||||
@@ -1015,9 +1050,28 @@ def findPlacement(ref, ignoreVertex=False):
|
||||
if hasattr(surface, "Rotation") and surface.Rotation is not None:
|
||||
plc.Rotation = App.Rotation(surface.Rotation)
|
||||
return obj.Placement.inverse() * plc
|
||||
return obj.Placement
|
||||
|
||||
# PartDesign datum lines
|
||||
if obj.isDerivedFrom("PartDesign::Line"):
|
||||
if hasattr(obj, "Shape") and not obj.Shape.isNull() and obj.Shape.Edges:
|
||||
edge = obj.Shape.Edges[0]
|
||||
points = getPointsFromVertexes(edge.Vertexes)
|
||||
mid = (points[0] + points[1]) * 0.5
|
||||
direction = round_vector(edge.Curve.Direction)
|
||||
plane = Part.Plane(App.Vector(), direction)
|
||||
plc = App.Placement()
|
||||
plc.Base = mid
|
||||
plc.Rotation = App.Rotation(plane.Rotation)
|
||||
return obj.Placement.inverse() * plc
|
||||
return obj.Placement
|
||||
|
||||
# PartDesign datum points
|
||||
if obj.isDerivedFrom("PartDesign::Point"):
|
||||
if hasattr(obj, "Shape") and not obj.Shape.isNull() and obj.Shape.Vertexes:
|
||||
plc = App.Placement()
|
||||
plc.Base = obj.Shape.Vertexes[0].Point
|
||||
return obj.Placement.inverse() * plc
|
||||
return obj.Placement
|
||||
|
||||
return App.Placement()
|
||||
@@ -1080,9 +1134,14 @@ def findPlacement(ref, ignoreVertex=False):
|
||||
if surface.TypeId == "Part::GeomCylinder":
|
||||
centerOfG = face.CenterOfGravity - surface.Center
|
||||
centerPoint = surface.Center + centerOfG
|
||||
centerPoint = centerPoint + App.Vector().projectToLine(centerOfG, surface.Axis)
|
||||
centerPoint = centerPoint + App.Vector().projectToLine(
|
||||
centerOfG, surface.Axis
|
||||
)
|
||||
plc.Base = centerPoint
|
||||
elif surface.TypeId == "Part::GeomTorus" or surface.TypeId == "Part::GeomSphere":
|
||||
elif (
|
||||
surface.TypeId == "Part::GeomTorus"
|
||||
or surface.TypeId == "Part::GeomSphere"
|
||||
):
|
||||
plc.Base = surface.Center
|
||||
elif surface.TypeId == "Part::GeomCone":
|
||||
plc.Base = surface.Apex
|
||||
@@ -1100,7 +1159,8 @@ def findPlacement(ref, ignoreVertex=False):
|
||||
plc.Base = (center_point.x, center_point.y, center_point.z)
|
||||
|
||||
elif (
|
||||
surface.TypeId == "Part::GeomCylinder" and curve.TypeId == "Part::GeomBSplineCurve"
|
||||
surface.TypeId == "Part::GeomCylinder"
|
||||
and curve.TypeId == "Part::GeomBSplineCurve"
|
||||
):
|
||||
# handle special case of 2 cylinder intersecting.
|
||||
plc.Base = findCylindersIntersection(obj, surface, edge, elt_index)
|
||||
@@ -1394,13 +1454,16 @@ def generatePropertySettings(documentObject):
|
||||
commands.append(f"obj.{propertyName} = {propertyValue:.5f}")
|
||||
elif propertyType == "App::PropertyInt" or propertyType == "App::PropertyBool":
|
||||
commands.append(f"obj.{propertyName} = {propertyValue}")
|
||||
elif propertyType == "App::PropertyString" or propertyType == "App::PropertyEnumeration":
|
||||
elif (
|
||||
propertyType == "App::PropertyString"
|
||||
or propertyType == "App::PropertyEnumeration"
|
||||
):
|
||||
commands.append(f'obj.{propertyName} = "{propertyValue}"')
|
||||
elif propertyType == "App::PropertyPlacement":
|
||||
commands.append(
|
||||
f"obj.{propertyName} = App.Placement("
|
||||
f"App.Vector({propertyValue.Base.x:.5f},{propertyValue.Base.y:.5f},{propertyValue.Base.z:.5f}),"
|
||||
f"App.Rotation(*{[round(n,5) for n in propertyValue.Rotation.getYawPitchRoll()]}))"
|
||||
f"App.Rotation(*{[round(n, 5) for n in propertyValue.Rotation.getYawPitchRoll()]}))"
|
||||
)
|
||||
elif propertyType == "App::PropertyXLinkSubHidden":
|
||||
commands.append(
|
||||
|
||||
Reference in New Issue
Block a user