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
This commit is contained in:
Tommaso Bianchi
2026-07-01 10:19:33 +02:00
co-authored by Claude Opus 4.8
parent 8cbf5b393b
commit 5a005d4728
6 changed files with 476 additions and 4 deletions
+54
View File
@@ -216,6 +216,8 @@ void DesignCanvas::reload(bool keep_view)
// Selection tint wins; otherwise the per-body override (Color tool) or the
// auto palette via body_color().
ColorRGBA c = m_body_selected ? sel_gold : body_color(b);
if (b == m_hl_body_target) c = ColorRGBA(0.30f, 0.90f, 0.70f, 1.0f); // target = teal-green
else if (b == m_hl_body_tool) c = ColorRGBA(1.00f, 0.55f, 0.15f, 1.0f); // tool = orange
if (m_body_translucent) c.a(0.30f);
v->set_color(c);
}
@@ -610,6 +612,44 @@ void DesignCanvas::set_on_revolve_angle_changed(std::function<void(double)> cb)
m_sketch_tool.on_revolve_angle_changed = std::move(cb);
}
void DesignCanvas::set_draft_gizmo(const Vec3d& face_centroid, const Vec3d& face_normal, double angle)
{
m_sketch_tool.set_draft_gizmo(face_centroid, face_normal, angle);
request_repaint();
}
void DesignCanvas::clear_draft_gizmo()
{
m_sketch_tool.clear_draft_gizmo();
request_repaint();
}
bool DesignCanvas::drafting() const { return m_sketch_tool.drafting(); }
void DesignCanvas::set_on_draft_angle_changed(std::function<void(double)> cb)
{
m_sketch_tool.set_on_draft_angle_changed(std::move(cb));
}
void DesignCanvas::set_cut_gizmo(const SketchPlane& plane, double offset, const Vec3d& body_center, double half_extent)
{
m_sketch_tool.set_cut_gizmo(plane, offset, body_center, half_extent);
request_repaint();
}
void DesignCanvas::clear_cut_gizmo()
{
m_sketch_tool.clear_cut_gizmo();
request_repaint();
}
bool DesignCanvas::cutting() const { return m_sketch_tool.cutting(); }
void DesignCanvas::set_on_cut_offset_changed(std::function<void(double)> cb)
{
m_sketch_tool.set_on_cut_offset_changed(std::move(cb));
}
void DesignCanvas::begin_pattern_gizmo(const SketchPlane& plane, const Vec3d& body_centroid,
bool circular, int count, int dir, double spacing, double angle)
{
@@ -759,6 +799,20 @@ void DesignCanvas::set_body_highlight(bool on)
reload(true); // recolours the body volume (selected = cyan tint)
}
void DesignCanvas::set_operand_bodies(int target_body, int tool_body)
{
if (m_hl_body_target == target_body && m_hl_body_tool == tool_body) return;
m_hl_body_target = target_body;
m_hl_body_tool = tool_body;
reload(true); // recolours the body volumes (same idiom set_body_highlight uses)
}
void DesignCanvas::set_highlight_sketches(std::vector<std::pair<int, ColorRGBA>> hl)
{
m_sketch_tool.set_highlight_sketches(std::move(hl));
request_repaint();
}
void DesignCanvas::set_body_translucent(bool on)
{
if (m_body_translucent == on) return;