Commit Graph
29465 Commits
Author SHA1 Message Date
Tommaso BianchiandClaude Opus 4.8 3ba6feb7a7 tests: fix hex-escape-out-of-range in CAD recipe 3mf test
gcc reads "\x10cad..." as one escape (c/a/d are hex digits → 0x10CAD > 255).
Split the string literal so the \x10 escape terminates. clang let it slide;
gcc (Linux/Windows CI) errored and blocked the OrcaSlicer build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-07-02 13:06:28 +02:00
Tommaso BianchiandClaude Opus 4.8 1673c2c760 Design tab: keyboard shortcuts, plane/axis toggles, section view
- Keyboard shortcuts (Onshape-style, three scoped layers): feature tools on
  Shift+letter, 2D sketch tools on single letters (in-sketch), view/nav on
  single letters (out-of-sketch). Dispatched via the DesignPanel CHAR_HOOK.
- View toggles: P = origin planes, A = world axis triad (render_view_helpers).
- Section view (non-destructive): a single horizontal clip that hides half the
  model to inspect inside, showing only the solid remaining half (no ghost).
  Left-panel "Section View" button or X toggles it; PageUp/PageDown move the
  plane; "Flip Section" button or F shows the opposite half. Never a body/Cut.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-07-01 23:19:18 +02:00
Tommaso BianchiandClaude Opus 4.8 de16d566b2 Design tab: value-label titles + 5 sketch/UX fixes
Six fixes to the Design tab, all live-verified on :10:
- Datum-plane re-pick: wxEVT_CHOICE on m_draw_plane re-planes the live sketch
- Delete-feature dismisses its lingering settings card (on_delete_feature)
- Revert rotation-orbit regression (no feed_bodies/reload on close_tool)
- Sketch undo/delete via focus-independent CHAR_HOOK (Ctrl+Z/Y, Delete)
- Fix undo hang: reset_autoedit() clears dangling auto-edit sequence
- Titled value fields: each inline dim field shows its role (Width, Height,
  Radius, Angle, Length, Side, Distance, Major, Minor)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-07-01 19:19:23 +02:00
Tommaso BianchiandClaude Opus 4.8 5a005d4728 Design: in-canvas gizmos for Draft/Cut + operand highlight for Boolean/Sweep/Loft
Closes the gizmo-parity gap (bd snaporca-4h5): the five solid features that were
card-only now give in-canvas feedback like their siblings.

Draft — angle-arc drag gizmo (clone of the Revolve gizmo): once a side face is
picked, a cyan arc anchored at the face centroid shows the taper angle; drag the
tip or type the angle, the live ghost tapers with it. Axis = world +Z (the neutral
pull direction), clamped [-89, 89].

Cut — plane offset-arrow + cutting-plane rectangle (clone of the Shell arrow, adds
a wire rectangle in the cut plane sized to the target body bbox). The arrow drags
the signed offset along the plane normal; the rectangle rides at the cut position;
the ghost splits live. (Also covers bd snaporca-1gh / snaporca-mmr.)

Boolean / Sweep / Loft — operand highlighting (new by-index highlight infra):
- Boolean tints the target body teal-green and the tool body orange (per-index
  body tint added to the DesignCanvas GLVolume colour loop + set_operand_bodies).
- Sweep tints the profile sketch cyan and the path sketch magenta.
- Loft tints every selected profile sketch green.
  Sketch tints reuse the DisplaySketch overlay via a feature-index -> colour map
  (sketch_hl_color); DisplaySketch struct unchanged. All self-gate by active tool
  and clear on close_tool.

Wiring mirrors the existing gizmo pattern 1:1 (m_*_active / render_* / set_* /
clear_* / update_* in refresh_preview / DesignCanvas passthroughs / render dispatch
+ on_mouse drag branch). Both forks; DesignSketchTool.{cpp,hpp} + DesignCanvas.hpp
+ DesignPanel.hpp byte-identical across forks. Built clean on both. Draft, Cut and
Boolean highlight live-verified on :10; Sweep/Loft sketch tint is code-complete and
build-clean (visual check pending — needs hand-drawn profile/path sketches).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-07-01 10:19:33 +02:00
Tommaso BianchiandClaude Opus 4.8 8cbf5b393b Design: Measure-style dimension labels (+ projection fix), New Design, tree auto-fit, i18n pin, UX
Sketch dimension labels — now identical to the Prepare/Preview Measure gizmo:
- draw_text repurposed to draw_dim_label: white ImGui text in a translucent-white box,
  mirroring GLGizmoMeasure::render_dimensioning exactly (push_common_window_style sets the
  text colour, BringWindowToDisplayFront, imgui_internal.h).
- ROOT-CAUSE FIX: world_to_screen_px multiplied two Eigen Transform3d objects
  ((proj * view).matrix()); a projection is not affine so Eigen mangled it -> garbage screen
  coords, so labels never appeared. Now proj.matrix() * view.matrix() like Measure. (That
  helper was previously [[maybe_unused]] dead code, never exercised.)
- Leaders: offset clear of the sketch line (no longer coincident with the geometry), single
  point-to-point dimension line + arrows, neutral colour, width 0.6 -> 0.2.
- dim_text appends mm/in on linear dims (angles keep the degree sign).

New Design + delete:
- New "New Design" button wipes the whole document (confirm dialog) — the clear-all the
  per-row Delete can't give. CadDocument::clear() now also clears bodies + display_body_meshes
  (it left them stale, so solids lingered after a clear).
- on_delete_feature: a Body-row selection now shows a helpful hint (bodies are recomputed
  results with no directly-removable feature) instead of silently doing nothing.

Feature tree: auto-fits its content (refresh_tree clamps height 1..9 rows, scrolls past),
instead of a fixed 140px block.

i18n (Design tab pinned English, per the UX contract):
- Restore the lost #undef _L / #define _L(s) wxString::FromUTF8(s) override atop DesignPanel.cpp;
  wrap all ~54 dropdown options in _L so the single lever governs them. feature_type_name left
  untranslated (machine-facing MCP JSON).

UX: per-card Value Confirm/Cancel buttons removed — the single ribbon action bar owns value
confirm/cancel via an m_value_cont guard in tool_confirm/tool_cancel. "needs a body" status
messages unified.

Both forks; DesignSketchTool.{cpp,hpp} + CadDocument.cpp byte-identical across forks. Built
clean; New Design / feature-delete / rotation / tree auto-fit live-verified on :10.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 23:21:04 +02:00
Tommaso BianchiandClaude Opus 4.8 6e11cfc49b Design: Measure-style dimension labels + restore English-only pin + UX consistency
Dimensions (uniform with Prepare/Preview):
- Repurpose DesignSketchTool::draw_text -> new draw_dim_label that renders each
  sketch dimension as the exact Prepare "Measure" gizmo label: white ImGui text
  in a translucent-white box, positioned via the existing world_to_screen_px
  projection inside the active ImGui frame. All 29 label call sites convert with
  no churn; the bespoke Hershey vector font is retired.
- dim_text appends mm/in on linear dims (angles keep the degree sign).
- Placed-dimension leaders simplified to a single point-to-point line + arrows in
  a neutral colour (no extension lines), matching the Measure look.

i18n (Design tab pinned English, per the UX contract):
- Restore the lost "#undef _L / #define _L(s) wxString::FromUTF8(s)" override atop
  DesignPanel.cpp so one lever de-translates the whole tab, ending the half-EN/IT
  state. Wrap all ~54 dropdown options in _L so the single lever governs them.
- feature_type_name left untranslated (it feeds the MCP JSON, machine-facing).

UX consistency:
- Remove the per-card Confirm/Cancel buttons from the Value card; the single ribbon
  action bar now owns value confirm/cancel via an m_value_cont guard in
  tool_confirm/tool_cancel (one confirm surface, per contract).
- Unify the eight divergent "needs a body" status messages to one template.

Both forks; DesignSketchTool.{cpp,hpp} byte-identical across forks. Built clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 22:01:54 +02:00
Tommaso BianchiandClaude Opus 4.8 f341ee2677 MCP bridge: expose all 16 methods live + fix optional-param required-ness
- snaporca_mcp_bridge.py: _param_schema maps array/object types + carries
  per-param description; _FALLBACK_TOOLS expanded slice-1 -> full 16-method
  surface (socket-down at client startup still shows the whole toolset)
- describe_tools: give genuinely-optional params a default (body -1, profile [],
  shell.face -1, extrude.distance2 0 / up_to_face -1) so the bridge no longer
  marks them required (draft.face/edge/path/a/b/reference stay required)

Product code byte-identical to snaporca (md5 match). orca_cad slicer builds clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 18:05:54 +02:00
Tommaso BianchiandClaude Opus 4.8 b93b9d558c Mirror [Deviation] surface_deviation test into test_caddocument.cpp
orca_cad's test_geometry.cpp is upstream Catch2 v3 with no CAD suite, so the
surface_deviation check lives alongside the CAD tests here. Built + ran green
in orca_cad's kernel-test docker: All tests passed (4 assertions). Both forks
now carry the test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 17:55:06 +02:00
Tommaso BianchiandClaude Opus 4.8 94cde2af21 MCP slice 5: body-targeted fillet/chamfer, ordered slice contours, surface-deviation validate, widen Build
- fillet/chamfer accept optional `body` (sets target_body; edge id resolved against THAT body)
- slice_body chains section segments into ordered contours, each flagged closed/open
- validate_against adds surface_deviation (one-sided Hausdorff via BRepExtrema_DistShapeShape)
- new actions pattern/shell/draft; extrude gains end=blind|symmetric|two_sided|through_all|up_to_face + taper/flip/distance2
- GeometryEngine::surface_deviation helper (byte-identical to snaporca; Catch2 [Deviation] test lives in snaporca, whose test_geometry.cpp carries the CAD suite)

Product code byte-identical to snaporca (md5 match). Both forks build clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 17:52:08 +02:00
Tommaso BianchiandClaude Opus 4.8 d2f97a752b MCP slice 4: widen Build (revolve, fillet, chamfer, hole, boolean) + profile
Reconstruction is no longer box-only. Five new actions, all thin
wrappers over existing CadDocument::add_* (the same kernel the GUI
calls): revolve (sketch -> add_revolve), fillet/chamfer targeted at a
measured edge id from query_topology, hole (add_hole), and boolean
(union/subtract/intersect over two bodies). extrude and revolve also
accept an optional closed profile=[[x,y],...] -> add_sketch_profile,
the Measure->Build bridge: feed a measured/sliced contour straight back.

Shared helpers plane_from / bool_from / profile_from. Each action is
transactional (checkpoint -> add -> recompute -> undo on failure ->
refresh) and returns post-state. Live-verified: fillet, chamfer (clean
edge), hole, profile-extrude (L), revolve (ring), boolean union (3->2
bodies). MCP method catalogue now 13.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 16:45:01 +02:00
Tommaso BianchiandClaude Opus 4.8 8db9544a1a MCP slice 3: import_step + validate_against (close the RE loop)
Add the Build-input and Validate ends of the reverse-engineering loop.
import_step loads a STEP as native B-rep bodies (the reference part to
measure), reusing the GUI Import path (read_step_solids -> Import
features -> recompute). validate_against compares a body to a reference
({step:path} | {body:id}) and reports volume delta %, bbox delta, and
centroid offset via OCCT GProp + Bnd_Box — the RE skill's actual
acceptance metric (the "scarto %"); surface-deviation heat-map is the
upgrade path.

With this the full Understand -> Measure -> Build -> Validate loop is
live: 8 methods (describe_tools/describe_scene/query_topology/measure/
slice_body/import_step/validate_against/extrude). Verified: import a STEP
then validate body vs same STEP = 0.0%% delta / 0.0mm offset.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 15:52:20 +02:00
Tommaso BianchiandClaude Opus 4.8 5b46b1ed1f MCP slice 2 (Measure): query_topology, measure, slice_body
The "evidence" half of the reverse-engineering loop — read-only
perception that turns a body into measured numbers. query_topology
lists faces (centroid/normal, cylinder radius+axis when round) and
edges (length, circle radius); measure returns distance (and angle when
both refs have a direction) between two {face|edge|point} refs;
slice_body cross-sections a body by a base plane at an offset and
returns world polylines (sections-as-evidence). All reuse GeometryEngine
topology accessors; slice_body adds one BRepAlgoAPI_Section call.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 15:42:44 +02:00
Tommaso BianchiandClaude Opus 4.8 294bbccd0b Add stdio MCP bridge for the control socket
Zero-dependency Python stdio MCP server that exposes the app's control
socket as first-class MCP tools. Builds the tool list live from the
app's own describe_tools reply (introspection drives the schema), and
forwards tools/call to the Unix socket. Falls back to the slice-1 tool
set and reports a clear error when the app socket is down — never
crashes. Registered via a workspace .mcp.json (ssh stdio to the build
host); activates on the next session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 15:37:39 +02:00
Tommaso BianchiandClaude Opus 4.8 4f8a0d133f Add MCP control surface (slice 1): socket server + describe/extrude
Predispose the Design tab to run under an external MCP agent. New
McpControl.{cpp,hpp} embeds a line-delimited JSON-RPC 2.0 server over a
Unix domain socket, off unless env SNAPORCA_MCP is set. Requests are
marshalled onto the wx main thread and run through the SAME CadDocument
kernel the GUI uses, via two thin DesignPanel hooks (mcp_doc /
mcp_after_change) — no parallel engine.

Slice-1 methods: describe_tools (introspection -> the bridge builds tool
schemas), describe_scene (feature tree + per-body bounding boxes), and
extrude (centred rectangle sketch -> new solid). Every op returns its
full post-state. POSIX-only; Windows compiles to a no-op.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 15:32:51 +02:00
Tommaso BianchiandClaude Opus 4.8 5ecb319dee Reject .f3d import with a STEP redirect hint
Fusion 360 .f3d uses Autodesk's closed ShapeManager kernel — no offline
reader exists and it is input-only even in Autodesk's own cloud API, so
native import/export is infeasible. Intercept .f3d at priv::load_files
(the single funnel for drag-drop and File > Open) and show a dialog
pointing the user to export STEP from Fusion, then load any other files
in the batch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 15:00:05 +02:00
Tommaso BianchiandClaude Opus 4.8 aa2907f730 Design: STEP export of the CAD model
Add an "Export STEP…" button to the Design panel that writes every body to a
.step file as native B-rep (not mesh).

- CadDocument::export_step: compound all bodies (applying their per-body Move
  display transform so the STEP matches what Commit ships) and write via OCCT
  STEPControl_Writer (AsIs). Full error handling incl. OCCT Standard_Failure.
- DesignPanel::on_export_step: bake any open preview, wxFileDialog save, export
  at the displayed body positions, status feedback.

Kernel write path verified with a standalone OCCT box->STEP->readback check
(1 solid, non-null) against the same OCCT build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 08:21:03 +02:00
Tommaso BianchiandClaude Opus 4.8 30713f0f23 Design: re-editable Boolean features
Boolean features can now be re-edited from the feature tree (op, target/tool
body, keep-tool, fuzzy tolerance), funnelling through the same replace_feature
path as every other editable feature.

- on_edit_feature: route CadFeatureType::Boolean to the Boolean card.
- load_feature_into_dialog: populate the Boolean card from the saved feature.
- populate_body_choices(as_of_feature): when re-editing, list the bodies as they
  existed just before the boolean (replay the recipe truncated to that slot) so a
  consumed tool body still appears and the saved target/tool selections round-trip
  instead of collapsing to one entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 07:56:30 +02:00
Tommaso BianchiandClaude Opus 4.8 71b7a73e86 Design tab: reference planes at bed centre, slot dims, hole cube handle, real threads
Port of the snaporca CAD work to the mainline fork.

- Onshape default planes (XY/XZ/YZ) at the bed centre (transparent, labelled);
  modeling origin unified to the bed centre (CadDocument::modeling_origin);
  world-axis triad moved to the bed centre on the Design canvas only.
- Datum plane: clickable ghost-plane base pick + draggable offset arrow.
- Slot: dims reassessed to inter-centre distance / radius / angle; fixed the
  duplicate cap-arc radius quote.
- Hole: 3D cube move-handle on the face; binds to the face on the first click;
  decluttered side-distance construction lines.
- Thread: derive the M spec (diameter/pitch/depth) from a picked cylindrical
  surface or circular edge (GeometryEngine::circle_of_edge); fuse the helical
  ridge onto the existing body; MakePipeShell fixed-binormal sweep (uniform, no
  twist) + self-intersection/param guards.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-30 00:24:39 +02:00
Tommaso BianchiandClaude Opus 4.8 852804450c Design re-edit: seed build_candidate from the edited feature (fix new-box bug)
Mirror of snaporca-cad 75045ff. Re-editing an Extrude spawned a NEW misplaced
box: build_candidate() rebuilt the feature from live tool state, but GUI
extrudes store their profile as `entities` (sketch_ref = -1) which the edit
card never restores, so the candidate had an empty profile and replace_feature
swapped in a degenerate extrude. Fix: when editing, seed the candidate from the
feature being edited and skip add-time structural re-derivation (profile source,
up-to-face, target body); the card still overrides scalar params.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-29 07:49:32 +02:00
Tommaso BianchiandClaude Opus 4.8 b355d04d3a CAD re-edit: mid-timeline rebuild tests + non-silent Edit fallback
Mirror of snaporca-cad a82cb0d. snaporca-88g — three [CadDocument] tests
proving recompute() replays the whole timeline, so editing any feature (not
just the last) rebuilds downstream: mid-timeline extrude edit -> fillet
rebuilds; first-feature sketch edit propagates the chain; the same survives
serialize_recipe()/deserialize_recipe(); a sketch->extrude->hole->chamfer
chain rebuilds hole+chamfer on a mid-edited extrude. All 3 pass (34 assertions,
Catch2 v3). on_edit_feature edits the tree-selected feature at any position
(13/16 types); Import/Boolean/Cut get a status message instead of a silent
no-op (full dialogs = follow-up snaporca-nu9).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-29 06:30:01 +02:00
Tommaso BianchiandClaude Opus 4.8 a121e30a13 Design canvas: gate direct-render hacks behind sw-GL detection
Mirror of snaporca-cad f3b665b. DesignCanvas had ~38 call-sites doing
`set_as_dirty(); render()` directly, tagged "llvmpipe: force repaint" —
software-GL workarounds from the headless :10 test box. On hardware GL this
bypasses the dirty/refresh cycle and burns frames outside the paint event.
Funnel all 38 through a new request_repaint() helper that branches on the
cached GL renderer string: hardware GL gets set_as_dirty()+wxGLCanvas::Refresh()
(render() runs inside the paint cycle), software GL keeps the direct render(),
undetected backend takes the safe direct path. Behaviour on the llvmpipe :10
box is byte-identical; hardware GL invalidates the canonical editor way.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-29 06:11:22 +02:00
Tommaso BianchiandClaude Opus 4.8 2929f66881 Design tab i18n: remove _L override, route strings through gettext
Mirror of snaporca-cad 0f53a09. DesignPanel.cpp pinned every _L() to
wxString::FromUTF8 via a TU-local #define, hardcoding English and bypassing
the gettext catalog — a hard review-blocker for upstream (OrcaSlicer ships
~20 locales). Remove the override so the 463 _L("...") call-sites route
through the real Slic3r::GUI::I18N::translate (wxGetTranslation). All args
are string literals; untranslated strings fall back to the source msgid, so
English is byte-identical while other locales now translate when .po entries
exist. xgettext scans source text, so .pot extraction is unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-29 06:04:42 +02:00
Tommaso BianchiandClaude Opus 4.8 36b2bd8bfc CAD persistence: implement recipe round-trip on the BBS 3mf backend (mirror)
Mirror of snaporca-cad ad822bf. The earlier mirror (2c0140afb9) implemented
persistence in the PrusaSlicer 3mf.cpp, but the GUI saves/loads projects via the
BBS-native backend (store_bbs_3mf / load_bbs_3mf), so the recipe was never
written to nor read from GUI-saved projects.

- bbs_3mf.cpp: BBS_CAD_RECIPE_FILE = "Metadata/SnapOrca_cad.bin"; writer
  _add_cad_recipe_file_to_archive (called after layer-height in store_bbs_3mf);
  reader branch in _load_model_from_file's metadata dispatch loop (iterate +
  iequals on m_filename — mz_zip_reader_locate_file does not work on these
  archives).
- Plater.cpp: load_files carries the Model-level cad_recipe onto q->model().
- test_3mf.cpp: [3mf] test asserting store_bbs_3mf embeds the recipe entry
  byte-for-byte (read back via miniz, Catch2 v3).

Verified on behemoth: libslic3r_tests + the new [3mf] BBS test pass; orca-slicer
GUI links clean. Round-trip verified live on snaporca-cad (identical code path).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-28 21:53:36 +02:00
Tommaso BianchiandClaude Opus 4.8 e985d95dfb Add missing color_palette.svg (Design colour-tool icon)
DesignPanel's per-body colour button references icon "color_palette" but the
asset was never ported with the CAD subsystem. On mainline OrcaSlicer the
missing bitmap throws during MainFrame construction → segfault at startup
(create_scaled_bitmap "Could not load bitmap: color_palette"). Copied from
snaporca-cad resources; runtime-loaded, no rebuild needed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-28 19:37:50 +02:00
Tommaso BianchiandClaude Opus 4.8 2c0140afb9 Mirror CAD persistence (K1+K2+G1) from snaporca-cad onto mainline OrcaSlicer
Dual-fork mandate: port the parametric-recipe 3MF persistence from
snaporca-cad commits ed19eac+147e1c4 so a saved project reopens with the
editable CAD feature tree, not just the baked mesh.

Shared kernel/format/GUI (identical to snaporca-cad):
- CadDocument serialize_recipe/deserialize_recipe (cereal BinaryArchive,
  versioned) + CadFeature split save/load + imported_solid<->BRep string.
- Model::cad_recipe carried through 3MF zip entry Metadata/SnapOrca_cad.bin
  (writer + binary-verbatim reader branch).
- DesignPanel on_commit() stamps the recipe; on_tab_shown() rehydrates a
  loaded project via load_recipe() (deserialize -> feed_bodies + refresh_tree).

Mainline-only adapters (no snaporca-cad counterpart — Catch2 v3 vs v2):
- tests/libslic3r/test_caddocument.cpp: <catch2/catch_all.hpp> +
  `using Catch::Approx;` (v3 scopes Approx under Catch::).
- tests/libslic3r/CMakeLists.txt: register test_caddocument.cpp (the
  original CAD port had left it out of the test build).

Verified on behemoth (snaporca-deps toolchain): libslic3r_tests clean;
[CadDocument] 17/18 (only the pre-existing tangent-to-circle SIGABRT fails,
identical to snaporca-tkz); K1 serialize round-trip + version-reject pass
(13 assertions); new [3mf] "CAD recipe blob survives a 3mf save/load cycle"
passes byte-for-byte; orca-slicer GUI links clean (186/186, DesignPanel.cpp
compiled). Interactive :10 click-through pending (no Design-tab automation).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-28 17:05:44 +02:00
Tommaso BianchiandClaude Opus 4.8 c22351f63a Fix GUI build on mainline OrcaSlicer: DropDown Item API + Bed3D::set_shape
Two Snapmaker->mainline API divergences surfaced once the ported CAD
subsystem compiled (the whole libslic3r CAD kernel + vendored slvs solver
built clean):

- DesignPanel: Snapmaker's DropDown took 3 parallel vectors
  (texts/tips/icons); mainline's is Item-based (std::vector<DropDown::Item>).
  Collapsed both flyout structs (FeatFlyout, ToolFlyout) to one Item vector.
  Event/selection path unchanged (both emit wxEVT_COMBOBOX + SetInt).
- DesignCanvas: mainline Bed3D::set_shape added extruder_areas/heights
  params before custom_model; pass empty vectors.

Build verified: links clean (orca-slicer, 280/280). Runtime reaches the GTK
event loop equivalently to the proven-good snaporca binary; full visual
Design-tab verification pending an interactive :10/x11vnc session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-28 15:14:15 +02:00
Tommaso BianchiandClaude Opus 4.8 0f4060c0a9 Orca-Cad: port SnapOrca Design (parametric CAD tab) onto mainline OrcaSlicer
Grafts the sketch-first CAD environment from snaporca-cad onto the mainline
OrcaSlicer/OrcaSlicer base (vs snaporca's Snapmaker/OrcaSlicer base):
- 133 new files: CadDocument/SketchEngine/GeometryEngine/SketchConstraints/
  SketchSolver/SketchInference/ThreadStandards + vendored libslvs solver;
  DesignPanel/DesignCanvas/DesignSketchTool/SketchInlineEditor GUI; GLGizmo
  Primitive/Sketch; 75 design icons; Catch2 tests.
- Integration hooks ported to mainline's diverged versions: Design tab in
  MainFrame, embedded design viewport + sketch overlay + per-canvas chrome
  suppression in GLCanvas3D/PartPlate, gizmo registration, Plater accessors,
  CMake wiring (libslvs subdir, CAD sources, OCCT ModelingAlgorithms=ON).

Structural integration complete; build verification pending.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-28 12:40:38 +02:00
Heiko LiebscherandClaude Opus 4.8 449a4cf9fc Update German (de) translation (#14465)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 16:37:15 +08:00
SoftFever 943a75af0a Preventing removal of old networking plugins on app version update as Orca allow user to pin the plugin version 2026-06-28 13:26:07 +08:00
yw4zandSoftFever 02bc8969a2 Fix: Missing inherited filaments on vendor profiles cannot found on OrcaFilamentLibrary (#12060)
* init

* ix: resolve OFL filament inherits in printer creation via base_bundle

---------

Co-authored-by: SoftFever <softfeverever@gmail.com>
2026-06-28 13:07:09 +08:00
SoftFeverandCopilot Autofix powered by AI c2e91cb86c validator: detect ambiguous (duplicate) filament subtypes per printer (#14459)
* validator: detect duplicate filament subtype per printer (opt-in)

A filament is matched from the AMS by (filament_id + printer compatibility);
if two compatible filament presets for one printer share a filament_id, the
match is ambiguous and the runtime silently picks whichever loads first.

Add PresetBundle::check_duplicate_filament_subtypes(), gated behind a new
has_errors(check_duplicate_filament_subtypes) parameter and the validator's
-f/--check_filament_subtypes flag (off by default). For each system printer it
groups its vendor's compatible filament presets by filament_id and errors on
any group of 2+, reporting each preset as a clickable file:// URI with a single
"how to fix" hint. CI runs it for BBL only (-v BBL -f) until the other vendors'
profiles are cleaned up.

* profiles: fix ambiguous BBL filament matches

Resolve the duplicate-filament-subtype errors flagged by the validator:
- align compatible_printers with Bambu Studio where Orca over-claimed a nozzle
  that already has a dedicated preset (Bambu PLA Basic/Matte/ABS @BBL H2DP;
  Bambu ASA/PETG HF @BBL H2DP 0.6 nozzle; Fiberon PETG-ESD @BBL X1)
- fix a copy-pasted printer name in Overture Matte PLA @BBL A1M 0.2 nozzle
- fix a wrong inherits in Panchroma PLA Silk @BBL X1C 0.2 nozzle (was inheriting
  Panchroma PLA @base, giving it filament_id GFPM001 instead of GFPM004)

Bump BBL profile version.

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-28 00:42:02 +08:00
Ian Chua a0846ec215 fix: update .info base_id if it is mismatched or empty (#14430)
* fix: update .info base_id if it is mismatched or empty

* Merge branch 'main' into fix/update-base-id-on-mismatch-or-missing

* early return
2026-06-27 23:07:44 +08:00
Ian Chua 0e8288de36 fix: old preset names should resolved renamed_from field (#14429)
* fix: old preset names should resolved renamed_from field

* chore: remove misleading comments

* Merge branch 'main' into fix/consider_renamed_from

* normalize_inherits

* improve find_preset2 performace
2026-06-27 22:15:43 +08:00
Ioannis Giannakas 0e4928f200 Introduce minimal chamber temperature field (gcode chamber_min_temperature (#14340)
Introduce minimal chamber temperature field (gcode chamber_min_temperature)
2026-06-27 13:27:01 +01:00
SoftFever 8cb2e4e01e profiles: deterministic setting_id from vendor/type/name (#14432)
* profiles: enforce globally-unique, per-vendor-namespaced setting_id

Many non-Bambu vendors copied Bambu's generic setting_ids (GFSA04 alone
appeared in 1557 files), so setting_id was not globally unique. This
namespaces every vendor's ids and reserves Bambu/OrcaFilamentLibrary space.

- Reserve "G*" (Bambu) and "O*" (OrcaFilamentLibrary) id spaces.
- Assign each other vendor a 2-char prefix (first+last letter, collision
  resolved) and renumber every instantiated preset to <PREFIX><NNNN>.
- Strip setting_id from base profiles (instantiation:false) per Bambu's
  convention; assign one to instantiated presets that lacked it.
- Remove the pre-existing misspelled "settings_id" key (91 files).
- filament_id is left untouched (it is a per-material id).
- Add one-time migration script scripts/assign_vendor_setting_ids.py with a
  persisted registry resources/profiles/vendor_prefixes.json. Re-runs freeze
  existing ids; only new vendors/profiles get new ids.
- Bump version in each changed vendor index file.
- Extend scripts/orca_extra_profile_check.py with a CI guard: global
  uniqueness, in-namespace, no base setting_id, no gaps, no settings_id typo.

7425 profile files changed across 61 vendors; 0 cross-vendor collisions;
validator clean; migration idempotent. BBL and OrcaFilamentLibrary id spaces
untouched.

* profiles: add setting_id authoring guide for new vendors / profiles

* profiles: drop in-repo README; setting_id guide now lives in the wiki

* profiles: derive setting_id deterministically from vendor/type/name

* bump profile version
2026-06-27 20:11:25 +08:00
Felix14_v2 3b58217b47 Review changes in Russian localization (#14422) 2026-06-26 16:54:36 -03:00
ExPikaPakaandSoftFever df95a30a0f Fix missing filament profiles in Filament Selection dialog (#14398)
* Resolve preset type based on nozle diameter if printer_variant is empty

* Fix incorectly resolving plastic type (PLA, ABS, etc.)

* Revert default print-variant handling as it can be not only nozzle diameter

---------

Co-authored-by: SoftFever <softfeverever@gmail.com>
2026-06-26 18:37:33 +08:00
SoftFever a1a9a0ce2b CI: add _x64 suffix to Windows installer/portable names for consistency with arm64 2026-06-26 16:39:13 +08:00
SoftFever b7ab7f4225 update locale 2026-06-26 11:56:29 +08:00
Myself 465125167b CrealityPrint: remove hardcoded :4408 from Device WebView URL (#14326)
* CrealityPrint: use printhost_port for WebView URL instead of hardcoded :4408

Fixes #4408 — when printhost_port is configured, use that port in the
Device WebView URL instead of always defaulting to :4408.

* CrealityPrint: remove hardcoded :4408 from Device WebView URL

Drop the CrealityPrint-specific get_print_host_webui override that
unconditionally appended :4408. The generic fallback in PrintHost
already uses print_host_webui/print_host config — users who need
Mainsail on port 4408 should set print_host_webui explicitly.

Fixes #4408
2026-06-26 02:21:42 +08:00
SoftFever 19755451a9 CI: download profile validator from nightly release 2026-06-26 02:14:57 +08:00
pallaswept 5d352294ed Allow appimage execution for non-owner (#14339) 2026-06-26 01:27:47 +08:00
SoftFever e3b4c6df84 Fix AMS overwrite sync showing filaments in wrong order (#14335) (#14408)
Syncing the filament list from AMS with the "Overwriting" option
  displayed the AMS filaments in the wrong (reversed) order in the
  preview, even though the filament mapping that was actually applied
  was correct. Reported on macOS with a Bambu X1C.

  The preview depends on MaterialHash being iterated in material-index
  order. MaterialHash is a WX_DECLARE_HASH_MAP, which under OrcaSlicer's
  current wxWidgets 3.3 build (wxUSE_STD_CONTAINERS=1) resolves to
  std::unordered_map; its iteration order is unspecified and on macOS
  (libc++) comes out reversed, which scrambled the preview. The same
  code is unaffected in BambuStudio because its older wxWidgets build
  still uses wx's own key-ordered hash table, so this only became
  visible after the wx upgrade.

  Fixes #14335
2026-06-26 01:20:38 +08:00
yw4z b06305f990 Plate toolbar improvements and fixes (slice button, keep view angle on slice, review button for failed plates, percentage and improve failed state) (#14292)
* Update Plater.cpp

* init

* Revert "Update Plater.cpp"

This reverts commit ae515bc7a4.

* fix empty plate showing as failed

* keep zooming on slice

* update

* add hover effect for active plate

* fix condition and match code

* Update GLCanvas3D.cpp

* fix button colors

* add hover effect to border of plate stats button

* fix scrollbar disappear while clicking plate buttons

* Update GLCanvas3D.cpp

* fix slicing percent for new plates

* update

* Update GLCanvas3D.cpp

* update plate states on config change

* fix non functional scrollbar
2026-06-25 22:31:33 +08:00
dbd9c22d80 feat: native Windows ARM64 build support (Snapdragon X Elite) (supersedes #14059) (#14381)
* feat: native Windows ARM64 build support

Builds on the merged DEPS_ARCH=arm64 plumbing (#13424) by adding the
dependency and source fixes needed for a green native ARM64 build on the
windows-11-arm runner. Validated end-to-end on Snapdragon X Elite hardware
(via a downstream fork using the same fixes); see OrcaSlicer/OrcaSlicer#8271
for the full writeup.

Dependencies:
- OpenEXR 2.5.5: ImfSimd.h hard-codes IMF_HAVE_SSE2 for any MSVC, pulling in
  <emmintrin.h> (x86-only) -> C1189. Patch the header to require an x86 target
  and force SSE cache vars off on ARM64.
- Boost.Context: use the winfib implementation on ARM64 (Windows Fiber API)
  to avoid the armasm64 / CMake ASM_ARMASM linker-module bug, while keeping
  the Boost::context target Boost.Asio needs.
- OpenCV: disable WITH_IPP on ARM64 (Intel IPP/IPP-ICV is x86/x64 only;
  otherwise ~200 unresolved ippicv* externals at link).
- OpenSSL: use VC-WIN64-ARM on ARM64.
- FindGLEW: add an ARM64 arch branch.

Sources:
- clipper Int128.hpp: _mul128 is an x64-only intrinsic guarded by _WIN64
  (true on ARM64); guard on _M_X64 and use the portable path.
- imgui imgui_widgets.cpp: fix va_start(vaList, &text) -> va_start(vaList, text)
  (the &-form compiled on x64 but is invalid on ARM64).
- crash reporter: StackWalker.cpp gains an _M_ARM64 branch; BaseException.cpp
  uses Cpsr instead of the x86-only EFlags on ARM64.

CI:
- New build_windows_arm64.yml on windows-11-arm: pins CMake 3.31.x, stages
  ARM64 GMP/MPFR from MSYS2 clangarm64 (with llvm-dlltool import libs),
  caches deps with a fixed-depth hashFiles key, builds and uploads the binary.

OCCT/STEP, SVG-to-3D and text emboss all build and work on ARM64 (no stubs
needed). Full feature parity with x64.

* fix(ci): use forward-slash DESTDIR to avoid CMake '\a' escape error

deps configure failed at GMP/GMP.cmake: "Invalid character escape '\a'"
because DESTDIR carried Windows backslashes (C:\a\...) and is re-parsed
when re-set with the /usr/local suffix. Pass DESTDIR (and the slicer's
DEPS prefix) with forward slashes via %CD:\=/%.

* fix(ci): don't export DESTDIR env var (CMake staged-install doubles paths)

Setting a DESTDIR *environment* variable made CMake treat it as the staged
install prefix and prepend it to every dependency's install path, so e.g.
FreeType installed to <DESTDIR>/a/.../OrcaSlicer_dep/usr/local and OCCT
then couldn't find its headers. Compute the forward-slash path into a
differently-named var (ORCA_DESTDIR) and pass it only via -DDESTDIR.

* ci(windows-arm64): fold ARM64 build into the standard Windows matrix

Replace the standalone build_windows_arm64.yml with a matrix entry on the
existing build_windows job, so x64 and ARM64 share one reusable workflow
chain (build_all -> build_check_cache -> build_deps -> build_orca), per
review feedback on #14059.

- build_all.yml: build_windows now matrices over {x64: windows-latest,
  arm64: windows-11-arm} and threads `arch` through. Self-hosted runner
  stays x64-only.
- build_check_cache.yml: cache key and dep-prefix path are now
  architecture-specific on Windows (deps/build-arm64/OrcaSlicer_dep).
- build_release_vs.bat: accept an `arm64` argument (mirrors
  build_release_vs2022.bat) -> uses `-A ARM64` and the build-arm64 tree.
  The top-level CMake auto-derives CMAKE_PREFIX_PATH from the build dir,
  so no explicit prefix is needed.
- build_deps.yml / build_orca.yml: gate the ARM64-only prep behind
  `inputs.arch == 'arm64'` -- pin CMake 3.31.x, and stage MSYS2
  clangarm64 GMP/MPFR import libs. NSIS installer/PDB/profile_validator
  remain x64-only; ARM64 ships the portable zip. Artifact names get an
  arch suffix to avoid collisions between the two Windows jobs.

https://claude.ai/code/session_0164c7ZhCLsYBmCiVN9pWDjK

* ci(temp): generate GMP/MPFR win-arm64 blobs to commit to repo

* feat(deps): add prebuilt GMP/MPFR win-arm64 blobs

The repo ships prebuilt GMP/MPFR import libs + DLLs for win-x64 and
win-x86; the Windows ARM64 build path copies from win-${DEPS_ARCH}
(CMakeLists.txt) but the win-arm64 blobs were missing, so the slicer
configure failed at "file COPY cannot find .../win-arm64/libgmp-10.dll".

Add win-arm64 libgmp-10.{dll,lib} and libmpfr-4.{dll,lib}, generated from
the MSYS2 clangarm64 gmp/mpfr packages with MSVC-compatible import libs via
llvm-dlltool. Headers are shared across arches and unchanged.

* simplify OpenEXR.cmake

* set default arch

* support msix

* ship installer

* try to fix webview2runtime issue

---------

Co-authored-by: Adam Behrman <adam.behrman@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Adam Behrman <abehrman@users.noreply.github.com>
2026-06-25 22:10:49 +08:00
wujie 67645760f2 Add Elegoo Centauri 2 machine profiles (#14402)
* feat(profiles,elegoo): add Elegoo Centauri 2 machine profiles

* chore(profiles,elegoo): add type/from to Elegoo process presets
2026-06-25 22:08:27 +08:00
NMandni4223 6c7f3629bc fix(profiles): Snapmaker U1 — add bed dimensions to fdm_U1 for all nozzle variants (#14391)
fix(profiles): add printable_area to fdm_U1 so all nozzle variants inherit correct 270x270 bed

The 0.2/0.6/0.8 nozzle profiles inherit from fdm_U1 which had no
printable_area defined, causing them to fall back to a smaller default
bed size. The 0.4 profile was the only one that set it explicitly.

Move printable_area and printable_height to the shared parent (fdm_U1)
so all Snapmaker U1 nozzle variants get the correct 270x270mm bed.
Bump vendor version to trigger profile re-sync on existing installs.

Co-authored-by: ni4223 <ni4223@users.noreply.github.com>
2026-06-25 22:04:10 +08:00
SoftFever 688127af5b Specify plate index for the 3mf workflow (#14404)
feat: forward plateindex for index-coded .gcode.3mf uploads

Gcode inside a .gcode.3mf is index-coded (Metadata/plate_<N>.gcode) and a
bundle may carry several, so the upload must name which plate to print —
even a single-plate bundle, since its entry is still indexed.

A 1-based plate index is stored in PrintHostUpload::extended_info when use_3mf
is set; the OctoPrint and Moonraker hosts forward it as a `plateindex` form
field. Servers that don't use it ignore the unknown field, so the plain G-code
path is unchanged.
2026-06-25 22:02:19 +08:00
SoftFever 0c5d85e516 Fix/skirt flow crash empty plate (#14403)
* Fix crash when arranging with per-object skirt on empty plate
2026-06-25 18:50:58 +08:00
SoftFever da074043f2 Fix fuzzy skin artifacting regression (#14376) (#14382)
Fix fuzzy skin artifacting (#14376)
2026-06-25 10:52:19 +08:00