Commit Graph
12 Commits
Author SHA1 Message Date
BFlatandClaude Opus 5.5 d0a21d2a7b M6: REST import of prototypes and variables; export panel polish (#42)
* M6: REST import of prototypes and variables; export panel polish

REST API file JSON import now brings prototyping and variables along:
- interactions: on click/hover/press/drag, after delay, mouse enter/leave/down/up and key
  triggers; navigate, open/swap/close overlay, back, scroll to, change to, open link and set
  variable actions (lone unconditional blocks inlined); dissolve, smart animate, move, push and
  slide transitions with easing incl. custom bezier and spring; the legacy transitionNodeID
- flow starting points (and the deprecated start node), overflowDirection, scrollBehavior,
  prototypeDevice and prototype background
- the local variables response (collections, modes with the default first, values, aliases,
  scopes), passed as `variables` to file.open / file.import (object, JSON text or path), found
  next to the file (<name>.variables.json / variables.json) or embedded; boundVariables, paint
  and text style bindings and explicitVariableModes map onto the fields variable.bind uses
- file.import appends variables, flows and prototype settings with the pages
- unsupported parts (video, gamepad, conditionals, variable modes, library variables) warn

Export panel: rows with a typed or preset size (2x, 512w, 512h), suffix and all five formats
through the new export.update command; export.add steps up (1x, 2x @2x, ...); a preview;
"Export N layers" through the new file.exportLayers (one file per setting, unique safe names)
in the panel and the Export dialog; file.export takes `size`. MCP open_file/export pass the new
params.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* M6: Inspect tab: properties with styles and variables, redlines on hover (#41)

The Inspect tab lists the selected layer's properties for handoff:
layout (size, position from the parent, rotation, opacity, radius), auto
layout (direction, gap, padding, alignment), typography, fills, strokes
and effects, each with the style or variable it comes from. Clicking a
value copies it. With the Inspect tab open, hovering measures distances
from the selection without holding Alt.

New command inspect.properties returns the same groups for agents.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:17:54 +07:00
BFlatandClaude Opus 5.5 476cdd95f1 M4: shape builder tool (Shift+M): merge or remove the regions of overlapping shapes (#39)
The selected shapes' outlines split the canvas into regions, computed as the faces of their
arrangement with linesweeper (curves kept, per-shape fill rules, holes and islands handled) and
cached per document version and selection.

- Engine: shapeBuilder.regions / merge / remove / mode commands, ToolId::ShapeBuilder and
  tool.shapeBuilder (catalog: Tools > Shape builder, Shift+M). Merge makes one vector from the
  picked regions styled like the top-most shape over the first; every shape covering a picked
  region loses that area (becomes a vector, or is deleted when nothing is left). One gesture or
  command is one undo step. Session::tool_key routes Enter (finish) and vector edit keys.
- Pathops: faces() (arrangement faces with their covering inputs) and union_faces().
- UI: region edges on the canvas, hovered/collected regions hatched (danger colour to remove),
  no transform box while building, a toolbar pill with Merge/Remove modes, a hint and Done; shared
  pill/tool-cell/divider/Done helpers; original merge/remove icons drawn in code.
- Tests: pathops faces; engine regions, merge, remove, curves, groups, rotation, pointer
  click/drag/Alt, modes, Escape/Enter, cache, junk parameters and degenerate geometry.
- Docs: ROADMAP, README, docs/mcp.md, docs/control-protocol.md, docs/parity.md.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:55:12 +07:00
BFlatandClaude Opus 5.5 e360b6fa52 M7: README: ArtCraft logo and app icon load in the private repo (#40)
GitHub doesn't render relative SVG images in a private repository's
README, and raw.githubusercontent.com doesn't serve private files, so the
ArtCraft logo, the footer mark and FigCraft's own row in the apps table
showed as broken images. Use the PNG versions of the same artwork (already
in docs/brand) and a repo-relative path for the app icon; both work for
private and public repos alike.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:52:47 +07:00
BFlatandClaude Opus 5.5 632c5ffc16 M4: right-to-left and mixed-direction text (Unicode bidi) (#34)
Text runs get bidi embedding levels from the Unicode bidi algorithm
(unicode-bidi, MIT/Apache-2.0). Right-to-left runs are shaped right to
left, kept in logical order for line breaking and placed in visual order
per line (rule L2, trailing spaces at the paragraph level). Glyphs and
lines know their direction, so the caret, clicks and selection
highlights follow right-to-left runs. Text without right-to-left
characters skips the analysis.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:12:14 +07:00
BFlatandClaude Opus 5.5 1c6f04bf62 M3: Variables editor with aliases, scopes, and rename/delete for variables, modes and collections (#33)
The Local variables window becomes a table editor: collections in a
sidebar, variables grouped by name with one value column per mode, typed
value cells (colour swatch + hex + alpha, number, string, boolean), alias
chips with a variable picker and detach, double-click rename, context
menus, and an Edit variable window for description and scopes.

New commands: variable.update (name, description, scopes),
variable.duplicate, variable.renameMode, variable.removeMode,
variable.renameCollection, variable.deleteCollection. variable.set
validates aliases (same type, no loops) and stores them by id; addMode
always picks a fresh mode id. Pickers offer only variables scoped to the
property. ui.set {variables} opens the editor on a collection.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:12:08 +07:00
BFlatandClaude Opus 5.5 e718518a08 M6: import REST API file JSON: pages, layers, paints, text runs, vectors, auto layout, components (#13)
- New `figcraft_format::rest`: imports the public REST API file JSON (`GET /v1/files/:key`, and
  the nodes endpoint's response) using the published reference only. Pages (name, background,
  flow starting points), the layer tree, names, visibility, lock, opacity, blend mode, masks.
- Geometry from `relativeTransform` (children of groups/booleans checked against
  `absoluteBoundingBox` to settle their space), else absolute bounds + rotation; sizes, corner
  radii (uniform and per corner), smoothing, clip content, constraints, export settings, layout
  grids.
- Paints: solid, linear/radial/angular/diamond gradients (handles map 1:1), image fills (fill,
  fit, tile, stretch, rotation, filters) with bytes from a resolver or a grey placeholder keyed by
  the imageRef; paint opacity, visibility and blend. Strokes: weight, per-side weights, align,
  caps, join, dashes, miter angle. Effects: drop/inner shadow (offset, radius, spread, show behind),
  layer and background blur.
- Vectors from `fillGeometry` (stroke-only vectors use the `strokeGeometry` outline), ellipse arc
  data, stars/polygons, boolean operations. Text: characters, type style (family, style or weight
  + italic, size, line height px/%/auto, letter spacing, case, decoration, alignment, auto resize,
  truncation, paragraph spacing/indent, OpenType flags, links), per-character overrides → styled
  runs (UTF-16 aware), list type.
- Auto layout: direction incl. grid, alignment, padding, gaps, wrap, hug/fixed/fill sizing (legacy
  and per-axis fields), absolute positioning, min/max, grid cells.
- Components and sets with descriptions and property definitions (names lose their `#id`
  suffix); instances of components in the file become instances with their property values and
  listed overrides; outside components and component cycles stay frames. Shared styles are created
  from the layers that use them, named from the metadata.
- Unknown types and fields are skipped with a counted warning list; sizes, depth (256), layer count
  (200,000), path length and list lengths are capped; nothing panics on junk.
- Engine: `file.open` / `file.import` / CLI detect the JSON by content, link imported instances to
  their mains (sources and overrides), read image fills from an `images` folder next to the file,
  never save over the JSON, and return `warnings`. `file.import` now remaps ids across all
  imported pages at once (instances keep their main and layer sources) and brings styles and page
  backgrounds along. `figcraft-cli info` prints load notes.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 03:36:30 +07:00
BFlatandClaude Opus 5.5 b7910c81f8 M4: text depth: inline IME composition, variable font axes, range-aware typography polish (#8)
- Inline IME composition: egui Preedit events become a composition held in the text edit
  session (`TextEdit.preedit`), shown inline at the caret with an underline and the IME cursor,
  reflowing the text; the document only gets the committed text (`text.edit.insert`). Composing
  over a selection replaces it; moving the caret or ending the edit drops an uncommitted
  composition. The IME candidate window follows the cursor inside the composition.
  New command `text.edit.preedit {text, cursor?}`; `text.edit.selection` reports it.
- Variable fonts: faces read their fvar axes (tag, name, range, default, hidden) and named
  instances. Named instances are offered as styles and resolve in `find`; a style name with no
  instance implies weight/italic/slant on the axes and optical size follows the font size.
  Per-run custom axis values (`TextStyle.variations`, serde default, omitted when empty) are applied
  in HarfRust shaping (ShaperInstance) and skrifa outlines/advances (cached per coordinates).
  PDF export outlines non-default instances instead of embedding the default one.
- Commands/props: `fontVariations` / `variationSettings` props (whole layer or start..end),
  `text.setVariations {variations, replace?}` (merges; edited range while editing),
  `text.fonts {family, style?, axes: true}`; `node.get` and copy/paste properties carry the axes.
  Picking a named style (Bold/Italic toggles, weight steps, fontStyle/fontWeight) drops custom
  wght/ital/slnt values and keeps the others.
- Type settings ▸ Variable tab for variable fonts: a slider (default tick, double-click to reset)
  and a field per visible axis, "Mixed" across differing styles, live drag as one undo step,
  "Reset to style". Long style/family names stay on one line with an ellipsis and a tooltip.
- Tests: variable font shaping/outlines/clamping/instances (skipped without a variable font),
  serde backward compatibility, preedit lifecycle and undo, variation commands/props/undo/junk;
  junk sweeps extended with variation and preedit params.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 03:07:41 +07:00
BFlatandClaude Opus 5.5 51fada8d8f M4: Assets panel: thumbnails, search, drag components onto the canvas into frames and auto layout (#5)
- Assets tab rebuilt as its own module: local components as two-column tiles with live
  thumbnails (re-rendered when a component's content changes, throttled), a search field that
  filters components and styles, and the local styles list.
- Drag a tile onto the canvas: a ghost follows the pointer, the frame under it highlights and auto
  layout frames show the insertion line; releasing drops an instance there, centred on the
  pointer. Clicking a tile places one in the middle of the view.
- New command `instance.place {component, x, y}` (page point; drops into the frame or auto layout
  slot under it; never inside its own main) for the CLI, control channel and MCP.
- The auto layout drop slot is shared with moving layers (`drop::auto_layout_slot`).
- Creating a component from a single shape names it after the shape.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 02:41:59 +07:00
BFlatandClaude Opus 5.5 4286a3b74b M2: auto layout depth: min/max UI, ignore auto layout toggle, text baseline alignment, grid tracks and cells (#3)
- Min/max width/height: the W/H sizing menus add min/max (at the current size) and remove them;
  limit rows edit or add the missing bound. The layout clamps Fixed, Hug and Fill children and
  the frame itself; a hugging text wider than its max width wraps at the max. min > max is kept
  ordered by node.set (the other bound follows); in the layout min wins.
- Ignore auto layout (absolute position): a toggle in the Position section; the child stays
  where it is, can't Fill, shows constraints and follows them when the auto layout frame resizes
  (by hugging, filling or a direct resize).
- Text baseline alignment for horizontal layouts ("Align text baselines"; crossAlign baseline):
  first-line baselines line up, other layers align to the top, nested auto layout frames use
  their first child's baseline. Measure gains text_baseline.
- Grid auto layout: column/row tracks (fixed px, hug, fr fill) via columnTracks / rowTracks or
  layout.setTrack, cells anchored by gridColumn / gridRow with gridColumnSpan / gridRowSpan,
  auto placement in reading order, rows grow to fit, hugging grids size to their tracks.
  Panel: column/row gap, track size rows, a child's cell and spans. Old files load unchanged
  (serde defaults; missing tracks are 1fr).
- Canvas handles: wrapped-row gaps and grid column/row gaps are draggable; a selected grid's
  tracks are outlined.
- The layout section moved from right.rs to layout_panel.rs; inspect reports min/max and a
  grid child's resolved gridCell; docs list the new props.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 02:23:43 +07:00
BFlatandClaude Opus 5.5 94e689fad6 M4: vector edit mode tools: pen branching, bend, paint bucket, lasso, cut, mirroring, point panel (#2)
- Edit-mode toolbar (Move V, Pen P, Bend hold Cmd, Paint bucket Shift+B, Lasso Q, Cut X, Done)
  replaces the tools while a vector is edited.
- Pen in edit mode continues open ends, branches from any point (vector networks), adds points on
  segments and closes paths into fill regions; dragging pulls out mirrored handles.
- Paint bucket fills or unfills any closed area: faces of the network (half-edge walk, nested
  pieces become holes), with a hatched preview of the area under the pointer.
- Bend tool / Cmd: bend segments, pull handles out of a point, click a smooth point to sharpen it.
- Lasso and marquee point selection, segment selection (shift adds), cut at a segment or a point.
- Per-point handle mirroring (none / angle / angle and length, inferred for existing files),
  Alt-drag breaks it; smooth/sharp points; join and merge selected points (Cmd+J, Shift+Cmd+J).
- Delete opens the path, Shift+Delete heals it; arrows nudge points; Cmd+A selects all points.
- Design panel shows the selected points' position, corner radius and mirroring.
- Every gesture is one undo step; edit mode ends when its layer is undone away.
- Paths that end on their start without a ClosePath (ellipse outlines) stay closed and filled.
- New commands (vector.edit.tool/pen/paint/cut/lasso/mirroring/smooth/position/nudge/connect/...)
  for the CLI, control channel and MCP; docs updated.
- Clippy: simplify a few boolean expressions flagged by the current toolchain.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 02:16:04 +07:00
Brandon ThomasandClaude Opus 5.5 8bb9f9534c README in the Crafting Apps style
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:56:03 -04:00
Brandon Thomas a66b3d2882 first commit 2026-10-09 11:38:50 -04:00