From e1327b2caa09d4fad8f5926a67cea55e05c97f76 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Tue, 17 Feb 2026 14:58:02 -0700 Subject: [PATCH] Refactor: Abstract dimension input and finalize creation logic to SketchTool Co-authored-by: aider (gemini/gemini-2.5-pro) --- src/LineTool.cpp | 250 +++++++++++++++++------------------------- src/LineTool.h | 6 +- src/RectangleTool.cpp | 178 +++++++++++------------------- src/RectangleTool.h | 6 +- src/SketchTool.cpp | 64 +++++++++++ src/SketchTool.h | 8 +- 6 files changed, 243 insertions(+), 269 deletions(-) diff --git a/src/LineTool.cpp b/src/LineTool.cpp index 712281a..7cc23e7 100644 --- a/src/LineTool.cpp +++ b/src/LineTool.cpp @@ -14,20 +14,17 @@ LineTool::LineTool(ViewportWidget* viewport) void LineTool::activate() { - m_isDefiningLine = false; + SketchTool::activate(); + m_dimensionModes << "length" << "angle"; + m_dimensionPropertyNames["length"] = "dimensionInput"; + m_dimensionPropertyNames["angle"] = "angleInput"; + m_viewport->setProperty("dimensionInput", ""); m_viewport->setProperty("angleInput", ""); m_viewport->setProperty("dimensionEditMode", "length"); m_viewport->setProperty("isChainedLine", false); } -void LineTool::deactivate() -{ - m_isDefiningLine = false; - m_viewport->setProperty("dimensionInput", ""); - m_viewport->setProperty("angleInput", ""); -} - void LineTool::mousePressEvent(QMouseEvent *event) { gp_Pnt p; @@ -38,7 +35,7 @@ void LineTool::mousePressEvent(QMouseEvent *event) double inputLength = 0; double inputAngleDegrees = 0; - if (m_isDefiningLine) { + if (m_isDefining) { if (!dimInput.isEmpty()) { bool ok; inputLength = dimInput.toDouble(&ok); @@ -51,7 +48,7 @@ void LineTool::mousePressEvent(QMouseEvent *event) } } - if (m_isDefiningLine && (lengthFromInput || angleFromInput)) { + if (m_isDefining && (lengthFromInput || angleFromInput)) { QVector3D worldPos; QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z()); @@ -130,9 +127,9 @@ void LineTool::mousePressEvent(QMouseEvent *event) } } - if (!m_isDefiningLine) { + if (!m_isDefining) { m_firstLinePoint = p; - m_isDefiningLine = true; + m_isDefining = true; m_viewport->setProperty("dimensionInput", QVariant("")); m_viewport->setProperty("angleInput", QVariant("")); m_viewport->setProperty("dimensionEditMode", "length"); @@ -158,7 +155,7 @@ void LineTool::mouseMoveEvent(QMouseEvent *event) m_viewport->setSnappingHorizontal(false); m_viewport->setSnappingVertical(false); - if (m_isDefiningLine && !m_viewport->isSnappingOrigin() && !m_viewport->isSnappingVertex()) { + if (m_isDefining && !m_viewport->isSnappingOrigin() && !m_viewport->isSnappingVertex()) { QVector3D worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z()); QVector3D delta = worldPos - startPos; @@ -188,148 +185,103 @@ void LineTool::mouseMoveEvent(QMouseEvent *event) } } -void LineTool::keyPressEvent(QKeyEvent *event) +void LineTool::finalizeCreation() { - if (m_isDefiningLine) { - if (event->key() == Qt::Key_Tab) { - QString currentMode = m_viewport->property("dimensionEditMode").toString(); - if (currentMode == "length") { - m_viewport->setProperty("dimensionEditMode", "angle"); - } else { - m_viewport->setProperty("dimensionEditMode", "length"); - } - m_viewport->update(); - return; - } + QVector3D worldPos; + QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z()); + // This is duplicated from paintGL to ensure consistent line creation + QString dimInput = m_viewport->property("dimensionInput").toString(); + QString angleInput = m_viewport->property("angleInput").toString(); + bool lengthFromInput = false; + bool angleFromInput = false; + double inputLength = 0; + double inputAngleDegrees = 0; - QString editMode = m_viewport->property("dimensionEditMode").toString(); - const char* propertyName = (editMode == "length") ? "dimensionInput" : "angleInput"; - QString currentInput = m_viewport->property(propertyName).toString(); - - if (event->key() >= Qt::Key_0 && event->key() <= Qt::Key_9) { - currentInput += event->text(); - m_viewport->setProperty(propertyName, currentInput); - m_viewport->update(); - return; - } else if (event->key() == Qt::Key_Period) { - if (!currentInput.contains('.')) { - currentInput += '.'; - m_viewport->setProperty(propertyName, currentInput); - m_viewport->update(); - } - return; - } else if (event->key() == Qt::Key_Backspace) { - if (!currentInput.isEmpty()) { - currentInput.chop(1); - m_viewport->setProperty(propertyName, currentInput); - m_viewport->update(); - } - return; - } else if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { - QVector3D worldPos; - QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z()); - // This is duplicated from paintGL to ensure consistent line creation - QString dimInput = m_viewport->property("dimensionInput").toString(); - QString angleInput = m_viewport->property("angleInput").toString(); - bool lengthFromInput = false; - bool angleFromInput = false; - double inputLength = 0; - double inputAngleDegrees = 0; - - if (!dimInput.isEmpty()) { - bool ok; - inputLength = dimInput.toDouble(&ok); - if (ok) lengthFromInput = true; - } - if (!angleInput.isEmpty()) { - bool ok; - inputAngleDegrees = angleInput.toDouble(&ok); - if (ok) angleFromInput = true; - } - - if (angleFromInput) { - QVector3D refDir; - if (m_viewport->property("isChainedLine").toBool()) { - refDir = m_viewport->property("previousLineDirection").value(); - } else { - if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refDir = QVector3D(1, 0, 0); - else refDir = QVector3D(0, 0, -1); - } - QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); - QVector3D mouseVec = currentMouseWorldPos - startPos; - double mouseAngle; - if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x())); - else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x())); - else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y())); - double refAngle; - if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.x())); - else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refAngle = qRadiansToDegrees(atan2(refDir.y(), refDir.x())); - else refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.y())); - double relativeMouseAngle = mouseAngle - refAngle; - while (relativeMouseAngle <= -180.0) relativeMouseAngle += 360.0; - while (relativeMouseAngle > 180.0) relativeMouseAngle -= 360.0; - double snappedAngle = 0; - if (relativeMouseAngle >= 0 && relativeMouseAngle < 90) { // Quadrant 1 - snappedAngle = inputAngleDegrees; - } else if (relativeMouseAngle >= 90 && relativeMouseAngle <= 180) { // Quadrant 2 - snappedAngle = 180.0 - inputAngleDegrees; - } else if (relativeMouseAngle < -90) { // Quadrant 3 - snappedAngle = -180.0 + inputAngleDegrees; - } else { // Quadrant 4 - snappedAngle = -inputAngleDegrees; - } - double finalAngleRad = qDegreesToRadians(refAngle + snappedAngle); - QVector3D finalDir; - if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) finalDir = QVector3D(cos(finalAngleRad), 0, sin(finalAngleRad)); - else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) finalDir = QVector3D(cos(finalAngleRad), sin(finalAngleRad), 0); - else finalDir = QVector3D(0, cos(finalAngleRad), sin(finalAngleRad)); - double lineLength; - if (lengthFromInput) lineLength = inputLength; - else { - lineLength = QVector3D::dotProduct(mouseVec, finalDir); - if (lineLength < 0) lineLength = 0; - } - worldPos = startPos + lineLength * finalDir; - } else if (lengthFromInput) { - QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); - QVector3D dir = (currentMouseWorldPos - startPos); - if (dir.length() > 1e-6) { - dir.normalize(); - worldPos = startPos + inputLength * dir; - } else { - if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos = startPos + QVector3D(inputLength, 0, 0); - else worldPos = startPos + QVector3D(0, inputLength, 0); - } - } else { - worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); - } - - gp_Pnt p; - p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); - - QVector3D prevDir = (worldPos - startPos).normalized(); - m_viewport->setProperty("previousLineDirection", QVariant::fromValue(prevDir)); - - m_viewport->addLine(m_firstLinePoint, p); - m_firstLinePoint = p; - m_viewport->setProperty("dimensionInput", QVariant("")); - m_viewport->setProperty("angleInput", QVariant("")); - m_viewport->setProperty("dimensionEditMode", "length"); - m_viewport->setProperty("isChainedLine", true); - m_viewport->update(); - return; - } else if (event->key() == Qt::Key_Escape) { - deactivate(); - m_viewport->deactivateActiveTool(); - m_viewport->update(); - return; - } + if (!dimInput.isEmpty()) { + bool ok; + inputLength = dimInput.toDouble(&ok); + if (ok) lengthFromInput = true; } + if (!angleInput.isEmpty()) { + bool ok; + inputAngleDegrees = angleInput.toDouble(&ok); + if (ok) angleFromInput = true; + } + + if (angleFromInput) { + QVector3D refDir; + if (m_viewport->property("isChainedLine").toBool()) { + refDir = m_viewport->property("previousLineDirection").value(); + } else { + if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refDir = QVector3D(1, 0, 0); + else refDir = QVector3D(0, 0, -1); + } + QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); + QVector3D mouseVec = currentMouseWorldPos - startPos; + double mouseAngle; + if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x())); + else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x())); + else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y())); + double refAngle; + if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.x())); + else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refAngle = qRadiansToDegrees(atan2(refDir.y(), refDir.x())); + else refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.y())); + double relativeMouseAngle = mouseAngle - refAngle; + while (relativeMouseAngle <= -180.0) relativeMouseAngle += 360.0; + while (relativeMouseAngle > 180.0) relativeMouseAngle -= 360.0; + double snappedAngle = 0; + if (relativeMouseAngle >= 0 && relativeMouseAngle < 90) { // Quadrant 1 + snappedAngle = inputAngleDegrees; + } else if (relativeMouseAngle >= 90 && relativeMouseAngle <= 180) { // Quadrant 2 + snappedAngle = 180.0 - inputAngleDegrees; + } else if (relativeMouseAngle < -90) { // Quadrant 3 + snappedAngle = -180.0 + inputAngleDegrees; + } else { // Quadrant 4 + snappedAngle = -inputAngleDegrees; + } + double finalAngleRad = qDegreesToRadians(refAngle + snappedAngle); + QVector3D finalDir; + if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) finalDir = QVector3D(cos(finalAngleRad), 0, sin(finalAngleRad)); + else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) finalDir = QVector3D(cos(finalAngleRad), sin(finalAngleRad), 0); + else finalDir = QVector3D(0, cos(finalAngleRad), sin(finalAngleRad)); + double lineLength; + if (lengthFromInput) lineLength = inputLength; + else { + lineLength = QVector3D::dotProduct(mouseVec, finalDir); + if (lineLength < 0) lineLength = 0; + } + worldPos = startPos + lineLength * finalDir; + } else if (lengthFromInput) { + QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); + QVector3D dir = (currentMouseWorldPos - startPos); + if (dir.length() > 1e-6) { + dir.normalize(); + worldPos = startPos + inputLength * dir; + } else { + if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos = startPos + QVector3D(inputLength, 0, 0); + else worldPos = startPos + QVector3D(0, inputLength, 0); + } + } else { + worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); + } + + gp_Pnt p; + p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); + + QVector3D prevDir = (worldPos - startPos).normalized(); + m_viewport->setProperty("previousLineDirection", QVariant::fromValue(prevDir)); + + m_viewport->addLine(m_firstLinePoint, p); + m_firstLinePoint = p; + m_viewport->setProperty("dimensionInput", QVariant("")); + m_viewport->setProperty("angleInput", QVariant("")); + m_viewport->setProperty("dimensionEditMode", "length"); + m_viewport->setProperty("isChainedLine", true); } void LineTool::paintGL() { - if (m_isDefiningLine) { + if (m_isDefining) { QVector vertices; QVector3D worldPos; QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z()); @@ -662,7 +614,7 @@ void LineTool::paintGL() void LineTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMatrix4x4& projection) { - if (m_isDefiningLine) { + if (m_isDefining) { QVector3D worldPos; QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z()); QString dimText; diff --git a/src/LineTool.h b/src/LineTool.h index 2919fa6..a532eb3 100644 --- a/src/LineTool.h +++ b/src/LineTool.h @@ -12,16 +12,16 @@ public: void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; - void keyPressEvent(QKeyEvent *event) override; void paintGL() override; void paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMatrix4x4& projection) override; void activate() override; - void deactivate() override; + +protected: + void finalizeCreation() override; private: - bool m_isDefiningLine = false; gp_Pnt m_firstLinePoint; }; diff --git a/src/RectangleTool.cpp b/src/RectangleTool.cpp index 676631d..fb16418 100644 --- a/src/RectangleTool.cpp +++ b/src/RectangleTool.cpp @@ -16,23 +16,20 @@ RectangleTool::RectangleTool(ViewportWidget* viewport) void RectangleTool::activate() { - m_isDefiningRectangle = false; + SketchTool::activate(); + m_dimensionModes << "height" << "width"; + m_dimensionPropertyNames["height"] = "heightInput"; + m_dimensionPropertyNames["width"] = "widthInput"; + m_viewport->setProperty("widthInput", ""); m_viewport->setProperty("heightInput", ""); m_viewport->setProperty("dimensionEditMode", "height"); } -void RectangleTool::deactivate() -{ - m_isDefiningRectangle = false; - m_viewport->setProperty("widthInput", ""); - m_viewport->setProperty("heightInput", ""); -} - void RectangleTool::mousePressEvent(QMouseEvent *event) { gp_Pnt p; - if (!m_isDefiningRectangle) { + if (!m_isDefining) { if (m_viewport->isSnappingOrigin()) { p.SetCoord(0, 0, 0); } else if (m_viewport->isSnappingVertex()) { @@ -42,7 +39,7 @@ void RectangleTool::mousePressEvent(QMouseEvent *event) p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); } m_firstRectanglePoint = p; - m_isDefiningRectangle = true; + m_isDefining = true; m_viewport->setProperty("widthInput", ""); m_viewport->setProperty("heightInput", ""); m_viewport->setProperty("dimensionEditMode", "height"); @@ -116,116 +113,71 @@ void RectangleTool::mouseMoveEvent(QMouseEvent *event) // To be implemented } -void RectangleTool::keyPressEvent(QKeyEvent *event) +void RectangleTool::finalizeCreation() { - if (m_isDefiningRectangle) { - if (event->key() == Qt::Key_Tab) { - QString currentMode = m_viewport->property("dimensionEditMode").toString(); - if (currentMode == "width") { - m_viewport->setProperty("dimensionEditMode", "height"); - } else { - m_viewport->setProperty("dimensionEditMode", "width"); - } - m_viewport->update(); - return; - } + QVector3D worldPos; + QVector3D startPos(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z()); - QString editMode = m_viewport->property("dimensionEditMode").toString(); - const char* propertyName = (editMode == "width") ? "widthInput" : "heightInput"; - QString currentInput = m_viewport->property(propertyName).toString(); + QString widthInput = m_viewport->property("widthInput").toString(); + QString heightInput = m_viewport->property("heightInput").toString(); + bool widthFromInput = false, heightFromInput = false; + double inputWidth = 0, inputHeight = 0; - if (event->key() >= Qt::Key_0 && event->key() <= Qt::Key_9) { - currentInput += event->text(); - m_viewport->setProperty(propertyName, currentInput); - m_viewport->update(); - return; - } else if (event->key() == Qt::Key_Period) { - if (!currentInput.contains('.')) { - currentInput += '.'; - m_viewport->setProperty(propertyName, currentInput); - m_viewport->update(); - } - return; - } else if (event->key() == Qt::Key_Backspace) { - if (!currentInput.isEmpty()) { - currentInput.chop(1); - m_viewport->setProperty(propertyName, currentInput); - m_viewport->update(); - } - return; - } else if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { - QVector3D worldPos; - QVector3D startPos(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z()); - - QString widthInput = m_viewport->property("widthInput").toString(); - QString heightInput = m_viewport->property("heightInput").toString(); - bool widthFromInput = false, heightFromInput = false; - double inputWidth = 0, inputHeight = 0; - - if (!widthInput.isEmpty()) { - bool ok; - inputWidth = widthInput.toDouble(&ok); - if (ok) widthFromInput = true; - } - if (!heightInput.isEmpty()) { - bool ok; - inputHeight = heightInput.toDouble(&ok); - if (ok) heightFromInput = true; - } - - if (widthFromInput || heightFromInput) { - QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); - QVector3D mouseDir = mousePos - startPos; - double current_w, current_h; - if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) { - current_w = qAbs(mouseDir.x()); - current_h = qAbs(mouseDir.z()); - } else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { - current_w = qAbs(mouseDir.x()); - current_h = qAbs(mouseDir.y()); - } else { // YZ - current_w = qAbs(mouseDir.y()); - current_h = qAbs(mouseDir.z()); - } - double rect_w = widthFromInput ? inputWidth : current_w; - double rect_h = heightFromInput ? inputHeight : current_h; - int signX = (mouseDir.x() >= 0) ? 1 : -1; - int signY = (mouseDir.y() >= 0) ? 1 : -1; - int signZ = (mouseDir.z() >= 0) ? 1 : -1; - worldPos = startPos; - if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) { - worldPos.setX(startPos.x() + signX * rect_w); - worldPos.setZ(startPos.z() + signZ * rect_h); - } else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { - worldPos.setX(startPos.x() + signX * rect_w); - worldPos.setY(startPos.y() + signY * rect_h); - } else { // YZ - worldPos.setY(startPos.y() + signY * rect_w); - worldPos.setZ(startPos.z() + signZ * rect_h); - } - } else { - worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); - } - - gp_Pnt p; - p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); - - emit m_viewport->rectangleAdded(m_firstRectanglePoint, p); - deactivate(); - m_viewport->update(); - return; - } else if (event->key() == Qt::Key_Escape) { - deactivate(); - m_viewport->deactivateActiveTool(); - m_viewport->update(); - return; - } + if (!widthInput.isEmpty()) { + bool ok; + inputWidth = widthInput.toDouble(&ok); + if (ok) widthFromInput = true; } + if (!heightInput.isEmpty()) { + bool ok; + inputHeight = heightInput.toDouble(&ok); + if (ok) heightFromInput = true; + } + + if (widthFromInput || heightFromInput) { + QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); + QVector3D mouseDir = mousePos - startPos; + double current_w, current_h; + if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) { + current_w = qAbs(mouseDir.x()); + current_h = qAbs(mouseDir.z()); + } else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { + current_w = qAbs(mouseDir.x()); + current_h = qAbs(mouseDir.y()); + } else { // YZ + current_w = qAbs(mouseDir.y()); + current_h = qAbs(mouseDir.z()); + } + double rect_w = widthFromInput ? inputWidth : current_w; + double rect_h = heightFromInput ? inputHeight : current_h; + int signX = (mouseDir.x() >= 0) ? 1 : -1; + int signY = (mouseDir.y() >= 0) ? 1 : -1; + int signZ = (mouseDir.z() >= 0) ? 1 : -1; + worldPos = startPos; + if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) { + worldPos.setX(startPos.x() + signX * rect_w); + worldPos.setZ(startPos.z() + signZ * rect_h); + } else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { + worldPos.setX(startPos.x() + signX * rect_w); + worldPos.setY(startPos.y() + signY * rect_h); + } else { // YZ + worldPos.setY(startPos.y() + signY * rect_w); + worldPos.setZ(startPos.z() + signZ * rect_h); + } + } else { + worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); + } + + gp_Pnt p; + p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); + + emit m_viewport->rectangleAdded(m_firstRectanglePoint, p); + deactivate(); } void RectangleTool::paintGL() { - if (m_isDefiningRectangle) { + if (m_isDefining) { QVector vertices; QVector3D worldPos; QVector3D startPos(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z()); @@ -320,7 +272,7 @@ void RectangleTool::paintGL() void RectangleTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMatrix4x4& projection) { - if (m_isDefiningRectangle) { + if (m_isDefining) { QVector3D worldPos; QVector3D p1_3d(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z()); diff --git a/src/RectangleTool.h b/src/RectangleTool.h index b3f229c..edefc79 100644 --- a/src/RectangleTool.h +++ b/src/RectangleTool.h @@ -12,16 +12,16 @@ public: void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; - void keyPressEvent(QKeyEvent *event) override; void paintGL() override; void paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMatrix4x4& projection) override; void activate() override; - void deactivate() override; + +protected: + void finalizeCreation() override; private: - bool m_isDefiningRectangle = false; gp_Pnt m_firstRectanglePoint; }; diff --git a/src/SketchTool.cpp b/src/SketchTool.cpp index a12a2df..918e209 100644 --- a/src/SketchTool.cpp +++ b/src/SketchTool.cpp @@ -1,5 +1,6 @@ #include "SketchTool.h" #include "ViewportWidget.h" +#include SketchTool::SketchTool(ViewportWidget* viewport) : QObject(viewport), m_viewport(viewport) @@ -8,8 +9,71 @@ SketchTool::SketchTool(ViewportWidget* viewport) void SketchTool::activate() { + m_isDefining = false; } void SketchTool::deactivate() { + m_isDefining = false; + for (const QString& propName : m_dimensionPropertyNames.values()) { + m_viewport->setProperty(propName, ""); + } + m_dimensionModes.clear(); + m_dimensionPropertyNames.clear(); +} + +void SketchTool::keyPressEvent(QKeyEvent *event) +{ + if (m_isDefining) { + if (event->key() == Qt::Key_Tab) { + if (m_dimensionModes.size() > 1) { + QString currentMode = m_viewport->property("dimensionEditMode").toString(); + int currentIndex = m_dimensionModes.indexOf(currentMode); + if (currentIndex != -1) { + int nextIndex = (currentIndex + 1) % m_dimensionModes.size(); + m_viewport->setProperty("dimensionEditMode", m_dimensionModes[nextIndex]); + m_viewport->update(); + } + } + return; + } + + QString editMode = m_viewport->property("dimensionEditMode").toString(); + if (m_dimensionPropertyNames.contains(editMode)) { + QString propertyName = m_dimensionPropertyNames[editMode]; + QString currentInput = m_viewport->property(propertyName).toString(); + + if (event->key() >= Qt::Key_0 && event->key() <= Qt::Key_9) { + currentInput += event->text(); + m_viewport->setProperty(propertyName, currentInput); + m_viewport->update(); + return; + } else if (event->key() == Qt::Key_Period) { + if (!currentInput.contains('.')) { + currentInput += '.'; + m_viewport->setProperty(propertyName, currentInput); + m_viewport->update(); + } + return; + } else if (event->key() == Qt::Key_Backspace) { + if (!currentInput.isEmpty()) { + currentInput.chop(1); + m_viewport->setProperty(propertyName, currentInput); + m_viewport->update(); + } + return; + } + } + + if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { + finalizeCreation(); + m_viewport->update(); + return; + } else if (event->key() == Qt::Key_Escape) { + deactivate(); + m_viewport->deactivateActiveTool(); + m_viewport->update(); + return; + } + } } diff --git a/src/SketchTool.h b/src/SketchTool.h index 9c8e906..4899410 100644 --- a/src/SketchTool.h +++ b/src/SketchTool.h @@ -2,6 +2,8 @@ #define SKETCHTOOL_H #include +#include +#include class QMouseEvent; class QKeyEvent; @@ -19,7 +21,7 @@ public: virtual void mousePressEvent(QMouseEvent *event) = 0; virtual void mouseMoveEvent(QMouseEvent *event) = 0; - virtual void keyPressEvent(QKeyEvent *event) = 0; + virtual void keyPressEvent(QKeyEvent *event); virtual void paintGL() = 0; virtual void paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMatrix4x4& projection) = 0; @@ -28,7 +30,11 @@ public: virtual void deactivate(); protected: + virtual void finalizeCreation() = 0; ViewportWidget* m_viewport; + bool m_isDefining = false; + QStringList m_dimensionModes; + QMap m_dimensionPropertyNames; }; #endif // SKETCHTOOL_H