refactor: Move LineTool event handling to LineTool and add tool APIs
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
256
src/LineTool.cpp
256
src/LineTool.cpp
@@ -30,7 +30,125 @@ void LineTool::deactivate()
|
|||||||
|
|
||||||
void LineTool::mousePressEvent(QMouseEvent *event)
|
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<QVector3D>();
|
||||||
|
} 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)
|
void LineTool::mouseMoveEvent(QMouseEvent *event)
|
||||||
@@ -40,7 +158,141 @@ void LineTool::mouseMoveEvent(QMouseEvent *event)
|
|||||||
|
|
||||||
void LineTool::keyPressEvent(QKeyEvent *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<QVector3D>();
|
||||||
|
} 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()
|
void LineTool::paintGL()
|
||||||
|
|||||||
@@ -455,6 +455,12 @@ void ViewportWidget::mousePressEvent(QMouseEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_activeSketchTool) {
|
||||||
|
m_activeSketchTool->mousePressEvent(event);
|
||||||
|
update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_currentPlane != SketchPlane::NONE && m_activeTool == static_cast<int>(ApplicationController::ToolType::Rectangle)) {
|
if (m_currentPlane != SketchPlane::NONE && m_activeTool == static_cast<int>(ApplicationController::ToolType::Rectangle)) {
|
||||||
gp_Pnt p;
|
gp_Pnt p;
|
||||||
if (!m_isDefiningRectangle) {
|
if (!m_isDefiningRectangle) {
|
||||||
@@ -540,128 +546,6 @@ void ViewportWidget::mousePressEvent(QMouseEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_currentPlane != SketchPlane::NONE && m_activeTool == static_cast<int>(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<QVector3D>();
|
|
||||||
} 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 {
|
} else {
|
||||||
lastPos = event->pos();
|
lastPos = event->pos();
|
||||||
}
|
}
|
||||||
@@ -840,137 +724,12 @@ void ViewportWidget::wheelEvent(QWheelEvent *event)
|
|||||||
|
|
||||||
void ViewportWidget::keyPressEvent(QKeyEvent *event)
|
void ViewportWidget::keyPressEvent(QKeyEvent *event)
|
||||||
{
|
{
|
||||||
if (m_isDefiningLine && m_activeTool == static_cast<int>(ApplicationController::ToolType::Line)) {
|
if (m_activeSketchTool) {
|
||||||
if (event->key() == Qt::Key_Tab) {
|
m_activeSketchTool->keyPressEvent(event);
|
||||||
QString currentMode = property("dimensionEditMode").toString();
|
|
||||||
if (currentMode == "length") {
|
|
||||||
setProperty("dimensionEditMode", "angle");
|
|
||||||
} else {
|
|
||||||
setProperty("dimensionEditMode", "length");
|
|
||||||
}
|
|
||||||
update();
|
update();
|
||||||
return;
|
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<QVector3D>();
|
|
||||||
} 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_isDefiningRectangle && m_activeTool == static_cast<int>(ApplicationController::ToolType::Rectangle)) {
|
if (m_isDefiningRectangle && m_activeTool == static_cast<int>(ApplicationController::ToolType::Rectangle)) {
|
||||||
if (event->key() == Qt::Key_Tab) {
|
if (event->key() == Qt::Key_Tab) {
|
||||||
QString currentMode = property("dimensionEditMode").toString();
|
QString currentMode = property("dimensionEditMode").toString();
|
||||||
@@ -1073,15 +832,7 @@ void ViewportWidget::keyPressEvent(QKeyEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event->key() == Qt::Key_Escape) {
|
if (event->key() == Qt::Key_Escape) {
|
||||||
if (m_isDefiningLine) {
|
if (m_isDefiningRectangle) {
|
||||||
m_isDefiningLine = false;
|
|
||||||
setProperty("dimensionInput", QVariant(""));
|
|
||||||
setProperty("angleInput", QVariant(""));
|
|
||||||
emit toolDeactivated();
|
|
||||||
update();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (m_isDefiningRectangle) {
|
|
||||||
m_isDefiningRectangle = false;
|
m_isDefiningRectangle = false;
|
||||||
setProperty("widthInput", "");
|
setProperty("widthInput", "");
|
||||||
setProperty("heightInput", "");
|
setProperty("heightInput", "");
|
||||||
@@ -1105,6 +856,16 @@ void ViewportWidget::keyPressEvent(QKeyEvent *event)
|
|||||||
QOpenGLWidget::keyPressEvent(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)
|
bool ViewportWidget::focusNextPrevChild(bool next)
|
||||||
{
|
{
|
||||||
if (m_activeTool != static_cast<int>(ApplicationController::ToolType::None)) {
|
if (m_activeTool != static_cast<int>(ApplicationController::ToolType::None)) {
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ public:
|
|||||||
bool isSnappingHorizontal() const { return m_isSnappingHorizontal; }
|
bool isSnappingHorizontal() const { return m_isSnappingHorizontal; }
|
||||||
bool isSnappingVertical() const { return m_isSnappingVertical; }
|
bool isSnappingVertical() const { return m_isSnappingVertical; }
|
||||||
|
|
||||||
|
void addLine(const gp_Pnt& start, const gp_Pnt& end);
|
||||||
|
void deactivateActiveTool();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onSketchModeStarted(SketchPlane plane);
|
void onSketchModeStarted(SketchPlane plane);
|
||||||
void onSketchModeEnded();
|
void onSketchModeEnded();
|
||||||
|
|||||||
Reference in New Issue
Block a user