From 95a651b6b0097d769c1eb32cb414dcec403ed070 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Tue, 17 Feb 2026 10:44:56 -0700 Subject: [PATCH] refactor: Move LineTool event handling to LineTool and add tool APIs Co-authored-by: aider (gemini/gemini-2.5-pro) --- src/LineTool.cpp | 256 ++++++++++++++++++++++++++++++++++++- src/ViewportWidget.cpp | 281 +++-------------------------------------- src/ViewportWidget.h | 3 + 3 files changed, 278 insertions(+), 262 deletions(-) diff --git a/src/LineTool.cpp b/src/LineTool.cpp index c8928b9..ca118c1 100644 --- a/src/LineTool.cpp +++ b/src/LineTool.cpp @@ -30,7 +30,125 @@ void LineTool::deactivate() void LineTool::mousePressEvent(QMouseEvent *event) { - // To be implemented + gp_Pnt p; + 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 (m_isDefiningLine) { + 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 (m_isDefiningLine && (lengthFromInput || angleFromInput)) { + QVector3D worldPos; + QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z()); + + 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(event->pos(), 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(event->pos(), 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); + } + } + p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); + } else { + if (m_viewport->isSnappingOrigin()) { + p.SetCoord(0, 0, 0); + } else if (m_viewport->isSnappingVertex()) { + p = m_viewport->snapVertex(); + } else { + QVector3D worldPos = m_viewport->unproject(event->pos(), m_viewport->currentPlane()); + if (m_viewport->isSnappingHorizontal()) { + if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) worldPos.setZ(m_firstLinePoint.Z()); + else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos.setY(m_firstLinePoint.Y()); + else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) worldPos.setZ(m_firstLinePoint.Z()); + } else if (m_viewport->isSnappingVertical()) { + if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) worldPos.setX(m_firstLinePoint.X()); + else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos.setX(m_firstLinePoint.X()); + else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) worldPos.setY(m_firstLinePoint.Y()); + } + p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); + } + } + + if (!m_isDefiningLine) { + m_firstLinePoint = p; + m_isDefiningLine = true; + m_viewport->setProperty("dimensionInput", QVariant("")); + m_viewport->setProperty("angleInput", QVariant("")); + m_viewport->setProperty("dimensionEditMode", "length"); + m_viewport->setProperty("isChainedLine", false); + } else { + QVector3D start(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z()); + QVector3D end(p.X(), p.Y(), p.Z()); + m_viewport->setProperty("previousLineDirection", QVariant::fromValue((end - start).normalized())); + + 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::mouseMoveEvent(QMouseEvent *event) @@ -40,7 +158,141 @@ void LineTool::mouseMoveEvent(QMouseEvent *event) void LineTool::keyPressEvent(QKeyEvent *event) { - // To be implemented + if (event->key() == Qt::Key_Escape) { + if (m_isDefiningLine) { + m_isDefiningLine = false; + m_viewport->setProperty("dimensionInput", QVariant("")); + m_viewport->setProperty("angleInput", QVariant("")); + m_viewport->deactivateActiveTool(); + return; + } + } + + 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"); + } + return; + } + + 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); + return; + } else if (event->key() == Qt::Key_Period) { + if (!currentInput.contains('.')) { + currentInput += '.'; + m_viewport->setProperty(propertyName, currentInput); + return; + } + } else if (event->key() == Qt::Key_Backspace) { + if (!currentInput.isEmpty()) { + currentInput.chop(1); + m_viewport->setProperty(propertyName, currentInput); + 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); + return; + } + } } void LineTool::paintGL() diff --git a/src/ViewportWidget.cpp b/src/ViewportWidget.cpp index 7139b9e..e619649 100644 --- a/src/ViewportWidget.cpp +++ b/src/ViewportWidget.cpp @@ -455,6 +455,12 @@ void ViewportWidget::mousePressEvent(QMouseEvent *event) return; } + if (m_activeSketchTool) { + m_activeSketchTool->mousePressEvent(event); + update(); + return; + } + if (m_currentPlane != SketchPlane::NONE && m_activeTool == static_cast(ApplicationController::ToolType::Rectangle)) { gp_Pnt p; if (!m_isDefiningRectangle) { @@ -540,128 +546,6 @@ void ViewportWidget::mousePressEvent(QMouseEvent *event) return; } - if (m_currentPlane != SketchPlane::NONE && m_activeTool == static_cast(ApplicationController::ToolType::Line)) { - gp_Pnt p; - QString dimInput = property("dimensionInput").toString(); - QString angleInput = property("angleInput").toString(); - bool lengthFromInput = false; - bool angleFromInput = false; - double inputLength = 0; - double inputAngleDegrees = 0; - - if (m_isDefiningLine) { - 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 (m_isDefiningLine && (lengthFromInput || angleFromInput)) { - QVector3D worldPos; - QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z()); - - if (angleFromInput) { - QVector3D refDir; - if (property("isChainedLine").toBool()) { - refDir = property("previousLineDirection").value(); - } else { - if (m_currentPlane == SketchPlane::XY || m_currentPlane == SketchPlane::XZ) refDir = QVector3D(1, 0, 0); - else refDir = QVector3D(0, 0, -1); - } - QVector3D currentMouseWorldPos = unproject(event->pos(), m_currentPlane); - QVector3D mouseVec = currentMouseWorldPos - startPos; - double mouseAngle; - if (m_currentPlane == SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x())); - else if (m_currentPlane == SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x())); - else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y())); - double refAngle; - if (m_currentPlane == SketchPlane::XY) refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.x())); - else if (m_currentPlane == 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_currentPlane == SketchPlane::XY) finalDir = QVector3D(cos(finalAngleRad), 0, sin(finalAngleRad)); - else if (m_currentPlane == 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 = unproject(event->pos(), m_currentPlane); - QVector3D dir = (currentMouseWorldPos - startPos); - if (dir.length() > 1e-6) { - dir.normalize(); - worldPos = startPos + inputLength * dir; - } else { - if (m_currentPlane == SketchPlane::XY || m_currentPlane == SketchPlane::XZ) worldPos = startPos + QVector3D(inputLength, 0, 0); - else worldPos = startPos + QVector3D(0, inputLength, 0); - } - } - p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); - } else { - if (m_isSnappingOrigin) { - p.SetCoord(0, 0, 0); - } else if (m_isSnappingVertex) { - p = m_snapVertex; - } else { - QVector3D worldPos = unproject(event->pos(), m_currentPlane); - if (m_isSnappingHorizontal) { - if (m_currentPlane == SketchPlane::XY) worldPos.setZ(m_firstLinePoint.Z()); - else if (m_currentPlane == SketchPlane::XZ) worldPos.setY(m_firstLinePoint.Y()); - else if (m_currentPlane == SketchPlane::YZ) worldPos.setZ(m_firstLinePoint.Z()); - } else if (m_isSnappingVertical) { - if (m_currentPlane == SketchPlane::XY) worldPos.setX(m_firstLinePoint.X()); - else if (m_currentPlane == SketchPlane::XZ) worldPos.setX(m_firstLinePoint.X()); - else if (m_currentPlane == SketchPlane::YZ) worldPos.setY(m_firstLinePoint.Y()); - } - p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); - } - } - - if (!m_isDefiningLine) { - m_firstLinePoint = p; - m_isDefiningLine = true; - setProperty("dimensionInput", QVariant("")); - setProperty("angleInput", QVariant("")); - setProperty("dimensionEditMode", "length"); - setProperty("isChainedLine", false); - } else { - QVector3D start(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z()); - QVector3D end(p.X(), p.Y(), p.Z()); - setProperty("previousLineDirection", QVariant::fromValue((end - start).normalized())); - - emit lineAdded(m_firstLinePoint, p); - m_firstLinePoint = p; - setProperty("dimensionInput", QVariant("")); - setProperty("angleInput", QVariant("")); - setProperty("dimensionEditMode", "length"); - setProperty("isChainedLine", true); - } - update(); - } } else { lastPos = event->pos(); } @@ -840,135 +724,10 @@ void ViewportWidget::wheelEvent(QWheelEvent *event) void ViewportWidget::keyPressEvent(QKeyEvent *event) { - if (m_isDefiningLine && m_activeTool == static_cast(ApplicationController::ToolType::Line)) { - if (event->key() == Qt::Key_Tab) { - QString currentMode = property("dimensionEditMode").toString(); - if (currentMode == "length") { - setProperty("dimensionEditMode", "angle"); - } else { - setProperty("dimensionEditMode", "length"); - } - update(); - return; - } - - QString editMode = property("dimensionEditMode").toString(); - const char* propertyName = (editMode == "length") ? "dimensionInput" : "angleInput"; - QString currentInput = property(propertyName).toString(); - - if (event->key() >= Qt::Key_0 && event->key() <= Qt::Key_9) { - currentInput += event->text(); - setProperty(propertyName, currentInput); - update(); - return; - } else if (event->key() == Qt::Key_Period) { - if (!currentInput.contains('.')) { - currentInput += '.'; - setProperty(propertyName, currentInput); - update(); - return; - } - } else if (event->key() == Qt::Key_Backspace) { - if (!currentInput.isEmpty()) { - currentInput.chop(1); - setProperty(propertyName, currentInput); - 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 = property("dimensionInput").toString(); - QString angleInput = 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 (property("isChainedLine").toBool()) { - refDir = property("previousLineDirection").value(); - } else { - if (m_currentPlane == SketchPlane::XY || m_currentPlane == SketchPlane::XZ) refDir = QVector3D(1, 0, 0); - else refDir = QVector3D(0, 0, -1); - } - QVector3D currentMouseWorldPos = unproject(m_currentMousePos, m_currentPlane); - QVector3D mouseVec = currentMouseWorldPos - startPos; - double mouseAngle; - if (m_currentPlane == SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x())); - else if (m_currentPlane == SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x())); - else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y())); - double refAngle; - if (m_currentPlane == SketchPlane::XY) refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.x())); - else if (m_currentPlane == 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_currentPlane == SketchPlane::XY) finalDir = QVector3D(cos(finalAngleRad), 0, sin(finalAngleRad)); - else if (m_currentPlane == 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 = unproject(m_currentMousePos, m_currentPlane); - QVector3D dir = (currentMouseWorldPos - startPos); - if (dir.length() > 1e-6) { - dir.normalize(); - worldPos = startPos + inputLength * dir; - } else { - if (m_currentPlane == SketchPlane::XY || m_currentPlane == SketchPlane::XZ) worldPos = startPos + QVector3D(inputLength, 0, 0); - else worldPos = startPos + QVector3D(0, inputLength, 0); - } - } else { - worldPos = unproject(m_currentMousePos, m_currentPlane); - } - - gp_Pnt p; - p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); - - QVector3D prevDir = (worldPos - startPos).normalized(); - setProperty("previousLineDirection", QVariant::fromValue(prevDir)); - - emit lineAdded(m_firstLinePoint, p); - m_firstLinePoint = p; - setProperty("dimensionInput", QVariant("")); - setProperty("angleInput", QVariant("")); - setProperty("dimensionEditMode", "length"); - setProperty("isChainedLine", true); - update(); - return; - } + if (m_activeSketchTool) { + m_activeSketchTool->keyPressEvent(event); + update(); + return; } if (m_isDefiningRectangle && m_activeTool == static_cast(ApplicationController::ToolType::Rectangle)) { @@ -1073,15 +832,7 @@ void ViewportWidget::keyPressEvent(QKeyEvent *event) } if (event->key() == Qt::Key_Escape) { - if (m_isDefiningLine) { - m_isDefiningLine = false; - setProperty("dimensionInput", QVariant("")); - setProperty("angleInput", QVariant("")); - emit toolDeactivated(); - update(); - return; - } - else if (m_isDefiningRectangle) { + if (m_isDefiningRectangle) { m_isDefiningRectangle = false; setProperty("widthInput", ""); setProperty("heightInput", ""); @@ -1105,6 +856,16 @@ void ViewportWidget::keyPressEvent(QKeyEvent *event) QOpenGLWidget::keyPressEvent(event); } +void ViewportWidget::addLine(const gp_Pnt& start, const gp_Pnt& end) +{ + emit lineAdded(start, end); +} + +void ViewportWidget::deactivateActiveTool() +{ + emit toolDeactivated(); +} + bool ViewportWidget::focusNextPrevChild(bool next) { if (m_activeTool != static_cast(ApplicationController::ToolType::None)) { diff --git a/src/ViewportWidget.h b/src/ViewportWidget.h index 50f9be0..2848157 100644 --- a/src/ViewportWidget.h +++ b/src/ViewportWidget.h @@ -53,6 +53,9 @@ public: bool isSnappingHorizontal() const { return m_isSnappingHorizontal; } bool isSnappingVertical() const { return m_isSnappingVertical; } + void addLine(const gp_Pnt& start, const gp_Pnt& end); + void deactivateActiveTool(); + public slots: void onSketchModeStarted(SketchPlane plane); void onSketchModeEnded();