Compare commits
13 Commits
7597f2f156
...
knoxmakers
| Author | SHA1 | Date | |
|---|---|---|---|
| 378853c641 | |||
| 7aea02f3af | |||
| 337b00601a | |||
| ee650f2b71 | |||
| a5ddc33a27 | |||
| a9c87f2adf | |||
| 5692f4bb08 | |||
| 9af24d49ee | |||
| 7211fd44ef | |||
| b72b468ad4 | |||
| 8a126fec7d | |||
| e0dc82c22d | |||
| c2fa54d3b4 |
@@ -45,8 +45,8 @@ jobs:
|
|||||||
git push origin HEAD:main
|
git push origin HEAD:main
|
||||||
|
|
||||||
# Create a unique tag for this bundle run
|
# Create a unique tag for this bundle run
|
||||||
DATETIME="$(date -u +%Y%m%d-%H%M%S)"
|
DATETIME="$(date -u +%Y%m%d)"
|
||||||
TAG="knox-makers-inkscape-${DATETIME}"
|
TAG="knoxmakers-inkscape-${DATETIME}"
|
||||||
SHA="$(git rev-parse HEAD)"
|
SHA="$(git rev-parse HEAD)"
|
||||||
|
|
||||||
git tag -a "$TAG" -m "Automated bundle: $TAG ($SHA)"
|
git tag -a "$TAG" -m "Automated bundle: $TAG ($SHA)"
|
||||||
@@ -67,7 +67,7 @@ jobs:
|
|||||||
CREATE_JSON="$(jq -n \
|
CREATE_JSON="$(jq -n \
|
||||||
--arg tag "$TAG" \
|
--arg tag "$TAG" \
|
||||||
--arg name "$TAG" \
|
--arg name "$TAG" \
|
||||||
--arg body "Automated bundle release.\n\nExcludes: scripts/, .gitea/\nCommit: $SHA\nUTC: $(date -u +'%Y-%m-%d %H:%M:%S')" \
|
--arg body "Automated bundle release." \
|
||||||
'{tag_name:$tag, name:$name, body:$body, draft:false, prerelease:false}')"
|
'{tag_name:$tag, name:$name, body:$body, draft:false, prerelease:false}')"
|
||||||
|
|
||||||
RELEASE_RESP="$(curl -fsS -X POST "$API_CREATE" \
|
RELEASE_RESP="$(curl -fsS -X POST "$API_CREATE" \
|
||||||
|
|||||||
45
.gitea/workflows/version.yml
Normal file
45
.gitea/workflows/version.yml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
name: version
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-version:
|
||||||
|
runs-on: [ubuntu-24.04]
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
rm -rf .git || true
|
||||||
|
rm -rf ./* ./.??* || true
|
||||||
|
git clone --depth 1 https://git.knoxmakers.org/KnoxMakers/knoxmakers-inkscape.git .
|
||||||
|
git checkout main
|
||||||
|
|
||||||
|
- name: Configure git identity
|
||||||
|
run: |
|
||||||
|
git config user.name "haxbot"
|
||||||
|
git config user.email "haxbot@knoxmakers.sh"
|
||||||
|
|
||||||
|
- name: Write version file
|
||||||
|
run: |
|
||||||
|
echo "${{ gitea.event.release.name }}" > version
|
||||||
|
|
||||||
|
- name: Commit and push version file
|
||||||
|
env:
|
||||||
|
HAXBOT_TOKEN: ${{ secrets.HAXBOT_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
git add version
|
||||||
|
|
||||||
|
if git diff --cached --quiet; then
|
||||||
|
echo "No changes to version file"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
git commit -m "version: ${{ gitea.event.release.name }}"
|
||||||
|
|
||||||
|
REPO_URL="https://x-access-token:${HAXBOT_TOKEN}@git.knoxmakers.org/KnoxMakers/knoxmakers-inkscape.git"
|
||||||
|
git remote set-url origin "$REPO_URL"
|
||||||
|
git push origin HEAD:main
|
||||||
25
README.md
25
README.md
@@ -1,2 +1,27 @@
|
|||||||
# knoxmakers-inkscape
|
# knoxmakers-inkscape
|
||||||
|
|
||||||
|
A bundled collection of Inkscape extensions for Knox Makers makerspace.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Download the latest release zip and extract into to your Inkscape extensions directory:
|
||||||
|
|
||||||
|
- **Linux**: `~/.config/inkscape/extensions/`
|
||||||
|
- **Linux (Flatpak)**: `~/.var/app/org.inkscape.Inkscape/config/inkscape/extensions/`
|
||||||
|
- **Linux (Snap)**: `~/snap/inkscape/current/.config/inkscape/extensions/`
|
||||||
|
- **macOS**: `~/Library/Application Support/org.inkscape.Inkscape/config/inkscape/extensions/`
|
||||||
|
- **Windows**: `%APPDATA%\inkscape\extensions\`
|
||||||
|
|
||||||
|
## Included Extensions
|
||||||
|
|
||||||
|
- **botbox3000** - Box generator for laser cutting
|
||||||
|
- **km-living-hinge** - Living hinge pattern generator
|
||||||
|
- **km-plot** - Detect and send designs to serial HPGL plotters/vinyl cutters
|
||||||
|
- **km-hatch** - Hatching/fill patterns
|
||||||
|
- **km-hershey** - Single Line text for plotting/engraving
|
||||||
|
|
||||||
|
Extensions appear under **Extensions > Knox Makers** in Inkscape.
|
||||||
|
|
||||||
|
## Releases
|
||||||
|
|
||||||
|
Automated bundles are created daily when upstream repositories have changes.
|
||||||
|
|||||||
3
extensions/botbox3000/.gitignore
vendored
3
extensions/botbox3000/.gitignore
vendored
@@ -1,6 +1,9 @@
|
|||||||
# Hidden files and directories (everything starting with .)
|
# Hidden files and directories (everything starting with .)
|
||||||
.*
|
.*
|
||||||
|
|
||||||
|
# Build output (release zips and their signatures)
|
||||||
|
dist/
|
||||||
|
|
||||||
# Python cache (but keep bundled deps/)
|
# Python cache (but keep bundled deps/)
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
|
|||||||
1
extensions/botbox3000/VERSION
Normal file
1
extensions/botbox3000/VERSION
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1.0.1
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
# Copyright (C) 2026 jondale
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -182,7 +184,7 @@ class Boxbot(inkex.EffectExtension):
|
|||||||
self.top_hole_inset = PathElement()
|
self.top_hole_inset = PathElement()
|
||||||
self.top_hole_inset.set_id(self.svg.get_unique_id("top_hole_inset"))
|
self.top_hole_inset.set_id(self.svg.get_unique_id("top_hole_inset"))
|
||||||
self.top_hole_inset.set('d', top_hole_inset_d)
|
self.top_hole_inset.set('d', top_hole_inset_d)
|
||||||
self.top_hole_inset.style = self.CUT_OUTER_STYLE
|
self.top_hole_inset.style = self.CUT_INNER_STYLE
|
||||||
top_tabs_group.append(self.top_hole_inset)
|
top_tabs_group.append(self.top_hole_inset)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|||||||
0
extensions/botbox3000/deps/inkex/deprecated-simple/run_command.py
Executable file → Normal file
0
extensions/botbox3000/deps/inkex/deprecated-simple/run_command.py
Executable file → Normal file
BIN
extensions/botbox3000/doc/logo.png
Normal file
BIN
extensions/botbox3000/doc/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 148 KiB |
@@ -1,4 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
# Copyright (C) 2026 jondale
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
# Copyright (C) 2026 jondale
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
|||||||
70
extensions/botbox3000/package.sh
Executable file
70
extensions/botbox3000/package.sh
Executable file
@@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build a distributable Inkscape extension zip at dist/boxbot-<version>.zip
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./package.sh [version] [--sign]
|
||||||
|
#
|
||||||
|
# version Set the version explicitly (used as-is, no bump). Saved to VERSION.
|
||||||
|
# With no version, the patch number in VERSION is incremented (x.y.Z+1).
|
||||||
|
# --sign Also produce a detached GPG signature (dist/boxbot-<version>.zip.sig).
|
||||||
|
#
|
||||||
|
# The zip bundles only the extension's own files in a boxbot/ folder. It does
|
||||||
|
# NOT include deps/ — the extension falls back to the inkex shipped with
|
||||||
|
# Inkscape (the sys.path shim is a no-op when deps/ is absent).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
repo_root="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
cd "$repo_root"
|
||||||
|
|
||||||
|
# Files that go into the package (allowlist: anything not here is excluded).
|
||||||
|
files="boxbot.inx boxbot.py offset.py placements.py livinghinge.py LICENSE README.md"
|
||||||
|
pkg="boxbot"
|
||||||
|
|
||||||
|
# Increment the patch component of a MAJOR.MINOR.PATCH version string.
|
||||||
|
bump_patch() {
|
||||||
|
local major minor patch
|
||||||
|
IFS='.' read -r major minor patch <<< "$1"
|
||||||
|
printf '%s.%s.%s' "${major:-0}" "${minor:-0}" "$(( ${patch:-0} + 1 ))"
|
||||||
|
}
|
||||||
|
|
||||||
|
version=""
|
||||||
|
sign=0
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--sign) sign=1 ;;
|
||||||
|
-*) echo "error: unknown option: $1" >&2; exit 1 ;;
|
||||||
|
*) version="$1" ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$version" ]; then
|
||||||
|
current="$(cat VERSION 2>/dev/null || true)"
|
||||||
|
[ -n "$current" ] || { echo "error: no VERSION file to increment" >&2; exit 1; }
|
||||||
|
version="$(bump_patch "$current")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Persist so the next run increments from here.
|
||||||
|
printf '%s\n' "$version" > VERSION
|
||||||
|
|
||||||
|
stage="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$stage"' EXIT
|
||||||
|
mkdir -p "$stage/$pkg"
|
||||||
|
for f in $files; do
|
||||||
|
[ -f "$f" ] || { echo "error: missing file: $f" >&2; exit 1; }
|
||||||
|
cp "$f" "$stage/$pkg/"
|
||||||
|
done
|
||||||
|
|
||||||
|
mkdir -p dist
|
||||||
|
out="dist/boxbot-${version}.zip"
|
||||||
|
rm -f "$out"
|
||||||
|
( cd "$stage" && zip -rq "$repo_root/$out" "$pkg" )
|
||||||
|
|
||||||
|
if [ "$sign" -eq 1 ]; then
|
||||||
|
rm -f "$out.sig"
|
||||||
|
gpg --output "$out.sig" --detach-sign "$out"
|
||||||
|
echo "signed -> $out.sig"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "built $out"
|
||||||
|
unzip -l "$out"
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
# Copyright (C) 2026 jondale
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -82,6 +84,16 @@ def point_at_length(path, target_length):
|
|||||||
return (last_point[0], last_point[1]), (1.0, 0.0)
|
return (last_point[0], last_point[1]), (1.0, 0.0)
|
||||||
|
|
||||||
|
|
||||||
|
def _apply_placement(item, x, y, angle):
|
||||||
|
# Bake placement into the path data; leaving it as a transform attr lets
|
||||||
|
# Inkscape shift the shape on ungroup (near-identity matrices lose the X translate).
|
||||||
|
transform = Transform()
|
||||||
|
transform.add_translate(x, y)
|
||||||
|
transform.add_rotate(angle)
|
||||||
|
item.path = item.path.transform(transform)
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
def pattern_along_path(path, num_items, item_width, start_offset, spacing, create_shape_fn):
|
def pattern_along_path(path, num_items, item_width, start_offset, spacing, create_shape_fn):
|
||||||
|
|
||||||
if isinstance(path, str):
|
if isinstance(path, str):
|
||||||
@@ -104,12 +116,7 @@ def pattern_along_path(path, num_items, item_width, start_offset, spacing, creat
|
|||||||
angle = math.degrees(math.atan2(tangent[1], tangent[0]))
|
angle = math.degrees(math.atan2(tangent[1], tangent[0]))
|
||||||
|
|
||||||
item = create_shape_fn(i)
|
item = create_shape_fn(i)
|
||||||
|
_apply_placement(item, point[0], point[1], angle)
|
||||||
transform = Transform()
|
|
||||||
transform.add_translate(point[0], point[1])
|
|
||||||
transform.add_rotate(angle)
|
|
||||||
|
|
||||||
item.transform = transform
|
|
||||||
items.append(item)
|
items.append(item)
|
||||||
|
|
||||||
elif spacing == "endpoints":
|
elif spacing == "endpoints":
|
||||||
@@ -120,12 +127,7 @@ def pattern_along_path(path, num_items, item_width, start_offset, spacing, creat
|
|||||||
angle = math.degrees(math.atan2(tangent[1], tangent[0]))
|
angle = math.degrees(math.atan2(tangent[1], tangent[0]))
|
||||||
|
|
||||||
item = create_shape_fn(i)
|
item = create_shape_fn(i)
|
||||||
|
_apply_placement(item, point[0], point[1], angle)
|
||||||
transform = Transform()
|
|
||||||
transform.add_translate(point[0], point[1])
|
|
||||||
transform.add_rotate(angle)
|
|
||||||
|
|
||||||
item.transform = transform
|
|
||||||
items.append(item)
|
items.append(item)
|
||||||
|
|
||||||
elif spacing == "simple":
|
elif spacing == "simple":
|
||||||
@@ -138,12 +140,7 @@ def pattern_along_path(path, num_items, item_width, start_offset, spacing, creat
|
|||||||
angle = math.degrees(math.atan2(tangent[1], tangent[0]))
|
angle = math.degrees(math.atan2(tangent[1], tangent[0]))
|
||||||
|
|
||||||
item = create_shape_fn(i)
|
item = create_shape_fn(i)
|
||||||
|
_apply_placement(item, point[0], point[1], angle)
|
||||||
transform = Transform()
|
|
||||||
transform.add_translate(point[0], point[1])
|
|
||||||
transform.add_rotate(angle)
|
|
||||||
|
|
||||||
item.transform = transform
|
|
||||||
items.append(item)
|
items.append(item)
|
||||||
|
|
||||||
return items
|
return items
|
||||||
|
|||||||
@@ -18,5 +18,5 @@ An Inkscape extension that fills closed shapes with parallel hatch lines. The ex
|
|||||||
|
|
||||||
Inspiration, examples, and code came from:
|
Inspiration, examples, and code came from:
|
||||||
|
|
||||||
- **Hatch Fill** from Evil Mad Scientist Laboratories and their EggBot extensions
|
- **Hatch Fill** from Evil Mad Scientist Laboratories and their EggBot extensions
|
||||||
https://github.com/evil-mad/EggBot/
|
https://github.com/evil-mad/EggBot/
|
||||||
|
|||||||
Reference in New Issue
Block a user