Port from snaporca: sketch-only projects save, scripted geometry arrives exact,

and a ladder that draws with the mouse

Three commits carried across (snaporca 4ffd60eacb, 421055c2ec, b71216ce0b):

1. A design made only of sketches must survive being saved. CadDocument::recompute
   returned false with "no solid-producing features" for a document that has no
   solid, and two callers read that as "unusable": the GUI syncs the 3MF recipe
   only after a successful recompute, so a sketch-only design was saved with no
   recipe at all, and deserialize_recipe ends with `return recompute()`, so even a
   project that carried one was refused on load. Having nothing to build is now a
   success; a feature that MEANT to build a solid and produced none still fails.
   DesignPanel::refresh_tree syncs the recipe too, for the paths that call
   m_doc.recompute() directly.

2. Scripted geometry arrives exact. The Horizontal/Vertical inference window and
   the endpoint weld window both close to zero for add_entities_scripted; void
   attribution probes from a point strictly inside each loop instead of from its
   first vertex. Corpus rung 39 graded / 39 fully clean, was 35 with 6 failures.

3. scripts/gui-ladder.py — 17 rungs, 84 properties, all driven by synthetic clicks
   and typed values rather than through the socket.

Parity 17 identical / 8 diverging as expected. Kernel suite here: 188 cases /
2532 assertions.

snaporca-mtav, snaporca-8xg1, snaporca-5hvl, snaporca-730j
This commit is contained in:
Tommaso Bianchi
2026-08-23 01:22:32 +02:00
parent 05ce2607a8
commit 82db99f337
7 changed files with 1211 additions and 11 deletions
+18
View File
@@ -6630,6 +6630,24 @@ void DesignPanel::load_recipe(const std::string& blob)
void DesignPanel::refresh_tree()
{
// The recipe mirrors the FEATURE LIST, and this is the moment the feature list changed —
// every add, delete, reorder, rename and suppression ends here to redraw the tree. Putting
// the sync in recompute_guarded instead tied it to "a solid was built", and CadDocument::
// recompute() returns FALSE for a document that has no solid ("no solid-producing features",
// CadDocument.cpp) — which is precisely a document the user has only drawn sketches in. So
// drawing a profile, pressing Confirm and saving wrote a 3MF with no SnapOrca_cad.bin in it
// at all, and the app reported success: the whole design was gone on reopen (snaporca-mtav).
// The three sites that say "a lone sketch yields an empty body; that is expected" call
// m_doc.recompute() directly and so never reached the sync either. One hook here covers all
// of them, including the live sketch tool's own commit path.
//
// ONLY when the document has something in it. sync_recipe_to_model() CLEARS the blob for an
// empty document, and the tree is also refreshed while the Design tab is still empty — before
// the deferred load at on_show() has had the chance to read the blob the project arrived
// with. Clearing there would destroy the recipe of every project being opened. Deleting the
// last feature still clears it, through the tree-edit call site that always did.
if (!m_doc.features.empty()) sync_recipe_to_model();
// Preserve the selected row across the rebuild — wxTreeCtrl::DeleteAllItems
// drops the selection, which made every edit/add feel like it "lost" the
// selection (and broke Edit/Move/Delete on the just-touched feature).