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
This commit is contained in:
Tommaso Bianchi
2026-07-01 23:19:18 +02:00
co-authored by Claude Opus 4.8
parent de16d566b2
commit 1673c2c760
6 changed files with 324 additions and 20 deletions
+49
View File
@@ -9,6 +9,7 @@
#include "libslic3r/Model.hpp"
#include "libslic3r/TriangleMesh.hpp"
#include "3DScene.hpp"
#include "MeshUtils.hpp" // ClippingPlane (section view)
#include "libslic3r/Config.hpp"
#include <boost/algorithm/string/predicate.hpp>
@@ -139,6 +140,7 @@ DesignCanvas::DesignCanvas(wxWindow* parent)
e.Skip();
});
auto* sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(m_canvas_widget, 1, wxEXPAND);
SetSizer(sizer);
@@ -782,6 +784,53 @@ void DesignCanvas::set_datum_planes(std::vector<SketchPlane> planes, std::vector
request_repaint();
}
bool DesignCanvas::toggle_planes()
{
const bool on = m_sketch_tool.toggle_show_planes();
request_repaint();
return on;
}
bool DesignCanvas::toggle_axes()
{
const bool on = m_sketch_tool.toggle_show_axes();
request_repaint();
return on;
}
void DesignCanvas::set_section_plane(bool on, double z, bool keep_upper)
{
m_section_on = on;
// The kept half must read as a SOLID part, never a see-through ghost: make sure no leftover
// preview translucency is applied while the section is on. Guarded — a no-op if already opaque.
if (on) { set_body_translucent(false); set_body_hidden(false); }
if (m_canvas) {
if (on) {
// GLCanvas3D turns the two clipping planes into a Z-RANGE: set_z_range(-p0.offset,
// p1.offset). keep_upper=false keeps the LOWER half (z in [-1e5, z]); keep_upper=true
// keeps the OPPOSITE, UPPER half (z in [z, +1e5]). Only HIDES geometry — no bodies.
if (keep_upper) {
m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d(0.0, 0.0, 1.0), -z)); // min_z = z
m_canvas->set_clipping_plane(1, ClippingPlane(Vec3d(0.0, 0.0, 1.0), 1.0e5)); // max_z = +1e5
} else {
m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d(0.0, 0.0, 1.0), 1.0e5)); // min_z = -1e5
m_canvas->set_clipping_plane(1, ClippingPlane(Vec3d(0.0, 0.0, 1.0), z)); // max_z = z
}
m_canvas->set_use_clipping_planes(true);
} else {
m_canvas->set_use_clipping_planes(false);
}
m_canvas->set_as_dirty();
}
request_repaint();
}
double DesignCanvas::model_mid_z() const
{
const BoundingBoxf3 bb = m_model.bounding_box_exact();
return bb.defined ? bb.center().z() : 0.0;
}
void DesignCanvas::set_readout(const std::string& text)
{
if (!m_hud || !m_hud_label || !m_canvas_widget) return;