diff --git a/localization/i18n/list.txt b/localization/i18n/list.txt
index 981e7a040a..b1ebb54f5e 100644
--- a/localization/i18n/list.txt
+++ b/localization/i18n/list.txt
@@ -295,8 +295,6 @@ src/slic3r/GUI/CAD/DesignSketchTool.cpp
src/slic3r/GUI/CAD/SketchInlineEditor.cpp
src/slic3r/GUI/CAD/DesignOffer.hpp
src/slic3r/GUI/CAD/DesignTextDialog.cpp
-src/slic3r/GUI/Gizmos/GLGizmoPrimitive.cpp
-src/slic3r/GUI/Gizmos/GLGizmoSketch.cpp
src/slic3r/GUI/KeyChord.cpp
src/slic3r/GUI/Shortcuts.cpp
src/libslic3r/CAD/CadDocument.cpp
diff --git a/resources/images/toolbar_modifier_cube_dark.svg b/resources/images/toolbar_modifier_cube_dark.svg
deleted file mode 100644
index 7e20cd0dd5..0000000000
--- a/resources/images/toolbar_modifier_cube_dark.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/resources/images/toolbar_sketch.svg b/resources/images/toolbar_sketch.svg
deleted file mode 100644
index 351b3e7924..0000000000
--- a/resources/images/toolbar_sketch.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
diff --git a/resources/images/toolbar_sketch_dark.svg b/resources/images/toolbar_sketch_dark.svg
deleted file mode 100644
index e5cf8d6859..0000000000
--- a/resources/images/toolbar_sketch_dark.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
diff --git a/src/libslic3r/CAD/CadDocument.cpp b/src/libslic3r/CAD/CadDocument.cpp
index 391ff56a87..cec5a3a74e 100644
--- a/src/libslic3r/CAD/CadDocument.cpp
+++ b/src/libslic3r/CAD/CadDocument.cpp
@@ -62,6 +62,7 @@
#include
#include
#include
+#include
#include // multi-body: compound of bodies for display/compat
#include
#include // outward-normal orientation for face-extrude
diff --git a/src/libslic3r/CAD/GeometryEngine.cpp b/src/libslic3r/CAD/GeometryEngine.cpp
index 827493fb26..454b37fce2 100644
--- a/src/libslic3r/CAD/GeometryEngine.cpp
+++ b/src/libslic3r/CAD/GeometryEngine.cpp
@@ -33,7 +33,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -53,6 +52,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -244,30 +244,6 @@ TopoDS_Shape GeometryEngine::mesh_to_brep(const indexed_triangle_set& its,
return shape;
}
-// ---- Primitive creation ----
-
-TopoDS_Solid GeometryEngine::make_primitive(const PrimitiveParams& params)
-{
- switch (params.type) {
- case PrimitiveType::Box:
- return BRepPrimAPI_MakeBox(gp_Pnt(-params.box_w/2, -params.box_d/2, 0),
- params.box_w, params.box_d, params.box_h).Solid();
- case PrimitiveType::Cylinder:
- return BRepPrimAPI_MakeCylinder(gp_Ax2(gp_Pnt(0,0,0), gp_Dir(0,0,1)),
- params.cyl_radius, params.cyl_height).Solid();
- case PrimitiveType::Sphere:
- return BRepPrimAPI_MakeSphere(gp_Pnt(0,0,params.sph_radius), params.sph_radius).Solid();
- case PrimitiveType::Cone:
- return BRepPrimAPI_MakeCone(gp_Ax2(gp_Pnt(0,0,0), gp_Dir(0,0,1)),
- params.cone_r1, params.cone_r2, params.cone_height).Solid();
- case PrimitiveType::Torus:
- return BRepPrimAPI_MakeTorus(gp_Ax2(gp_Pnt(0,0,params.torus_r2), gp_Dir(0,0,1)),
- params.torus_r1, params.torus_r2).Solid();
- default:
- return BRepPrimAPI_MakeBox(gp_Pnt(-10,-10,0), 20,20,20).Solid();
- }
-}
-
// ---- Face classification ----
FaceGroup GeometryEngine::classify_face(const TopoDS_Face& face, const TopoDS_Shape& /*solid*/)
@@ -545,19 +521,6 @@ GeometryEngine::MassProps GeometryEngine::mass_properties(const TopoDS_Shape& sh
return p;
}
-std::string GeometryEngine::primitive_name(PrimitiveType type)
-{
- switch (type) {
- // TRN Default name of an object created from the box primitive shape.
- case PrimitiveType::Box: return _u8L("Box");
- case PrimitiveType::Cylinder: return _u8L("Cylinder");
- case PrimitiveType::Sphere: return _u8L("Sphere");
- case PrimitiveType::Cone: return _u8L("Cone");
- case PrimitiveType::Torus: return _u8L("Torus");
- default: return _u8L("Unknown");
- }
-}
-
// ---- Topology accessors ----
int GeometryEngine::face_count(const TopoDS_Shape& shape)
diff --git a/src/libslic3r/CAD/GeometryEngine.hpp b/src/libslic3r/CAD/GeometryEngine.hpp
index e7e92c0438..66f00859be 100644
--- a/src/libslic3r/CAD/GeometryEngine.hpp
+++ b/src/libslic3r/CAD/GeometryEngine.hpp
@@ -4,15 +4,8 @@
#include "libslic3r/Point.hpp"
#include "libslic3r/TriangleMesh.hpp"
-#include
-#include
-#include
-#include
-#include
#include
#include
-#include
-#include
#include
#include
#include
@@ -20,44 +13,11 @@
namespace Slic3r {
-enum class PrimitiveType { Box, Cylinder, Sphere, Cone, Torus, COUNT };
-enum class DressUpType { Fillet, Chamfer };
enum class FaceGroup { Top, Bottom, Lateral, All };
-struct PrimitiveParams {
- PrimitiveType type{PrimitiveType::Box};
- double box_w{20}, box_h{20}, box_d{20};
- double cyl_radius{10}, cyl_height{20};
- double sph_radius{10};
- double cone_r1{10}, cone_r2{5}, cone_height{20};
- double torus_r1{10}, torus_r2{3};
-
- // Dress-up
- bool dressup_enabled{false};
- DressUpType dressup_type{DressUpType::Fillet};
- FaceGroup dressup_faces{FaceGroup::All};
- double dressup_radius{1.0}; // fillet radius
- double dressup_chamfer_dist{1.0}; // chamfer distance (symmetric)
-
- // Mesh quality — the Design tab's own density (CadDocument::linear_deflection), so a
- // primitive and the same body modelled in the Design tab reach the screen alike.
- double linear_deflection{0.003};
- double angular_deflection{0.5};
-
- template
- void serialize(Archive& ar) {
- ar(type, box_w, box_h, box_d, cyl_radius, cyl_height, sph_radius,
- cone_r1, cone_r2, cone_height, torus_r1, torus_r2,
- dressup_enabled, dressup_type, dressup_faces, dressup_radius, dressup_chamfer_dist,
- linear_deflection, angular_deflection);
- }
-};
-
class GeometryEngine
{
public:
- static TopoDS_Solid make_primitive(const PrimitiveParams& params);
-
// Read a STEP file into its top-level solids (one TopoDS_Shape per solid; falls back to
// the whole shape if it contains no closed solids). Reuses OCCT's STEPControl_Reader,
// already linked via Format/STEP.cpp — no new dependency. err is set on failure (empty result).
@@ -132,7 +92,6 @@ public:
static TriangleMesh tessellate(const TopoDS_Shape& shape,
double linear_deflection = 0.003,
double angular_deflection = 0.5);
- static std::string primitive_name(PrimitiveType type);
// Topology accessors for in-viewport face/edge picking (Design tab). Face index is the
// TopExp_Explorer(shape, TopAbs_FACE) ordinal — identical to SketchEngine::tessellate's
diff --git a/src/libslic3r/CAD/SketchEngine.hpp b/src/libslic3r/CAD/SketchEngine.hpp
index 93fbf72cb9..22dade5af0 100644
--- a/src/libslic3r/CAD/SketchEngine.hpp
+++ b/src/libslic3r/CAD/SketchEngine.hpp
@@ -3,7 +3,6 @@
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/Point.hpp"
-#include "libslic3r/CAD/GeometryEngine.hpp"
#include
#include
@@ -211,30 +210,6 @@ ConstraintPlan plan_entity_constraint(const std::vector& ents,
bool solve_sketch_entities(std::vector& entities,
const std::vector& constraints);
-struct SketchParams {
- // Extrude/Revolve
- double extrude_len{10}; bool extrude_sym{false}; double extrude_taper{0};
- double revolve_deg{360};
- bool is_pocket{false}; // cut into selected object instead of new
-
- // Dress-up
- bool dressup_enabled{false};
- DressUpType dressup_type{DressUpType::Fillet};
- FaceGroup dressup_faces{FaceGroup::All};
- double dressup_radius{1.0};
- double dressup_chamfer_dist{1.0};
-
- // Mesh
- double linear_deflection{0.01};
-
- template
- void serialize(Archive& ar) {
- ar(extrude_len, extrude_sym, extrude_taper, revolve_deg, is_pocket,
- dressup_enabled, dressup_type, dressup_faces, dressup_radius, dressup_chamfer_dist,
- linear_deflection);
- }
-};
-
class SketchEngine
{
public:
diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt
index e7839ad194..b313c4fe42 100644
--- a/src/slic3r/CMakeLists.txt
+++ b/src/slic3r/CMakeLists.txt
@@ -849,11 +849,6 @@ if (SLIC3R_CAD)
GUI/CAD/SketchInlineEditor.hpp
GUI/CAD/McpControl.cpp
GUI/CAD/McpControl.hpp
- GUI/Gizmos/GLGizmoSketch.cpp
- GUI/Gizmos/GLGizmoSketch.hpp
- # Needs GeometryEngine (make_primitive / apply_fillet / tessellate).
- GUI/Gizmos/GLGizmoPrimitive.cpp
- GUI/Gizmos/GLGizmoPrimitive.hpp
)
endif ()
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPrimitive.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPrimitive.cpp
deleted file mode 100644
index e74507596e..0000000000
--- a/src/slic3r/GUI/Gizmos/GLGizmoPrimitive.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-#include "GLGizmoPrimitive.hpp"
-#include "slic3r/GUI/GLCanvas3D.hpp"
-#include "slic3r/GUI/ImGuiWrapper.hpp"
-#include "slic3r/GUI/Plater.hpp"
-#include "slic3r/GUI/NotificationManager.hpp"
-#include "libslic3r/Model.hpp"
-#include
-#include "slic3r/GUI/Gizmos/GLGizmoBase.hpp"
-#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
-#include "libslic3r/CAD/GeometryEngine.hpp"
-#include
-#include
-#include "slic3r/GUI/GUI_App.hpp"
-#include
-#include
-#include
-
-#ifndef IMGUI_DEFINE_MATH_OPERATORS
-#define IMGUI_DEFINE_MATH_OPERATORS
-#endif
-#include
-#include "libslic3r/TriangleMesh.hpp"
-#include "slic3r/GUI/I18N.hpp"
-
-namespace Slic3r {
-namespace GUI {
-
-GLGizmoPrimitive::GLGizmoPrimitive(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
- : GLGizmoBase(parent, icon_filename, sprite_id) {}
-
-bool GLGizmoPrimitive::on_init() { return true; }
-std::string GLGizmoPrimitive::on_get_name() const { return _u8L("Primitive"); }
-// Part of the experimental CAD feature: built into every CAD build, but offered in the Prepare
-// toolbar only when that feature is switched on in Preferences — switched off, Prepare must be
-// exactly what it is without it.
-bool GLGizmoPrimitive::on_is_activable() const { return wxGetApp().is_enable_cad_feature(); }
-bool GLGizmoPrimitive::on_is_selectable() const { return wxGetApp().is_enable_cad_feature(); }
-void GLGizmoPrimitive::on_render() {}
-void GLGizmoPrimitive::on_set_state()
-{ if (m_state == EState::On) { m_params = PrimitiveParams{}; m_preview_dirty = true; } }
-
-bool GLGizmoPrimitive::on_mouse(const wxMouseEvent&) { return false; }
-
-CommonGizmosDataID GLGizmoPrimitive::on_get_requirements() const
-{ return CommonGizmosDataID(int(CommonGizmosDataID::SelectionInfo) | int(CommonGizmosDataID::InstancesHider)); }
-
-void GLGizmoPrimitive::on_load(cereal::BinaryInputArchive& ar)
-{ ar(m_params); m_preview_dirty = true; }
-void GLGizmoPrimitive::on_save(cereal::BinaryOutputArchive& ar) const
-{ ar(m_params); }
-
-void GLGizmoPrimitive::apply_preset(const char*, double w, double h, double d)
-{
- m_params.type = PrimitiveType::Box;
- m_params.box_w = w; m_params.box_h = h; m_params.box_d = d;
- m_preview_dirty = true;
-}
-
-static void gen_mesh_and_add(PrimitiveParams& p, const char* snap_name)
-{
- TopoDS_Solid solid = GeometryEngine::make_primitive(p);
- TopoDS_Shape shape = solid;
- if (p.dressup_enabled) {
- if (p.dressup_type == DressUpType::Fillet)
- shape = GeometryEngine::apply_fillet(shape, p.dressup_radius, p.dressup_faces);
- else
- shape = GeometryEngine::apply_chamfer(shape, p.dressup_chamfer_dist, p.dressup_faces);
- }
- TriangleMesh mesh = GeometryEngine::tessellate(shape, p.linear_deflection, p.angular_deflection);
- if (mesh.its.indices.empty()) {
- wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::WarningNotificationLevel, _u8L("Empty mesh generated"));
- return;
- }
- wxGetApp().plater()->take_snapshot(snap_name);
- ModelObject* mo = wxGetApp().model().add_object();
- std::string name = GeometryEngine::primitive_name(p.type);
- if (p.dressup_enabled && p.dressup_type == DressUpType::Fillet) name += " (Fillet)";
- else if (p.dressup_enabled) name += " (Chamfer)";
- mo->name = name;
- mo->add_volume(std::move(mesh))->set_new_unique_id();
- mo->ensure_on_bed();
- wxGetApp().plater()->update();
-}
-
-void GLGizmoPrimitive::apply_primitive() { gen_mesh_and_add(m_params, "Add Primitive"); }
-
-void GLGizmoPrimitive::on_render_input_window(float x, float y, float bottom_limit)
-{
- y = std::min(y, bottom_limit - ImGui::GetWindowHeight());
- const float scale = m_parent.get_scale();
- ImGuiWrapper::push_toolbar_style(scale);
- GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f);
- GizmoImguiBegin("Primitive", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove
- | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse
- | ImGuiWindowFlags_NoTitleBar);
-
- if (ImGui::CollapsingHeader(_u8L("Shape").c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
- const std::string names_s[] = {_u8L("Box"), _u8L("Cylinder"), _u8L("Sphere"), _u8L("Cone"), _u8L("Torus")};
- const char* names[] = {names_s[0].c_str(), names_s[1].c_str(), names_s[2].c_str(), names_s[3].c_str(), names_s[4].c_str()};
- int cur = (int)m_params.type;
- if (ImGui::Combo("##type", &cur, names, (int)PrimitiveType::COUNT)) {
- m_params.type = (PrimitiveType)cur;
- m_preview_dirty = true;
- }
- // TRN Primitive gizmo: label in front of the preset cube size buttons
- ImGui::TextUnformatted(_u8L("Quick:").c_str());
- ImGui::SameLine();
- if (ImGui::SmallButton("10mm")) apply_preset("10mm cube", 10, 10, 10);
- ImGui::SameLine();
- if (ImGui::SmallButton("20mm")) apply_preset("20mm cube", 20, 20, 20);
- ImGui::SameLine();
- if (ImGui::SmallButton("50mm")) apply_preset("50mm cube", 50, 50, 50);
- }
-
- ImGui::Separator();
-
- if (ImGui::CollapsingHeader(_u8L("Dimensions").c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
- auto dim = [&](const char* label, double& val, double step=0.5, double fast=5.0) {
- ImGui::SetNextItemWidth(130);
- if (ImGui::InputDouble(label, &val, step, fast, "%.1f mm")) m_preview_dirty = true;
- if (val < 0.5) val = 0.5;
- };
- switch (m_params.type) {
- case PrimitiveType::Box:
- dim(_u8L("Width (X)").c_str(), m_params.box_w);
- dim(_u8L("Depth (Y)").c_str(), m_params.box_d);
- dim(_u8L("Height (Z)").c_str(), m_params.box_h);
- break;
- case PrimitiveType::Cylinder:
- dim(_u8L("Radius").c_str(), m_params.cyl_radius);
- dim(_u8L("Height").c_str(), m_params.cyl_height);
- break;
- case PrimitiveType::Sphere:
- dim(_u8L("Radius").c_str(), m_params.sph_radius);
- break;
- case PrimitiveType::Cone:
- // TRN Primitive gizmo: bottom radius of a cone ("Top R" is the top radius)
- dim(_u8L("Bottom R").c_str(), m_params.cone_r1);
- dim(_u8L("Top R").c_str(), m_params.cone_r2);
- dim(_u8L("Height").c_str(), m_params.cone_height);
- break;
- case PrimitiveType::Torus:
- // TRN Primitive gizmo: major radius of a torus ("Minor R" is the tube radius)
- dim(_u8L("Major R").c_str(), m_params.torus_r1);
- dim(_u8L("Minor R").c_str(), m_params.torus_r2, 0.1, 1.0);
- break;
- default: break;
- }
- }
-
- ImGui::Separator();
-
- if (ImGui::CollapsingHeader(_u8L("Fillet / Chamfer").c_str())) {
- ImGui::Checkbox(_u8L("Enable").c_str(), &m_params.dressup_enabled);
- if (m_params.dressup_enabled) {
- const std::string dn_s[] = {_u8L("Fillet"), _u8L("Chamfer")};
- const char* dn[] = {dn_s[0].c_str(), dn_s[1].c_str()};
- int du = (int)m_params.dressup_type;
- ImGui::SetNextItemWidth(100);
- if (ImGui::Combo("##dtype", &du, dn, 2)) { m_params.dressup_type = (DressUpType)du; m_preview_dirty = true; }
- const std::string fn_s[] = {_u8L("All edges"), _u8L("Top edges"), _u8L("Bottom edges"), _u8L("Lateral edges")};
- const char* fn[] = {fn_s[0].c_str(), fn_s[1].c_str(), fn_s[2].c_str(), fn_s[3].c_str()};
- int fg = (int)m_params.dressup_faces;
- ImGui::SetNextItemWidth(140);
- if (ImGui::Combo(_u8L("Edges").c_str(), &fg, fn, 4)) { m_params.dressup_faces = (FaceGroup)fg; m_preview_dirty = true; }
- if (m_params.dressup_type == DressUpType::Fillet) {
- ImGui::SetNextItemWidth(100);
- if (ImGui::InputDouble(_u8L("Radius").c_str(), &m_params.dressup_radius, 0.1, 1.0, "%.1f mm")) {
- if (m_params.dressup_radius < 0.1) m_params.dressup_radius = 0.1;
- m_preview_dirty = true;
- }
- } else {
- ImGui::SetNextItemWidth(100);
- if (ImGui::InputDouble(_u8L("Distance").c_str(), &m_params.dressup_chamfer_dist, 0.1, 1.0, "%.1f mm")) {
- if (m_params.dressup_chamfer_dist < 0.1) m_params.dressup_chamfer_dist = 0.1;
- m_preview_dirty = true;
- }
- }
- }
- }
-
- ImGui::Separator();
-
- if (ImGui::CollapsingHeader(_u8L("Quality").c_str())) {
- ImGui::SetNextItemWidth(130);
- if (ImGui::InputDouble(_u8L("Mesh resolution").c_str(), &m_params.linear_deflection, 0.001, 0.1, "%.3f mm")) {
- if (m_params.linear_deflection < 0.001) m_params.linear_deflection = 0.001;
- if (m_params.linear_deflection > 1.0) m_params.linear_deflection = 1.0;
- m_preview_dirty = true;
- }
- }
-
- ImGui::Separator();
-
- if (ImGui::Button(_u8L("Add Shape").c_str(), {-1, 28}))
- apply_primitive();
-
- if (ImGui::Button(_u8L("Close").c_str(), {-1, 0}))
- m_parent.reset_all_gizmos();
-
- GizmoImguiEnd();
- ImGuiWrapper::pop_toolbar_style();
-}
-
-} // namespace GUI
-} // namespace Slic3r
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPrimitive.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPrimitive.hpp
deleted file mode 100644
index eef44a64c4..0000000000
--- a/src/slic3r/GUI/Gizmos/GLGizmoPrimitive.hpp
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef slic3r_GLGizmoPrimitive_hpp_
-#define slic3r_GLGizmoPrimitive_hpp_
-
-#include "GLGizmoBase.hpp"
-#include "GLGizmosCommon.hpp"
-#include "libslic3r/CAD/GeometryEngine.hpp"
-#include
-#include
-#include
-#include "libslic3r/TriangleMesh.hpp"
-
-namespace Slic3r {
-namespace GUI {
-
-class GLGizmoPrimitive : public GLGizmoBase
-{
-public:
- GLGizmoPrimitive(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
- ~GLGizmoPrimitive() = default;
-
- bool on_mouse(const wxMouseEvent& mouse_event) override;
-
-protected:
- bool on_init() override;
- std::string on_get_name() const override;
- bool on_is_activable() const override;
- bool on_is_selectable() const override;
- void on_render() override;
- void on_set_state() override;
- CommonGizmosDataID on_get_requirements() const override;
- void on_render_input_window(float x, float y, float bottom_limit) override;
-
- void on_load(cereal::BinaryInputArchive& ar) override;
- void on_save(cereal::BinaryOutputArchive& ar) const override;
-
-private:
- void apply_primitive();
- void apply_preset(const char* name, double w, double h, double d);
-
- PrimitiveParams m_params;
- TriangleMesh m_preview_mesh;
- bool m_preview_dirty{true};
-};
-
-} // namespace GUI
-} // namespace Slic3r
-
-#endif // slic3r_GLGizmoPrimitive_hpp_
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSketch.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSketch.cpp
deleted file mode 100644
index 4561a1eac6..0000000000
--- a/src/slic3r/GUI/Gizmos/GLGizmoSketch.cpp
+++ /dev/null
@@ -1,488 +0,0 @@
-#include "GLGizmoSketch.hpp"
-#include "slic3r/GUI/GLCanvas3D.hpp"
-#include "slic3r/GUI/ImGuiWrapper.hpp"
-#include "slic3r/GUI/Plater.hpp"
-#include "slic3r/GUI/NotificationManager.hpp"
-#include "slic3r/GUI/format.hpp"
-#include "libslic3r/Model.hpp"
-#include
-#include
-#include
-#include
-#include "slic3r/GUI/Gizmos/GLGizmoBase.hpp"
-#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
-#include "libslic3r/CAD/SketchEngine.hpp"
-#include "libslic3r/Point.hpp"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "libslic3r/CAD/GeometryEngine.hpp"
-#include
-#include "slic3r/GUI/GUI_App.hpp"
-#include
-#include
-
-#ifndef IMGUI_DEFINE_MATH_OPERATORS
-#define IMGUI_DEFINE_MATH_OPERATORS
-#endif
-#include
-#include "libslic3r/TriangleMesh.hpp"
-#include "slic3r/GUI/I18N.hpp"
-#include "slic3r/GUI/Selection.hpp"
-
-namespace Slic3r {
-namespace GUI {
-
-GLGizmoSketch::GLGizmoSketch(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
- : GLGizmoBase(parent, icon_filename, sprite_id) {}
-
-bool GLGizmoSketch::on_init() { return true; }
-std::string GLGizmoSketch::on_get_name() const { return _u8L("Sketch"); }
-// Part of the experimental CAD feature: built into every CAD build, but offered in the Prepare
-// toolbar only when that feature is switched on in Preferences — switched off, Prepare must be
-// exactly what it is without it.
-bool GLGizmoSketch::on_is_activable() const { return wxGetApp().is_enable_cad_feature(); }
-bool GLGizmoSketch::on_is_selectable() const { return wxGetApp().is_enable_cad_feature(); }
-void GLGizmoSketch::on_render() {}
-void GLGizmoSketch::on_set_state() { if (m_state == EState::On) clear_all(); }
-bool GLGizmoSketch::on_mouse(const wxMouseEvent&) { return false; }
-
-CommonGizmosDataID GLGizmoSketch::on_get_requirements() const
-{ return CommonGizmosDataID(int(CommonGizmosDataID::SelectionInfo)); }
-
-void GLGizmoSketch::on_load(cereal::BinaryInputArchive& ar)
-{
- ar(m_tool, m_profiles, m_plane, m_sp, m_rect_w, m_rect_h, m_circle_r, m_poly_sides, m_poly_r, m_snap_grid, m_grid_step);
- m_active_profile = -1;
-}
-
-void GLGizmoSketch::on_save(cereal::BinaryOutputArchive& ar) const
-{
- ar(m_tool, m_profiles, m_plane, m_sp, m_rect_w, m_rect_h, m_circle_r, m_poly_sides, m_poly_r, m_snap_grid, m_grid_step);
-}
-
-SketchProfile& GLGizmoSketch::active_profile()
-{
- if (m_active_profile < 0 || m_active_profile >= (int)m_profiles.size()) {
- m_profiles.emplace_back();
- m_active_profile = (int)m_profiles.size() - 1;
- }
- return m_profiles[m_active_profile];
-}
-
-bool GLGizmoSketch::has_closed_profile() const
-{
- for (auto& p : m_profiles) if (p.closed && p.points.size() >= 3) return true;
- return false;
-}
-
-void GLGizmoSketch::clear_all()
-{
- m_profiles.clear();
- m_canvas_points.clear();
- m_active_profile = -1;
-}
-
-void GLGizmoSketch::add_closed_profile()
-{
- auto& ap = active_profile();
- if (ap.points.size() >= 3) {
- ap.closed = true;
- m_active_profile = -1;
- }
-}
-
-void GLGizmoSketch::delete_profile(int idx)
-{
- if (idx >= 0 && idx < (int)m_profiles.size()) {
- m_profiles.erase(m_profiles.begin() + idx);
- if (m_active_profile >= (int)m_profiles.size()) m_active_profile = -1;
- }
-}
-
-Vec2d GLGizmoSketch::snap(Vec2d pt) const
-{
- if (!m_snap_grid) return pt;
- double gs = m_grid_step;
- return {round(pt.x() / gs) * gs, round(pt.y() / gs) * gs};
-}
-
-void GLGizmoSketch::build_preset_profile()
-{
- auto& ap = active_profile();
- ap.clear();
- auto add = [&](double x, double y) { ap.points.emplace_back(x, y); };
- switch (m_tool) {
- case SketchTool::Rectangle:
- add(-m_rect_w/2, -m_rect_h/2); add( m_rect_w/2, -m_rect_h/2);
- add( m_rect_w/2, m_rect_h/2); add(-m_rect_w/2, m_rect_h/2);
- ap.closed = true; m_active_profile = -1; break;
- case SketchTool::Circle:
- for (int i = 0; i <= m_circle_seg; ++i) {
- double a = 2.0*M_PI*i/m_circle_seg;
- add(cos(a)*m_circle_r, sin(a)*m_circle_r);
- }
- ap.closed = true; m_active_profile = -1; break;
- case SketchTool::Polygon:
- for (int i = 0; i < m_poly_sides; ++i) {
- double a = 2.0*M_PI*i/m_poly_sides - M_PI/2;
- add(cos(a)*m_poly_r, sin(a)*m_poly_r);
- }
- ap.closed = true; m_active_profile = -1; break;
- default: break;
- }
-}
-
-void GLGizmoSketch::handle_canvas_click(ImVec2 pos)
-{
- Vec2d pt = snap({pos.x / m_canvas_scale, -pos.y / m_canvas_scale});
- if (m_tool == SketchTool::Line) {
- auto& ap = active_profile();
- if (ap.points.size() >= 3 && (pt - ap.points.front()).norm() < m_grid_step) {
- ap.points.push_back(ap.points.front());
- ap.closed = true;
- m_active_profile = -1;
- return;
- }
- ap.points.push_back(pt);
- }
-}
-
-void GLGizmoSketch::draw_canvas()
-{
- ImDrawList* dl = ImGui::GetWindowDrawList();
- ImVec2 pos = ImGui::GetCursorScreenPos();
- float w = 280, h = 200;
- ImVec2 end(pos.x+w, pos.y+h);
- float cx = pos.x+w/2, cy = pos.y+h/2;
- auto tc = [&](const ImVec2& p) { return ImVec2(cx+p.x*m_canvas_scale, cy-p.y*m_canvas_scale); };
-
- dl->AddRectFilled(pos, end, IM_COL32(28,28,36,255));
- dl->AddRect(pos, end, IM_COL32(55,55,68,255));
-
- float gs = m_grid_step;
- for (float g = 0; g < w; g += gs * m_canvas_scale) {
- ImU32 gc = (int(g/(gs*m_canvas_scale)) % 5 == 0) ? IM_COL32(60,60,75,100) : IM_COL32(45,45,55,60);
- dl->AddLine({pos.x+g,pos.y}, {pos.x+g,end.y}, gc);
- }
- for (float g = 0; g < h; g += gs * m_canvas_scale) {
- ImU32 gc = (int(g/(gs*m_canvas_scale)) % 5 == 0) ? IM_COL32(60,60,75,100) : IM_COL32(45,45,55,60);
- dl->AddLine({pos.x,pos.y+g}, {end.x,pos.y+g}, gc);
- }
-
- dl->AddLine({cx,pos.y},{cx,end.y}, IM_COL32(70,70,85,180), 1.5f);
- dl->AddLine({pos.x,cy},{end.x,cy}, IM_COL32(70,70,85,180), 1.5f);
- dl->AddText({end.x-12, cy+2}, IM_COL32(120,120,140,200), "X");
- dl->AddText({cx+4, pos.y+2}, IM_COL32(120,120,140,200), "Y");
-
- for (size_t pi = 0; pi < m_profiles.size(); ++pi) {
- auto& prof = m_profiles[pi];
- if (prof.points.size() < 2) continue;
- std::vector sp;
- for (auto& p : prof.points) sp.push_back(tc({(float)p.x(), (float)p.y()}));
- if (prof.closed && sp.size() >= 3) {
- bool is_outer = (pi == 0);
- ImU32 fill = is_outer ? IM_COL32(0,180,90,35) : IM_COL32(180,60,60,35);
- ImU32 line = is_outer ? IM_COL32(0,220,100,255) : IM_COL32(220,80,80,255);
- dl->AddConvexPolyFilled(sp.data(), (int)sp.size(), fill);
- for (size_t i=0; iAddLine(sp[i], sp[(i+1)%sp.size()], line, (pi==0)?2.5f:2.0f);
- for (size_t i=0; iAddCircleFilled(sp[i], 3.0f, IM_COL32(255,255,255,255));
- }
- }
-
- auto& ap = active_profile();
- if (!ap.closed && ap.points.size() >= 1) {
- std::vector sp;
- for (auto& p : ap.points) sp.push_back(tc({(float)p.x(), (float)p.y()}));
- for (size_t i=1; iAddLine(sp[i-1], sp[i], IM_COL32(0,200,255,200), 2.0f);
- for (auto& s : sp) dl->AddCircleFilled(s, 3.5f, IM_COL32(100,200,255,255));
- ImVec2 mouse = ImGui::GetMousePos();
- if (mouse.x > pos.x && mouse.x < end.x && mouse.y > pos.y && mouse.y < end.y)
- dl->AddLine(sp.back(), mouse, IM_COL32(100,160,220,120), 1.5f);
- }
-
- ImGui::InvisibleButton("canvas", ImVec2(w,h));
- if (ImGui::IsItemHovered()) {
- ImVec2 m = ImGui::GetMousePos();
- Vec2d sk({(m.x-cx)/m_canvas_scale, -(m.y-cy)/m_canvas_scale});
- if (m_snap_grid) sk = snap(sk);
- auto txt = wxString::Format("X:%.1f Y:%.1f", sk.x(), sk.y()).ToStdString();
- dl->AddText({pos.x+4, end.y-16}, IM_COL32(160,160,180,200), txt.c_str());
- if (ImGui::IsMouseClicked(ImGuiMouseButton_Left))
- handle_canvas_click({(m.x-cx)/m_canvas_scale, -(m.y-cy)/m_canvas_scale});
- if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
- auto& ap2 = active_profile();
- if (ap2.points.size() >= 3) {
- ap2.points.push_back(ap2.points.front());
- ap2.closed = true;
- m_active_profile = -1;
- }
- }
- }
-}
-
-TopoDS_Shape GLGizmoSketch::build_combined_shape()
-{
- if (m_profiles.empty() || !m_profiles[0].closed)
- throw std::runtime_error(_u8L("No outer profile"));
-
- TopoDS_Wire outer_wire = m_profiles[0].to_occt_wire(m_plane);
- BRepBuilderAPI_MakeFace face_maker(outer_wire);
- if (!face_maker.IsDone()) throw std::runtime_error(_u8L("Failed to make outer face"));
-
- for (size_t i = 1; i < m_profiles.size(); ++i) {
- if (!m_profiles[i].closed) continue;
- TopoDS_Wire inner = m_profiles[i].to_occt_wire(m_plane);
- face_maker.Add(inner);
- }
- face_maker.Build();
- if (!face_maker.IsDone()) throw std::runtime_error(_u8L("Failed to build face with holes"));
-
- TopoDS_Face face = face_maker.Face();
-
- TopoDS_Shape shape;
- if (m_sp.revolve_deg < 360.0 && m_sp.revolve_deg > 0.0) {
- gp_Pnt o(m_plane.origin.x(), m_plane.origin.y(), m_plane.origin.z());
- gp_Dir xd(m_plane.x_axis.x(), m_plane.x_axis.y(), m_plane.x_axis.z());
- gp_Ax1 axis(o, xd);
- BRepPrimAPI_MakeRevol rev(face, axis, m_sp.revolve_deg * M_PI / 180.0);
- if (!rev.IsDone()) throw std::runtime_error(_u8L("Revolve failed"));
- shape = rev.Shape();
- } else {
- shape = SketchEngine::make_extrude_face(face, m_plane, m_sp.extrude_len, m_sp.extrude_sym);
- }
-
- if (m_sp.dressup_enabled) {
- if (m_sp.dressup_type == DressUpType::Fillet)
- shape = GeometryEngine::apply_fillet(shape, m_sp.dressup_radius, m_sp.dressup_faces);
- else
- shape = GeometryEngine::apply_chamfer(shape, m_sp.dressup_chamfer_dist, m_sp.dressup_faces);
- }
- return shape;
-}
-
-void GLGizmoSketch::on_render_input_window(float x, float y, float bottom_limit)
-{
- y = std::min(y, bottom_limit - ImGui::GetWindowHeight());
- const float scale = m_parent.get_scale();
- ImGuiWrapper::push_toolbar_style(scale);
- GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f);
- GizmoImguiBegin("Sketch", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove
- | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse
- | ImGuiWindowFlags_NoTitleBar);
-
- if (ImGui::CollapsingHeader(_u8L("Profile").c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
- const std::string names_s[] = {_u8L("Line"), _u8L("Rectangle"), _u8L("Circle"), _u8L("Polygon")};
- const char* names[] = {names_s[0].c_str(), names_s[1].c_str(), names_s[2].c_str(), names_s[3].c_str()};
- int cur = (int)m_tool;
- if (ImGui::Combo("##shape", &cur, names, (int)SketchTool::COUNT)) {
- m_tool = (SketchTool)cur;
- if (m_tool != SketchTool::Line) build_preset_profile();
- }
- ImGui::SameLine();
- if (m_imgui->button("+##newprofile")) m_active_profile = -1;
- if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", _u8L("Start new profile (for holes)").c_str());
-
- if (m_tool == SketchTool::Rectangle) {
- ImGui::SetNextItemWidth(80); if (ImGui::InputDouble(_u8L("Width").c_str(), &m_rect_w,1,10,"%.0f")) build_preset_profile();
- ImGui::SameLine();
- ImGui::SetNextItemWidth(80); if (ImGui::InputDouble(_u8L("Height").c_str(), &m_rect_h,1,10,"%.0f")) build_preset_profile();
- } else if (m_tool == SketchTool::Circle) {
- ImGui::SetNextItemWidth(80); if (ImGui::InputDouble(_u8L("Radius").c_str(), &m_circle_r,1,5,"%.0f")) build_preset_profile();
- ImGui::SameLine();
- ImGui::SetNextItemWidth(80); if (ImGui::SliderInt(_u8L("Segments").c_str(), &m_circle_seg,8,64)) build_preset_profile();
- } else if (m_tool == SketchTool::Polygon) {
- ImGui::SetNextItemWidth(80); if (ImGui::SliderInt(_u8L("Sides").c_str(), &m_poly_sides,3,12)) build_preset_profile();
- ImGui::SameLine();
- ImGui::SetNextItemWidth(80); if (ImGui::InputDouble((_u8L("Radius") + "##poly").c_str(), &m_poly_r,1,5,"%.0f")) build_preset_profile();
- } else {
- ImGui::Text("%s", _u8L("Click on canvas to draw").c_str());
- }
-
- ImGui::Checkbox(_u8L("Snap to grid").c_str(), &m_snap_grid);
- ImGui::SameLine();
- ImGui::SetNextItemWidth(80); ImGui::InputFloat(_u8L("Grid step").c_str(), &m_grid_step, 1, 5, "%.0f mm");
-
- draw_canvas();
-
- if (!m_profiles.empty()) {
- ImGui::Text("%s: %zu", _u8L("Profiles").c_str(), m_profiles.size());
- for (int i = 0; i < (int)m_profiles.size(); ++i) {
- auto& p = m_profiles[i];
- ImGui::PushID(i);
- bool outer = (i == 0);
- ImVec4 col = outer ? ImVec4(0,1,0,1) : ImVec4(1,0.3f,0.3f,1);
- const std::string label = outer ? _u8L("Outer") : _u8L("Hole");
- const std::string state = p.closed ? _u8L("closed") : std::string();
- // TRN Sketch gizmo profile list: "Outer" or "Hole", profile number, point count, "closed" or nothing
- ImGui::TextColored(col, "%s", GUI::format(_u8L("%1% %2%: %3% points %4%"), label, i + 1, p.points.size(), state).c_str());
- ImGui::SameLine();
- if (ImGui::SmallButton("X")) delete_profile(i);
- ImGui::PopID();
- }
- }
- }
-
- ImGui::Separator();
-
- bool is_revolve = false;
- bool has_sel = false;
-
- if (ImGui::CollapsingHeader(_u8L("Operation").c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
- static int pi = 0;
- const std::string plane_names[] = {_u8L("XY (Top)"), _u8L("XZ (Front)"), _u8L("YZ (Side)")};
- const char* planes[] = {plane_names[0].c_str(), plane_names[1].c_str(), plane_names[2].c_str()};
- if (ImGui::Combo(_u8L("Plane").c_str(), &pi, planes, 3))
- m_plane = (pi==0) ? SketchPlane::XY() : (pi==1) ? SketchPlane::XZ() : SketchPlane::YZ();
-
- is_revolve = (m_sp.revolve_deg > 0 && m_sp.revolve_deg < 360);
- ImGui::SetNextItemWidth(100);
- if (ImGui::InputDouble(_u8L("Revolve deg").c_str(), &m_sp.revolve_deg, 15, 90, "%.0f")) {
- if (m_sp.revolve_deg > 360) m_sp.revolve_deg = 360;
- if (m_sp.revolve_deg < 0) m_sp.revolve_deg = 0;
- }
- if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", _u8L("Set to 0 for extrude, >0 for revolve").c_str());
-
- if (!is_revolve) {
- ImGui::SetNextItemWidth(100);
- ImGui::InputDouble(_u8L("Length").c_str(), &m_sp.extrude_len, 0.5, 5, "%.1f mm");
- ImGui::SameLine();
- ImGui::Checkbox(_u8L("Symmetric").c_str(), &m_sp.extrude_sym);
- }
-
- has_sel = !m_parent.get_selection().is_empty();
- if (has_sel) {
- if (ImGui::Checkbox(_u8L("Pocket (cut)").c_str(), &m_sp.is_pocket))
- if (m_sp.is_pocket) m_sp.dressup_enabled = false;
- } else m_sp.is_pocket = false;
- }
-
- ImGui::Separator();
-
- if (!m_sp.is_pocket && ImGui::CollapsingHeader(_u8L("Fillet / Chamfer").c_str())) {
- ImGui::Checkbox(_u8L("Enable").c_str(), &m_sp.dressup_enabled);
- if (m_sp.dressup_enabled) {
- const std::string dn_s[] = {_u8L("Fillet"), _u8L("Chamfer")};
- const char* dn[] = {dn_s[0].c_str(), dn_s[1].c_str()};
- int du = (int)m_sp.dressup_type;
- ImGui::SetNextItemWidth(100);
- if (ImGui::Combo("##dtype", &du, dn, 2)) m_sp.dressup_type = (DressUpType)du;
- const std::string fn_s[] = {_u8L("All edges"), _u8L("Top edges"), _u8L("Bottom edges"), _u8L("Lateral edges")};
- const char* fn[] = {fn_s[0].c_str(), fn_s[1].c_str(), fn_s[2].c_str(), fn_s[3].c_str()};
- int fg = (int)m_sp.dressup_faces;
- ImGui::SetNextItemWidth(140);
- ImGui::Combo(_u8L("Edges").c_str(), &fg, fn, 4); m_sp.dressup_faces = (FaceGroup)fg;
- ImGui::SetNextItemWidth(100);
- if (m_sp.dressup_type == DressUpType::Fillet)
- ImGui::InputDouble(_u8L("Radius").c_str(), &m_sp.dressup_radius, 0.1, 1, "%.1f mm");
- else
- ImGui::InputDouble(_u8L("Distance").c_str(), &m_sp.dressup_chamfer_dist, 0.1, 1, "%.1f mm");
- }
- }
-
- ImGui::Separator();
-
- bool ok = has_closed_profile();
- if (ok) ImGui::TextColored({0,1,0,1}, "%s", wxString::Format(_L_PLURAL("%zu closed profile", "%zu closed profiles",
- unsigned(m_profiles.size())), m_profiles.size()).ToUTF8().data());
- else ImGui::TextColored({0.6f,0.6f,0.6f,1}, "%s", _u8L("Draw a closed profile to enable").c_str());
-
- auto btn = [&](const char* label, bool enabled) {
- if (!enabled) { ImGui::PushItemFlag(ImGuiItemFlags_Disabled,true); ImGui::PushStyleColor(ImGuiCol_Button,{0.25f,0.25f,0.25f,1}); }
- bool clicked = ImGui::Button(label, {-1,0});
- if (!enabled) { ImGui::PopStyleColor(); ImGui::PopItemFlag(); }
- return clicked && enabled;
- };
-
- if (m_sp.is_pocket && has_sel) {
- if (btn(_u8L("Pocket (cut)").c_str(), ok)) apply_pocket();
- } else if (is_revolve) {
- if (btn(_u8L("Revolve").c_str(), ok)) apply_revolve();
- } else {
- if (btn(_u8L_CONTEXT("Extrude", "Design").c_str(), ok)) apply_extrude();
- }
-
- if (ImGui::Button(_u8L("Clear all").c_str(), {-1,0})) clear_all();
- if (ImGui::Button(_u8L("Close").c_str(), {-1,0})) m_parent.reset_all_gizmos();
-
- GizmoImguiEnd();
- ImGuiWrapper::pop_toolbar_style();
-}
-
-void GLGizmoSketch::apply_extrude()
-{
- try {
- TopoDS_Shape shape = build_combined_shape();
- TriangleMesh mesh = SketchEngine::tessellate(shape, m_sp.linear_deflection);
- if (mesh.its.indices.empty()) throw std::runtime_error(_u8L("Empty result"));
- wxGetApp().plater()->take_snapshot("Sketch Extrude");
- ModelObject* mo = wxGetApp().model().add_object();
- mo->name = "Extrusion";
- mo->add_volume(std::move(mesh))->set_new_unique_id();
- mo->ensure_on_bed();
- wxGetApp().plater()->update();
- clear_all();
- } catch (const std::exception& e) {
- wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel, GUI::format(_u8L("Extrude: %1%"), e.what()));
- }
-}
-
-void GLGizmoSketch::apply_revolve()
-{
- try {
- TopoDS_Shape shape = build_combined_shape();
- TriangleMesh mesh = SketchEngine::tessellate(shape, m_sp.linear_deflection);
- if (mesh.its.indices.empty()) throw std::runtime_error(_u8L("Empty result"));
- wxGetApp().plater()->take_snapshot("Sketch Revolve");
- ModelObject* mo = wxGetApp().model().add_object();
- mo->name = "Revolve";
- mo->add_volume(std::move(mesh))->set_new_unique_id();
- mo->ensure_on_bed();
- wxGetApp().plater()->update();
- clear_all();
- } catch (const std::exception& e) {
- wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel, GUI::format(_u8L("Revolve: %1%"), e.what()));
- }
-}
-
-void GLGizmoSketch::apply_pocket()
-{
- try {
- Selection& sel = m_parent.get_selection();
- int obj_idx = sel.get_object_idx();
- if (obj_idx < 0) throw std::runtime_error(_u8L("No object selected"));
- ModelObject* mo = wxGetApp().model().objects[obj_idx];
-
- TopoDS_Wire outer = m_profiles[0].to_occt_wire(m_plane);
- BRepBuilderAPI_MakeFace fm(outer);
- if (!fm.IsDone()) throw std::runtime_error(_u8L("Face failed"));
- for (size_t i = 1; i < m_profiles.size(); ++i)
- if (m_profiles[i].closed) fm.Add(m_profiles[i].to_occt_wire(m_plane));
- fm.Build();
- if (!fm.IsDone()) throw std::runtime_error(_u8L("Face with holes failed"));
-
- TopoDS_Shape tool = SketchEngine::make_extrude_face(fm.Face(), m_plane, m_sp.extrude_len + 5.0, false);
- TriangleMesh tool_mesh = SketchEngine::tessellate(tool, m_sp.linear_deflection);
- if (tool_mesh.its.indices.empty()) throw std::runtime_error(_u8L("Tool mesh empty"));
-
- wxGetApp().plater()->take_snapshot("Sketch Pocket");
- mo->add_volume(std::move(tool_mesh), ModelVolumeType::NEGATIVE_VOLUME)->set_new_unique_id();
- mo->ensure_on_bed();
- wxGetApp().plater()->update();
- clear_all();
- wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::RegularNotificationLevel, _u8L("Pocket added (negative volume)").c_str());
- } catch (const std::exception& e) {
- wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel, GUI::format(_u8L("Pocket: %1%"), e.what()));
- }
-}
-
-} // namespace GUI
-} // namespace Slic3r
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSketch.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSketch.hpp
deleted file mode 100644
index 257fac8c6d..0000000000
--- a/src/slic3r/GUI/Gizmos/GLGizmoSketch.hpp
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef slic3r_GLGizmoSketch_hpp_
-#define slic3r_GLGizmoSketch_hpp_
-
-#include "GLGizmoBase.hpp"
-#include "GLGizmosCommon.hpp"
-#include "libslic3r/CAD/SketchEngine.hpp"
-#include
-#include
-#include
-#include
-#include
-#include
-#include "libslic3r/Point.hpp"
-
-namespace Slic3r {
-namespace GUI {
-
-enum class SketchTool { Line, Rectangle, Circle, Polygon, COUNT };
-
-class GLGizmoSketch : public GLGizmoBase
-{
-public:
- GLGizmoSketch(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
-
- bool on_mouse(const wxMouseEvent& mouse_event) override;
-
-protected:
- bool on_init() override;
- std::string on_get_name() const override;
- bool on_is_activable() const override;
- bool on_is_selectable() const override;
- void on_render() override;
- void on_set_state() override;
- CommonGizmosDataID on_get_requirements() const override;
- void on_render_input_window(float x, float y, float bottom_limit) override;
-
- void on_load(cereal::BinaryInputArchive& ar) override;
- void on_save(cereal::BinaryOutputArchive& ar) const override;
-
-private:
- SketchTool m_tool{SketchTool::Line};
- std::vector m_profiles; // multiple profiles (outer + holes)
- SketchPlane m_plane{SketchPlane::XY()};
- SketchParams m_sp;
-
- // Shape presets
- double m_rect_w{20}, m_rect_h{15};
- double m_circle_r{10}; int m_circle_seg{32};
- int m_poly_sides{6}; double m_poly_r{10};
-
- // Canvas
- std::vector m_canvas_points;
- Vec2d m_canvas_center{0,0};
- float m_canvas_scale{5.0f};
- bool m_snap_grid{true};
- float m_grid_step{5.0f};
-
- // Current profile being drawn
- int m_active_profile{-1};
-
- SketchProfile& active_profile();
- bool has_closed_profile() const;
-
- void build_preset_profile();
- void add_closed_profile();
- void delete_profile(int idx);
- void clear_all();
-
- TopoDS_Shape build_combined_shape(); // all profiles as face with holes
- void apply_extrude();
- void apply_revolve();
- void apply_pocket();
- void draw_canvas();
- void handle_canvas_click(ImVec2 pos);
- Vec2d snap(Vec2d pt) const;
-};
-
-} // namespace GUI
-} // namespace Slic3r
-
-#endif // slic3r_GLGizmoSketch_hpp_
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
index f8c65e9ac9..00bdd13bcb 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
@@ -50,10 +50,6 @@
#include
#include
#include "libslic3r/AppConfig.hpp"
-#ifdef SLIC3R_CAD
-#include "slic3r/GUI/Gizmos/GLGizmoPrimitive.hpp"
-#include "slic3r/GUI/Gizmos/GLGizmoSketch.hpp"
-#endif
#include "libslic3r/Model.hpp"
@@ -217,14 +213,6 @@ void GLGizmosManager::switch_gizmos_icon_filename()
case (EType::BrimEars):
gizmo->set_icon_filename(m_is_dark ? "toolbar_brimears_dark.svg" : "toolbar_brimears.svg");
break;
-#ifdef SLIC3R_CAD
- case (EType::Primitive):
- gizmo->set_icon_filename(m_is_dark ? "toolbar_modifier_cube_dark.svg" : "toolbar_modifier_cube.svg");
- break;
- case (EType::Sketch):
- gizmo->set_icon_filename(m_is_dark ? "toolbar_sketch_dark.svg" : "toolbar_sketch.svg");
- break;
-#endif
}
}
@@ -270,14 +258,6 @@ bool GLGizmosManager::init()
m_gizmos.emplace_back(new GLGizmoAssembly(m_parent, m_is_dark ? "toolbar_assembly_dark.svg" : "toolbar_assembly.svg", EType::Assembly));
m_gizmos.emplace_back(new GLGizmoSimplify(m_parent, "reduce_triangles.svg", EType::Simplify));
m_gizmos.emplace_back(new GLGizmoBrimEars(m_parent, m_is_dark ? "toolbar_brimears_dark.svg" : "toolbar_brimears.svg", EType::BrimEars));
-#ifdef SLIC3R_CAD
- // Registered last: Primitive and Sketch are the final entries before Undefined, so
- // omitting them leaves every preceding m_gizmos index (indexed by EType) untouched.
- if (wxGetApp().is_enable_cad_feature()) {
- m_gizmos.emplace_back(new GLGizmoPrimitive(m_parent, m_is_dark ? "toolbar_modifier_cube_dark.svg" : "toolbar_modifier_cube.svg", static_cast(Primitive)));
- m_gizmos.emplace_back(new GLGizmoSketch(m_parent, m_is_dark ? "toolbar_sketch_dark.svg" : "toolbar_sketch.svg", static_cast(Sketch)));
- }
-#endif
//m_gizmos.emplace_back(new GLGizmoSlaSupports(m_parent, "sla_supports.svg", sprite_id++));
//m_gizmos.emplace_back(new GLGizmoFaceDetector(m_parent, "face recognition.svg", sprite_id++));
//m_gizmos.emplace_back(new GLGizmoHollow(m_parent, "hollow.svg", sprite_id++));
@@ -1375,8 +1355,7 @@ GLGizmoBase* GLGizmosManager::get_current() const
GLGizmoBase* GLGizmosManager::get_gizmo(GLGizmosManager::EType type) const
{
- // m_gizmos ends before the enum does when the CAD gizmos are not registered.
- return type < m_gizmos.size() ? m_gizmos[type].get() : nullptr;
+ return ((type == Undefined) || m_gizmos.empty()) ? nullptr : m_gizmos[type].get();
}
GLGizmosManager::EType GLGizmosManager::get_gizmo_from_name(const std::string& gizmo_name) const
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
index 855e26c102..3f53eeaa93 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
@@ -102,12 +102,6 @@ public:
Assembly,
Simplify,
BrimEars,
-#ifdef SLIC3R_CAD
- // Both need the CAD kernel (GeometryEngine); keep them last so that with
- // SLIC3R_CAD off the enum matches upstream's numbering exactly.
- Primitive,
- Sketch,
-#endif
//SlaSupports,
// BBS
//FaceRecognition,