Add-ons: Parametric Shape Tool — re-editable stars, polygons, rings, arrows, gears and more

Path Precision Tools gains the Parametric Shape Tool: ten kinds of shape
(rectangle, ellipse, polygon, star, ring, arrow, cross, heart, gear,
speech bubble) that stay editable as numbers.

- Geometry in vectorcraft_pathops::addons::pathtools::shapes: each kind's
  outline, corner rounding limited to the middle of a side, a fingerprint
  of the outline, recovery of centre, size and rotation after a move,
  turn or scale, and recognition of plain rectangles, ellipses and
  regular polygons.
- The tool (parametricShape, All Tools drawer and Object › Plug-ins ›
  Path Precision Tools only, no shortcut): drag from the centre (Shift:
  45° steps), arrow keys change the count and values while dragging,
  handles edit a selected shape, double-click places one.
- Commands addon.pathtools.shape.create / .set / .convert, one undo step
  each; params checked (counts 3..1000, sizes up to 16384 pt).
- A shape keeps its numbers in one object-data entry (vc-pathtools-shape)
  that SVG export already leaves out; anchor edits make it a plain path.
- Parametric Shape panel, cursor stand-in, catalog rows in all 25
  languages, docs and tests.
This commit is contained in:
bflatastic
2026-10-30 20:55:14 +07:00
parent b496226ab5
commit 27ed249b1f
48 changed files with 2551 additions and 24 deletions
+2 -2
View File
@@ -379,7 +379,7 @@ fn drop_targets_follow_the_buttons_edges() {
fn addon_tools_are_in_the_drawer_not_the_toolbars() {
let mut app = app();
let addon: Vec<&str> = vectorcraft_tools::addons::GROUPS.iter().flat_map(|g| g.iter().map(|t| t.id)).collect();
assert_eq!(addon, ["anchorEraserBrush", "extendPath", "measureInspect", "smartPen"]);
assert_eq!(addon, ["anchorEraserBrush", "extendPath", "measureInspect", "parametricShape", "smartPen"]);
for advanced in [false, true] {
if advanced {
app.run("window.toolbarAdvanced", json!({})).unwrap();
@@ -389,7 +389,7 @@ fn addon_tools_are_in_the_drawer_not_the_toolbars() {
let listed = |id: &str| {
sections().iter().find(|(_, tools)| tools.iter().any(|t| t.id == id)).map(|(h, tools)| (*h, tools.iter().map(|t| t.id).collect::<Vec<_>>()))
};
assert_eq!(listed("extendPath"), Some(("Path Precision Tools", addon[..3].to_vec())));
assert_eq!(listed("extendPath"), Some(("Path Precision Tools", addon[..4].to_vec())));
assert_eq!(listed("smartPen"), Some(("Smart Pen", vec!["smartPen"])));
for tool in ["extendPath", "smartPen"] {
app.run("toolbar.addTool", json!({"tool": tool})).unwrap();