Compare commits
98 Commits
v0.1.0
...
docs/mdboo
| Author | SHA1 | Date | |
|---|---|---|---|
| 64bde8d97a | |||
| a9de667914 | |||
|
|
353efe51e2 | ||
| 6d828a6459 | |||
|
|
b7374d7b1f | ||
| 7ef7ce1dfc | |||
| 7411508b36 | |||
| 766f9b491c | |||
| ad34cffcd6 | |||
| cecd4988a8 | |||
|
|
977fa3c934 | ||
|
|
f0f4c068d2 | ||
|
|
5f43b534d9 | ||
| 599d4b23a8 | |||
| d136ee3ebe | |||
| 561d634934 | |||
|
|
eb57f80e72 | ||
|
|
098f0233c4 | ||
| 68690f3b22 | |||
| 087fe99324 | |||
| 7033744656 | |||
|
|
84c1776f92 | ||
| f391c526cd | |||
| ac4f01c5c0 | |||
| 1d2a11572d | |||
|
|
b3a6c9d925 | ||
| 7c84eeb68d | |||
|
|
590cb9f6c3 | ||
|
|
0a0ac547ef | ||
|
|
6773ca0dfd | ||
|
|
82e7362a56 | ||
| cf523f1d87 | |||
|
|
4bf74cf339 | ||
| 3b07a0f99b | |||
|
|
9cabb29824 | ||
| 793e6bdd49 | |||
| b6ab14cc6f | |||
| da46073d68 | |||
|
|
262dfa583d | ||
|
|
cc5ba638d1 | ||
|
|
35302154ae | ||
|
|
be7f1d9221 | ||
|
|
10b5c9d584 | ||
|
|
ee839c23b8 | ||
|
|
67f825c305 | ||
| 440df2a9be | |||
|
|
1750949afd | ||
| b2c6fc2ebc | |||
|
|
d0c67455dc | ||
|
|
62906b0269 | ||
| 99bc7629e7 | |||
|
|
d95c850b7b | ||
| 1f7dae4f11 | |||
| 1d7e4e2eef | |||
|
|
fe50b1595e | ||
|
|
0e5a259d14 | ||
|
|
bfb2728f8d | ||
|
|
7bec3d5c3b | ||
|
|
145c29d7d6 | ||
|
|
8ba7b73aa8 | ||
|
|
1e4deea130 | ||
|
|
3923e2e4b9 | ||
|
|
9e29b76fbc | ||
|
|
88e025f1c6 | ||
|
|
772d3b3288 | ||
|
|
dfa2b73966 | ||
|
|
056b015e78 | ||
| 6649372f7b | |||
| 5db68dab25 | |||
|
|
c59c704da3 | ||
|
|
a2200b4042 | ||
|
|
c858706d48 | ||
|
|
724440dcb7 | ||
|
|
2f594dac0a | ||
|
|
939b81385e | ||
|
|
84b69b935b | ||
| a6e84552da | |||
| 015df38328 | |||
| db85277f26 | |||
| 679aaec6d4 | |||
| deeb6376f7 | |||
| 103fc28bc6 | |||
| 79c85ed2e5 | |||
| 38358e431d | |||
| 5319387030 | |||
| 405e04bd3e | |||
| 7535a48ec4 | |||
| 1c309a0ca8 | |||
| 2d7735b4c1 | |||
| 69414c5dc5 | |||
| c28d6f92cf | |||
| 224feda4ad | |||
| 67e5598b2e | |||
| 7431746ef0 | |||
| 044983330c | |||
| d60db282ea | |||
| 2a5a645ace | |||
| 434ae797a4 |
11
.gitea/runner/cleanup.service
Normal file
@@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=Kindred Create CI runner disk cleanup
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/opt/runner/cleanup.sh
|
||||
Environment=CLEANUP_THRESHOLD=85
|
||||
Environment=CACHE_MAX_AGE_DAYS=7
|
||||
StandardOutput=append:/var/log/runner-cleanup.log
|
||||
StandardError=append:/var/log/runner-cleanup.log
|
||||
220
.gitea/runner/cleanup.sh
Executable file
@@ -0,0 +1,220 @@
|
||||
#!/usr/bin/env bash
|
||||
# Runner disk cleanup script for Kindred Create CI/CD
|
||||
#
|
||||
# Designed to run as a cron job on the pubworker host:
|
||||
# */30 * * * * /path/to/cleanup.sh >> /var/log/runner-cleanup.log 2>&1
|
||||
#
|
||||
# Or install the systemd timer (see cleanup.timer / cleanup.service).
|
||||
#
|
||||
# What it cleans:
|
||||
# 1. Docker: stopped containers, dangling images, build cache
|
||||
# 2. act_runner action cache: keeps only the newest entry per key prefix
|
||||
# 3. act_runner workspaces: removes leftover build workspaces
|
||||
# 4. System: apt cache, old logs
|
||||
#
|
||||
# What it preserves:
|
||||
# - The current runner container and its image
|
||||
# - The most recent cache entry per prefix (so ccache hits still work)
|
||||
# - Everything outside of known CI paths
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Configuration -- adjust these to match your runner setup
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Disk usage threshold (percent) -- only run aggressive cleanup above this
|
||||
THRESHOLD=${CLEANUP_THRESHOLD:-85}
|
||||
|
||||
# act_runner cache directory (default location)
|
||||
CACHE_DIR=${CACHE_DIR:-/root/.cache/actcache}
|
||||
|
||||
# act_runner workspace directories
|
||||
WORKSPACES=(
|
||||
"/root/.cache/act"
|
||||
"/workspace"
|
||||
)
|
||||
|
||||
# Maximum age (days) for cache entries before unconditional deletion
|
||||
CACHE_MAX_AGE_DAYS=${CACHE_MAX_AGE_DAYS:-7}
|
||||
|
||||
# Maximum age (days) for Docker images not used by running containers
|
||||
DOCKER_IMAGE_MAX_AGE=${DOCKER_IMAGE_MAX_AGE:-48h}
|
||||
|
||||
# Log prefix
|
||||
LOG_PREFIX="[runner-cleanup]"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
log() { echo "$(date '+%Y-%m-%d %H:%M:%S') ${LOG_PREFIX} $*"; }
|
||||
|
||||
disk_usage_pct() {
|
||||
df --output=pcent / | tail -1 | tr -dc '0-9'
|
||||
}
|
||||
|
||||
bytes_to_human() {
|
||||
numfmt --to=iec-i --suffix=B "$1" 2>/dev/null || echo "${1}B"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 1: Check if cleanup is needed
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
usage=$(disk_usage_pct)
|
||||
log "Disk usage: ${usage}% (threshold: ${THRESHOLD}%)"
|
||||
|
||||
if [ "$usage" -lt "$THRESHOLD" ]; then
|
||||
log "Below threshold, running light cleanup only"
|
||||
AGGRESSIVE=false
|
||||
else
|
||||
log "Above threshold, running aggressive cleanup"
|
||||
AGGRESSIVE=true
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 2: Docker cleanup (always runs, safe)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
log "--- Docker cleanup ---"
|
||||
|
||||
# Remove stopped containers
|
||||
stopped=$(docker ps -aq --filter status=exited --filter status=dead 2>/dev/null | wc -l)
|
||||
if [ "$stopped" -gt 0 ]; then
|
||||
docker rm $(docker ps -aq --filter status=exited --filter status=dead) 2>/dev/null || true
|
||||
log "Removed ${stopped} stopped containers"
|
||||
fi
|
||||
|
||||
# Remove dangling images (untagged layers)
|
||||
dangling=$(docker images -q --filter dangling=true 2>/dev/null | wc -l)
|
||||
if [ "$dangling" -gt 0 ]; then
|
||||
docker rmi $(docker images -q --filter dangling=true) 2>/dev/null || true
|
||||
log "Removed ${dangling} dangling images"
|
||||
fi
|
||||
|
||||
# Prune build cache
|
||||
docker builder prune -f --filter "until=${DOCKER_IMAGE_MAX_AGE}" 2>/dev/null || true
|
||||
log "Pruned Docker build cache older than ${DOCKER_IMAGE_MAX_AGE}"
|
||||
|
||||
if [ "$AGGRESSIVE" = true ]; then
|
||||
# Remove all images not used by running containers
|
||||
running_images=$(docker ps -q 2>/dev/null | xargs -r docker inspect --format='{{.Image}}' | sort -u)
|
||||
all_images=$(docker images -q 2>/dev/null | sort -u)
|
||||
for img in $all_images; do
|
||||
if ! echo "$running_images" | grep -q "$img"; then
|
||||
docker rmi -f "$img" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
log "Removed unused Docker images (aggressive)"
|
||||
|
||||
# Prune volumes
|
||||
docker volume prune -f 2>/dev/null || true
|
||||
log "Pruned unused Docker volumes"
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 3: act_runner action cache cleanup
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
log "--- Action cache cleanup ---"
|
||||
|
||||
if [ -d "$CACHE_DIR" ]; then
|
||||
before=$(du -sb "$CACHE_DIR" 2>/dev/null | cut -f1)
|
||||
|
||||
# Delete cache entries older than max age
|
||||
find "$CACHE_DIR" -type f -mtime "+${CACHE_MAX_AGE_DAYS}" -delete 2>/dev/null || true
|
||||
find "$CACHE_DIR" -type d -empty -delete 2>/dev/null || true
|
||||
|
||||
after=$(du -sb "$CACHE_DIR" 2>/dev/null | cut -f1)
|
||||
freed=$((before - after))
|
||||
log "Cache cleanup freed $(bytes_to_human $freed) (entries older than ${CACHE_MAX_AGE_DAYS}d)"
|
||||
else
|
||||
log "Cache directory not found: ${CACHE_DIR}"
|
||||
|
||||
# Try common alternative locations
|
||||
for alt in /var/lib/act_runner/.cache/actcache /home/*/.cache/actcache; do
|
||||
if [ -d "$alt" ]; then
|
||||
log "Found cache at: $alt (update CACHE_DIR config)"
|
||||
CACHE_DIR="$alt"
|
||||
find "$CACHE_DIR" -type f -mtime "+${CACHE_MAX_AGE_DAYS}" -delete 2>/dev/null || true
|
||||
find "$CACHE_DIR" -type d -empty -delete 2>/dev/null || true
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 4: Workspace cleanup
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
log "--- Workspace cleanup ---"
|
||||
|
||||
for ws in "${WORKSPACES[@]}"; do
|
||||
if [ -d "$ws" ]; then
|
||||
# Remove workspace dirs not modified in the last 2 hours
|
||||
# (active builds should be touching files continuously)
|
||||
before=$(du -sb "$ws" 2>/dev/null | cut -f1)
|
||||
find "$ws" -mindepth 1 -maxdepth 1 -type d -mmin +120 -exec rm -rf {} + 2>/dev/null || true
|
||||
after=$(du -sb "$ws" 2>/dev/null | cut -f1)
|
||||
freed=$((before - after))
|
||||
if [ "$freed" -gt 0 ]; then
|
||||
log "Workspace $ws: freed $(bytes_to_human $freed)"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 5: System cleanup
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
log "--- System cleanup ---"
|
||||
|
||||
# apt cache
|
||||
apt-get clean 2>/dev/null || true
|
||||
|
||||
# Truncate large log files (keep last 1000 lines)
|
||||
for logfile in /var/log/syslog /var/log/daemon.log /var/log/kern.log; do
|
||||
if [ -f "$logfile" ] && [ "$(stat -c%s "$logfile" 2>/dev/null)" -gt 104857600 ]; then
|
||||
tail -1000 "$logfile" > "${logfile}.tmp" && mv "${logfile}.tmp" "$logfile"
|
||||
log "Truncated $logfile (was >100MB)"
|
||||
fi
|
||||
done
|
||||
|
||||
# Journal logs older than 3 days
|
||||
journalctl --vacuum-time=3d 2>/dev/null || true
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 6: Emergency cleanup (only if still critical)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
usage=$(disk_usage_pct)
|
||||
if [ "$usage" -gt 95 ]; then
|
||||
log "CRITICAL: Still at ${usage}% after cleanup"
|
||||
|
||||
# Nuclear option: remove ALL docker data except running containers
|
||||
docker system prune -af --volumes 2>/dev/null || true
|
||||
log "Ran docker system prune -af --volumes"
|
||||
|
||||
# Clear entire action cache
|
||||
if [ -d "$CACHE_DIR" ]; then
|
||||
rm -rf "${CACHE_DIR:?}/"*
|
||||
log "Cleared entire action cache"
|
||||
fi
|
||||
|
||||
usage=$(disk_usage_pct)
|
||||
log "After emergency cleanup: ${usage}%"
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Summary
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
usage=$(disk_usage_pct)
|
||||
log "Cleanup complete. Disk usage: ${usage}%"
|
||||
|
||||
# Report top space consumers for diagnostics
|
||||
log "Top 10 directories under /var:"
|
||||
du -sh /var/*/ 2>/dev/null | sort -rh | head -10 | while read -r line; do
|
||||
log " $line"
|
||||
done
|
||||
10
.gitea/runner/cleanup.timer
Normal file
@@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Run CI runner cleanup every 30 minutes
|
||||
|
||||
[Timer]
|
||||
OnBootSec=5min
|
||||
OnUnitActiveSec=30min
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
@@ -22,6 +22,17 @@ jobs:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
|
||||
steps:
|
||||
- name: Free disk space
|
||||
run: |
|
||||
echo "=== Disk usage before cleanup ==="
|
||||
df -h /
|
||||
rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache 2>/dev/null || true
|
||||
rm -rf /usr/local/share/boost /usr/share/swift 2>/dev/null || true
|
||||
apt-get autoremove -y 2>/dev/null || true
|
||||
apt-get clean 2>/dev/null || true
|
||||
echo "=== Disk usage after cleanup ==="
|
||||
df -h /
|
||||
|
||||
- name: Install system prerequisites
|
||||
run: |
|
||||
apt-get update -qq
|
||||
@@ -36,8 +47,12 @@ jobs:
|
||||
submodules: recursive
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Fetch tags (for git describe)
|
||||
run: git fetch --tags --no-recurse-submodules origin
|
||||
- name: Fetch latest tag (for git describe)
|
||||
run: |
|
||||
latest_tag=$(git ls-remote --tags --sort=-v:refname origin 'refs/tags/v*' | grep -v '\^{}' | head -n1 | awk '{print $2}')
|
||||
if [ -n "$latest_tag" ]; then
|
||||
git fetch --no-recurse-submodules --force --depth=1 origin "+${latest_tag}:${latest_tag}"
|
||||
fi
|
||||
|
||||
- name: Install pixi
|
||||
run: |
|
||||
@@ -46,12 +61,16 @@ jobs:
|
||||
export PATH="$HOME/.pixi/bin:$PATH"
|
||||
pixi --version
|
||||
|
||||
- name: Compute cache date key
|
||||
id: cache-date
|
||||
run: echo "date=$(date -u +%Y%m%d)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Restore ccache
|
||||
id: ccache-restore
|
||||
uses: https://github.com/actions/cache/restore@v4
|
||||
with:
|
||||
path: /tmp/ccache-kindred-create
|
||||
key: ccache-build-${{ github.ref_name }}-${{ github.sha }}
|
||||
key: ccache-build-${{ github.ref_name }}-${{ steps.cache-date.outputs.date }}
|
||||
restore-keys: |
|
||||
ccache-build-${{ github.ref_name }}-
|
||||
ccache-build-main-
|
||||
@@ -60,6 +79,7 @@ jobs:
|
||||
run: |
|
||||
mkdir -p $CCACHE_DIR
|
||||
pixi run ccache -z
|
||||
pixi run ccache -p
|
||||
|
||||
- name: Configure (CMake)
|
||||
run: pixi run cmake --preset conda-linux-release
|
||||
@@ -71,11 +91,11 @@ jobs:
|
||||
run: pixi run ccache -s
|
||||
|
||||
- name: Save ccache
|
||||
if: always()
|
||||
if: always() && steps.ccache-restore.outputs.cache-hit != 'true'
|
||||
uses: https://github.com/actions/cache/save@v4
|
||||
with:
|
||||
path: /tmp/ccache-kindred-create
|
||||
key: ccache-build-${{ github.ref_name }}-${{ github.sha }}
|
||||
key: ccache-build-${{ github.ref_name }}-${{ steps.cache-date.outputs.date }}
|
||||
|
||||
- name: Run C++ unit tests
|
||||
continue-on-error: true
|
||||
|
||||
22
.gitea/workflows/docs.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
name: Deploy Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: docs
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- 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,7 +3,7 @@ name: Release Build
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ["v*"]
|
||||
tags: ["v*", "latest"]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
@@ -31,6 +31,18 @@ jobs:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
|
||||
steps:
|
||||
- name: Free disk space
|
||||
run: |
|
||||
echo "=== Disk usage before cleanup ==="
|
||||
df -h /
|
||||
# Remove pre-installed bloat common in runner images
|
||||
rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache 2>/dev/null || true
|
||||
rm -rf /usr/local/share/boost /usr/share/swift 2>/dev/null || true
|
||||
apt-get autoremove -y 2>/dev/null || true
|
||||
apt-get clean 2>/dev/null || true
|
||||
echo "=== Disk usage after cleanup ==="
|
||||
df -h /
|
||||
|
||||
- name: Install system prerequisites
|
||||
run: |
|
||||
apt-get update -qq
|
||||
@@ -45,8 +57,12 @@ jobs:
|
||||
submodules: recursive
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Fetch tags
|
||||
run: git fetch --tags --no-recurse-submodules origin
|
||||
- name: Fetch latest tag (for git describe)
|
||||
run: |
|
||||
latest_tag=$(git ls-remote --tags --sort=-v:refname origin 'refs/tags/v*' | grep -v '\^{}' | head -n1 | awk '{print $2}')
|
||||
if [ -n "$latest_tag" ]; then
|
||||
git fetch --no-recurse-submodules --force --depth=1 origin "+${latest_tag}:${latest_tag}"
|
||||
fi
|
||||
|
||||
- name: Install pixi
|
||||
run: |
|
||||
@@ -55,20 +71,26 @@ jobs:
|
||||
export PATH="$HOME/.pixi/bin:$PATH"
|
||||
pixi --version
|
||||
|
||||
- name: Compute cache date key
|
||||
id: cache-date
|
||||
run: echo "date=$(date -u +%Y%m%d)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Restore ccache
|
||||
id: ccache-restore
|
||||
uses: https://github.com/actions/cache/restore@v4
|
||||
with:
|
||||
path: /tmp/ccache-kindred-create
|
||||
key: ccache-release-linux-${{ github.sha }}
|
||||
key: ccache-release-linux-${{ steps.cache-date.outputs.date }}
|
||||
restore-keys: |
|
||||
ccache-release-linux-
|
||||
ccache-build-main-
|
||||
|
||||
- name: Prepare ccache
|
||||
run: |
|
||||
mkdir -p $CCACHE_DIR
|
||||
# Ensure ccache is accessible to rattler-build's subprocess
|
||||
export PATH="$(pixi run bash -c 'echo $PATH')"
|
||||
pixi run ccache -z
|
||||
pixi run ccache -p
|
||||
|
||||
- name: Build release package (AppImage)
|
||||
working-directory: package/rattler-build
|
||||
@@ -80,11 +102,19 @@ jobs:
|
||||
run: pixi run ccache -s
|
||||
|
||||
- name: Save ccache
|
||||
if: always()
|
||||
if: always() && steps.ccache-restore.outputs.cache-hit != 'true'
|
||||
uses: https://github.com/actions/cache/save@v4
|
||||
with:
|
||||
path: /tmp/ccache-kindred-create
|
||||
key: ccache-release-linux-${{ github.sha }}
|
||||
key: ccache-release-linux-${{ steps.cache-date.outputs.date }}
|
||||
|
||||
- name: Clean up intermediate build files
|
||||
run: |
|
||||
# Remove pixi package cache and build work dirs to free space for .deb
|
||||
rm -rf package/rattler-build/.pixi/build 2>/dev/null || true
|
||||
find /root/.cache/rattler -type f -delete 2>/dev/null || true
|
||||
echo "=== Disk usage after cleanup ==="
|
||||
df -h /
|
||||
|
||||
- name: Build .deb package
|
||||
run: |
|
||||
@@ -105,7 +135,7 @@ jobs:
|
||||
with:
|
||||
name: release-linux
|
||||
path: |
|
||||
package/rattler-build/linux/*.AppImage
|
||||
package/rattler-build/linux/FreeCAD_*.AppImage
|
||||
package/rattler-build/linux/*.deb
|
||||
package/rattler-build/linux/*-SHA256.txt
|
||||
package/rattler-build/linux/*.sha256
|
||||
@@ -113,174 +143,176 @@ jobs:
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# macOS: DMG (Intel + Apple Silicon)
|
||||
# TODO: Re-enable when macOS runners are available or cross-compilation is set up
|
||||
# ---------------------------------------------------------------------------
|
||||
build-macos:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: macos-13
|
||||
arch: x86_64
|
||||
- runner: macos-14
|
||||
arch: arm64
|
||||
|
||||
runs-on: ${{ matrix.runner }}
|
||||
|
||||
env:
|
||||
CCACHE_DIR: /tmp/ccache-kindred-create
|
||||
CCACHE_COMPRESS: "true"
|
||||
CCACHE_COMPRESSLEVEL: "6"
|
||||
CCACHE_MAXSIZE: "4G"
|
||||
CCACHE_SLOPPINESS: "include_file_ctime,include_file_mtime,pch_defines,time_macros"
|
||||
CCACHE_BASEDIR: ${{ github.workspace }}
|
||||
BUILD_TAG: ${{ github.ref_name || inputs.tag }}
|
||||
CFLAGS: "-O3"
|
||||
CXXFLAGS: "-O3"
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: https://github.com/actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Fetch tags
|
||||
run: git fetch --tags --no-recurse-submodules origin
|
||||
|
||||
- name: Install pixi
|
||||
run: |
|
||||
curl -fsSL https://pixi.sh/install.sh | bash
|
||||
echo "$HOME/.pixi/bin" >> $GITHUB_PATH
|
||||
export PATH="$HOME/.pixi/bin:$PATH"
|
||||
pixi --version
|
||||
|
||||
- name: Restore ccache
|
||||
id: ccache-restore
|
||||
uses: https://github.com/actions/cache/restore@v4
|
||||
with:
|
||||
path: /tmp/ccache-kindred-create
|
||||
key: ccache-release-macos-${{ matrix.arch }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-release-macos-${{ matrix.arch }}-
|
||||
|
||||
- name: Prepare ccache
|
||||
run: |
|
||||
mkdir -p $CCACHE_DIR
|
||||
pixi run ccache -z
|
||||
|
||||
- name: Build release package (DMG)
|
||||
working-directory: package/rattler-build
|
||||
run: |
|
||||
pixi install
|
||||
pixi run -e package create_bundle
|
||||
|
||||
- name: Show ccache statistics
|
||||
run: pixi run ccache -s
|
||||
|
||||
- name: Save ccache
|
||||
if: always()
|
||||
uses: https://github.com/actions/cache/save@v4
|
||||
with:
|
||||
path: /tmp/ccache-kindred-create
|
||||
key: ccache-release-macos-${{ matrix.arch }}-${{ github.sha }}
|
||||
|
||||
- name: List built artifacts
|
||||
run: |
|
||||
echo "=== macOS ${{ matrix.arch }} release artifacts ==="
|
||||
ls -lah package/rattler-build/osx/*.dmg* 2>/dev/null || true
|
||||
|
||||
- name: Upload macOS artifacts
|
||||
uses: https://github.com/actions/upload-artifact@v3
|
||||
with:
|
||||
name: release-macos-${{ matrix.arch }}
|
||||
path: |
|
||||
package/rattler-build/osx/*.dmg
|
||||
package/rattler-build/osx/*-SHA256.txt
|
||||
if-no-files-found: error
|
||||
# build-macos:
|
||||
# strategy:
|
||||
# fail-fast: false
|
||||
# matrix:
|
||||
# include:
|
||||
# - runner: macos-13
|
||||
# arch: x86_64
|
||||
# - runner: macos-14
|
||||
# arch: arm64
|
||||
#
|
||||
# runs-on: ${{ matrix.runner }}
|
||||
#
|
||||
# env:
|
||||
# CCACHE_DIR: /tmp/ccache-kindred-create
|
||||
# CCACHE_COMPRESS: "true"
|
||||
# CCACHE_COMPRESSLEVEL: "6"
|
||||
# CCACHE_MAXSIZE: "4G"
|
||||
# CCACHE_SLOPPINESS: "include_file_ctime,include_file_mtime,pch_defines,time_macros"
|
||||
# CCACHE_BASEDIR: ${{ github.workspace }}
|
||||
# BUILD_TAG: ${{ github.ref_name || inputs.tag }}
|
||||
# CFLAGS: "-O3"
|
||||
# CXXFLAGS: "-O3"
|
||||
#
|
||||
# steps:
|
||||
# - name: Checkout repository
|
||||
# uses: https://github.com/actions/checkout@v4
|
||||
# with:
|
||||
# submodules: recursive
|
||||
# fetch-depth: 1
|
||||
#
|
||||
# - name: Fetch tags
|
||||
# run: git fetch --tags --force --no-recurse-submodules origin
|
||||
#
|
||||
# - name: Install pixi
|
||||
# run: |
|
||||
# curl -fsSL https://pixi.sh/install.sh | bash
|
||||
# echo "$HOME/.pixi/bin" >> $GITHUB_PATH
|
||||
# export PATH="$HOME/.pixi/bin:$PATH"
|
||||
# pixi --version
|
||||
#
|
||||
# - name: Restore ccache
|
||||
# id: ccache-restore
|
||||
# uses: https://github.com/actions/cache/restore@v4
|
||||
# with:
|
||||
# path: /tmp/ccache-kindred-create
|
||||
# key: ccache-release-macos-${{ matrix.arch }}-${{ github.sha }}
|
||||
# restore-keys: |
|
||||
# ccache-release-macos-${{ matrix.arch }}-
|
||||
#
|
||||
# - name: Prepare ccache
|
||||
# run: |
|
||||
# mkdir -p $CCACHE_DIR
|
||||
# pixi run ccache -z
|
||||
#
|
||||
# - name: Build release package (DMG)
|
||||
# working-directory: package/rattler-build
|
||||
# run: |
|
||||
# pixi install
|
||||
# pixi run -e package create_bundle
|
||||
#
|
||||
# - name: Show ccache statistics
|
||||
# run: pixi run ccache -s
|
||||
#
|
||||
# - name: Save ccache
|
||||
# if: always()
|
||||
# uses: https://github.com/actions/cache/save@v4
|
||||
# with:
|
||||
# path: /tmp/ccache-kindred-create
|
||||
# key: ccache-release-macos-${{ matrix.arch }}-${{ github.sha }}
|
||||
#
|
||||
# - name: List built artifacts
|
||||
# run: |
|
||||
# echo "=== macOS ${{ matrix.arch }} release artifacts ==="
|
||||
# ls -lah package/rattler-build/osx/*.dmg* 2>/dev/null || true
|
||||
#
|
||||
# - name: Upload macOS artifacts
|
||||
# uses: https://github.com/actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: release-macos-${{ matrix.arch }}
|
||||
# path: |
|
||||
# package/rattler-build/osx/*.dmg
|
||||
# package/rattler-build/osx/*-SHA256.txt
|
||||
# if-no-files-found: error
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Windows: .exe installer + .7z archive
|
||||
# TODO: Re-enable when Windows runners are available or cross-compilation is set up
|
||||
# ---------------------------------------------------------------------------
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
|
||||
env:
|
||||
CCACHE_DIR: C:\ccache-kindred-create
|
||||
CCACHE_COMPRESS: "true"
|
||||
CCACHE_COMPRESSLEVEL: "6"
|
||||
CCACHE_MAXSIZE: "4G"
|
||||
CCACHE_SLOPPINESS: "include_file_ctime,include_file_mtime,pch_defines,time_macros"
|
||||
CCACHE_BASEDIR: ${{ github.workspace }}
|
||||
BUILD_TAG: ${{ github.ref_name || inputs.tag }}
|
||||
CFLAGS: "/O2"
|
||||
CXXFLAGS: "/O2"
|
||||
MAKE_INSTALLER: "true"
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: https://github.com/actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Fetch tags
|
||||
shell: bash
|
||||
run: git fetch --tags --no-recurse-submodules origin
|
||||
|
||||
- name: Install pixi
|
||||
shell: bash
|
||||
run: |
|
||||
curl -fsSL https://pixi.sh/install.sh | bash
|
||||
echo "$HOME/.pixi/bin" >> $GITHUB_PATH
|
||||
export PATH="$HOME/.pixi/bin:$PATH"
|
||||
pixi --version
|
||||
|
||||
- name: Restore ccache
|
||||
id: ccache-restore
|
||||
uses: https://github.com/actions/cache/restore@v4
|
||||
with:
|
||||
path: C:\ccache-kindred-create
|
||||
key: ccache-release-windows-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-release-windows-
|
||||
|
||||
- name: Build release package
|
||||
shell: bash
|
||||
working-directory: package/rattler-build
|
||||
run: |
|
||||
pixi install
|
||||
pixi run -e package create_bundle
|
||||
|
||||
- name: Save ccache
|
||||
if: always()
|
||||
uses: https://github.com/actions/cache/save@v4
|
||||
with:
|
||||
path: C:\ccache-kindred-create
|
||||
key: ccache-release-windows-${{ github.sha }}
|
||||
|
||||
- name: List built artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
echo "=== Windows release artifacts ==="
|
||||
ls -lah package/rattler-build/windows/*.7z* 2>/dev/null || true
|
||||
ls -lah package/rattler-build/windows/*.exe 2>/dev/null || true
|
||||
ls -lah package/rattler-build/windows/*-SHA256.txt 2>/dev/null || true
|
||||
|
||||
- name: Upload Windows artifacts
|
||||
uses: https://github.com/actions/upload-artifact@v3
|
||||
with:
|
||||
name: release-windows
|
||||
path: |
|
||||
package/rattler-build/windows/*.7z
|
||||
package/rattler-build/windows/*.exe
|
||||
package/rattler-build/windows/*-SHA256.txt
|
||||
if-no-files-found: error
|
||||
# build-windows:
|
||||
# runs-on: windows-latest
|
||||
#
|
||||
# env:
|
||||
# CCACHE_DIR: C:\ccache-kindred-create
|
||||
# CCACHE_COMPRESS: "true"
|
||||
# CCACHE_COMPRESSLEVEL: "6"
|
||||
# CCACHE_MAXSIZE: "4G"
|
||||
# CCACHE_SLOPPINESS: "include_file_ctime,include_file_mtime,pch_defines,time_macros"
|
||||
# CCACHE_BASEDIR: ${{ github.workspace }}
|
||||
# BUILD_TAG: ${{ github.ref_name || inputs.tag }}
|
||||
# CFLAGS: "/O2"
|
||||
# CXXFLAGS: "/O2"
|
||||
# MAKE_INSTALLER: "true"
|
||||
#
|
||||
# steps:
|
||||
# - name: Checkout repository
|
||||
# uses: https://github.com/actions/checkout@v4
|
||||
# with:
|
||||
# submodules: recursive
|
||||
# fetch-depth: 1
|
||||
#
|
||||
# - name: Fetch tags
|
||||
# shell: bash
|
||||
# run: git fetch --tags --force --no-recurse-submodules origin
|
||||
#
|
||||
# - name: Install pixi
|
||||
# shell: bash
|
||||
# run: |
|
||||
# curl -fsSL https://pixi.sh/install.sh | bash
|
||||
# echo "$HOME/.pixi/bin" >> $GITHUB_PATH
|
||||
# export PATH="$HOME/.pixi/bin:$PATH"
|
||||
# pixi --version
|
||||
#
|
||||
# - name: Restore ccache
|
||||
# id: ccache-restore
|
||||
# uses: https://github.com/actions/cache/restore@v4
|
||||
# with:
|
||||
# path: C:\ccache-kindred-create
|
||||
# key: ccache-release-windows-${{ github.sha }}
|
||||
# restore-keys: |
|
||||
# ccache-release-windows-
|
||||
#
|
||||
# - name: Build release package
|
||||
# shell: bash
|
||||
# working-directory: package/rattler-build
|
||||
# run: |
|
||||
# pixi install
|
||||
# pixi run -e package create_bundle
|
||||
#
|
||||
# - name: Save ccache
|
||||
# if: always()
|
||||
# uses: https://github.com/actions/cache/save@v4
|
||||
# with:
|
||||
# path: C:\ccache-kindred-create
|
||||
# key: ccache-release-windows-${{ github.sha }}
|
||||
#
|
||||
# - name: List built artifacts
|
||||
# shell: bash
|
||||
# run: |
|
||||
# echo "=== Windows release artifacts ==="
|
||||
# ls -lah package/rattler-build/windows/*.7z* 2>/dev/null || true
|
||||
# ls -lah package/rattler-build/windows/*.exe 2>/dev/null || true
|
||||
# ls -lah package/rattler-build/windows/*-SHA256.txt 2>/dev/null || true
|
||||
#
|
||||
# - name: Upload Windows artifacts
|
||||
# uses: https://github.com/actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: release-windows
|
||||
# path: |
|
||||
# package/rattler-build/windows/*.7z
|
||||
# package/rattler-build/windows/*.exe
|
||||
# package/rattler-build/windows/*-SHA256.txt
|
||||
# if-no-files-found: error
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Create Gitea release from all platform artifacts
|
||||
# ---------------------------------------------------------------------------
|
||||
publish-release:
|
||||
needs: [build-linux, build-macos, build-windows]
|
||||
needs: [build-linux] # TODO: Add build-macos, build-windows when runners are available
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
@@ -313,24 +345,82 @@ jobs:
|
||||
ls -lah release/
|
||||
|
||||
- name: Create release
|
||||
uses: https://gitea.com/actions/release-action@main
|
||||
with:
|
||||
files: release/*
|
||||
title: "Kindred Create ${{ env.BUILD_TAG }}"
|
||||
body: |
|
||||
## Kindred Create ${{ env.BUILD_TAG }}
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
GITEA_URL: ${{ github.server_url }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: |
|
||||
TAG="${BUILD_TAG}"
|
||||
|
||||
### Downloads
|
||||
# Build JSON payload entirely in Python to avoid shell/Python type mismatches
|
||||
PAYLOAD=$(python3 -c "
|
||||
import json, re
|
||||
tag = '${TAG}'
|
||||
prerelease = bool(re.search(r'(rc|beta|alpha)', tag))
|
||||
body = '''## Kindred Create {tag}
|
||||
|
||||
| Platform | File |
|
||||
|----------|------|
|
||||
| Linux (AppImage) | `KindredCreate-*-Linux-x86_64.AppImage` |
|
||||
| Linux (Debian/Ubuntu) | `kindred-create_*.deb` |
|
||||
| macOS (Intel) | `KindredCreate-*-macOS-x86_64.dmg` |
|
||||
| macOS (Apple Silicon) | `KindredCreate-*-macOS-arm64.dmg` |
|
||||
| Windows (Installer) | `KindredCreate-*-Windows-x86_64-installer.exe` |
|
||||
| Windows (Portable) | `KindredCreate-*-Windows-x86_64.7z` |
|
||||
### Downloads
|
||||
|
||||
SHA256 checksums are provided alongside each artifact.
|
||||
prerelease: ${{ contains(github.ref_name, 'rc') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'alpha') }}
|
||||
api_key: ${{ secrets.RELEASE_TOKEN }}
|
||||
| Platform | File |
|
||||
|----------|------|
|
||||
| Linux (AppImage) | \`KindredCreate-*-Linux-x86_64.AppImage\` |
|
||||
| Linux (Debian/Ubuntu) | \`kindred-create_*.deb\` |
|
||||
|
||||
*macOS and Windows builds are not yet available.*
|
||||
|
||||
SHA256 checksums are provided alongside each artifact.'''.format(tag=tag)
|
||||
print(json.dumps({
|
||||
'tag_name': tag,
|
||||
'name': f'Kindred Create {tag}',
|
||||
'body': body,
|
||||
'prerelease': prerelease,
|
||||
}))
|
||||
")
|
||||
|
||||
# Delete existing release for this tag (if any) so we can recreate
|
||||
existing=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${GITEA_URL}/api/v1/repos/${REPO}/releases/tags/${TAG}")
|
||||
if [ "$existing" = "200" ]; then
|
||||
release_id=$(curl -s \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${GITEA_URL}/api/v1/repos/${REPO}/releases/tags/${TAG}" | \
|
||||
python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
|
||||
curl -s -X DELETE \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${GITEA_URL}/api/v1/repos/${REPO}/releases/${release_id}"
|
||||
echo "Deleted existing release ${release_id} for tag ${TAG}"
|
||||
fi
|
||||
|
||||
# Create release
|
||||
response=$(curl -s -w "\n%{http_code}" -X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$PAYLOAD" \
|
||||
"${GITEA_URL}/api/v1/repos/${REPO}/releases")
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
body=$(echo "$response" | sed '$d')
|
||||
|
||||
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
|
||||
echo "::error::Failed to create release (HTTP ${http_code}): ${body}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
release_id=$(echo "$body" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
|
||||
echo "Created release ${release_id}"
|
||||
|
||||
# Upload assets
|
||||
for file in release/*; do
|
||||
filename=$(basename "$file")
|
||||
echo "Uploading ${filename}..."
|
||||
upload_resp=$(curl -s -w "\n%{http_code}" -X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-F "attachment=@${file}" \
|
||||
"${GITEA_URL}/api/v1/repos/${REPO}/releases/${release_id}/assets?name=${filename}")
|
||||
upload_code=$(echo "$upload_resp" | tail -1)
|
||||
if [ "$upload_code" -lt 200 ] || [ "$upload_code" -ge 300 ]; then
|
||||
echo "::warning::Failed to upload ${filename} (HTTP ${upload_code})"
|
||||
else
|
||||
echo " done."
|
||||
fi
|
||||
done
|
||||
|
||||
3
.gitignore
vendored
@@ -71,3 +71,6 @@ files_to_translate.txt
|
||||
# pixi environments
|
||||
.pixi
|
||||
*.egg-info
|
||||
|
||||
# mdBook build output
|
||||
docs/book/
|
||||
|
||||
2
.gitmodules
vendored
@@ -15,4 +15,4 @@
|
||||
url = https://git.kindred-systems.com/forbes/ztools.git
|
||||
[submodule "mods/silo"]
|
||||
path = mods/silo
|
||||
url = https://git.kindred-systems.com/kindred/silo.git
|
||||
url = https://git.kindred-systems.com/kindred/silo-mod.git
|
||||
|
||||
200
CONTRIBUTING.md
@@ -1,111 +1,131 @@
|
||||
# FreeCAD Contribution Process (FCP)
|
||||
# Contributing to Kindred Create
|
||||
|
||||
FreeCAD's contribution process is inspired by the Collective Code Construction Contract which itself is an evolution of the github.com Fork and Pull Model.
|
||||
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.
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
|
||||
## 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
|
||||
```
|
||||
|
||||
## 0. Status
|
||||
See the [README](README.md) for full build instructions.
|
||||
|
||||
FreeCAD is in a transition period. The following are to be regarded as GUIDELINES for contribution submission and acceptance. For historical reasons, the actual process MAY diverge from this process during the transition. Such deviations SHOULD be noted and discussed whenever possible.
|
||||
## Branch and PR workflow
|
||||
|
||||
## 1. Goals
|
||||
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.
|
||||
|
||||
The FreeCAD Contribution Process is expressed here with the following specific goals in mind:
|
||||
## Commit messages
|
||||
|
||||
1. To provide transparency and fairness in the contribution process.
|
||||
2. To allow contributions to be included as quickly as possible.
|
||||
3. To preserve and improve the code quality while encouraging appropriate experimentation and risk-taking.
|
||||
4. To minimize dependence on individual Contributors by encouraging a large pool of active Contributors.
|
||||
5. To be inclusive of many viewpoints and to harness a diverse set of skills.
|
||||
6. To provide an encouraging environment where Contributors learn and improve their skills.
|
||||
7. To protect the free and open nature of the FreeCAD project.
|
||||
Use [Conventional Commits](https://www.conventionalcommits.org/):
|
||||
|
||||
## 2. Fundamentals
|
||||
| Prefix | Purpose |
|
||||
|--------|---------|
|
||||
| `feat:` | New feature |
|
||||
| `fix:` | Bug fix |
|
||||
| `chore:` | Maintenance, dependencies |
|
||||
| `docs:` | Documentation only |
|
||||
| `art:` | Icons, theme, visual assets |
|
||||
|
||||
1. FreeCAD uses the git distributed revision control system.
|
||||
2. Source code for the main application and related subprojects is hosted on github.com in the FreeCAD organization.
|
||||
3. Problems are discrete, well-defined limitations or bugs.
|
||||
4. FreeCAD uses GitHub's issue-tracking system to track problems and contributions. For help requests and general discussions, use the project forum.
|
||||
5. Contributions are sets of code changes that resolve a single problem.
|
||||
6. FreeCAD uses the Pull Request workflow for evaluating and accepting contributions.
|
||||
Examples:
|
||||
- `feat: add datum point creation mode`
|
||||
- `fix(gui): correct menu icon size on Wayland`
|
||||
- `chore: update silo submodule`
|
||||
|
||||
## 3. Roles
|
||||
1. "User": A member of the wider FreeCAD community who uses the software.
|
||||
2. "Contributor": A person who submits a contribution that resolves a previously identified problem. Contributors do not have commit access to the repository unless they are also Maintainers. Everyone, without distinction or discrimination, SHALL have an equal right to become a Contributor.
|
||||
3. "Maintainer": A person who merges contributions. Maintainers may or may not be Contributors. Their role is to enforce the process. Maintainers have commit access to the repository.
|
||||
4. "Administrator": Administrators have additional authority to maintain the list of designated Maintainers.
|
||||
## Code style
|
||||
|
||||
## 4. Licensing, Ownership, and Credit
|
||||
1. FreeCAD is distributed under the Lesser General Public License, version 2, or superior (LGPL2+). Additional details can be found in the LICENSE file.
|
||||
2. All contributions to FreeCAD MUST use a compatible license.
|
||||
3. All contributions are owned by their authors unless assigned to another.
|
||||
4. FreeCAD does not have a mandatory copyright assignment policy.
|
||||
5. A Contributor who wishes to be identified in the Credits section of the application "About" dialog is responsible for identifying themselves. They should modify the Contributors file and submit a PR with a single commit for this modification only. The contributors file is found at https://github.com/FreeCAD/FreeCAD/blob/main/src/Doc/CONTRIBUTORS
|
||||
6. A contributor who does not wish to assume the copyright of their contribution MAY choose to assign it to the [FreeCAD project association](https://fpa.freecad.org) by mentioning **Copyright (c) 2022 The FreeCAD project association <fpa@freecad.org>** in the file's license code block.
|
||||
### C/C++
|
||||
|
||||
## 5. Contribution Requirements
|
||||
Formatted with **clang-format** (config in `.clang-format`). Static analysis via **clang-tidy** (config in `.clang-tidy`).
|
||||
|
||||
1. Contributions are submitted in the form of Pull Requests (PR).
|
||||
2. Maintainers and Contributors MUST have a GitHub account and SHOULD use their real names or a well-known alias.
|
||||
3. If the GitHub username differs from the username on the FreeCAD Forum, effort SHOULD be taken to avoid confusion.
|
||||
4. A PR SHOULD be a minimal and accurate answer to exactly one identified and agreed-on problem.
|
||||
5. A PR SHOULD refrain from adding additional dependencies to the FreeCAD project unless no other option is available.
|
||||
6. Code submissions MUST adhere to the code style guidelines of the project if these are defined.
|
||||
7. If a PR contains multiple commits, each commit MUST compile cleanly when merged with all previous commits of the same PR. Each commit SHOULD add value to the history of the project. Checkpoint commits SHOULD be squashed.
|
||||
8. A PR SHALL NOT include non-trivial code from other projects unless the Contributor is the original author of that code.
|
||||
9. A PR MUST compile cleanly and pass project self-tests on all target platforms.
|
||||
10. Changes that break python API used by extensions SHALL be avoided. If it is not possible to avoid breaking changes, the amount of them MUST be minimized and PR MUST clearly describe all breaking changes with clear description on how to replace no longer working solution with newer one. Contributor SHOULD search for addons that will be broken and list them in the PR.
|
||||
11. Each commit message in a PR MUST succinctly explain what the commit achieves. The commit message SHALL follow the suggestions in the `git commit --help` documentation, section DISCUSSION.
|
||||
12. The PR Title MUST succinctly explain what the PR achieves. The Body MAY be as detailed as needed. If a PR changes the user interface (UI), the body of the text MUST include a presentation of these UI changes, preferably with screenshots of the previous and revised state.
|
||||
13. If a PR contains the work of another author (for example, if it is cherry-picked from a fork by someone other than the PR-submitter):
|
||||
1. the PR description MUST contain proper attribution as the first line, for example: "This is work of XYZ cherry-picked from <link>";
|
||||
2. all commits MUST have proper authorship, i.e. be authored by the original author and committed by the author of the PR;
|
||||
3. if changes to cherry-picked commits are necessary they SHOULD be done as follow-up commits. If it is not possible to do so, then the modified commits MUST contain a `Co-Authored-By` trailer in their commit message.
|
||||
14. A “Valid PR” is one which satisfies the above requirements.
|
||||
### Python
|
||||
|
||||
## 6. Process
|
||||
Formatted with **black** (100-character line length). Linted with **pylint** (config in `.pylintrc`).
|
||||
|
||||
1. Change on the project follows the pattern of accurately identifying problems and applying minimal, accurate solutions to these problems.
|
||||
2. To request changes, a User logs an issue on the project GitHub issue tracker.
|
||||
3. The User or Contributor SHOULD write the issue by describing the problem they face or observe. Links to the forum or other resources are permitted but the issue SHOULD be complete and accurate and SHOULD NOT require the reader to visit the forum or any other platform to understand what is being described.
|
||||
4. Issue authors SHOULD strive to describe the minimum acceptable condition.
|
||||
5. Issue authors SHOULD focus on User tasks and avoid comparisons to other software solutions.
|
||||
6. The User or Contributor SHOULD seek consensus on the accuracy of their observation and the value of solving the problem.
|
||||
7. To submit a solution to a problem, a Contributor SHALL create a pull request back to the project.
|
||||
8. Contributors and Maintainers SHALL NOT commit changes directly to the target branch.
|
||||
9. To discuss a proposed solution, Users MAY comment on the Pull Request in GitHub. Forum conversations regarding the solution SHOULD be discouraged and conversation redirected to the Pull Request or the related issue.
|
||||
10. To accept or reject a Pull Request, a Maintainer SHALL use GitHub's interface.
|
||||
11. Maintainers SHOULD NOT merge their own PRs except:
|
||||
1. in exceptional cases, such as non-responsiveness from other Maintainers for an extended period.
|
||||
2. If the Maintainer is also the primary developer of the workbench or subsystem.
|
||||
### Pre-commit hooks
|
||||
|
||||
12. Maintainers SHALL merge valid PRs from other Contributors rapidly.
|
||||
13. Maintainers MAY, at their discretion merge PRs that have not met all criteria to be considered valid to:
|
||||
1. end fruitless discussions
|
||||
2. capture toxic contributions in the historical record
|
||||
3. engage with the Contributor on improving their contribution quality.
|
||||
14. Maintainers SHALL NOT make value judgments on correct contributions.
|
||||
15. If a PR requires significant further work before merging, the PR SHOULD be moved to draft status.
|
||||
16. If a PR is complete, but should not be merged yet (for example, because it depends on another in-process PR), the "On hold" label SHOULD be applied.
|
||||
17. Any Contributor who has value judgments on a PR SHOULD express these via their own PR.
|
||||
18. The User who created an issue SHOULD close the issue after checking the PR is successful.
|
||||
19. Maintainers SHOULD close issues that are left open without action or update for an unreasonable period.
|
||||
```bash
|
||||
pip install pre-commit
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
## 7. Branches and Releases
|
||||
This runs clang-format, black, and pylint automatically on staged files.
|
||||
|
||||
1. The project SHALL have one branch (“main”) that always holds the latest in-progress version and SHOULD always build.
|
||||
2. The project SHALL NOT use topic branches for any reason. Personal forks MAY use topic branches.
|
||||
3. To make a stable release a Maintainer SHALL tag the repository. Stable releases SHALL always be released from the repository main branch.
|
||||
## Submodules
|
||||
|
||||
## 8. Project Administration
|
||||
Kindred Create uses git submodules for addon workbenches:
|
||||
|
||||
1. Project Administrators are those individuals who are members of the FreeCAD Github organization and have the role of 'owner'. They have the task of administering the organization including adding and removing individuals from various teams.
|
||||
2. Project Administrator is a technical role necessitated by the GitHub platform. Except for the specific exceptions listed below, the Project Administrators do not make the decision about individual team members. Rather, they carry out the collective wishes of the Maintainers team. Project Administrators will be selected from the Maintainers team by the Maintainers themselves.
|
||||
3. To ensure continuity there SHALL be at least four Project Administrators at all times.
|
||||
4. The project Administrators will manage the set of project Maintainers. They SHALL maintain a sufficiently large pool of Maintainers to ensure their succession and permit timely review of contributions. If the pool of Maintainers is insufficient, the Project Administrators will request that the Maintainers select additional individuals to add.
|
||||
5. Contributors who have a history of successful PRs and have demonstrated continued professionalism should be invited to be Maintainers.
|
||||
6. Administrators SHOULD remove Maintainers who are inactive for an extended period, or who repeatedly fail to apply this process accurately.
|
||||
7. The list of Maintainers SHALL be publicly accessible and reflective of current activity on the project.
|
||||
8. Administrators SHALL act expediently to protect the FreeCAD infrastructure and resources.
|
||||
9. Administrators SHOULD block or ban “bad actors” who cause stress, animosity, or confusion to others in the project. This SHOULD be done after public discussion, with a chance for all parties to speak. A bad actor is someone who repeatedly ignores the rules and culture of the project, who is hostile or offensive, who impedes the productive exchange of information, and who is unable to self-correct their behavior when asked to do so by others.
|
||||
| Submodule | Path | Repository |
|
||||
|-----------|------|------------|
|
||||
| ztools | `mods/ztools` | `git.kindred-systems.com/forbes/ztools` |
|
||||
| silo-mod | `mods/silo` | `git.kindred-systems.com/kindred/silo-mod` |
|
||||
|
||||
To update a submodule:
|
||||
|
||||
```bash
|
||||
cd mods/silo
|
||||
git checkout main && git pull
|
||||
cd ../..
|
||||
git add mods/silo
|
||||
git commit -m "chore: update silo submodule"
|
||||
```
|
||||
|
||||
If you cloned without `--recursive`, initialize submodules with:
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
## Theme and QSS changes
|
||||
|
||||
The Catppuccin Mocha theme has **three QSS copies** that must be kept in sync:
|
||||
|
||||
1. `resources/preferences/KindredCreate/KindredCreate.qss` (canonical)
|
||||
2. `src/Gui/Stylesheets/KindredCreate.qss`
|
||||
3. `src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss`
|
||||
|
||||
When modifying the theme, apply changes to all three files. Note that the copies have intentional differences (e.g., tree branch rendering style), so do not blindly copy between them -- apply edits individually.
|
||||
|
||||
See [KNOWN_ISSUES.md](docs/KNOWN_ISSUES.md) for the planned QSS consolidation.
|
||||
|
||||
## Preference pack
|
||||
|
||||
Default preferences are defined in `resources/preferences/KindredCreate/KindredCreate.cfg`. This XML file uses FreeCAD's parameter format:
|
||||
|
||||
```xml
|
||||
<FCParamGroup Name="GroupName">
|
||||
<FCBool Name="Setting" Value="1"/>
|
||||
<FCInt Name="Setting" Value="42"/>
|
||||
<FCText Name="Setting">value</FCText>
|
||||
</FCParamGroup>
|
||||
```
|
||||
|
||||
Changes here affect the out-of-box experience for all users.
|
||||
|
||||
## CI/CD
|
||||
|
||||
- **Build workflow** (`build.yml`): Runs on every push to `main` and on PRs. Builds in Ubuntu 24.04 container, runs C++ and Python tests.
|
||||
- **Release workflow** (`release.yml`): Triggered by `v*` tags. Builds AppImage and .deb packages.
|
||||
|
||||
See [docs/CI_CD.md](docs/CI_CD.md) for full details.
|
||||
|
||||
## Architecture
|
||||
|
||||
For an overview of the codebase structure, bootstrap flow, and design decisions, see:
|
||||
|
||||
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) -- Bootstrap flow and source layout
|
||||
- [docs/COMPONENTS.md](docs/COMPONENTS.md) -- Feature inventory
|
||||
- [docs/INTEGRATION_PLAN.md](docs/INTEGRATION_PLAN.md) -- Architecture layers and roadmap
|
||||
|
||||
## License
|
||||
|
||||
All contributions must be compatible with [LGPL-2.1-or-later](LICENSE).
|
||||
|
||||
61
docs/ARCHITECTURE.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Architecture
|
||||
|
||||
## Bootstrap flow
|
||||
|
||||
```
|
||||
FreeCAD startup
|
||||
└─ src/Mod/Create/Init.py
|
||||
└─ setup_kindred_addons()
|
||||
├─ exec(mods/ztools/ztools/Init.py)
|
||||
└─ exec(mods/silo/freecad/Init.py)
|
||||
|
||||
└─ src/Mod/Create/InitGui.py
|
||||
├─ setup_kindred_workbenches()
|
||||
│ ├─ exec(mods/ztools/ztools/InitGui.py)
|
||||
│ │ ├─ registers ZToolsWorkbench
|
||||
│ │ └─ installs _ZToolsPartDesignManipulator (global)
|
||||
│ └─ exec(mods/silo/freecad/InitGui.py)
|
||||
│ └─ registers SiloWorkbench
|
||||
└─ Deferred setup (QTimer):
|
||||
├─ 1500ms: _register_silo_origin() → registers Silo FileOrigin
|
||||
├─ 2000ms: _setup_silo_auth_panel() → "Database Auth" dock
|
||||
├─ 3000ms: _check_silo_first_start() → settings prompt
|
||||
├─ 4000ms: _setup_silo_activity_panel() → "Database Activity" dock (SSE)
|
||||
└─ 10000ms: _check_for_updates() → update checker (Gitea API)
|
||||
```
|
||||
|
||||
## Key source layout
|
||||
|
||||
```
|
||||
src/Mod/Create/ Kindred bootstrap module (Python)
|
||||
├── Init.py Adds mods/ addon paths, loads Init.py files
|
||||
├── InitGui.py Loads workbenches, installs Silo manipulators
|
||||
├── version.py.in CMake template → version.py (build-time)
|
||||
└── update_checker.py Checks Gitea releases API for updates
|
||||
|
||||
src/Gui/FileOrigin.h/.cpp FileOrigin base class + LocalFileOrigin
|
||||
src/Gui/CommandOrigin.cpp Origin_Commit/Pull/Push/Info/BOM commands
|
||||
src/Gui/OriginManager.h/.cpp Origin lifecycle management
|
||||
src/Gui/OriginSelectorWidget.h/.cpp UI for origin selection
|
||||
|
||||
mods/ztools/ [submodule] ztools workbench
|
||||
├── ztools/InitGui.py ZToolsWorkbench + PartDesign manipulator
|
||||
├── ztools/ztools/
|
||||
│ ├── commands/ Datum, pattern, pocket, assembly, spreadsheet
|
||||
│ ├── datums/core.py Datum creation via Part::AttachExtension
|
||||
│ └── resources/ Icons, theme utilities
|
||||
└── CatppuccinMocha/ Theme preference pack (QSS)
|
||||
|
||||
mods/silo/ [submodule -> silo-mod.git] FreeCAD workbench
|
||||
├── silo-client/ [submodule -> silo-client.git] shared API client
|
||||
│ └── silo_client/ SiloClient, SiloSettings, CATEGORY_NAMES
|
||||
└── freecad/ FreeCAD workbench (Python)
|
||||
├── InitGui.py SiloWorkbench
|
||||
├── silo_commands.py Commands + FreeCADSiloSettings adapter
|
||||
└── silo_origin.py FileOrigin backend for Silo
|
||||
|
||||
src/Gui/Stylesheets/ QSS themes and SVG assets
|
||||
src/Gui/PreferencePacks/ KindredCreate preference pack (cfg + build-time QSS)
|
||||
```
|
||||
|
||||
See [INTEGRATION_PLAN.md](INTEGRATION_PLAN.md) for architecture layers and phase status.
|
||||
@@ -7,7 +7,7 @@ Kindred Create uses Gitea Actions for continuous integration and release builds.
|
||||
| Workflow | Trigger | Purpose | Artifacts |
|
||||
|----------|---------|---------|-----------|
|
||||
| `build.yml` | Push to `main`, pull requests | Build + test | Linux tarball |
|
||||
| `release.yml` | Tags matching `v*` | Multi-platform release | AppImage, .deb, .dmg, .exe, .7z |
|
||||
| `release.yml` | Tags matching `v*` or `latest` | Release build | AppImage, .deb |
|
||||
|
||||
All builds run on public runners in dockerized mode. No host-mode or internal infrastructure is required.
|
||||
|
||||
@@ -34,14 +34,16 @@ Runs on every push to `main` and on pull requests. Builds the project in an Ubun
|
||||
|
||||
### Caching
|
||||
|
||||
ccache is persisted between builds using `actions/cache`. Cache keys are scoped by branch and commit SHA, with fallback to the branch key then `main`.
|
||||
ccache is persisted between builds using `actions/cache`. Cache keys use a date suffix so entries rotate daily (one save per day per branch). Saves are skipped when the exact key already exists, preventing duplicate entries that fill runner storage.
|
||||
|
||||
```
|
||||
Key: ccache-build-{branch}-{sha}
|
||||
Key: ccache-build-{branch}-{YYYYMMDD}
|
||||
Fallback: ccache-build-{branch}-
|
||||
Fallback: ccache-build-main-
|
||||
```
|
||||
|
||||
Release builds use a separate key namespace (`ccache-release-linux-{YYYYMMDD}`) because they compile with different optimization flags (`-O3`). The rattler-build script (`build.sh`) explicitly sets `CCACHE_DIR` and `CCACHE_BASEDIR` since rattler-build does not forward environment variables from the parent process.
|
||||
|
||||
ccache configuration: 4 GB max, zlib compression level 6, sloppy mode for include timestamps and PCH.
|
||||
|
||||
---
|
||||
@@ -63,17 +65,19 @@ Tags containing `rc`, `beta`, or `alpha` are marked as pre-releases.
|
||||
|
||||
### Platform matrix
|
||||
|
||||
| Job | Runner | Container | Preset | Output |
|
||||
|-----|--------|-----------|--------|--------|
|
||||
| `build-linux` | `ubuntu-latest` | `ubuntu:24.04` | `conda-linux-release` | AppImage, .deb |
|
||||
| `build-macos` (Intel) | `macos-13` | native | `conda-macos-release` | .dmg (x86_64) |
|
||||
| `build-macos` (Apple Silicon) | `macos-14` | native | `conda-macos-release` | .dmg (arm64) |
|
||||
| `build-windows` | `windows-latest` | native | `conda-windows-release` | .exe (NSIS), .7z |
|
||||
| Job | Runner | Container | Preset | Output | Status |
|
||||
|-----|--------|-----------|--------|--------|--------|
|
||||
| `build-linux` | `ubuntu-latest` | `ubuntu:24.04` | `conda-linux-release` | AppImage, .deb | Active |
|
||||
| `build-macos` (Intel) | `macos-13` | native | `conda-macos-release` | .dmg (x86_64) | Disabled |
|
||||
| `build-macos` (Apple Silicon) | `macos-14` | native | `conda-macos-release` | .dmg (arm64) | Disabled |
|
||||
| `build-windows` | `windows-latest` | native | `conda-windows-release` | .exe (NSIS), .7z | Disabled |
|
||||
|
||||
All four jobs run concurrently. After all succeed, `publish-release` collects artifacts and creates the Gitea release.
|
||||
Only the Linux build is currently active. macOS and Windows jobs are defined but commented out pending runner availability or cross-compilation support. After `build-linux` succeeds, `publish-release` collects artifacts and creates the Gitea release.
|
||||
|
||||
### Linux build
|
||||
|
||||
Both workflows start with a disk cleanup step that removes pre-installed bloat (dotnet, Android SDK, etc.) to free space for the build.
|
||||
|
||||
Uses the rattler-build packaging pipeline:
|
||||
|
||||
1. `pixi install` in `package/rattler-build/`
|
||||
@@ -81,9 +85,10 @@ Uses the rattler-build packaging pipeline:
|
||||
3. The bundle script:
|
||||
- Copies the pixi conda environment to an AppDir
|
||||
- Strips unnecessary files (includes, static libs, cmake files, `__pycache__`)
|
||||
- Downloads `appimagetool` and creates a squashfs AppImage (zstd compressed)
|
||||
- Generates SHA256 checksums
|
||||
4. `package/debian/build-deb.sh` builds a .deb from the AppDir
|
||||
- Downloads `appimagetool`, extracts it with `--appimage-extract` (FUSE unavailable in containers), and runs via `squashfs-root/AppRun`
|
||||
- Creates a squashfs AppImage (zstd compressed) with SHA256 checksums
|
||||
4. Intermediate build files are cleaned up to free space for the .deb step
|
||||
5. `package/debian/build-deb.sh` builds a .deb from the AppDir
|
||||
- Installs to `/opt/kindred-create/` with wrapper scripts in `/usr/bin/`
|
||||
- Sets up LD_LIBRARY_PATH, QT_PLUGIN_PATH, PYTHONPATH in wrappers
|
||||
- Creates desktop entry, MIME types, AppStream metainfo
|
||||
@@ -123,10 +128,15 @@ Builds natively on Windows runner:
|
||||
|
||||
`publish-release` runs after all platform builds succeed:
|
||||
|
||||
1. Downloads all artifacts from `build-linux`, `build-macos`, `build-windows`
|
||||
2. Collects release files (AppImage, .deb, .dmg, .7z, .exe, checksums)
|
||||
3. Creates a Gitea release via `gitea.com/actions/release-action`
|
||||
4. Requires `RELEASE_TOKEN` secret with repository write permissions
|
||||
1. Downloads all artifacts from completed build jobs
|
||||
2. Collects release files (AppImage, .deb, checksums) into a `release/` directory
|
||||
3. Deletes any existing Gitea release for the same tag (allows re-running)
|
||||
4. Creates a new Gitea release via the REST API (`/api/v1/repos/{owner}/{repo}/releases`)
|
||||
5. Uploads each artifact as a release attachment via the API
|
||||
|
||||
The release payload (tag name, body, prerelease flag) is built entirely in Python to avoid shell/Python type mismatches. Tags containing `rc`, `beta`, or `alpha` are automatically marked as pre-releases.
|
||||
|
||||
Requires `RELEASE_TOKEN` secret with repository write permissions.
|
||||
|
||||
---
|
||||
|
||||
@@ -174,6 +184,27 @@ container:
|
||||
network: bridge
|
||||
```
|
||||
|
||||
### Runner cleanup daemon
|
||||
|
||||
A cleanup script at `.gitea/runner/cleanup.sh` prevents disk exhaustion on self-hosted runners. It uses a tiered approach based on disk usage thresholds:
|
||||
|
||||
| Threshold | Action |
|
||||
|-----------|--------|
|
||||
| 70% | Docker cleanup (stopped containers, dangling images, build cache) |
|
||||
| 80% | Purge act_runner cache entries older than 7 days, clean inactive workspaces |
|
||||
| 90% | System cleanup (apt cache, old logs, journal vacuum to 100 MB) |
|
||||
| 95% | Emergency: remove all act_runner cache entries and Docker images |
|
||||
|
||||
Install via the provided systemd units (`.gitea/runner/cleanup.service` and `.gitea/runner/cleanup.timer`) to run every 30 minutes:
|
||||
|
||||
```bash
|
||||
sudo cp .gitea/runner/cleanup.sh /usr/local/bin/runner-cleanup.sh
|
||||
sudo cp .gitea/runner/cleanup.service /etc/systemd/system/
|
||||
sudo cp .gitea/runner/cleanup.timer /etc/systemd/system/
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now cleanup.timer
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Secrets
|
||||
@@ -214,11 +245,12 @@ Defined in `CMakePresets.json`. Release builds use:
|
||||
|
||||
### ccache
|
||||
|
||||
Compiler cache is used across all builds to speed up incremental compilation. Cache is persisted between CI runs via `actions/cache`. Configuration:
|
||||
Compiler cache is used across all builds to speed up incremental compilation. Cache is persisted between CI runs via `actions/cache` with date-based key rotation. Configuration:
|
||||
|
||||
- Max size: 4 GB
|
||||
- Compression: zlib level 6
|
||||
- Sloppy mode: include timestamps, PCH defines, time macros
|
||||
- `CCACHE_BASEDIR`: set to workspace root (build workflow) or `$SRC_DIR` (rattler-build) for path normalization across runs
|
||||
|
||||
---
|
||||
|
||||
@@ -243,9 +275,12 @@ The Docker container installs only minimal dependencies. If a new dependency is
|
||||
ccache misses spike when:
|
||||
- The compiler version changes (pixi update)
|
||||
- CMake presets change configuration flags
|
||||
- The cache key doesn't match (new branch, force-pushed SHA)
|
||||
- First build of the day (date-based key rotates daily)
|
||||
- New branch without a prior cache (falls back to `main` cache)
|
||||
|
||||
Check `pixi run ccache -s` output for hit/miss ratios.
|
||||
For release builds, ensure `build.sh` is correctly setting `CCACHE_DIR=/tmp/ccache-kindred-create` -- rattler-build does not forward environment variables from the workflow, so ccache config must be set inside the script.
|
||||
|
||||
Check `pixi run ccache -s` output (printed in the "Show ccache statistics" step) for hit/miss ratios. The "Prepare ccache" step also prints the full ccache configuration via `ccache -p`.
|
||||
|
||||
### Submodule checkout fails
|
||||
|
||||
|
||||
116
docs/COMPONENTS.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# Components
|
||||
|
||||
## ztools workbench
|
||||
|
||||
**Registered commands (9):**
|
||||
|
||||
| Command | Function |
|
||||
|---------|----------|
|
||||
| `ZTools_DatumCreator` | Create datum planes, axes, points (16 modes) |
|
||||
| `ZTools_DatumManager` | Manage existing datum objects |
|
||||
| `ZTools_EnhancedPocket` | Flip-side pocket (cut outside sketch profile) |
|
||||
| `ZTools_RotatedLinearPattern` | Linear pattern with incremental rotation |
|
||||
| `ZTools_AssemblyLinearPattern` | Pattern assembly components linearly |
|
||||
| `ZTools_AssemblyPolarPattern` | Pattern assembly components around axis |
|
||||
| `ZTools_SpreadsheetStyle{Bold,Italic,Underline}` | Text style toggles |
|
||||
| `ZTools_SpreadsheetAlign{Left,Center,Right}` | Cell alignment |
|
||||
| `ZTools_Spreadsheet{BgColor,TextColor,QuickAlias}` | Colors and alias creation |
|
||||
|
||||
**PartDesign integration** via `_ZToolsPartDesignManipulator`:
|
||||
- `ZTools_DatumCreator`, `ZTools_DatumManager` → "Part Design Helper Features" toolbar
|
||||
- `ZTools_EnhancedPocket` → "Part Design Modeling Features" toolbar
|
||||
- `ZTools_RotatedLinearPattern` → "Part Design Transformation Features" toolbar
|
||||
- Same commands inserted into Part Design menu after `PartDesign_Boolean`
|
||||
|
||||
**Datum types (7):** offset_from_face, offset_from_plane, midplane, 3_points, normal_to_edge, angled, tangent_to_cylinder. All except tangent_to_cylinder use `Part::AttachExtension` for automatic parametric updates.
|
||||
|
||||
---
|
||||
|
||||
## Origin commands (C++)
|
||||
|
||||
The Origin abstraction (`src/Gui/FileOrigin.h`) provides a backend-agnostic interface for document storage. Commands delegate to the active `FileOrigin` implementation (currently `LocalFileOrigin` for local files, `SiloOrigin` via `mods/silo/freecad/silo_origin.py` for Silo-tracked documents).
|
||||
|
||||
**Registered commands (5):**
|
||||
|
||||
| Command | Function | Icon |
|
||||
|---------|----------|------|
|
||||
| `Origin_Commit` | Commit changes as a new revision | `silo-commit` |
|
||||
| `Origin_Pull` | Pull a specific revision from the origin | `silo-pull` |
|
||||
| `Origin_Push` | Push local changes to the origin | `silo-push` |
|
||||
| `Origin_Info` | Show document information from origin | `silo-info` |
|
||||
| `Origin_BOM` | Show Bill of Materials for this document | `silo-bom` |
|
||||
|
||||
These appear in the File menu and "Origin Tools" toolbar across all workbenches (see `src/Gui/Workbench.cpp`).
|
||||
|
||||
---
|
||||
|
||||
## Silo workbench
|
||||
|
||||
**Registered commands (14):**
|
||||
|
||||
| Command | Function |
|
||||
|---------|----------|
|
||||
| `Silo_New` | Create new Silo-tracked document |
|
||||
| `Silo_Open` | Open file from Silo database |
|
||||
| `Silo_Save` | Save to Silo (create revision) |
|
||||
| `Silo_Commit` | Commit current revision |
|
||||
| `Silo_Pull` | Pull latest revision from server |
|
||||
| `Silo_Push` | Push local changes to server |
|
||||
| `Silo_Info` | View item metadata and history |
|
||||
| `Silo_BOM` | Bill of materials dialog (BOM + Where Used) |
|
||||
| `Silo_TagProjects` | Assign project tags |
|
||||
| `Silo_Rollback` | Rollback to previous revision |
|
||||
| `Silo_SetStatus` | Set revision status (draft/review/released/obsolete) |
|
||||
| `Silo_Settings` | Configure API URL, projects dir, SSL certificates |
|
||||
| `Silo_Auth` | Login/logout authentication panel |
|
||||
|
||||
**Global integration** via the origin system in `src/Gui/`:
|
||||
- File toolbar: `Std_Origin` selector widget + `Std_New`/`Std_Open`/`Std_Save` (delegate to current origin)
|
||||
- Origin Tools toolbar: `Origin_Commit`/`Origin_Pull`/`Origin_Push`/`Origin_Info`/`Origin_BOM` (auto-disable by capability)
|
||||
- Silo origin registered at startup by `src/Mod/Create/InitGui.py`
|
||||
|
||||
**Dock panels:**
|
||||
- Database Auth (2000ms) -- Login/logout and API token management
|
||||
- Database Activity (4000ms) -- Real-time server event feed via SSE (Server-Sent Events) with automatic reconnection and exponential backoff
|
||||
- Start Panel -- In-viewport landing page with recent files and Silo integration
|
||||
|
||||
**Server architecture:** Go REST API (38+ routes) + PostgreSQL + MinIO S3. Authentication via local (bcrypt), LDAP, or OIDC backends. SSE endpoint for real-time event streaming. See `mods/silo/docs/` for server documentation.
|
||||
|
||||
**LibreOffice Calc extension** ([silo-calc](https://git.kindred-systems.com/kindred/silo-calc.git)): BOM management, item creation, and AI-assisted descriptions via OpenRouter API. Shares the same Silo REST API and auth token system via the shared [silo-client](https://git.kindred-systems.com/kindred/silo-client.git) package.
|
||||
|
||||
---
|
||||
|
||||
## Theme
|
||||
|
||||
**Canonical source:** `src/Gui/Stylesheets/KindredCreate.qss`
|
||||
|
||||
The PreferencePacks copy (`src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss`) is generated at build time via `configure_file()` in `src/Gui/PreferencePacks/CMakeLists.txt`. Only the Stylesheets copy needs to be maintained.
|
||||
|
||||
Notable theme customizations beyond standard Catppuccin colors:
|
||||
- `QGroupBox::indicator` styling to match `QCheckBox::indicator` (consistent checkbox appearance)
|
||||
- `QLabel[haslink="true"]` link color (`#b4befe` Catppuccin Lavender) -- picked up by FreeCAD to set `QPalette::Link`
|
||||
- Spanning-line tree branch indicators
|
||||
|
||||
---
|
||||
|
||||
## Icon infrastructure
|
||||
|
||||
### Qt resource icons (`src/Gui/Icons/`)
|
||||
|
||||
5 `silo-*` SVGs registered in `resource.qrc`, used by C++ Origin commands:
|
||||
|
||||
`silo-bom.svg`, `silo-commit.svg`, `silo-info.svg`, `silo-pull.svg`, `silo-push.svg`
|
||||
|
||||
### Silo module icons (`mods/silo/freecad/resources/icons/`)
|
||||
|
||||
10 SVGs loaded at runtime by the `_icon()` function in `silo_commands.py`:
|
||||
|
||||
`silo-auth.svg`, `silo-bom.svg`, `silo-commit.svg`, `silo-info.svg`, `silo-new.svg`, `silo-open.svg`, `silo-pull.svg`, `silo-push.svg`, `silo-save.svg`, `silo.svg`
|
||||
|
||||
### Missing icons
|
||||
|
||||
3 command icon names have no corresponding SVG file: `silo-tag`, `silo-rollback`, `silo-status`. The `_icon()` function returns an empty string for these, so `Silo_TagProjects`, `Silo_Rollback`, and `Silo_SetStatus` render without toolbar icons.
|
||||
|
||||
### Palette
|
||||
|
||||
All silo-* icons use the Catppuccin Mocha color scheme. See `kindred-icons/README.md` for palette specification and icon design standards.
|
||||
84
docs/KNOWN_ISSUES.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Known Issues
|
||||
|
||||
## Issues
|
||||
|
||||
### Critical
|
||||
|
||||
1. ~~**QSS duplication.**~~ Resolved. The canonical QSS lives in `src/Gui/Stylesheets/KindredCreate.qss`. The PreferencePacks copy is now generated at build time via `configure_file()` in `src/Gui/PreferencePacks/CMakeLists.txt`. The unused `resources/preferences/KindredCreate/` directory has been removed.
|
||||
|
||||
2. **WorkbenchManipulator timing.** The `_ZToolsPartDesignManipulator` appends commands by name. If ZToolsWorkbench hasn't been activated when the user switches to PartDesign, the commands may not be registered. The manipulator API tolerates missing commands silently, but buttons won't appear.
|
||||
|
||||
3. ~~**Silo shortcut persistence.**~~ Resolved. `Silo_ToggleMode` removed; file operations now delegate to the selected origin via the unified origin system.
|
||||
|
||||
### High
|
||||
|
||||
4. **Silo authentication not production-hardened.** Local auth (bcrypt) works end-to-end. LDAP (FreeIPA) and OIDC (Keycloak) backends are coded but depend on infrastructure not yet deployed. FreeCAD client has `Silo_Auth` dock panel for login and API token management. Server has session middleware (`alexedwards/scs`), CSRF protection (`nosurf`), and role-based access control (admin/editor/viewer). Migration `009_auth.sql` adds users, api_tokens, and sessions tables.
|
||||
|
||||
5. **No unit tests.** Zero test coverage for ztools and Silo FreeCAD commands. Silo Go backend also lacks tests.
|
||||
|
||||
6. **Assembly solver datum handling is minimal.** The `findPlacement()` fix in `src/Mod/Assembly/UtilsAssembly.py` extracts placement from `obj.Shape.Faces[0]` for `PartDesign::Plane` and from shape vertex for `PartDesign::Point`. Does not handle empty shapes or non-planar datum objects.
|
||||
|
||||
### Medium
|
||||
|
||||
7. **`Silo_BOM` requires Silo-tracked document.** Depends on `SiloPartNumber` property. Unregistered documents show a warning with no registration path.
|
||||
|
||||
8. **PartDesign menu insertion fragility.** `_ZToolsPartDesignManipulator.modifyMenuBar()` inserts after `PartDesign_Boolean`. If upstream renames this command, insertions silently fail.
|
||||
|
||||
9. **tangent_to_cylinder falls back to manual placement.** TangentPlane MapMode requires a vertex reference not collected by the current UI.
|
||||
|
||||
10. **`delete_bom_entry()` bypasses error normalization.** Uses raw `urllib.request` instead of `SiloClient._request()`.
|
||||
|
||||
11. **Missing Silo icons.** Three commands reference icons that don't exist: `silo-tag.svg` (`Silo_TagProjects`), `silo-rollback.svg` (`Silo_Rollback`), `silo-status.svg` (`Silo_SetStatus`). The `_icon()` function returns an empty string, so these commands render without toolbar icons.
|
||||
|
||||
### Fixed (retain for reference)
|
||||
|
||||
12. **OndselSolver Newton-Raphson convergence.** `NewtonRaphson::isConvergedToNumericalLimit()` compared `dxNorms->at(iterNo)` to itself instead of `dxNorms->at(iterNo - 1)`. This prevented convergence detection on complex assemblies, causing solver exhaustion and "grounded object moved" warnings. Fixed in Kindred fork (`src/3rdParty/OndselSolver`). Needs upstreaming to `FreeCAD/OndselSolver`.
|
||||
|
||||
13. **Assembly solver crash on document restore.** `AssemblyObject::onChanged()` called `updateSolveStatus()` when the Group property changed during document restore, triggering the solver while child objects were still deserializing (SIGSEGV). Fixed with `isRestoring()` and `isPerformingTransaction()` guards at `src/Mod/Assembly/App/AssemblyObject.cpp:143`.
|
||||
|
||||
14. **`DlgSettingsGeneral::applyMenuIconSize` visibility.** The method was `private` but called from `StartupProcess.cpp`. Fixed by moving to `public` (PR #49). Also required `Dialog::` namespace qualifier in `StartupProcess.cpp`.
|
||||
|
||||
---
|
||||
|
||||
## Incomplete features
|
||||
|
||||
### Silo
|
||||
|
||||
| Feature | Status | Notes |
|
||||
|---------|--------|-------|
|
||||
| Authentication | Local auth complete | LDAP/OIDC backends coded, pending infrastructure. Auth dock panel available. |
|
||||
| CSRF protection | Implemented | `nosurf` library on web form routes |
|
||||
| File locking | Not implemented | Needed to prevent concurrent edits |
|
||||
| Odoo ERP integration | Stub only | Returns "not yet implemented" |
|
||||
| Part number date segments | Broken | `formatDate()` returns error |
|
||||
| Location/inventory APIs | Tables exist, no handlers | |
|
||||
| CSV import rollback | Not implemented | `bom_handlers.go` |
|
||||
| SSE event streaming | Implemented | Reconnect logic with exponential backoff |
|
||||
| Database Activity panel | Implemented | Dock panel showing real-time server events |
|
||||
| Start panel | Implemented | In-viewport start page with recent files and Silo integration |
|
||||
|
||||
### ztools
|
||||
|
||||
| Feature | Status | Notes |
|
||||
|---------|--------|-------|
|
||||
| Tangent-to-cylinder attachment | Manual fallback | No vertex ref in UI |
|
||||
| Angled datum live editing | Incomplete | AttachmentOffset not updated in panel |
|
||||
| Assembly pattern undo | Not implemented | |
|
||||
|
||||
---
|
||||
|
||||
## Next steps
|
||||
|
||||
1. **Authentication hardening** -- Deploy FreeIPA and Keycloak infrastructure. End-to-end test LDAP and OIDC flows. Harden token rotation and session expiry.
|
||||
|
||||
2. **BOM-Assembly bridge** -- Auto-populate Silo BOM from Assembly component links on save.
|
||||
|
||||
3. **File locking** -- Pessimistic locks on `Silo_Open` to prevent concurrent edits. Requires server-side lock table and client-side lock display.
|
||||
|
||||
4. **Build system** -- CMake install rules for `mods/` submodules so packages include ztools and Silo without manual steps.
|
||||
|
||||
5. **Test coverage** -- Unit tests for ztools datum creation, Silo FreeCAD commands, and Go API endpoints.
|
||||
|
||||
6. **QSS consolidation** -- Eliminate the 3-copy QSS duplication via build-time copy or symlinks. The canonical source is `resources/preferences/KindredCreate/KindredCreate.qss`.
|
||||
|
||||
7. **Update notification UI** -- Display in-app notification when a new release is available (issue #30). The update checker backend is already implemented.
|
||||
31
docs/OVERVIEW.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Kindred Create
|
||||
|
||||
**Last updated:** 2026-02-08
|
||||
**Branch:** main @ `cf523f1d87a`
|
||||
**Kindred Create:** v0.1.0
|
||||
**FreeCAD base:** v1.0.0
|
||||
|
||||
## Documentation
|
||||
|
||||
| Document | Contents |
|
||||
|----------|----------|
|
||||
| [ARCHITECTURE.md](ARCHITECTURE.md) | Bootstrap flow, source layout, submodules |
|
||||
| [COMPONENTS.md](COMPONENTS.md) | ztools, Silo, Origin commands, theme, icons |
|
||||
| [KNOWN_ISSUES.md](KNOWN_ISSUES.md) | Bugs, incomplete features, next steps |
|
||||
| [INTEGRATION_PLAN.md](INTEGRATION_PLAN.md) | Architecture layers, integration phases |
|
||||
| [CI_CD.md](CI_CD.md) | Build and release workflows |
|
||||
|
||||
## Submodules
|
||||
|
||||
| Submodule | Path | Source | Pinned commit |
|
||||
|-----------|------|--------|---------------|
|
||||
| ztools | `mods/ztools` | `git.kindred-systems.com/forbes/ztools` | `3298d1c` |
|
||||
| silo-mod | `mods/silo` | `git.kindred-systems.com/kindred/silo-mod` | `f9924d3` |
|
||||
| OndselSolver | `src/3rdParty/OndselSolver` | `git.kindred-systems.com/kindred/solver` | `fe41fa3` |
|
||||
| GSL | `src/3rdParty/GSL` | `github.com/microsoft/GSL` | `756c91a` |
|
||||
| AddonManager | `src/Mod/AddonManager` | `github.com/FreeCAD/AddonManager` | `01e242e` |
|
||||
| googletest | `tests/lib` | `github.com/google/googletest` | `56efe39` |
|
||||
|
||||
The silo submodule was split from a monorepo into three repos: `silo-client` (shared Python API client), `silo-mod` (FreeCAD workbench, used as Create's submodule), and `silo-calc` (LibreOffice Calc extension). The `silo-mod` repo includes `silo-client` as its own submodule.
|
||||
|
||||
OndselSolver is forked from `github.com/FreeCAD/OndselSolver` to carry a Newton-Raphson convergence fix (see [KNOWN_ISSUES.md](KNOWN_ISSUES.md#12)).
|
||||
@@ -1,215 +0,0 @@
|
||||
# Repository State
|
||||
|
||||
**Last updated:** 2026-02-03
|
||||
**Branch:** main @ `0ef9ffcf51`
|
||||
**Kindred Create:** v0.1.0
|
||||
**FreeCAD base:** v1.0.0
|
||||
|
||||
## Submodules
|
||||
|
||||
| Submodule | Path | Source | Pinned commit |
|
||||
|-----------|------|--------|---------------|
|
||||
| ztools | `mods/ztools` | `gitea.kindred.internal/kindred/ztools-0065` | `d2f94c3` |
|
||||
| silo | `mods/silo` | `gitea.kindred.internal/kindred/silo-0062` | `17a10ab` |
|
||||
| OndselSolver | `src/3rdParty/OndselSolver` | `gitea.kindred.internal/kindred/ondsel` | `e32c9cd` |
|
||||
| GSL | `src/3rdParty/GSL` | `github.com/microsoft/GSL` | `756c91a` |
|
||||
| AddonManager | `src/Mod/AddonManager` | `github.com/FreeCAD/AddonManager` | `01e242e` |
|
||||
| googletest | `tests/lib` | `github.com/google/googletest` | `56efe39` |
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### Bootstrap flow
|
||||
|
||||
```
|
||||
FreeCAD startup
|
||||
└─ src/Mod/Create/Init.py
|
||||
└─ setup_kindred_addons()
|
||||
├─ exec(mods/ztools/ztools/Init.py)
|
||||
└─ exec(mods/silo/pkg/freecad/Init.py)
|
||||
|
||||
└─ src/Mod/Create/InitGui.py
|
||||
├─ setup_kindred_workbenches()
|
||||
│ ├─ exec(mods/ztools/ztools/InitGui.py)
|
||||
│ │ ├─ registers ZToolsWorkbench
|
||||
│ │ └─ installs _ZToolsPartDesignManipulator (global)
|
||||
│ └─ exec(mods/silo/pkg/freecad/InitGui.py)
|
||||
│ └─ registers SiloWorkbench
|
||||
└─ Deferred setup (QTimer):
|
||||
├─ 1500ms: _setup_silo_auth_panel() → "Database Auth" dock
|
||||
├─ 2000ms: _setup_silo_menu() → SiloMenuManipulator
|
||||
├─ 3000ms: _check_silo_first_start() → settings prompt
|
||||
└─ 4000ms: _setup_silo_activity_panel() → "Database Activity" dock
|
||||
```
|
||||
|
||||
### Key source layout
|
||||
|
||||
```
|
||||
src/Mod/Create/ Kindred bootstrap module (Python)
|
||||
├── Init.py Adds mods/ addon paths, loads Init.py files
|
||||
└── InitGui.py Loads workbenches, installs Silo manipulators
|
||||
|
||||
mods/ztools/ [submodule] ztools workbench
|
||||
├── ztools/InitGui.py ZToolsWorkbench + PartDesign manipulator
|
||||
├── ztools/ztools/
|
||||
│ ├── commands/ Datum, pattern, pocket, assembly, spreadsheet
|
||||
│ ├── datums/core.py Datum creation via Part::AttachExtension
|
||||
│ └── resources/ Icons, theme utilities
|
||||
└── CatppuccinMocha/ Theme preference pack (QSS)
|
||||
|
||||
mods/silo/ [submodule] Silo parts database
|
||||
├── cmd/ Go server entry points
|
||||
├── internal/ Go API, database, storage packages
|
||||
├── pkg/freecad/ FreeCAD workbench (Python)
|
||||
│ ├── InitGui.py SiloWorkbench
|
||||
│ └── silo_commands.py Commands + SiloClient API
|
||||
├── deployments/ Docker compose configuration
|
||||
└── migrations/ PostgreSQL schema migrations
|
||||
|
||||
src/Gui/Stylesheets/ QSS themes and SVG assets
|
||||
resources/preferences/ Canonical preference pack (KindredCreate)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Component status
|
||||
|
||||
### ztools workbench
|
||||
|
||||
**Registered commands (9):**
|
||||
|
||||
| Command | Function |
|
||||
|---------|----------|
|
||||
| `ZTools_DatumCreator` | Create datum planes, axes, points (16 modes) |
|
||||
| `ZTools_DatumManager` | Manage existing datum objects |
|
||||
| `ZTools_EnhancedPocket` | Flip-side pocket (cut outside sketch profile) |
|
||||
| `ZTools_RotatedLinearPattern` | Linear pattern with incremental rotation |
|
||||
| `ZTools_AssemblyLinearPattern` | Pattern assembly components linearly |
|
||||
| `ZTools_AssemblyPolarPattern` | Pattern assembly components around axis |
|
||||
| `ZTools_SpreadsheetStyle{Bold,Italic,Underline}` | Text style toggles |
|
||||
| `ZTools_SpreadsheetAlign{Left,Center,Right}` | Cell alignment |
|
||||
| `ZTools_Spreadsheet{BgColor,TextColor,QuickAlias}` | Colors and alias creation |
|
||||
|
||||
**PartDesign integration** via `_ZToolsPartDesignManipulator`:
|
||||
- `ZTools_DatumCreator`, `ZTools_DatumManager` → "Part Design Helper Features" toolbar
|
||||
- `ZTools_EnhancedPocket` → "Part Design Modeling Features" toolbar
|
||||
- `ZTools_RotatedLinearPattern` → "Part Design Transformation Features" toolbar
|
||||
- Same commands inserted into Part Design menu after `PartDesign_Boolean`
|
||||
|
||||
**Datum types (7):** offset_from_face, offset_from_plane, midplane, 3_points, normal_to_edge, angled, tangent_to_cylinder. All except tangent_to_cylinder use `Part::AttachExtension` for automatic parametric updates.
|
||||
|
||||
### Silo workbench
|
||||
|
||||
**Registered commands (13):**
|
||||
|
||||
| Command | Function |
|
||||
|---------|----------|
|
||||
| `Silo_New` | Create new Silo-tracked document |
|
||||
| `Silo_Open` | Open file from Silo database |
|
||||
| `Silo_Save` | Save to Silo (create revision) |
|
||||
| `Silo_Commit` | Commit current revision |
|
||||
| `Silo_Pull` | Pull latest revision from server |
|
||||
| `Silo_Push` | Push local changes to server |
|
||||
| `Silo_Info` | View item metadata and history |
|
||||
| `Silo_BOM` | Bill of materials dialog (BOM + Where Used) |
|
||||
| `Silo_TagProjects` | Assign project tags |
|
||||
| `Silo_Rollback` | Rollback to previous revision |
|
||||
| `Silo_SetStatus` | Set revision status (draft/review/released/obsolete) |
|
||||
| `Silo_Settings` | Configure API URL, projects dir, SSL certificates |
|
||||
| `Silo_ToggleMode` | Swap Ctrl+O/S/N between FreeCAD and Silo commands |
|
||||
|
||||
**Global integration** via `SiloMenuManipulator` in `src/Mod/Create/InitGui.py`:
|
||||
- File menu: Silo_New, Silo_Open, Silo_Save, Silo_Commit, Silo_Pull, Silo_Push, Silo_BOM
|
||||
- File toolbar: Silo_ToggleMode button
|
||||
|
||||
**Server architecture:** Go REST API (38 routes) + PostgreSQL + MinIO. See `mods/silo/docs/REPOSITORY_STATUS.md` for route details.
|
||||
|
||||
### Theme
|
||||
|
||||
**Canonical source:** `resources/preferences/KindredCreate/KindredCreate.qss`
|
||||
|
||||
Four copies must stay in sync:
|
||||
1. `resources/preferences/KindredCreate/KindredCreate.qss` (canonical)
|
||||
2. `src/Gui/Stylesheets/KindredCreate.qss`
|
||||
3. `src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss`
|
||||
4. `mods/ztools/CatppuccinMocha/CatppuccinMocha.qss`
|
||||
|
||||
---
|
||||
|
||||
## Known issues
|
||||
|
||||
### Critical
|
||||
|
||||
1. **QSS duplication.** Four copies of the stylesheet must be kept in sync manually. A build step or symlinks should eliminate this.
|
||||
|
||||
2. **WorkbenchManipulator timing.** The `_ZToolsPartDesignManipulator` appends commands by name. If ZToolsWorkbench hasn't been activated when the user switches to PartDesign, the commands may not be registered. The manipulator API tolerates missing commands silently, but buttons won't appear.
|
||||
|
||||
3. **Silo shortcut persistence.** `Silo_ToggleMode` stores original shortcuts in a module-level dict. If FreeCAD crashes with Silo mode on, original shortcuts are lost on next launch.
|
||||
|
||||
### High
|
||||
|
||||
4. **No authentication on Silo server.** All API endpoints are publicly accessible. Required before multi-user deployment.
|
||||
|
||||
5. **No unit tests.** Zero test coverage for ztools and Silo FreeCAD commands. Silo Go backend also lacks tests.
|
||||
|
||||
6. **Assembly solver datum handling is minimal.** The `findPlacement()` fix extracts placement from `obj.Shape.Faces[0]` for `PartDesign::Plane`. Does not handle empty shapes or non-planar datum objects.
|
||||
|
||||
### Medium
|
||||
|
||||
7. **`Silo_BOM` requires Silo-tracked document.** Depends on `SiloPartNumber` property. Unregistered documents show a warning with no registration path.
|
||||
|
||||
8. **PartDesign menu insertion fragility.** `_ZToolsPartDesignManipulator.modifyMenuBar()` inserts after `PartDesign_Boolean`. If upstream renames this command, insertions silently fail.
|
||||
|
||||
9. **tangent_to_cylinder falls back to manual placement.** TangentPlane MapMode requires a vertex reference not collected by the current UI.
|
||||
|
||||
10. **`delete_bom_entry()` bypasses error normalization.** Uses raw `urllib.request` instead of `SiloClient._request()`.
|
||||
|
||||
---
|
||||
|
||||
## Incomplete features
|
||||
|
||||
### Silo
|
||||
|
||||
| Feature | Status | Notes |
|
||||
|---------|--------|-------|
|
||||
| Authentication/authorization | Not implemented | Required for multi-user |
|
||||
| File locking | Not implemented | Needed to prevent concurrent edits |
|
||||
| Odoo ERP integration | Stub only | Returns "not yet implemented" |
|
||||
| Part number date segments | Broken | `formatDate()` returns error |
|
||||
| Location/inventory APIs | Tables exist, no handlers | |
|
||||
| CSRF protection | Not implemented | Web UI only |
|
||||
| CSV import rollback | Not implemented | `bom_handlers.go` |
|
||||
|
||||
### ztools
|
||||
|
||||
| Feature | Status | Notes |
|
||||
|---------|--------|-------|
|
||||
| Tangent-to-cylinder attachment | Manual fallback | No vertex ref in UI |
|
||||
| Angled datum live editing | Incomplete | AttachmentOffset not updated in panel |
|
||||
| Assembly pattern undo | Not implemented | |
|
||||
|
||||
### Integration plan
|
||||
|
||||
| Phase | Feature | Status |
|
||||
|-------|---------|--------|
|
||||
| 1 | Addon auto-loading | Done |
|
||||
| 2 | Enhanced Pocket as C++ feature | Not started |
|
||||
| 3 | Datum C++ helpers | Not started (Python approach used) |
|
||||
| 4 | Theme moved to Create module | Partial (QSS synced, not relocated) |
|
||||
| 5 | Silo deep integration | Done |
|
||||
| 6 | Build system install rules for mods/ | Partial (CI/CD done, CMake install rules pending) |
|
||||
|
||||
---
|
||||
|
||||
## Next steps
|
||||
|
||||
1. **Authentication** -- LDAP/FreeIPA integration for Silo multi-user deployment. Server needs auth middleware; FreeCAD client needs credential storage.
|
||||
|
||||
2. **BOM-Assembly bridge** -- Auto-populate Silo BOM from Assembly component links on save.
|
||||
|
||||
3. **File locking** -- Pessimistic locks on `Silo_Open` to prevent concurrent edits. Requires server-side lock table and client-side lock display.
|
||||
|
||||
4. **Build system** -- CMake install rules for `mods/` submodules so packages include ztools and Silo without manual steps.
|
||||
|
||||
5. **Test coverage** -- Unit tests for ztools datum creation, Silo FreeCAD commands, and Go API endpoints.
|
||||
17
docs/book.toml
Normal file
@@ -0,0 +1,17 @@
|
||||
[book]
|
||||
title = "Kindred Create Documentation"
|
||||
authors = ["Kindred Systems LLC"]
|
||||
language = "en"
|
||||
multilingual = false
|
||||
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
67
docs/src/guide/silo.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Silo
|
||||
|
||||
Silo is an item database and part management system for Kindred Create. It provides revision-controlled storage for CAD files, 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:
|
||||
|
||||
- **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, used as Create's submodule), and `silo-calc` (LibreOffice Calc extension).
|
||||
|
||||
## Workbench commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| New | Create a new item in the database |
|
||||
| Open | Open an item by part number |
|
||||
| Save | Save the current document locally |
|
||||
| Commit | Save current state as a new revision with comment |
|
||||
| Pull | Download an item by part number |
|
||||
| Push | Batch upload modified files |
|
||||
| Info | View revision history and metadata |
|
||||
| BOM | View or edit the bill of materials |
|
||||
| TagProjects | Tag items with project identifiers |
|
||||
| Rollback | Revert to a previous revision |
|
||||
| SetStatus | Change item lifecycle status |
|
||||
| Settings | Configure Silo server connection |
|
||||
| Auth | Authenticate with the Silo server |
|
||||
|
||||
## Origin integration
|
||||
|
||||
Silo registers as a **file origin** via the `FileOrigin` interface in `src/Gui/`. This makes Silo commands (Commit, Pull, Push, Info, BOM) available in the File menu and Origin Tools toolbar across all workbenches.
|
||||
|
||||
The registration happens via a deferred QTimer (1500ms after startup) in `src/Mod/Create/InitGui.py`.
|
||||
|
||||
## Configuration
|
||||
|
||||
The FreeCAD workbench reads configuration from:
|
||||
|
||||
- `SILO_API_URL` — Server API endpoint (default: `http://localhost:8080/api`)
|
||||
- `SILO_PROJECTS_DIR` — Local projects directory (default: `~/projects`)
|
||||
|
||||
On first launch, Kindred Create prompts for Silo server configuration via the Settings command.
|
||||
|
||||
## Server setup
|
||||
|
||||
See `mods/silo/README.md` for full server deployment instructions. Quick start:
|
||||
|
||||
```bash
|
||||
# Database setup
|
||||
psql -h psql.kindred.internal -U silo -d silo -f migrations/001_initial.sql
|
||||
|
||||
# Configure
|
||||
cp config.example.yaml config.yaml
|
||||
# Edit config.yaml with your settings
|
||||
|
||||
# Run server
|
||||
go run ./cmd/silod
|
||||
```
|
||||
|
||||
The server supports LDAP and OIDC authentication, and provides a real-time activity feed via Server-Sent Events (SSE).
|
||||
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.
|
||||
48
docs/src/guide/ztools.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# ztools
|
||||
|
||||
ztools is a pure-Python FreeCAD workbench that consolidates part design, assembly, and sketcher tools into a single unified interface.
|
||||
|
||||
- **Submodule path:** `mods/ztools/`
|
||||
- **Source:** `git.kindred-systems.com/forbes/ztools`
|
||||
|
||||
## Features
|
||||
|
||||
### Datum Creator
|
||||
|
||||
Nine commands for creating datum geometry (planes, axes, points) with 16 creation modes. Modes include offset from face, through three points, normal to edge, and more. These are accessed from the ztools toolbar and are also injected into the PartDesign workbench.
|
||||
|
||||
### Enhanced Pocket
|
||||
|
||||
Extends FreeCAD's Pocket feature with flip-side cutting — the ability to cut outside the sketch profile rather than inside.
|
||||
|
||||
### Assembly Patterns
|
||||
|
||||
Linear and polar patterning tools for assemblies. Create regular arrangements of components without manually placing each one.
|
||||
|
||||
### Spreadsheet Formatting
|
||||
|
||||
Commands for formatting spreadsheet cells: bold, italic, underline, text alignment, and cell colors. Accessible from the ztools toolbar when a spreadsheet is active.
|
||||
|
||||
## PartDesign injection
|
||||
|
||||
ztools registers a `_ZToolsPartDesignManipulator` that hooks into the PartDesign workbench at startup. This injects ztools commands into PartDesign's menus and toolbars so they are available without switching workbenches.
|
||||
|
||||
The registration happens in `mods/ztools/ztools/ztools/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/ # 9 command implementations
|
||||
│ ├── datums/core.py # Datum creation (16 modes)
|
||||
│ └── resources/ # Icons and theme
|
||||
└── CatppuccinMocha/ # Theme preference pack
|
||||
```
|
||||
|
||||
## Further reading
|
||||
|
||||
- `mods/ztools/KINDRED_INTEGRATION.md` — integration architecture notes
|
||||
- `mods/ztools/ROADMAP.md` — planned features
|
||||
25
docs/src/introduction.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# 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.
|
||||
|
||||
**Update checker** — On startup, Kindred Create checks the Gitea releases API for newer versions and logs the result.
|
||||
|
||||
## 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>
|
||||
45
docs/src/reference/configuration.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Configuration
|
||||
|
||||
## Silo workbench
|
||||
|
||||
The Silo workbench stores its configuration in FreeCAD's parameter system under `User parameter:BaseApp/Preferences/Mod/KindredSilo`.
|
||||
|
||||
### Environment variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `SILO_API_URL` | `http://localhost:8080/api` | Silo server API endpoint |
|
||||
| `SILO_PROJECTS_DIR` | `~/projects` | Local directory for checked-out files |
|
||||
|
||||
### FreeCAD parameters
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `ApiUrl` | String | (empty) | Silo server URL |
|
||||
| `FirstStartChecked` | Bool | false | Whether the first-start prompt has been shown |
|
||||
|
||||
## Update checker
|
||||
|
||||
Configuration lives in `User parameter:BaseApp/Preferences/Mod/KindredCreate/Update`.
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `CheckEnabled` | Bool | true | Enable/disable update checks |
|
||||
| `CheckIntervalDays` | Int | 1 | Minimum days between checks |
|
||||
| `LastCheckTimestamp` | String | (empty) | ISO 8601 timestamp of last check |
|
||||
| `SkippedVersion` | String | (empty) | Version the user chose to skip |
|
||||
|
||||
The update checker queries the Gitea releases API at:
|
||||
```
|
||||
https://git.kindred-systems.com/api/v1/repos/kindred/create/releases
|
||||
```
|
||||
|
||||
## Theme
|
||||
|
||||
The default theme is **Catppuccin Mocha** (`KindredCreate.qss`). It is applied via the KindredCreate preference pack at startup.
|
||||
|
||||
To switch themes, go to **Edit > Preferences > General > Stylesheet** and select a different QSS file.
|
||||
|
||||
## Build presets
|
||||
|
||||
See `CMakePresets.json` for available build configurations. The pixi tasks (`configure`, `build`, etc.) use these presets automatically.
|
||||
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
@@ -0,0 +1,8 @@
|
||||
/* Kindred Create docs - minor overrides for coal theme */
|
||||
:root {
|
||||
--sidebar-width: 280px;
|
||||
}
|
||||
|
||||
.sidebar .sidebar-scrollbox {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
9
kindred-icons/AddonManager.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<rect x="6" y="6" width="9" height="9" rx="1" fill="none" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<rect x="17" y="6" width="9" height="9" rx="1" fill="none" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
<rect x="6" y="17" width="9" height="9" rx="1" fill="none" stroke="#f9e2af" stroke-width="1.5"/>
|
||||
<rect x="17" y="17" width="9" height="9" rx="1" fill="none" stroke="#cba6f7" stroke-width="1.5"/>
|
||||
<line x1="21" y1="19" x2="21" y2="25" stroke="#cba6f7" stroke-width="1.5"/>
|
||||
<line x1="18" y1="22" x2="24" y2="22" stroke="#cba6f7" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 675 B |
99
kindred-icons/AssemblyWorkbench.svg
Normal file
@@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg7"
|
||||
sodipodi:docname="AssemblyWorkbench.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs7" />
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="25"
|
||||
inkscape:cx="16"
|
||||
inkscape:cy="16"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1011"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg7" />
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="28"
|
||||
height="28"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<!-- Multiple parts assembled -->
|
||||
<!-- Part 1 - cube -->
|
||||
<path
|
||||
d="M6 18 L6 12 L12 9 L18 12 L18 18 L12 21 Z"
|
||||
fill="#45475a"
|
||||
stroke="#a6e3a1"
|
||||
stroke-width="1.5"
|
||||
id="path1" />
|
||||
<path
|
||||
d="M6 12 L12 15 L18 12"
|
||||
stroke="#a6e3a1"
|
||||
stroke-width="1"
|
||||
fill="none"
|
||||
id="path2" />
|
||||
<path
|
||||
d="M12 15 L12 21"
|
||||
stroke="#a6e3a1"
|
||||
stroke-width="1"
|
||||
id="path3" />
|
||||
<!-- Part 2 - connected piece -->
|
||||
<path
|
||||
d="m 15.16,22.52 v -6 l 6,-3 6,3 v 6 l -6,3 z"
|
||||
fill="#45475a"
|
||||
stroke="#94e2d5"
|
||||
stroke-width="1.5"
|
||||
id="path4"
|
||||
style="stroke:#74c7ec;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 15.16,16.52 6,3 6,-3"
|
||||
stroke="#94e2d5"
|
||||
stroke-width="1"
|
||||
fill="none"
|
||||
id="path5"
|
||||
style="stroke:#74c7ec;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 21.16,19.52 v 6"
|
||||
stroke="#94e2d5"
|
||||
stroke-width="1"
|
||||
id="path6"
|
||||
style="stroke:#74c7ec;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 11.11,13.318525 v -6 l 6,-3 6,3 v 6 l -6,3 z"
|
||||
fill="#45475a"
|
||||
stroke="#94e2d5"
|
||||
stroke-width="1.5"
|
||||
id="path4-6" />
|
||||
<path
|
||||
d="m 11.11,7.318525 6,3 6,-3"
|
||||
stroke="#94e2d5"
|
||||
stroke-width="1"
|
||||
fill="none"
|
||||
id="path5-2" />
|
||||
<path
|
||||
d="m 17.11,10.318525 v 6"
|
||||
stroke="#94e2d5"
|
||||
stroke-width="1"
|
||||
id="path6-9" />
|
||||
<!-- Connection indicator -->
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
11
kindred-icons/Assembly_CreateAssembly.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Multiple parts -->
|
||||
<rect x="5" y="14" width="8" height="8" rx="1" fill="#45475a" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
<rect x="19" y="14" width="8" height="8" rx="1" fill="#45475a" stroke="#94e2d5" stroke-width="1.5"/>
|
||||
<!-- Connection line -->
|
||||
<line x1="13" y1="18" x2="19" y2="18" stroke="#a6e3a1" stroke-width="2" stroke-dasharray="2,2"/>
|
||||
<!-- Plus sign for create -->
|
||||
<circle cx="24" cy="8" r="5" fill="#a6e3a1"/>
|
||||
<path d="M24 5.5 L24 10.5 M21.5 8 L26.5 8" stroke="#1e1e2e" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 678 B |
16
kindred-icons/Assembly_CreateJointDistance.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Two parts -->
|
||||
<rect x="4" y="12" width="8" height="10" rx="1" fill="#45475a" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
<rect x="20" y="12" width="8" height="10" rx="1" fill="#45475a" stroke="#94e2d5" stroke-width="1.5"/>
|
||||
<!-- Distance dimension -->
|
||||
<line x1="12" y1="17" x2="20" y2="17" stroke="#f9e2af" stroke-width="1.5"/>
|
||||
<line x1="12" y1="14" x2="12" y2="20" stroke="#f9e2af" stroke-width="1"/>
|
||||
<line x1="20" y1="14" x2="20" y2="20" stroke="#f9e2af" stroke-width="1"/>
|
||||
<!-- Arrows -->
|
||||
<path d="M12 17 L14 15 L14 19 Z" fill="#f9e2af"/>
|
||||
<path d="M20 17 L18 15 L18 19 Z" fill="#f9e2af"/>
|
||||
<!-- Distance value -->
|
||||
<rect x="13" y="6" width="6" height="5" rx="1" fill="#313244" stroke="#fab387" stroke-width="1"/>
|
||||
<text x="16" y="10" font-family="monospace" font-size="5" fill="#cdd6f4" text-anchor="middle">d</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 976 B |
12
kindred-icons/Assembly_CreateJointFixed.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Two parts -->
|
||||
<rect x="5" y="10" width="10" height="12" rx="1" fill="#45475a" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
<rect x="17" y="10" width="10" height="12" rx="1" fill="#45475a" stroke="#94e2d5" stroke-width="1.5"/>
|
||||
<!-- Fixed joint indicator - lock -->
|
||||
<rect x="13" y="14" width="6" height="6" rx="1" fill="#f9e2af" stroke="#fab387" stroke-width="1"/>
|
||||
<path d="M14 14 L14 12 A2 2 0 0 1 18 12 L18 14" fill="none" stroke="#fab387" stroke-width="1.5"/>
|
||||
<!-- Ground symbol -->
|
||||
<line x1="10" y1="26" x2="22" y2="26" stroke="#6c7086" stroke-width="2"/>
|
||||
<line x1="12" y1="28" x2="20" y2="28" stroke="#6c7086" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 785 B |
12
kindred-icons/Assembly_CreateJointRevolute.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Two parts connected by revolute joint -->
|
||||
<rect x="4" y="12" width="10" height="8" rx="1" fill="#45475a" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
<rect x="18" y="12" width="10" height="8" rx="1" fill="#45475a" stroke="#94e2d5" stroke-width="1.5"/>
|
||||
<!-- Revolute joint - hinge circle -->
|
||||
<circle cx="16" cy="16" r="5" fill="#313244" stroke="#f9e2af" stroke-width="2"/>
|
||||
<circle cx="16" cy="16" r="2" fill="#fab387"/>
|
||||
<!-- Rotation arrow -->
|
||||
<path d="M22 6 A8 8 0 0 1 10 6" stroke="#fab387" stroke-width="2" fill="none" stroke-linecap="round"/>
|
||||
<path d="M12 4 L10 6 L12 9" stroke="#fab387" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 820 B |
13
kindred-icons/Assembly_CreateJointSlider.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Rail/track -->
|
||||
<rect x="4" y="14" width="24" height="4" rx="1" fill="#45475a" stroke="#6c7086" stroke-width="1"/>
|
||||
<!-- Sliding part -->
|
||||
<rect x="10" y="10" width="8" height="12" rx="1" fill="#45475a" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
<!-- Slide direction arrows -->
|
||||
<path d="M6 8 L4 8 L4 24 L6 24" stroke="#f9e2af" stroke-width="2" fill="none" stroke-linecap="round"/>
|
||||
<path d="M26 8 L28 8 L28 24 L26 24" stroke="#f9e2af" stroke-width="2" fill="none" stroke-linecap="round"/>
|
||||
<!-- Motion arrow -->
|
||||
<path d="M20 16 L26 16" stroke="#94e2d5" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M23 13 L27 16 L23 19" stroke="#94e2d5" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 871 B |
10
kindred-icons/Assembly_InsertLink.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Part being inserted -->
|
||||
<path d="M8 20 L8 12 L14 9 L20 12 L20 20 L14 23 Z" fill="#45475a" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
<path d="M8 12 L14 15 L20 12" stroke="#a6e3a1" stroke-width="1" fill="none"/>
|
||||
<path d="M14 15 L14 23" stroke="#a6e3a1" stroke-width="1"/>
|
||||
<!-- Arrow indicating insertion -->
|
||||
<path d="M24 8 L24 18" stroke="#94e2d5" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M21 15 L24 19 L27 15" stroke="#94e2d5" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 668 B |
87
kindred-icons/Constraint_Dimension.svg
Normal file
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
sodipodi:docname="Constraint_Dimension.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs5" />
|
||||
<sodipodi:namedview
|
||||
id="namedview5"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="25"
|
||||
inkscape:cx="16"
|
||||
inkscape:cy="19.2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1011"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg5" />
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="28"
|
||||
height="28"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<!-- Line being dimensioned -->
|
||||
<!-- Dimension line -->
|
||||
<line
|
||||
x1="6"
|
||||
y1="12"
|
||||
x2="26"
|
||||
y2="12"
|
||||
stroke="#a6e3a1"
|
||||
stroke-width="1.5"
|
||||
id="line2" />
|
||||
<!-- Extension lines -->
|
||||
<line
|
||||
x1="6"
|
||||
y1="20"
|
||||
x2="6"
|
||||
y2="10"
|
||||
stroke="#a6e3a1"
|
||||
stroke-width="1"
|
||||
id="line3" />
|
||||
<line
|
||||
x1="26"
|
||||
y1="20"
|
||||
x2="26"
|
||||
y2="10"
|
||||
stroke="#a6e3a1"
|
||||
stroke-width="1"
|
||||
id="line4" />
|
||||
<!-- Arrows -->
|
||||
<path
|
||||
d="M6 12 L10 10 L10 14 Z"
|
||||
fill="#a6e3a1"
|
||||
id="path4" />
|
||||
<path
|
||||
d="M26 12 L22 10 L22 14 Z"
|
||||
fill="#a6e3a1"
|
||||
id="path5" />
|
||||
<line
|
||||
x1="6"
|
||||
y1="20"
|
||||
x2="26"
|
||||
y2="20"
|
||||
stroke="#f9e2af"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
id="line1" />
|
||||
<!-- Dimension text -->
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
13
kindred-icons/Constraint_Horizontal.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Horizontal line -->
|
||||
<line x1="6" y1="16" x2="26" y2="16" stroke="#f9e2af" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<!-- End points -->
|
||||
<circle cx="6" cy="16" r="2.5" fill="#fab387"/>
|
||||
<circle cx="26" cy="16" r="2.5" fill="#fab387"/>
|
||||
<!-- H indicator -->
|
||||
<text x="16" y="10" font-family="sans-serif" font-size="8" font-weight="bold" fill="#a6e3a1" text-anchor="middle">H</text>
|
||||
<!-- Constraint arrows -->
|
||||
<path d="M10 22 L6 22 L6 20" stroke="#a6e3a1" stroke-width="1.5" fill="none" stroke-linecap="round"/>
|
||||
<path d="M22 22 L26 22 L26 20" stroke="#a6e3a1" stroke-width="1.5" fill="none" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 772 B |
76
kindred-icons/Constraint_Perpendicular.svg
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
sodipodi:docname="Constraint_Perpendicular.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="namedview2"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="25"
|
||||
inkscape:cx="16"
|
||||
inkscape:cy="16"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1011"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="28"
|
||||
height="28"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<!-- Horizontal line -->
|
||||
<path
|
||||
d="m 15.969398,16.225639 h 6.224963 v 5.744963"
|
||||
fill="none"
|
||||
stroke="#a6e3a1"
|
||||
stroke-width="2.99007"
|
||||
id="path2"
|
||||
style="stroke-width:1.85574803;stroke-dasharray:none" />
|
||||
<line
|
||||
x1="6"
|
||||
y1="22"
|
||||
x2="26"
|
||||
y2="22"
|
||||
stroke="#f9e2af"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
id="line1" />
|
||||
<!-- Vertical line -->
|
||||
<line
|
||||
x1="16"
|
||||
y1="6"
|
||||
x2="16"
|
||||
y2="22"
|
||||
stroke="#f9e2af"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
id="line2" />
|
||||
<!-- Right angle indicator -->
|
||||
<!-- Intersection point -->
|
||||
<circle
|
||||
cx="16"
|
||||
cy="22"
|
||||
r="2"
|
||||
fill="#fab387"
|
||||
id="circle2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
9
kindred-icons/Constraint_PointOnPoint.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Two lines meeting at a point -->
|
||||
<line x1="6" y1="26" x2="16" y2="16" stroke="#f9e2af" stroke-width="2"/>
|
||||
<line x1="26" y1="6" x2="16" y2="16" stroke="#f9e2af" stroke-width="2"/>
|
||||
<!-- Coincident point -->
|
||||
<circle cx="16" cy="16" r="4" fill="#a6e3a1"/>
|
||||
<circle cx="16" cy="16" r="2" fill="#1e1e2e"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 451 B |
13
kindred-icons/Constraint_Vertical.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Vertical line -->
|
||||
<line x1="16" y1="6" x2="16" y2="26" stroke="#f9e2af" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<!-- End points -->
|
||||
<circle cx="16" cy="6" r="2.5" fill="#fab387"/>
|
||||
<circle cx="16" cy="26" r="2.5" fill="#fab387"/>
|
||||
<!-- V indicator -->
|
||||
<text x="24" y="18" font-family="sans-serif" font-size="8" font-weight="bold" fill="#a6e3a1" text-anchor="middle">V</text>
|
||||
<!-- Constraint arrows -->
|
||||
<path d="M8 10 L8 6 L10 6" stroke="#a6e3a1" stroke-width="1.5" fill="none" stroke-linecap="round"/>
|
||||
<path d="M8 22 L8 26 L10 26" stroke="#a6e3a1" stroke-width="1.5" fill="none" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 766 B |
117
kindred-icons/Document.svg
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="Document.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect5"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.8970359,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect4"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,2.25625,0,1 @ F,0,0,1,0,1.411235,0,1 @ F,0,0,1,0,1.2732549,0,1 @ F,0,0,1,0,2.25625,0,1 @ F,0,0,1,0,1.875,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="namedview4"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="10.90625"
|
||||
inkscape:cy="12.21875"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1371"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<rect
|
||||
width="32"
|
||||
height="32"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<path
|
||||
d="m 10.246497,6 h 8.332515 a 3.4070227,3.4070227 22.5 0 1 2.409129,0.9978938 l 2.101779,2.101779 a 3.0739092,3.0739092 67.5 0 1 0.900327,2.1735822 l 0,12.470495 A 2.25625,2.25625 135 0 1 21.733997,26 H 9.8652468 a 1.875,1.875 45 0 1 -1.875,-1.875 V 8.25625 A 2.25625,2.25625 135 0 1 10.246497,6 Z"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path1"
|
||||
inkscape:path-effect="#path-effect4"
|
||||
inkscape:original-d="M 7.9902468,6 H 19.990247 l 4,4 V 26 H 7.9902468 Z" />
|
||||
<path
|
||||
d="m 19.707388,5.8623613 v 3.4443418 a 0.8970359,0.8970359 45 0 0 0.897036,0.8970359 h 3.385823"
|
||||
fill="none"
|
||||
stroke="#74c7ec"
|
||||
stroke-width="1.61701"
|
||||
id="path2"
|
||||
style="stroke:#89b4fa;stroke-width:1.5;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:path-effect="#path-effect5"
|
||||
inkscape:original-d="m 19.707388,5.8623613 v 4.3413777 h 4.282859" />
|
||||
<line
|
||||
x1="11"
|
||||
y1="14"
|
||||
x2="21"
|
||||
y2="14"
|
||||
stroke="#74c7ec"
|
||||
stroke-width="1.5"
|
||||
id="line2"
|
||||
style="stroke-linecap:round" />
|
||||
<line
|
||||
x1="11"
|
||||
y1="18"
|
||||
x2="21"
|
||||
y2="18"
|
||||
stroke="#74c7ec"
|
||||
stroke-width="1.5"
|
||||
id="line3"
|
||||
style="stroke-linecap:round" />
|
||||
<line
|
||||
x1="11"
|
||||
y1="22"
|
||||
x2="17"
|
||||
y2="22"
|
||||
stroke="#74c7ec"
|
||||
stroke-width="1.5"
|
||||
id="line4"
|
||||
style="stroke-linecap:round" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
16
kindred-icons/DraftWorkbench.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Drafting tools - pencil and triangle -->
|
||||
<!-- Triangle/Set square -->
|
||||
<path d="M6 26 L6 10 L22 26 Z" fill="#45475a" stroke="#fab387" stroke-width="1.5"/>
|
||||
<!-- Pencil -->
|
||||
<g transform="translate(16, 4) rotate(45)">
|
||||
<rect x="0" y="0" width="4" height="16" rx="0.5" fill="#f9e2af" stroke="#fab387" stroke-width="1"/>
|
||||
<path d="M0 16 L2 20 L4 16 Z" fill="#585b70" stroke="#fab387" stroke-width="0.5"/>
|
||||
<rect x="0" y="0" width="4" height="3" fill="#f38ba8"/>
|
||||
</g>
|
||||
<!-- Grid dots -->
|
||||
<circle cx="10" cy="22" r="1" fill="#6c7086"/>
|
||||
<circle cx="14" cy="22" r="1" fill="#6c7086"/>
|
||||
<circle cx="10" cy="18" r="1" fill="#6c7086"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 790 B |
5
kindred-icons/DrawStyleAsIs.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<ellipse cx="16" cy="16" rx="10" ry="6" fill="none" stroke="#cdd6f4" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="16" cy="16" r="3" fill="none" stroke="#cdd6f4" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 344 B |
5
kindred-icons/DrawStyleFlatLines.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<path d="M5.5 9.5 16 4l10.5 5.5v13L16 28 5.5 22.5z" fill="#45475a" stroke="#89b4fa" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M5.5 9.5 16 15l10.5-5.5M16 15v13" fill="none" stroke="#89b4fa" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 419 B |
5
kindred-icons/DrawStyleNoShading.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<path d="M5.5 9.5 16 4l10.5 5.5v13L16 28 5.5 22.5z" fill="#585b70" stroke="#cdd6f4" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M5.5 9.5 16 15l10.5-5.5M16 15v13" fill="none" stroke="#cdd6f4" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 419 B |
10
kindred-icons/DrawStylePoints.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<circle cx="16" cy="4" r="1.5" fill="#cdd6f4"/>
|
||||
<circle cx="5.5" cy="9.5" r="1.5" fill="#cdd6f4"/>
|
||||
<circle cx="26.5" cy="9.5" r="1.5" fill="#cdd6f4"/>
|
||||
<circle cx="16" cy="15" r="1.5" fill="#cdd6f4"/>
|
||||
<circle cx="5.5" cy="22.5" r="1.5" fill="#cdd6f4"/>
|
||||
<circle cx="26.5" cy="22.5" r="1.5" fill="#cdd6f4"/>
|
||||
<circle cx="16" cy="28" r="1.5" fill="#cdd6f4"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 491 B |
5
kindred-icons/DrawStyleShaded.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<path d="M5.5 9.5 16 4l10.5 5.5v13L16 28 5.5 22.5z" fill="#45475a" stroke="#cdd6f4" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M5.5 9.5 16 15l10.5-5.5M16 15v13" fill="none" stroke="#cdd6f4" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 419 B |
5
kindred-icons/DrawStyleWireFrame.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<path d="M5.5 9.5 16 4l10.5 5.5v13L16 28 5.5 22.5z" fill="none" stroke="#cdd6f4" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M5.5 9.5 16 15l10.5-5.5M16 15v13" fill="none" stroke="#cdd6f4" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 416 B |
5
kindred-icons/Feature.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<path d="M8 24 L8 12 L16 6 L24 12 L24 24 Z" fill="none" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<path d="M8 12 L16 18 L24 12 M16 18 L16 6" fill="none" stroke="#74c7ec" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 314 B |
7
kindred-icons/Geoassembly.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<rect x="6" y="10" width="8" height="12" rx="1" fill="none" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
<rect x="18" y="10" width="8" height="12" rx="1" fill="none" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
<line x1="14" y1="14" x2="18" y2="14" stroke="#94e2d5" stroke-width="2"/>
|
||||
<line x1="14" y1="18" x2="18" y2="18" stroke="#94e2d5" stroke-width="2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 476 B |
9
kindred-icons/Geofeaturegroup.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<circle cx="16" cy="16" r="8" fill="none" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<circle cx="16" cy="16" r="4" fill="none" stroke="#74c7ec" stroke-width="1.5"/>
|
||||
<line x1="16" y1="4" x2="16" y2="8" stroke="#74c7ec" stroke-width="1.5"/>
|
||||
<line x1="16" y1="24" x2="16" y2="28" stroke="#74c7ec" stroke-width="1.5"/>
|
||||
<line x1="4" y1="16" x2="8" y2="16" stroke="#74c7ec" stroke-width="1.5"/>
|
||||
<line x1="24" y1="16" x2="28" y2="16" stroke="#74c7ec" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 595 B |
5
kindred-icons/Group.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<rect x="6" y="10" width="20" height="16" rx="2" fill="none" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<path d="M6 10 L6 8 C6 7 7 6 8 6 L14 6 L16 10" fill="none" stroke="#74c7ec" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 323 B |
5
kindred-icons/InTray.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<path d="M6 16 L6 24 L26 24 L26 16 L20 16 L18 20 L14 20 L12 16 Z" fill="none" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<path d="M16 6 L16 14 M12 10 L16 14 L20 10" stroke="#74c7ec" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 325 B |
6
kindred-icons/InTray_missed_notifications.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<path d="M6 16 L6 24 L26 24 L26 16 L20 16 L18 20 L14 20 L12 16 Z" fill="none" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<circle cx="24" cy="8" r="4" fill="#f38ba8"/>
|
||||
<text x="24" y="11" text-anchor="middle" font-family="sans-serif" font-size="6" font-weight="bold" fill="#313244">!</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 414 B |
6
kindred-icons/Invisible.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<ellipse cx="16" cy="16" rx="10" ry="6" fill="none" stroke="#585b70" stroke-width="1.5"/>
|
||||
<circle cx="16" cy="16" r="3" fill="#585b70"/>
|
||||
<line x1="6" y1="24" x2="26" y2="8" stroke="#f38ba8" stroke-width="2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 338 B |
55
kindred-icons/Link.svg
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
sodipodi:docname="Link.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs3" />
|
||||
<sodipodi:namedview
|
||||
id="namedview3"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="25.632621"
|
||||
inkscape:cx="14.005591"
|
||||
inkscape:cy="15.839192"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1371"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg3" />
|
||||
<rect
|
||||
width="32"
|
||||
height="32"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<path
|
||||
d="M 12.013793,20 H 8.0137931 a 4,4 0 0 1 0,-8 h 3.9999999"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path1" />
|
||||
<path
|
||||
d="m 20.013793,12 h 4 a 4,4 0 0 1 0,8 h -4"
|
||||
fill="none"
|
||||
stroke="#74c7ec"
|
||||
stroke-width="1.5"
|
||||
id="path2"
|
||||
style="stroke:#89b4fa;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:#89b4fa;stroke-width:1.77369;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 9.6965515,16 H 22.303449"
|
||||
id="path3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
62
kindred-icons/LinkArray.svg
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<rect
|
||||
width="32"
|
||||
height="32"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<circle
|
||||
cx="10"
|
||||
cy="10"
|
||||
r="4"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="circle1" />
|
||||
<circle
|
||||
cx="22"
|
||||
cy="10"
|
||||
r="4"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="circle2" />
|
||||
<circle
|
||||
cx="10"
|
||||
cy="22"
|
||||
r="4"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="circle3" />
|
||||
<circle
|
||||
cx="22"
|
||||
cy="22"
|
||||
r="4"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="circle4" />
|
||||
<line
|
||||
x1="14"
|
||||
y1="10"
|
||||
x2="18"
|
||||
y2="10"
|
||||
stroke="#cba6f7"
|
||||
stroke-width="1.5"
|
||||
id="line1" />
|
||||
<line
|
||||
x1="10"
|
||||
y1="14"
|
||||
x2="10"
|
||||
y2="18"
|
||||
stroke="#cba6f7"
|
||||
stroke-width="1.5"
|
||||
id="line2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
52
kindred-icons/LinkArrayOverlay.svg
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<rect
|
||||
width="32"
|
||||
height="32"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<rect
|
||||
x="6"
|
||||
y="6"
|
||||
width="10"
|
||||
height="10"
|
||||
rx="1.5"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="rect2" />
|
||||
<rect
|
||||
x="10"
|
||||
y="10"
|
||||
width="10"
|
||||
height="10"
|
||||
rx="1.5"
|
||||
fill="#313244"
|
||||
stroke="#cba6f7"
|
||||
stroke-width="1.5"
|
||||
id="rect3" />
|
||||
<rect
|
||||
x="14"
|
||||
y="14"
|
||||
width="10"
|
||||
height="10"
|
||||
rx="1.5"
|
||||
fill="#313244"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="rect4" />
|
||||
<circle
|
||||
cx="24"
|
||||
cy="8"
|
||||
r="4"
|
||||
fill="none"
|
||||
stroke="#a6e3a1"
|
||||
stroke-width="1.5"
|
||||
id="circle1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 910 B |
35
kindred-icons/LinkElement.svg
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<rect
|
||||
width="32"
|
||||
height="32"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<rect
|
||||
x="8"
|
||||
y="8"
|
||||
width="10"
|
||||
height="10"
|
||||
rx="1.5"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="rect2" />
|
||||
<path
|
||||
d="M 18,18 24,24"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path1" />
|
||||
<circle
|
||||
cx="24"
|
||||
cy="24"
|
||||
r="3"
|
||||
fill="#cba6f7"
|
||||
id="circle1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 636 B |
48
kindred-icons/LinkGroup.svg
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<rect
|
||||
width="32"
|
||||
height="32"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<rect
|
||||
x="6"
|
||||
y="10"
|
||||
width="20"
|
||||
height="14"
|
||||
rx="2"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="rect2" />
|
||||
<circle
|
||||
cx="12"
|
||||
cy="17"
|
||||
r="3"
|
||||
fill="none"
|
||||
stroke="#cba6f7"
|
||||
stroke-width="1.5"
|
||||
id="circle1" />
|
||||
<circle
|
||||
cx="20"
|
||||
cy="17"
|
||||
r="3"
|
||||
fill="none"
|
||||
stroke="#cba6f7"
|
||||
stroke-width="1.5"
|
||||
id="circle2" />
|
||||
<line
|
||||
x1="15"
|
||||
y1="17"
|
||||
x2="17"
|
||||
y2="17"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="line1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 838 B |
69
kindred-icons/LinkImport.svg
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
sodipodi:docname="LinkImport.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs3" />
|
||||
<sodipodi:namedview
|
||||
id="namedview3"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="25.632621"
|
||||
inkscape:cx="14.005591"
|
||||
inkscape:cy="15.800179"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1371"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg3" />
|
||||
<rect
|
||||
width="32"
|
||||
height="32"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<path
|
||||
d="M 12.013793,20 H 8.0137931 a 4,4 0 0 1 0,-8 h 3.9999999"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path1" />
|
||||
<path
|
||||
d="m 20.013793,12 h 4 a 4,4 0 0 1 0,8 h -4"
|
||||
fill="none"
|
||||
stroke="#74c7ec"
|
||||
stroke-width="1.5"
|
||||
id="path2"
|
||||
style="stroke:#89b4fa;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:#89b4fa;stroke-width:1.77369;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 9.6965515,16 H 22.303449"
|
||||
id="path3" />
|
||||
<circle
|
||||
cx="25.513792"
|
||||
cy="-9.2321157"
|
||||
fill="#a6e3a1"
|
||||
id="circle2"
|
||||
style="stroke-width:0.999999"
|
||||
transform="scale(1,-1)"
|
||||
r="5" />
|
||||
<path
|
||||
d="M 25.51379,11.732116 V 6.7321179 m -2.499999,2.4999988 h 5"
|
||||
stroke="#1e1e2e"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
id="path3-7" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
42
kindred-icons/LinkImportAll.svg
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<rect
|
||||
width="32"
|
||||
height="32"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<circle
|
||||
cx="10"
|
||||
cy="10"
|
||||
r="3"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="circle1" />
|
||||
<circle
|
||||
cx="22"
|
||||
cy="10"
|
||||
r="3"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="circle2" />
|
||||
<circle
|
||||
cx="10"
|
||||
cy="20"
|
||||
r="3"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="circle3" />
|
||||
<path
|
||||
d="M 24,18 24,26 18,22 Z"
|
||||
fill="#a6e3a1"
|
||||
id="path1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 764 B |
34
kindred-icons/LinkOverlay.svg
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<rect
|
||||
width="32"
|
||||
height="32"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<rect
|
||||
x="6"
|
||||
y="6"
|
||||
width="12"
|
||||
height="12"
|
||||
rx="1.5"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="rect2" />
|
||||
<rect
|
||||
x="14"
|
||||
y="14"
|
||||
width="12"
|
||||
height="12"
|
||||
rx="1.5"
|
||||
fill="#313244"
|
||||
stroke="#cba6f7"
|
||||
stroke-width="1.5"
|
||||
id="rect3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 616 B |
42
kindred-icons/LinkReplace.svg
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<rect
|
||||
width="32"
|
||||
height="32"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<circle
|
||||
cx="10"
|
||||
cy="16"
|
||||
r="5"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="circle1" />
|
||||
<circle
|
||||
cx="22"
|
||||
cy="16"
|
||||
r="5"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="circle2" />
|
||||
<path
|
||||
d="M 13,12 19,12 M 19,12 17,10 M 19,12 17,14"
|
||||
stroke="#a6e3a1"
|
||||
stroke-width="1.5"
|
||||
fill="none"
|
||||
id="path1" />
|
||||
<path
|
||||
d="M 19,20 13,20 M 13,20 15,18 M 13,20 15,22"
|
||||
stroke="#f38ba8"
|
||||
stroke-width="1.5"
|
||||
fill="none"
|
||||
id="path2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 837 B |
62
kindred-icons/LinkSelect.svg
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
sodipodi:docname="LinkSelect.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs3" />
|
||||
<sodipodi:namedview
|
||||
id="namedview3"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="25.632621"
|
||||
inkscape:cx="14.005591"
|
||||
inkscape:cy="15.800179"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1371"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg3" />
|
||||
<rect
|
||||
width="32"
|
||||
height="32"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<path
|
||||
d="M 12.013793,20 H 8.0137931 a 4,4 0 0 1 0,-8 h 3.9999999"
|
||||
fill="none"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path1" />
|
||||
<path
|
||||
d="m 20.013793,12 h 4 a 4,4 0 0 1 0,8 h -4"
|
||||
fill="none"
|
||||
stroke="#74c7ec"
|
||||
stroke-width="1.5"
|
||||
id="path2"
|
||||
style="stroke:#89b4fa;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:#89b4fa;stroke-width:1.77369;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 9.6965515,16 H 22.303449"
|
||||
id="path3" />
|
||||
<rect
|
||||
style="fill:none;stroke:#fab387;stroke-width:1.056;stroke-dasharray:1.05599999, 2.11199999;stroke-linejoin:round;stroke-linecap:round;stroke-dashoffset:15.41759968;stroke-opacity:1"
|
||||
id="rect2"
|
||||
width="28.12822"
|
||||
height="14.785847"
|
||||
x="1.9358902"
|
||||
y="8.6070766" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
19
kindred-icons/MeshWorkbench.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Mesh triangles -->
|
||||
<path d="M16 6 L6 24 L26 24 Z" fill="#45475a" stroke="#f5c2e7" stroke-width="1.5"/>
|
||||
<!-- Internal mesh lines -->
|
||||
<line x1="16" y1="6" x2="11" y2="15" stroke="#f5c2e7" stroke-width="1"/>
|
||||
<line x1="16" y1="6" x2="21" y2="15" stroke="#f5c2e7" stroke-width="1"/>
|
||||
<line x1="11" y1="15" x2="21" y2="15" stroke="#f5c2e7" stroke-width="1"/>
|
||||
<line x1="11" y1="15" x2="6" y2="24" stroke="#f5c2e7" stroke-width="1"/>
|
||||
<line x1="21" y1="15" x2="26" y2="24" stroke="#f5c2e7" stroke-width="1"/>
|
||||
<line x1="11" y1="15" x2="16" y2="24" stroke="#f5c2e7" stroke-width="1"/>
|
||||
<line x1="21" y1="15" x2="16" y2="24" stroke="#f5c2e7" stroke-width="1"/>
|
||||
<!-- Vertices -->
|
||||
<circle cx="16" cy="6" r="2" fill="#f2cdcd"/>
|
||||
<circle cx="6" cy="24" r="2" fill="#f2cdcd"/>
|
||||
<circle cx="26" cy="24" r="2" fill="#f2cdcd"/>
|
||||
<circle cx="11" cy="15" r="1.5" fill="#f2cdcd"/>
|
||||
<circle cx="21" cy="15" r="1.5" fill="#f2cdcd"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
11
kindred-icons/PartDesignWorkbench.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- 3D extruded shape representing Part Design -->
|
||||
<path d="M8 22 L8 12 L16 8 L24 12 L24 22 L16 26 Z" fill="#45475a" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<path d="M8 12 L16 16 L24 12" stroke="#89b4fa" stroke-width="1.5" fill="none"/>
|
||||
<path d="M16 16 L16 26" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<!-- Top face highlight -->
|
||||
<path d="M8 12 L16 8 L24 12 L16 16 Z" fill="#74c7ec" fill-opacity="0.3"/>
|
||||
<!-- Gear accent indicating design/engineering -->
|
||||
<circle cx="16" cy="14" r="3" fill="none" stroke="#74c7ec" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 682 B |
13
kindred-icons/PartDesign_Body.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- 3D body representation -->
|
||||
<path d="M6 22 L6 10 L16 6 L26 10 L26 22 L16 26 Z" fill="#45475a" stroke="#89b4fa" stroke-width="2"/>
|
||||
<path d="M6 10 L16 14 L26 10" stroke="#89b4fa" stroke-width="2" fill="none"/>
|
||||
<path d="M16 14 L16 26" stroke="#89b4fa" stroke-width="2"/>
|
||||
<!-- Top face highlight -->
|
||||
<path d="M6 10 L16 6 L26 10 L16 14 Z" fill="#74c7ec" fill-opacity="0.4"/>
|
||||
<!-- Origin indicator -->
|
||||
<circle cx="16" cy="16" r="2" fill="#a6e3a1"/>
|
||||
<line x1="16" y1="12" x2="16" y2="20" stroke="#a6e3a1" stroke-width="1"/>
|
||||
<line x1="12" y1="16" x2="20" y2="16" stroke="#a6e3a1" stroke-width="1"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 750 B |
76
kindred-icons/PartDesign_Chamfer.svg
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
sodipodi:docname="PartDesign_Chamfer.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs5" />
|
||||
<sodipodi:namedview
|
||||
id="namedview5"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="22.627417"
|
||||
inkscape:cx="11.136932"
|
||||
inkscape:cy="18.473165"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1011"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg5" />
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="28"
|
||||
height="28"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<!-- Block with chamfered edge -->
|
||||
<path
|
||||
d="M 6,24 5.9375,16.0625 11.171008,8.026064 16,6 26,10 V 24 L 16,28 Z M 20.923535,12.327039 26.006643,9.9805673 Z"
|
||||
fill="#45475a"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path1"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
<path
|
||||
d="M 16,19.88 V 28"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path3"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
d="M 5.721457,16 10.416889,7.8973687 21,12 16.132583,20.145165 Z"
|
||||
fill="#a6e3a1"
|
||||
fill-opacity="0.3"
|
||||
id="path5"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
style="opacity:1;fill:#a6e3a1;fill-opacity:1" />
|
||||
<!-- Chamfer cut on edge -->
|
||||
<!-- Chamfer face -->
|
||||
<path
|
||||
d="M 21.289264,12.075764 15.938527,20.29433"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5847"
|
||||
id="path3-0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
d="M 11.313916,7.9020371 5.8336127,16.235844"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.61498"
|
||||
id="path3-0-3"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
78
kindred-icons/PartDesign_Fillet.svg
Normal file
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
sodipodi:docname="PartDesign_Fillet.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs5" />
|
||||
<sodipodi:namedview
|
||||
id="namedview5"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="22.627417"
|
||||
inkscape:cx="2.8284271"
|
||||
inkscape:cy="17.412504"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1371"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg5" />
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="28"
|
||||
height="28"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<!-- Block with chamfered edge -->
|
||||
<path
|
||||
d="M 6,24 6.1584709,15.885723 10.508095,8.6005883 16,6 26,10 V 24 L 16,28 Z M 20.923535,12.327039 26.006643,9.9805673 Z"
|
||||
fill="#45475a"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path1"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
<path
|
||||
d="M 16,19.88 V 28"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path3"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
d="M 5.721457,16 10.416889,7.8973687 21,12 l -3.708852,3.943415 -1.158565,4.20175 z"
|
||||
fill="#a6e3a1"
|
||||
fill-opacity="0.3"
|
||||
id="path5"
|
||||
sodipodi:nodetypes="cccccc"
|
||||
style="opacity:1;fill:#a6e3a1;fill-opacity:1" />
|
||||
<!-- Chamfer cut on edge -->
|
||||
<!-- Chamfer face -->
|
||||
<path
|
||||
d="m 25.554002,10.020735 c 0,0 -2.839088,1.13525 -4.950437,2.544214 -1.652011,1.102435 -2.601422,2.423855 -3.100562,3.159378 -1.011406,1.490386 -1.47202,3.667857 -1.538841,4.165681 -0.0066,0.04949 -0.01392,7.861307 -0.01392,7.861307 m 7.653323,-14.186366"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5847"
|
||||
id="path3-0"
|
||||
sodipodi:nodetypes="csssc"
|
||||
style="fill:none" />
|
||||
<path
|
||||
d="m 16.23145,6.006509 c 0,0 -3.524098,1.0247646 -5.635447,2.4337286 -1.6520107,1.1024351 -2.6014217,2.4238554 -3.1005617,3.1593784 -1.011406,1.490386 -1.47202,3.667857 -1.538841,4.165681 -0.0066,0.04949 0.2070509,8.612608 0.2070509,8.612608"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5847"
|
||||
id="path3-0-6"
|
||||
sodipodi:nodetypes="csssc"
|
||||
style="fill:none" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
13
kindred-icons/PartDesign_Hole.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Block with hole -->
|
||||
<path d="M4 22 L4 10 L16 6 L28 10 L28 22 L16 26 Z" fill="#45475a" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<path d="M4 10 L16 14 L28 10" stroke="#89b4fa" stroke-width="1.5" fill="none"/>
|
||||
<path d="M16 14 L16 26" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<!-- Circular hole on top -->
|
||||
<ellipse cx="16" cy="11" rx="5" ry="2" fill="#1e1e2e" stroke="#f38ba8" stroke-width="1.5"/>
|
||||
<!-- Hole depth indication -->
|
||||
<path d="M11 11 L11 18" stroke="#f38ba8" stroke-width="1" stroke-dasharray="2,1"/>
|
||||
<path d="M21 11 L21 18" stroke="#f38ba8" stroke-width="1" stroke-dasharray="2,1"/>
|
||||
<ellipse cx="16" cy="18" rx="5" ry="2" fill="none" stroke="#f38ba8" stroke-width="1" stroke-dasharray="2,1"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 855 B |
64
kindred-icons/PartDesign_NewSketch.svg
Normal file
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
sodipodi:docname="PartDesign_NewSketch.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs3" />
|
||||
<sodipodi:namedview
|
||||
id="namedview3"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="36.25"
|
||||
inkscape:cx="16"
|
||||
inkscape:cy="16"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1371"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg3" />
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="28"
|
||||
height="28"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<!-- Sketch plane -->
|
||||
<path
|
||||
d="m 4,17.158621 12,-8.0000003 12,8.0000003 -12,8 z"
|
||||
fill="#45475a"
|
||||
stroke="#f9e2af"
|
||||
stroke-width="1.5"
|
||||
id="path1" />
|
||||
<!-- Grid on plane -->
|
||||
<!-- Sketch geometry -->
|
||||
<!-- Plus sign for "new" -->
|
||||
<circle
|
||||
cx="23.092838"
|
||||
cy="-10.553846"
|
||||
fill="#a6e3a1"
|
||||
id="circle2"
|
||||
style="stroke-width:0.999999"
|
||||
transform="scale(1,-1)"
|
||||
r="5" />
|
||||
<path
|
||||
d="M 23.092837,13.053846 V 8.0538483 m -2.499999,2.4999987 h 5"
|
||||
stroke="#1e1e2e"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
id="path3-7" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
62
kindred-icons/PartDesign_Pad.svg
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="28"
|
||||
height="28"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<!-- Base sketch profile -->
|
||||
<path
|
||||
d="M 6,24 6,20 14,18 26,20 26,24 14,26 Z"
|
||||
fill="#45475a"
|
||||
stroke="#6c7086"
|
||||
stroke-width="1"
|
||||
id="path1" />
|
||||
<!-- Extruded body -->
|
||||
<path
|
||||
d="M 6,20 6,10 14,8 26,10 26,20 14,22 Z"
|
||||
fill="#45475a"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path2" />
|
||||
<path
|
||||
d="M 6,10 14,12 26,10"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
fill="none"
|
||||
id="path3" />
|
||||
<path
|
||||
d="M 14,12 V 22"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path4" />
|
||||
<!-- Top face -->
|
||||
<path
|
||||
d="M 6,10 14,8 26,10 14,12 Z"
|
||||
fill="#74c7ec"
|
||||
fill-opacity="0.4"
|
||||
id="path5" />
|
||||
<!-- Extrude arrow -->
|
||||
<path
|
||||
d="M 20,18 V 6"
|
||||
stroke="#a6e3a1"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
id="path6" />
|
||||
<path
|
||||
d="M 17,9 20,5 23,9"
|
||||
stroke="#a6e3a1"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
fill="none"
|
||||
id="path7" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
67
kindred-icons/PartDesign_Pocket.svg
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="28"
|
||||
height="28"
|
||||
rx="4"
|
||||
fill="#313244"
|
||||
id="rect1" />
|
||||
<!-- Solid block -->
|
||||
<path
|
||||
d="M 4,22 4,10 16,6 28,10 28,22 16,26 Z"
|
||||
fill="#45475a"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path1" />
|
||||
<path
|
||||
d="M 4,10 16,14 28,10"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
fill="none"
|
||||
id="path2" />
|
||||
<path
|
||||
d="M 16,14 V 26"
|
||||
stroke="#89b4fa"
|
||||
stroke-width="1.5"
|
||||
id="path3" />
|
||||
<!-- Pocket cut-out -->
|
||||
<path
|
||||
d="M 10,12 16,10 22,12 22,18 16,20 10,18 Z"
|
||||
fill="#1e1e2e"
|
||||
stroke="#f38ba8"
|
||||
stroke-width="1.5"
|
||||
id="path4" />
|
||||
<path
|
||||
d="M 10,12 16,14 22,12"
|
||||
stroke="#f38ba8"
|
||||
stroke-width="1"
|
||||
fill="none"
|
||||
id="path5" />
|
||||
<path
|
||||
d="M 16,14 V 20"
|
||||
stroke="#f38ba8"
|
||||
stroke-width="1"
|
||||
id="path6" />
|
||||
<!-- Cut arrow -->
|
||||
<path
|
||||
d="M 16,8 V 16"
|
||||
stroke="#f38ba8"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
id="path7" />
|
||||
<path
|
||||
d="M 14,13 16,17 18,13"
|
||||
stroke="#f38ba8"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
fill="none"
|
||||
id="path8" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
12
kindred-icons/PartDesign_Revolution.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Revolved shape - vase/cone profile -->
|
||||
<ellipse cx="16" cy="24" rx="10" ry="3" fill="#45475a" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<path d="M6 24 Q6 12 12 8 L20 8 Q26 12 26 24" fill="#45475a" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<ellipse cx="16" cy="8" rx="4" ry="1.5" fill="#74c7ec" fill-opacity="0.4" stroke="#89b4fa" stroke-width="1"/>
|
||||
<!-- Axis line -->
|
||||
<line x1="16" y1="4" x2="16" y2="28" stroke="#a6e3a1" stroke-width="1.5" stroke-dasharray="3,2"/>
|
||||
<!-- Rotation arrow -->
|
||||
<path d="M22 6 A6 6 0 0 1 22 14" stroke="#a6e3a1" stroke-width="2" fill="none" stroke-linecap="round"/>
|
||||
<path d="M20 12 L22 15 L25 13" stroke="#a6e3a1" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 870 B |
9
kindred-icons/PartWorkbench.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Simple 3D primitive - cube with boolean indication -->
|
||||
<path d="M6 20 L6 10 L16 6 L26 10 L26 20 L16 24 Z" fill="#45475a" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<path d="M6 10 L16 14 L26 10" stroke="#89b4fa" stroke-width="1.5" fill="none"/>
|
||||
<path d="M16 14 L16 24" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<!-- Boolean cut-out indication -->
|
||||
<circle cx="18" cy="15" r="4" fill="#313244" stroke="#74c7ec" stroke-width="1.5" stroke-dasharray="2,1"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 595 B |
121
kindred-icons/README.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Kindred Create Icons
|
||||
|
||||
This directory contains custom Catppuccin Mocha themed SVG icons that override the default FreeCAD icons.
|
||||
|
||||
## How It Works
|
||||
|
||||
Icons placed in this directory are loaded **before** the default FreeCAD icons. To override an icon, simply create an SVG file with the same name as the original icon.
|
||||
|
||||
For example, to override `document-save.svg`, create `kindred-icons/document-save.svg`.
|
||||
|
||||
## Icon Design Standards
|
||||
|
||||
All Kindred Create icons follow these guidelines:
|
||||
|
||||
### Template
|
||||
|
||||
```svg
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Icon content using Catppuccin Mocha colors -->
|
||||
</svg>
|
||||
```
|
||||
|
||||
### Specifications
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| ViewBox | 32x32 |
|
||||
| Background | Rounded rect, rx=4, fill=`#313244` (surface0) |
|
||||
| Stroke width | 1.5-2.5 for main elements |
|
||||
| Style | Flat, minimal, geometric |
|
||||
|
||||
### Catppuccin Mocha Palette
|
||||
|
||||
| Color | Hex | Usage |
|
||||
|-------|-----|-------|
|
||||
| Base | `#1e1e2e` | Deep backgrounds |
|
||||
| Mantle | `#181825` | Darker backgrounds |
|
||||
| Crust | `#11111b` | Darkest backgrounds |
|
||||
| Surface0 | `#313244` | **Icon backgrounds** |
|
||||
| Surface1 | `#45475a` | Elevated surfaces |
|
||||
| Surface2 | `#585b70` | Higher surfaces |
|
||||
| Overlay0 | `#6c7086` | Subtle elements |
|
||||
| Overlay1 | `#7f849c` | More visible overlays |
|
||||
| Overlay2 | `#9399b2` | Prominent overlays |
|
||||
| Subtext0 | `#a6adc8` | Tertiary text |
|
||||
| Subtext1 | `#bac2de` | Secondary text |
|
||||
| Text | `#cdd6f4` | **Primary text/strokes** |
|
||||
| Lavender | `#b4befe` | Soft purple accent |
|
||||
| Blue | `#89b4fa` | **File operations** |
|
||||
| Sapphire | `#74c7ec` | Links, info |
|
||||
| Sky | `#89dceb` | Light blue accent |
|
||||
| Teal | `#94e2d5` | Success secondary |
|
||||
| Green | `#a6e3a1` | **Edit operations, Creation/Success** |
|
||||
| Yellow | `#f9e2af` | **View operations** |
|
||||
| Peach | `#fab387` | **View accents** |
|
||||
| Maroon | `#eba0ac` | Soft red |
|
||||
| Red | `#f38ba8` | **Deletion/Error** |
|
||||
| Mauve | `#cba6f7` | **System/Settings** |
|
||||
| Lavender | `#b4befe` | **System accents** |
|
||||
| Pink | `#f5c2e7` | Decorative |
|
||||
| Flamingo | `#f2cdcd` | Soft accents |
|
||||
| Rosewater | `#f5e0dc` | Lightest accent |
|
||||
|
||||
### Workbench Color Coding
|
||||
|
||||
Each workbench uses a distinct accent color:
|
||||
|
||||
| Workbench | Primary | Accent |
|
||||
|-----------|---------|--------|
|
||||
| Part Design | Blue `#89b4fa` | Sapphire `#74c7ec` |
|
||||
| Sketcher | Yellow `#f9e2af` | Peach `#fab387` |
|
||||
| Assembly | Green `#a6e3a1` | Teal `#94e2d5` |
|
||||
| TechDraw | Mauve `#cba6f7` | Lavender `#b4befe` |
|
||||
| Spreadsheet | Sky `#89dceb` | Sapphire `#74c7ec` |
|
||||
| Mesh | Pink `#f5c2e7` | Flamingo `#f2cdcd` |
|
||||
| Draft | Peach `#fab387` | Yellow `#f9e2af` |
|
||||
|
||||
## Adding New Icons
|
||||
|
||||
1. Identify the original icon name (e.g., `document-save.svg`)
|
||||
2. Create your SVG using the template above
|
||||
3. Save it in this directory with the exact same filename
|
||||
4. The new icon will be used on next application start
|
||||
|
||||
## Finding Original Icon Names
|
||||
|
||||
Original icons are located in:
|
||||
- `src/Gui/Icons/` - Core GUI icons
|
||||
- `src/Mod/*/Gui/Resources/icons/` - Module-specific icons
|
||||
|
||||
Use the same filename to override.
|
||||
|
||||
## Icon Categories
|
||||
|
||||
The icon set covers these categories:
|
||||
|
||||
| Category | Count | Examples |
|
||||
|----------|-------|----------|
|
||||
| File Operations | 15+ | document-save, document-open, Std_Export |
|
||||
| Edit Operations | 20+ | edit-undo, edit-copy, edit-paste |
|
||||
| View Operations | 35+ | zoom-in, DrawStyle*, Std_View* |
|
||||
| System/Settings | 15+ | preferences-system, help-browser |
|
||||
| Tree View | 15 | Tree_*, tree-* |
|
||||
| Link/Structure | 15+ | Link*, Feature, Group |
|
||||
| Workbenches | 8 | PartDesignWorkbench, SketcherWorkbench |
|
||||
| PartDesign | 8 | PartDesign_Pad, PartDesign_Pocket |
|
||||
| Sketcher | 10+ | Sketcher_Create*, Constraint_* |
|
||||
| Assembly | 6 | Assembly_Create*, Assembly_Insert* |
|
||||
| Navigation | 10+ | button_*, cursor-* |
|
||||
| Selection | 8 | *-selection, clear-selection |
|
||||
| DAG View | 4 | dagView* |
|
||||
|
||||
**Total: 191 icons**
|
||||
|
||||
## Related Issues
|
||||
|
||||
- Epic: https://git.kindred-systems.com/kindred/create/issues/7
|
||||
- Phase 1 (Core): https://git.kindred-systems.com/kindred/create/issues/4
|
||||
- Phase 2 (Workbench): https://git.kindred-systems.com/kindred/create/issues/5
|
||||
- Phase 3 (Complete): https://git.kindred-systems.com/kindred/create/issues/6
|
||||
15
kindred-icons/SketcherWorkbench.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Grid lines representing sketch plane -->
|
||||
<line x1="6" y1="10" x2="26" y2="10" stroke="#45475a" stroke-width="1"/>
|
||||
<line x1="6" y1="16" x2="26" y2="16" stroke="#45475a" stroke-width="1"/>
|
||||
<line x1="6" y1="22" x2="26" y2="22" stroke="#45475a" stroke-width="1"/>
|
||||
<line x1="10" y1="6" x2="10" y2="26" stroke="#45475a" stroke-width="1"/>
|
||||
<line x1="16" y1="6" x2="16" y2="26" stroke="#45475a" stroke-width="1"/>
|
||||
<line x1="22" y1="6" x2="22" y2="26" stroke="#45475a" stroke-width="1"/>
|
||||
<!-- Sketch profile -->
|
||||
<path d="M8 20 L8 12 L14 8 L24 8 L24 18 L18 24 L8 20" fill="none" stroke="#f9e2af" stroke-width="2" stroke-linejoin="round"/>
|
||||
<!-- Constraint point -->
|
||||
<circle cx="8" cy="12" r="2" fill="#fab387"/>
|
||||
<circle cx="24" cy="8" r="2" fill="#fab387"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 911 B |
12
kindred-icons/Sketcher_CreateArc.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Arc -->
|
||||
<path d="M6 24 A14 14 0 0 1 26 24" fill="none" stroke="#f9e2af" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<!-- End points -->
|
||||
<circle cx="6" cy="24" r="2.5" fill="#fab387"/>
|
||||
<circle cx="26" cy="24" r="2.5" fill="#fab387"/>
|
||||
<!-- Center point -->
|
||||
<circle cx="16" cy="24" r="2" fill="#fab387" fill-opacity="0.6"/>
|
||||
<!-- Radius indicator -->
|
||||
<line x1="16" y1="24" x2="16" y2="10" stroke="#fab387" stroke-width="1" stroke-dasharray="2,2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 602 B |
9
kindred-icons/Sketcher_CreateCircle.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Circle -->
|
||||
<circle cx="16" cy="16" r="10" fill="none" stroke="#f9e2af" stroke-width="2.5"/>
|
||||
<!-- Center point -->
|
||||
<circle cx="16" cy="16" r="2.5" fill="#fab387"/>
|
||||
<!-- Radius line -->
|
||||
<line x1="16" y1="16" x2="26" y2="16" stroke="#fab387" stroke-width="1.5" stroke-dasharray="2,2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 435 B |
8
kindred-icons/Sketcher_CreateLine.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Line -->
|
||||
<line x1="6" y1="26" x2="26" y2="6" stroke="#f9e2af" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<!-- End points -->
|
||||
<circle cx="6" cy="26" r="3" fill="#fab387"/>
|
||||
<circle cx="26" cy="6" r="3" fill="#fab387"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 368 B |
11
kindred-icons/Sketcher_CreatePoint.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Point with crosshair -->
|
||||
<circle cx="16" cy="16" r="5" fill="#fab387"/>
|
||||
<circle cx="16" cy="16" r="3" fill="#f9e2af"/>
|
||||
<!-- Crosshair lines -->
|
||||
<line x1="16" y1="6" x2="16" y2="11" stroke="#f9e2af" stroke-width="1.5"/>
|
||||
<line x1="16" y1="21" x2="16" y2="26" stroke="#f9e2af" stroke-width="1.5"/>
|
||||
<line x1="6" y1="16" x2="11" y2="16" stroke="#f9e2af" stroke-width="1.5"/>
|
||||
<line x1="21" y1="16" x2="26" y2="16" stroke="#f9e2af" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 602 B |
10
kindred-icons/Sketcher_CreateRectangle.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Rectangle -->
|
||||
<rect x="6" y="8" width="20" height="16" rx="1" fill="none" stroke="#f9e2af" stroke-width="2.5"/>
|
||||
<!-- Corner points -->
|
||||
<circle cx="6" cy="8" r="2.5" fill="#fab387"/>
|
||||
<circle cx="26" cy="8" r="2.5" fill="#fab387"/>
|
||||
<circle cx="6" cy="24" r="2.5" fill="#fab387"/>
|
||||
<circle cx="26" cy="24" r="2.5" fill="#fab387"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 481 B |
20
kindred-icons/SpreadsheetWorkbench.svg
Normal file
@@ -0,0 +1,20 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Spreadsheet grid -->
|
||||
<rect x="5" y="5" width="22" height="22" rx="1" fill="#45475a" stroke="#89dceb" stroke-width="1.5"/>
|
||||
<!-- Header row -->
|
||||
<rect x="5" y="5" width="22" height="5" fill="#585b70"/>
|
||||
<!-- Column dividers -->
|
||||
<line x1="12" y1="5" x2="12" y2="27" stroke="#6c7086" stroke-width="1"/>
|
||||
<line x1="20" y1="5" x2="20" y2="27" stroke="#6c7086" stroke-width="1"/>
|
||||
<!-- Row dividers -->
|
||||
<line x1="5" y1="10" x2="27" y2="10" stroke="#6c7086" stroke-width="1"/>
|
||||
<line x1="5" y1="16" x2="27" y2="16" stroke="#6c7086" stroke-width="1"/>
|
||||
<line x1="5" y1="22" x2="27" y2="22" stroke="#6c7086" stroke-width="1"/>
|
||||
<!-- Header labels -->
|
||||
<text x="8" y="9" font-family="monospace" font-size="4" fill="#cdd6f4">A</text>
|
||||
<text x="15" y="9" font-family="monospace" font-size="4" fill="#cdd6f4">B</text>
|
||||
<text x="23" y="9" font-family="monospace" font-size="4" fill="#cdd6f4">C</text>
|
||||
<!-- Cell highlight -->
|
||||
<rect x="12" y="10" width="8" height="6" fill="#74c7ec" fill-opacity="0.3" stroke="#89dceb" stroke-width="1"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
10
kindred-icons/Std_DuplicateSelection.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Original object -->
|
||||
<rect x="6" y="6" width="12" height="12" rx="2" fill="#45475a" stroke="#6c7086" stroke-width="1.5"/>
|
||||
<!-- Duplicate object -->
|
||||
<rect x="14" y="14" width="12" height="12" rx="2" fill="#45475a" stroke="#94e2d5" stroke-width="1.5"/>
|
||||
<!-- Plus badge -->
|
||||
<circle cx="24" cy="8" r="5" fill="#a6e3a1"/>
|
||||
<path d="M24 5.5 L24 10.5 M21.5 8 L26.5 8" stroke="#1e1e2e" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 574 B |
9
kindred-icons/Std_Export.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Document -->
|
||||
<path d="M8 5 L8 27 L24 27 L24 11 L18 5 Z" fill="#45475a" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<path d="M18 5 L18 11 L24 11" fill="#313244" stroke="#89b4fa" stroke-width="1.5" stroke-linejoin="round"/>
|
||||
<!-- Arrow pointing out of document -->
|
||||
<path d="M12 16 L4 16" stroke="#fab387" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M7 13 L4 16 L7 19" stroke="#fab387" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 617 B |
6
kindred-icons/Std_HideObjects.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="4" fill="#313244"/>
|
||||
<ellipse cx="16" cy="16" rx="10" ry="6" fill="none" stroke="#585b70" stroke-width="1.5"/>
|
||||
<circle cx="16" cy="16" r="3" fill="#585b70"/>
|
||||
<line x1="6" y1="24" x2="26" y2="8" stroke="#f38ba8" stroke-width="2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 338 B |
9
kindred-icons/Std_Import.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Document -->
|
||||
<path d="M8 5 L8 27 L24 27 L24 11 L18 5 Z" fill="#45475a" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<path d="M18 5 L18 11 L24 11" fill="#313244" stroke="#89b4fa" stroke-width="1.5" stroke-linejoin="round"/>
|
||||
<!-- Arrow pointing into document -->
|
||||
<path d="M4 16 L12 16" stroke="#a6e3a1" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M9 13 L12 16 L9 19" stroke="#a6e3a1" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 616 B |
7
kindred-icons/Std_Refresh.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Circular arrow -->
|
||||
<path d="M16 6 A10 10 0 1 1 6 16" fill="none" stroke="#cba6f7" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<!-- Arrow head -->
|
||||
<path d="M16 6 L13 10 L19 10 Z" fill="#b4befe"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 343 B |
14
kindred-icons/Std_SaveAll.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect x="2" y="2" width="28" height="28" rx="4" fill="#313244"/>
|
||||
<!-- Back floppy -->
|
||||
<path d="M11 4 L11 20 L25 20 L25 8 L21 4 Z" fill="#45475a" stroke="#6c7086" stroke-width="1"/>
|
||||
<!-- Front floppy -->
|
||||
<path d="M5 8 L5 28 L19 28 L19 12 L15 8 Z" fill="#45475a" stroke="#89b4fa" stroke-width="1.5"/>
|
||||
<!-- Metal slider on front -->
|
||||
<rect x="8" y="8" width="6" height="5" rx="1" fill="#1e1e2e" stroke="#6c7086" stroke-width="0.75"/>
|
||||
<!-- Label area on front -->
|
||||
<rect x="7" y="16" width="10" height="5" rx="1" fill="#cdd6f4"/>
|
||||
<!-- Multiple indicator -->
|
||||
<circle cx="24" cy="24" r="5" fill="#a6e3a1"/>
|
||||
<text x="24" y="27" font-family="sans-serif" font-size="8" font-weight="bold" fill="#1e1e2e" text-anchor="middle">2</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 814 B |