Repository navigation
editor: GUI-first modeling over SDK operations (features, sketches, assemblies) and new sketch/assembly operations - #72
Merged
Merged
Conversation
…s over it features.py is a hand-curated table of 24 operations (primitives, profiles, booleans, hole, fillet, chamfer, shell, patterns, transforms) with typed slots and a template that renders the cells; a drift test checks every template against the live signatures. gui_features.py adds, edits and deletes features through the editor's own cell commands (an edit carries the code it was made from, so an agent's concurrent edit is never overwritten) and keeps an undo/redo history. Routes: GET /api/features/specs, GET /api/features, POST /api/features. Generated cells are ordinary cells (params cell + feature cell, selectors inline, a '# gui:' line to rebuild the form). Primitives and extrudes carry readable face tags; a selection recipe tries the tags first and checks the count. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…, and the protocol in the skill sca new --kind blank writes a part notebook with no cells; the first GUI feature adds the product cell that builds the Part from it, and later features that consume that body move it along. editor-collaboration.md says what a GUI cell looks like, that GUI commands never overwrite an edit made in between, and how the inline selection recipes behave. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…r dialogs The Features tab lists the notebook's features (GUI-made ones editable, code ones marked), shows each one's errors, offers undo/redo and a banner when the product does not build from the tip. Operations are added from a floating command bar (category chips, keyword search, Up/Down/Enter, docked top or bottom, collapsible) fed by a command registry; each one opens a non-modal dialog generated from the operation's typed slots, with viewport picks for faces and edges and a 'use picked face' helper for holes. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…nt for a canvas sketch_doc.py is the document a 2D canvas edits (points, lines, circles, arcs, 24 constraint kinds, the profile that becomes the face): validation (every id and number that reaches code is checked), the sketch cell it renders to (dimensions become scad.var sliders in the params cell), and solve(): the SDK solver without recording anything, returning status, degrees of freedom, solved points, diagnostics and the profiles (about 1.3 ms for a small sketch). POST /api/sketch/solve serves it. features.py gets a face-producing 'sketch' operation and extrude/revolve/cut/boss from a sketch; the feature service keeps solids and profiles apart (tip, open bodies, defaults, the plane normal a profile extrudes along). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
assembly_doc.py is the document a GUI edits (components with placements, the grounded one, fixed/revolute/prismatic/gear/belt/ rack-pinion constraints between connector frames): validation, and three cells it renders to (params sliders for placements and joint drives, one scad.use per child, one layout cell that builds and solves the assembly in a single pass so no cell carries the whole assembly through a chain). The feature service adds, edits, deletes and undoes the three cells together and keeps the undo history valid when a cell is re-created. GET /api/assembly/parts lists the workspace's parts and, with ?path=, the connectors a part declares. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
An SVG 2D editor for the sketch document: select/move, point, line, circle, arc, construction, auto horizontal/vertical, pan and zoom, snapping; a constraint toolbar that enables by the current selection; dimensions edited in place (double-click the label); live solve at every drag step with a temporary fix on the dragged point; status, degrees of freedom and diagnostics; closed loops found client-side and matched to the solver's profiles so the outer profile and the holes can be picked; plane selector. The sketch feature dialog hosts it in a wide docked panel; profile slots are selects over the notebook's sketches and the extrude direction follows the profile's plane normal. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
set_connectors replaces the list of connector frames of the part the product cell builds; the list lives in a marker line the GUI reads back, each frame becomes an add_connector_rpart call, and the first product the GUI makes is a recorded make_part_rpart so connectors can be added to it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ormal
The sketch plane is a name (XY, XZ, YZ) or a frame {origin, x_axis, y_axis} (the SDK already takes one), validated to be unit and
square; profiles report their normal vector, and the sketch-based operations take 'normal of the sketch plane' as a direction,
which is the default. This is what sketching on a picked face needs.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…DK operations Trim removes the part of a line, circle or arc that contains a point, between the nearest crossings (or the ones named in against); extend lengthens a line until it meets the next entity. Both work on the solved geometry, keep the sketch connected (point_on ties, horizontal/vertical kept, dimensions that cannot hold dropped), are recorded in the operation graph and replay from model JSON. diff_sketch_rsketchdiff reports what an edit created, removed and changed. C++ in src/cpp/src/sketch/edit.cpp, bound in bind_sketch.cpp, with doctest cases, Python tests and API pages; the two operations join the canonical core op set. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…edits are the SDK's operations Sketching happens in the viewport (the camera turns to the chosen plane or face, the model stays visible and orbitable, the drawing is an SVG overlay projected through the live camera); the separate canvas panel is gone. The sketch plane can be a face frame. Trim and extend are not editor features: sketch_doc.apply_edit builds the SDK Sketch from the document, calls scad.<op>_rsketch and turns the result back; the command line (sca sketch op) and /api/sketch/op are the same thin bridge. Cut/boss/extrude from a sketch accept 'against the normal'; profiles carry a plane label; an edit that removes parameters writes the feature cell before the params cell so no cell reads a name that is gone. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Trim (T) and Extend (E) in sketch mode call /api/sketch/op, which runs the SDK's trim_rsketch / extend_rsketch; the frontend only builds the request, picks the nearer end and adopts the answer (undoable, errors shown, created entities flash). The Assembly tab edits the assembly document (components from the workspace's parts, placements, grounding, constraints with connector pickers), shows connector frames as gizmos in the viewport (clickable to fill a picker) and writes the part-side connectors from picked faces. The feature state's undo count now follows the open notebook. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…nd explode_rassembly fillet_corner/chamfer_corner round or bevel the corner of two lines that share a point (tangent and radius/length constraints keep it defined); project_rsketch brings geometry from another sketch or from the edges of a shape into a sketch as fixed construction geometry, which is how sketches in different planes are related; explode_rassembly returns an assembly with the component placements displaced for an exploded view (factor, centre or axis, per-component directions and weights). C++, bound, recorded, replayable, stubbed, documented and tested like trim/extend. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…sembly document /api/sketch/op reaches fillet_corner, chamfer_corner and project (the source is another sketch feature of the notebook, named by from_sketch); the assembly document can carry an exploded view: the product becomes scad.explode_rassembly of the solved assembly and the factor is a slider variable. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… errors shown where they happen Corner tools (R, H) pick a corner or two lines and ask for the radius or distance; Project (J) brings another sketch's geometry in as muted fixed reference geometry; the Assembly panel gets an exploded-view section. All three send the request and adopt the SDK's answer. A feature that fails to run keeps its dialog open with the error, and the next submit edits it instead of adding a duplicate. The feature dialog docks below the Inspector header. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… by its code Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…r components Connector frames were SVG lines whose screen directions were normalised to a fixed length, which destroyed foreshortening when the camera rotated; they are now three.js objects in the viewer's scene (X red, Y green, Z blue with cone heads, Z longer, a translucent contact plane), depth-tested with a faint ghost pass for the hidden ones, sized from the model and following the component's node. The pieces are reusable: scene/layers (a layer host with picking, hover/selected state, apparent-size scaling, ghost materials, anchoring to a node) and components/scene (SceneLabel anchored to a 3D point, AxisTriad, useSceneLayer, axis colours). The first camera view now fits the whole bounding sphere with a margin. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…tual action bar, sketch on a face Finished sketches are drawn in the viewport all the time (dim when an extrusion already uses them, an eye per sketch remembered per notebook, hover and selection linked with the tree); sketches are selectable (a SKETCH selection mode, or armed from a form) and the Extrude/Revolve/Cut/Boss forms take the selected sketch as their profile; 'Finish and extrude' finishes and opens the extrude form with the new sketch. A contextual action bar shows the commands that fit the selection (a planar face: Sketch on this face, Hole here, Shell; a sketch: Extrude, Revolve, Cut, Boss, Edit), driven by a when(selection) predicate on registry commands. The plane chooser highlights faces on hover and refuses curved ones with the reason; the cut form shows the direction as an arrow with a flip button. General pieces live in components/ (ActionBar, HintBanner, SelectionBar). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…tersect) A part holds one solid, so the operations that make a new solid (primitives, extrusions, revolutions, lofts, sweeps, and the sketch extrude/revolve) get an Operation slot and a Combine-with slot instead of leaving a second body beside the first: the solid is built as a private tool and joined to, cut from or intersected with the body so far in the same cell, the feature's role follows the operation, and the product follows. 'New body' starts the first body. Slots can be shown only for some values of another slot (show_when), and the feature state defaults the operation to join when a body exists. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…lid is made The Operation slot of a new solid is a segmented control (New body only when there is no body yet), the Combine-with slot shows as a line when one body is open, slots can be shown only for some values of another slot, and the stand-alone cut/union/intersect and sketch cut/boss commands are hidden unless several bodies are open: a selected sketch offers Extrude (join) and Extrude (cut) as presets of the one Extrude dialog. The chooser and its keyboard logic are general components. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
A button-first way to model in
sca edit, built on one rule: every capability is an SDK operation an agent can call in code; the editor is a UI over them.SDK (C++, recorded, replayable, stubbed, documented, tested)
trim_rsketch,extend_rsketch,diff_sketch_rsketchdifffillet_corner_rsketch,chamfer_corner_rsketch,project_rsketch(relates sketches on different planes)explode_rassembly(exploded view as an assembly operation, factor is ascad.var)Editor (Python)
# ---- params ----+# ---- feature ----with a# gui:line); drift tests check every template against the live signaturesPOST /api/features; every edit carries the code it was made from, so a concurrent agent edit is refused (409), never overwrittenPOST /api/sketch/solve, andPOST /api/sketch/opwhich only calls the SDK edit operations; sketches can lie on any plane frame (a picked face)scad.use/ one layout cell (no cell carries the assembly through a chain); connectors of a part; exploded viewsca feature ...andsca sketch ...for agents;sca new --kind blankeditor-collaboration.mddocuments the# gui:rules and the commandsEditor web UI
scene/layersandcomponents/scene)Also in this branch: the skill entry redesign is not here (already on dev); the C++ SDK operations are the first commits.
Tests
test/, the seven untracked old test files excluded as before)skillbuild --checkOKKnown limits
component_id; the frontend matches the last segment of the node idscene/sketch-layer.tsandscene/layers/); to be unified🤖 Generated with Claude Code