diff --git a/src/ViewportWidget.cpp b/src/ViewportWidget.cpp index bfb8608..f46d0d2 100644 --- a/src/ViewportWidget.cpp +++ b/src/ViewportWidget.cpp @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include struct PntComparator { bool operator()(const gp_Pnt& a, const gp_Pnt& b) const { @@ -62,7 +65,7 @@ ViewportWidget::ViewportWidget(QWidget *parent) setMouseTracking(true); setFocusPolicy(Qt::StrongFocus); - m_currentPlane = SketchPlane::XY; + m_currentPlane = gp_Ax2(gp::Origin(), gp::DZ()); m_toolIcons.insert(static_cast(ApplicationController::ToolType::Line), new QSvgRenderer(QString(":/icons/line.svg"), this)); m_toolIcons.insert(static_cast(ApplicationController::ToolType::Rectangle), new QSvgRenderer(QString(":/icons/rectangle.svg"), this)); @@ -145,12 +148,12 @@ void ViewportWidget::paintGL() // Sketch grid rendering if (m_isSelectingPlane) { - if (m_highlightedPlane != SketchPlane::NONE) { - m_sketchGrid->paintGL(static_cast(m_highlightedPlane), m_shaderProgram, m_colorLoc); + if (m_highlightedPlane) { + m_sketchGrid->paintGL(m_highlightedPlane.value(), m_shaderProgram, m_colorLoc); } } - if (m_currentPlane != SketchPlane::NONE) { - m_sketchGrid->paintGL(static_cast(m_currentPlane), m_shaderProgram, m_colorLoc); + if (m_currentPlane) { + m_sketchGrid->paintGL(m_currentPlane.value(), m_shaderProgram, m_colorLoc); } if (m_isSelectingPlane) { @@ -207,8 +210,8 @@ void ViewportWidget::paintGL() glDisable(GL_CULL_FACE); QPainter painter(this); - if (m_currentPlane != SketchPlane::NONE) { - m_sketchGrid->paintAxisLabels(painter, static_cast(m_currentPlane), model, projection); + if (m_currentPlane) { + m_sketchGrid->paintAxisLabels(painter, m_currentPlane.value(), model, projection); } m_featureBrowser->paint(painter, width(), height()); m_viewCube->paint2D(painter, width(), height()); @@ -235,8 +238,10 @@ void ViewportWidget::mousePressEvent(QMouseEvent *event) m_camera->mousePressEvent(event); if (event->button() == Qt::MiddleButton && !(QApplication::keyboardModifiers() & Qt::ShiftModifier)) { - m_camera->startRotation(unproject(event->pos(), m_currentPlane)); - update(); + if (m_currentPlane) { + m_camera->startRotation(unproject(event->pos(), m_currentPlane.value())); + update(); + } } if (event->button() == Qt::LeftButton) { @@ -247,10 +252,10 @@ void ViewportWidget::mousePressEvent(QMouseEvent *event) } if (m_isSelectingPlane) { - if (m_highlightedPlane != SketchPlane::NONE) { - emit planeSelected(m_highlightedPlane); + if (m_highlightedPlane) { + emit planeSelected(m_highlightedPlane.value()); m_isSelectingPlane = false; - m_highlightedPlane = SketchPlane::NONE; + m_highlightedPlane.reset(); update(); } return; @@ -270,8 +275,17 @@ void ViewportWidget::mouseMoveEvent(QMouseEvent *event) m_currentMousePos = event->pos(); if (m_isSelectingPlane) { - SketchPlane newHighlight = checkPlaneSelection(m_currentMousePos); - if (newHighlight != m_highlightedPlane) { + auto newHighlight = checkPlaneSelection(m_currentMousePos); + bool needsUpdate = newHighlight.has_value() != m_highlightedPlane.has_value(); + if (!needsUpdate && newHighlight) { + // Very basic check, assumes planes are one of the 3 cardinal ones + // and checkPlaneSelection returns them consistently. + if (!newHighlight->Direction().IsEqual(m_highlightedPlane->Direction(), 1e-9)) { + needsUpdate = true; + } + } + + if (needsUpdate) { m_highlightedPlane = newHighlight; update(); } @@ -291,8 +305,10 @@ void ViewportWidget::mouseMoveEvent(QMouseEvent *event) void ViewportWidget::wheelEvent(QWheelEvent *event) { - QVector3D worldPos = unproject(event->position().toPoint(), m_currentPlane); - m_camera->wheelEvent(event, worldPos); + if (m_currentPlane) { + QVector3D worldPos = unproject(event->position().toPoint(), m_currentPlane.value()); + m_camera->wheelEvent(event, worldPos); + } } void ViewportWidget::keyPressEvent(QKeyEvent *event) @@ -305,8 +321,8 @@ void ViewportWidget::keyPressEvent(QKeyEvent *event) if (event->key() == Qt::Key_Escape) { if (m_isSelectingPlane) { m_isSelectingPlane = false; - m_highlightedPlane = SketchPlane::NONE; - m_currentPlane = SketchPlane::XY; + m_highlightedPlane.reset(); + m_currentPlane = gp_Ax2(gp::Origin(), gp::DZ()); update(); return; } @@ -371,19 +387,19 @@ bool ViewportWidget::focusNextPrevChild(bool next) return QOpenGLWidget::focusNextPrevChild(next); } -void ViewportWidget::onSketchModeStarted(SketchPlane plane) +void ViewportWidget::onSketchModeStarted(const gp_Ax2& plane) { m_currentPlane = plane; m_camera->saveState(); - m_camera->animateToPlaneView(static_cast(plane)); + m_camera->animateToPlaneView(plane); } void ViewportWidget::onPlaneSelectionModeStarted() { m_isSelectingPlane = true; - m_highlightedPlane = SketchPlane::NONE; - m_currentPlane = SketchPlane::NONE; + m_highlightedPlane.reset(); + m_currentPlane.reset(); update(); } @@ -395,7 +411,7 @@ void ViewportWidget::onSketchModeEnded() void ViewportWidget::onRestoreStateAnimationFinished() { // Return to showing the base XY grid when not in a sketch - m_currentPlane = SketchPlane::XY; + m_currentPlane = gp_Ax2(gp::Origin(), gp::DZ()); update(); } @@ -467,7 +483,7 @@ void ViewportWidget::onActiveToolChanged(int tool) } } -QVector3D ViewportWidget::unproject(const QPoint& screenPos, SketchPlane plane) +QVector3D ViewportWidget::unproject(const QPoint& screenPos, const gp_Ax2& plane) { QMatrix4x4 model = m_camera->modelViewMatrix(); @@ -496,17 +512,13 @@ QVector3D ViewportWidget::unproject(const QPoint& screenPos, SketchPlane plane) QVector3D rayOrigin(nearPoint_world); QVector3D rayDir = (QVector3D(farPoint_world) - rayOrigin).normalized(); - QVector3D planeNormal; - switch (plane) { - case SketchPlane::XY: planeNormal = QVector3D(0, 0, 1); break; - case SketchPlane::XZ: planeNormal = QVector3D(0, 1, 0); break; - case SketchPlane::YZ: planeNormal = QVector3D(1, 0, 0); break; - case SketchPlane::NONE: return QVector3D(); - } + const auto& planeNormalDir = plane.Direction(); + QVector3D planeNormal(planeNormalDir.X(), planeNormalDir.Y(), planeNormalDir.Z()); float denom = QVector3D::dotProduct(planeNormal, rayDir); if (qAbs(denom) > 1e-6) { - QVector3D p0(0,0,0); + const auto& planeOriginPnt = plane.Location(); + QVector3D p0(planeOriginPnt.X(), planeOriginPnt.Y(), planeOriginPnt.Z()); float t = QVector3D::dotProduct(p0 - rayOrigin, planeNormal) / denom; return rayOrigin + t * rayDir; } @@ -702,52 +714,56 @@ void ViewportWidget::drawSelectionPlanes() // XY Plane (Top) QVector xyQuad = { planeOffset, -planeOffset, 0, planeOffset + planeSize, -planeOffset, 0, planeOffset + planeSize, -planeOffset - planeSize, 0, planeOffset, -planeOffset - planeSize, 0 }; - drawPlane(xyQuad, m_highlightedPlane == SketchPlane::XY); + drawPlane(xyQuad, m_highlightedPlane && m_highlightedPlane->Direction().IsEqual(gp::DZ(), 1e-9)); // XZ Plane (Front) QVector xzQuad = { planeOffset, 0, planeOffset, planeOffset + planeSize, 0, planeOffset, planeOffset + planeSize, 0, planeOffset + planeSize, planeOffset, 0, planeOffset + planeSize }; - drawPlane(xzQuad, m_highlightedPlane == SketchPlane::XZ); + drawPlane(xzQuad, m_highlightedPlane && m_highlightedPlane->Direction().IsEqual(gp::DY(), 1e-9)); // YZ Plane (Right) QVector yzQuad = { 0, -planeOffset, planeOffset, 0, -planeOffset, planeOffset + planeSize, 0, -planeOffset - planeSize, planeOffset + planeSize, 0, -planeOffset - planeSize, planeOffset }; - drawPlane(yzQuad, m_highlightedPlane == SketchPlane::YZ); + drawPlane(yzQuad, m_highlightedPlane && m_highlightedPlane->Direction().IsEqual(gp::DX(), 1e-9)); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); } -ViewportWidget::SketchPlane ViewportWidget::checkPlaneSelection(const QPoint& screenPos) +std::optional ViewportWidget::checkPlaneSelection(const QPoint& screenPos) { const float planeSize = 5.0f; const float planeOffset = 1.0f; + gp_Ax2 yzPlane(gp_Pnt(0, 0, 0), gp::DX()); + gp_Ax2 xzPlane(gp_Pnt(0, 0, 0), gp::DY()); + gp_Ax2 xyPlane(gp_Pnt(0, 0, 0), gp::DZ()); + QVector3D intersection; // Check front to back to handle overlaps // YZ plane (Right) - intersection = unproject(screenPos, SketchPlane::YZ); + intersection = unproject(screenPos, yzPlane); if (intersection.y() >= -planeOffset - planeSize && intersection.y() <= -planeOffset && intersection.z() >= planeOffset && intersection.z() <= planeOffset + planeSize) { - return SketchPlane::YZ; + return gp_Ax2(gp_Pnt(0, -planeOffset, planeOffset), gp::DX()); } // XZ plane (Front) - intersection = unproject(screenPos, SketchPlane::XZ); + intersection = unproject(screenPos, xzPlane); if (intersection.x() >= planeOffset && intersection.x() <= planeOffset + planeSize && intersection.z() >= planeOffset && intersection.z() <= planeOffset + planeSize) { - return SketchPlane::XZ; + return gp_Ax2(gp_Pnt(planeOffset, 0, planeOffset), gp::DY()); } // XY plane (Top) - intersection = unproject(screenPos, SketchPlane::XY); + intersection = unproject(screenPos, xyPlane); if (intersection.x() >= planeOffset && intersection.x() <= planeOffset + planeSize && intersection.y() >= -planeOffset - planeSize && intersection.y() <= -planeOffset) { - return SketchPlane::XY; + return gp_Ax2(gp_Pnt(planeOffset, -planeOffset, 0), gp::DZ()); } - return SketchPlane::NONE; + return std::nullopt; } diff --git a/src/ViewportWidget.h b/src/ViewportWidget.h index e9d2161..84f502a 100644 --- a/src/ViewportWidget.h +++ b/src/ViewportWidget.h @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -35,26 +37,19 @@ class ViewportWidget : public QOpenGLWidget, protected QOpenGLFunctions Q_OBJECT public: - enum class SketchPlane { - NONE, - XY, - XZ, - YZ - }; - explicit ViewportWidget(QWidget *parent = nullptr); ~ViewportWidget(); void setDocument(Document* document); QVector3D project(const QVector3D& worldCoord, const QMatrix4x4& modelView, const QMatrix4x4& projection, const QRect& viewport); - QVector3D unproject(const QPoint& screenPos, SketchPlane plane); + QVector3D unproject(const QPoint& screenPos, const gp_Ax2& plane); QOpenGLShaderProgram* shaderProgram() { return m_shaderProgram; } QOpenGLBuffer& vbo() { return m_vbo; } int colorLoc() const { return m_colorLoc; } Camera* camera() const { return m_camera; } Document* document() const { return m_document; } - SketchPlane currentPlane() const { return m_currentPlane; } + std::optional currentPlane() const { return m_currentPlane; } const QPoint& currentMousePos() const { return m_currentMousePos; } bool isSnappingOrigin() const; bool isSnappingVertex() const; @@ -69,7 +64,7 @@ public: void deactivateActiveTool(); public slots: - void onSketchModeStarted(SketchPlane plane); + void onSketchModeStarted(const gp_Ax2& plane); void onSketchModeEnded(); void onPlaneSelectionModeStarted(); void onActiveToolChanged(int tool); @@ -78,7 +73,7 @@ signals: void lineAdded(const gp_Pnt& start, const gp_Pnt& end); void rectangleAdded(const gp_Pnt& corner1, const gp_Pnt& corner2); void circleAdded(const gp_Pnt& center, double radius); - void planeSelected(SketchPlane plane); + void planeSelected(const gp_Ax2& plane); void toolDeactivated(); private slots: @@ -100,7 +95,7 @@ private: void initShaders(); void drawSketch(const SketchFeature* sketch); void drawSelectionPlanes(); - ViewportWidget::SketchPlane checkPlaneSelection(const QPoint& screenPos); + std::optional checkPlaneSelection(const QPoint& screenPos); QMatrix4x4 projection; QOpenGLShaderProgram* m_shaderProgram = nullptr; @@ -116,10 +111,10 @@ private: SketchGrid* m_sketchGrid = nullptr; FeatureBrowser* m_featureBrowser = nullptr; Document* m_document = nullptr; - SketchPlane m_currentPlane = SketchPlane::NONE; + std::optional m_currentPlane; bool m_isSelectingPlane = false; - SketchPlane m_highlightedPlane = SketchPlane::NONE; + std::optional m_highlightedPlane; int m_activeTool = 0; SketchTool* m_activeSketchTool = nullptr;