mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 02:41:17 +00:00
The constraint list follows you into a live sketch
The rows, their ✗ buttons and the click-to-highlight were all built against m_doc.features[m_constrain_feat].entity_constraints — a COMMITTED feature. A live sketch has no committed feature, so the card was hidden for the whole session and the list it would have shown was empty by construction. Every constraint applied while drawing was nameless: the badge said one existed, nothing said which. rebuild_constraint_list now picks its source by scope. live_constraint_scope() is the same discriminator apply_constraint already used to route to apply_live_constraint — both Constrain modes set m_active, so is_sketching() alone would claim the live scope while the committed manager is open. delete_constraint and highlight_constraint_entities branch on it too, and the card shows in Sketch mode as well as Constrain. Keeping the rows in step needed a signal that did not exist: on_solve_state fires on every frame of a drag, so rebuilding from it would rebuild the list continuously. The tool now fires on_constraints_changed only when the constraint SET changes — one added by try_add_constraints, one removed by remove_constraint (the indexed form the badge click and the ✗ row now share). The rebuild is deferred through CallAfter. One of its callers is the ✗ button's own click handler, and rebuild_constraint_list destroys those buttons: deleting the window whose handler is still on the stack is a use-after-free. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011FbJKJAJxxkhDTs9XdZzKA
This commit is contained in:
co-authored by
Claude Opus 5
parent
b250a2b858
commit
9858080aa0
@@ -2359,8 +2359,10 @@ bool DesignSketchTool::try_add_constraints(const std::vector<SketchEntityConstra
|
||||
if (cands.empty()) return true;
|
||||
const size_t mark = m_constraints.size();
|
||||
for (const auto& c : cands) m_constraints.push_back(c);
|
||||
if (solve_sketch_entities(m_entities, m_constraints))
|
||||
if (solve_sketch_entities(m_entities, m_constraints)) {
|
||||
if (on_constraints_changed) on_constraints_changed();
|
||||
return true;
|
||||
}
|
||||
m_constraints.resize(mark); // roll back the conflicting batch
|
||||
// No re-solve to "restore": a failed solve no longer touches the geometry
|
||||
// (SketchSolver.cpp only writes back on success), so m_entities still holds the
|
||||
@@ -2381,13 +2383,20 @@ bool DesignSketchTool::remove_constraint_near(const Vec2d& p)
|
||||
if (d < best_d && g.con >= 0 && g.con < int(m_constraints.size())) { best_d = d; best = g.con; }
|
||||
}
|
||||
if (best < 0) return false;
|
||||
m_constraints.erase(m_constraints.begin() + best);
|
||||
return remove_constraint(best);
|
||||
}
|
||||
|
||||
bool DesignSketchTool::remove_constraint(int idx)
|
||||
{
|
||||
if (idx < 0 || idx >= int(m_constraints.size())) return false;
|
||||
m_constraints.erase(m_constraints.begin() + idx);
|
||||
// resolve_live(), not a bare solve: it is the path that recomputes the DoF, clears the
|
||||
// per-entity conflict flags and fires on_solve_state. Solving directly would relax the
|
||||
// geometry while leaving the DoF readout and any red over-constrained tint stale — the
|
||||
// readout would still describe the constraint that was just deleted.
|
||||
resolve_live();
|
||||
m_glyph_hits.clear(); // stale until the next render rebuilds them
|
||||
if (on_constraints_changed) on_constraints_changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user