Commit Graph
13 Commits
Author SHA1 Message Date
dotCooCoo 4519346cfb Layers: the Layers panel's commands refuse a boolean given as text
layer.new, layer.selectAll, layer.target, layer.move, layer.template,
layer.pasteRemembersLayers and layer.releaseToLayers read their on/off
params with bool_or or as_bool, which falls back to a default for a
value that is not true or false. layer.new {"top": "true"} added the
layer above the current one instead of on top, layer.template
{"on": "false"} and layer.pasteRemembersLayers {"on": "false"} turned
the option on when it was off, layer.move {"copy": "true"} moved the
rows instead of copying them, layer.selectAll and layer.target with
"add": "true" replaced the selection, and layer.releaseToLayers
{"build": "true"} released the objects without building up copies.

These commands now fail with "`<key>` must be true or false" for a
value that is not true, false or null, as the artboard and Object menu
commands do, and leave the document, the selection, the highlighted
rows and the undo history as they were. layer.newSublayer, which takes
layer.new's options, refuses such a top too. A null is read as a key
left out.

docs/mcp.md also lists showCenterMark, showCrossHairs and
showVideoSafeAreas among the keys artboard.new and artboard.setProps
refuse in this way, as they already did.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-29 09:57:33 +07:00
dotCooCoo 1deb1ec152 Artboards: artboard.new and artboard.setProps refuse a number or name of the wrong type
artboard.setProps refused an x, y, width or height given as text, but
artboard.new read such a value as the key left out: {"x": "10"} added
an artboard at the default position and recorded an undo step. Both
commands read a name that is not a string, such as 5, as no name, so
artboard.new gave the default name and artboard.setProps kept the old
one.

artboard.new now refuses an x, y, width or height that is not a number
with "`<key>` must be a number, not <value>", the message
artboard.setProps gives, and both commands refuse such a name with
"`name` must be a string", for each entry of artboard.setProps'
artboards too. They refuse it before they change anything. A null is
still read as the key left out.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-29 09:57:33 +07:00
NetterSilverandClaude Haiku 5.5 ad43722a56 Accept whole-number floats as grid divider counts
Found while testing crates/engine/src/cmd/create.rs:584 (dividers)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 09:57:33 +07:00
Dylan M. Taylor 484d25582c Merge remote-tracking branch 'origin/main' into pr-4299-ff 2026-10-28 17:20:12 -04:00
Dylan M. Taylor 12414aa9f6 Make PDF export comparison deterministic 2026-10-28 19:53:43 +00:00
Dylan M. Taylor 0b821b3c54 Extract engine command and state helpers 2026-10-28 16:44:14 +00:00
skylar 1ffc04506c fix(engine): honor explicit ends when joining direct selections 2026-10-27 11:11:36 -06:00
el-j 464a0710b7 Merge remote-tracking branch 'upstream/main' into fix/compound-path-pen-join 2026-10-27 14:33:06 +01:00
ham9zah 0365cf3ae3 Appearance: shared rows map one by one, and effect dialogs edit each copy (#4174)
Review follow-ups:

- items_per_target maps each requested row on its own. Rows deleted or
  duplicated together, one shared and one not, fell back to the literal
  indices in every object, so the other objects could lose the wrong
  items. The first object takes its own rows; each other object takes
  its copies of the shared ones only.
- effect.dialog takes `aligned` (the panel passes it on a mixed
  selection's shared effect row), and its OK and preview run
  effect.setParams with it, so the dialog edits each object's own copy
  of the effect instead of the first object's index in every object.

Tests: removing a shared stroke with an unshared fill leaves the other
object's fills; an aligned dialog's command carries `aligned`.
2026-10-27 14:36:13 +07:00
ham9zah 8305ccf998 Appearance: a mixed selection lists the attributes its objects share (#4174)
With several objects selected whose appearances differ in anything (two
circles whose fills differ but whose stroke and effect are the same),
the Appearance panel showed only "Mixed Appearances": no stroke, effect
or opacity row, so attributes the objects share couldn't be edited
together. It now lists what they share, as the issue describes:

- `vectorcraft_doc::appearance::SharedStack` (with `align`, a stacking-
  order longest-common-subsequence match) gives the fills, strokes and
  object-level effects every object has an equal copy of, and where each
  is in every object's own stack.
- The panel's object row names the objects' common kind ("Path",
  "Ellipse"; "Mixed Objects" only when kinds differ, as the Control bar
  does), with an italic "Mixed Appearances" row under it when they
  differ, then only the shared rows with their usual controls. The
  Opacity row reads "Mixed" when opacity or blend mode differ (an edit
  sets them all). The object row shows no fill chip when the fills
  differ. Rows aren't dragged in a mixed selection: where a row would go
  in each of several different stacks isn't one place.
- The engine maps a shared row to each object's own item: the active
  item (a row of the first selected object's stack) always does, so the
  Color, Stroke and Transparency panels edit every object's matching
  item, and the item and effect commands do with `aligned: true`
  (appearance.setItem / removeItem / duplicateItem, effect.remove /
  duplicate / setParams / lightingPreset, transparency.set), each as
  one undo step. moveItem and effect.move refuse aligned rows of
  differing stacks. Without `aligned`, explicit indices keep their
  meaning for single objects and scripts.
- "Mixed" is added to every catalog.

Tests: the shared stack of the issue's case, of a stroke at another
index, of nothing alike and of equal stacks, and that matches never
cross; editing the shared stroke edits both strokes (at index 1 and 2)
in one undo step that restores both, also through stroke.set on the
active row; removing a shared effect and adding a fill reach both, and
reordering differing stacks is refused; the panel lists kind, note,
Stroke, Feather and Opacity, not Fill, the full stack for alike objects
and "Mixed Objects" for a path and type. The existing object-row test
now expects the kind for two rectangles and the shared rows when their
opacity differs.
2026-10-27 14:36:13 +07:00
NetterSilverandClaude Haiku 5.5 23f0d323b0 Accept whole-number floats and reject invalid counts for polygon, star and spiral
Found while testing crates/engine/src/cmd/create.rs:344 (polygon) and :358 (star; shape.spiral `segments` at :507 reads the same way)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 14:36:12 +07:00
aiongg f1d427762b style: cargo fmt on files moved without formatting 2026-10-26 19:32:10 +00:00
aiongg 83eec43b18 refactor(engine): move tests_*.rs to tests/<topic>.rs 2026-10-26 18:26:56 +00:00