Files
unnamed-cad-software/src/Camera.cpp
2026-02-17 11:26:41 -07:00

220 lines
6.1 KiB
C++

#include "Camera.h"
#include "ViewportWidget.h"
#include <QApplication>
#include <QWheelEvent>
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>
Camera::Camera(QObject *parent) : QObject(parent)
{
// Set initial view to an isometric angle on the XY plane
m_xRot = 30 * 16;
m_yRot = -45 * 16;
m_zoom = -20.0f;
m_panX = 0.0f;
m_panY = 0.0f;
}
void Camera::processMouseMovement(QMouseEvent* event, const QPoint& lastPos)
{
int dx = event->pos().x() - lastPos.x();
int dy = event->pos().y() - lastPos.y();
if (event->buttons() & Qt::MiddleButton) {
if (QApplication::keyboardModifiers() & Qt::ShiftModifier) {
// Pan
setPanX(m_panX + dx / 100.0f);
setPanY(m_panY - dy / 100.0f);
} else {
// Rotate
setXRotation(m_xRot + 8 * dy);
setYRotation(m_yRot + 8 * dx);
}
}
}
void Camera::processWheel(QWheelEvent* event)
{
QPoint numDegrees = event->angleDelta() / 8;
if (!numDegrees.isNull()) {
setZoom(m_zoom + numDegrees.y() / 5.0f);
}
}
QMatrix4x4 Camera::modelViewMatrix() const
{
QMatrix4x4 model;
model.translate(m_panX, m_panY, m_zoom);
model.rotate(m_xRot / 16.0f, 1, 0, 0);
model.rotate(m_yRot / 16.0f, 0, 1, 0);
return model;
}
float Camera::xRotation() const { return m_xRot; }
void Camera::setXRotation(float angle)
{
if (angle != m_xRot) {
m_xRot = angle;
emit cameraChanged();
}
}
float Camera::yRotation() const { return m_yRot; }
void Camera::setYRotation(float angle)
{
if (angle != m_yRot) {
m_yRot = angle;
emit cameraChanged();
}
}
float Camera::zoom() const { return m_zoom; }
void Camera::setZoom(float value)
{
if (value != m_zoom) {
m_zoom = value;
emit cameraChanged();
}
}
float Camera::panX() const { return m_panX; }
void Camera::setPanX(float value)
{
if (value != m_panX) {
m_panX = value;
emit cameraChanged();
}
}
float Camera::panY() const { return m_panY; }
void Camera::setPanY(float value)
{
if (value != m_panY) {
m_panY = value;
emit cameraChanged();
}
}
void Camera::saveState()
{
m_savedXRot = m_xRot;
m_savedYRot = m_yRot;
m_savedPanX = m_panX;
m_savedPanY = m_panY;
m_savedZoom = m_zoom;
}
void Camera::restoreState()
{
setXRotation(m_savedXRot);
setYRotation(m_savedYRot);
setPanX(m_savedPanX);
setPanY(m_savedPanY);
setZoom(m_savedZoom);
}
void Camera::animateToPlaneView(int plane)
{
float targetXRot = xRotation();
float targetYRot = yRotation();
switch (static_cast<ViewportWidget::SketchPlane>(plane)) {
case ViewportWidget::SketchPlane::XY: // Top view
targetXRot = 90 * 16;
targetYRot = 0;
break;
case ViewportWidget::SketchPlane::XZ: // Front view
targetXRot = 0;
targetYRot = 0;
break;
case ViewportWidget::SketchPlane::YZ: // Right view
targetXRot = 0;
targetYRot = -90 * 16;
break;
case ViewportWidget::SketchPlane::NONE:
break;
}
auto* animGroup = new QParallelAnimationGroup(this);
auto* xRotAnim = new QPropertyAnimation(this, "xRotation");
xRotAnim->setDuration(300);
xRotAnim->setStartValue(xRotation());
xRotAnim->setEndValue(targetXRot);
xRotAnim->setEasingCurve(QEasingCurve::InOutQuad);
animGroup->addAnimation(xRotAnim);
auto* yRotAnim = new QPropertyAnimation(this, "yRotation");
yRotAnim->setDuration(300);
yRotAnim->setStartValue(yRotation());
yRotAnim->setEndValue(targetYRot);
yRotAnim->setEasingCurve(QEasingCurve::InOutQuad);
animGroup->addAnimation(yRotAnim);
auto* panXAnim = new QPropertyAnimation(this, "panX");
panXAnim->setDuration(300);
panXAnim->setStartValue(panX());
panXAnim->setEndValue(0.0f);
panXAnim->setEasingCurve(QEasingCurve::InOutQuad);
animGroup->addAnimation(panXAnim);
auto* panYAnim = new QPropertyAnimation(this, "panY");
panYAnim->setDuration(300);
panYAnim->setStartValue(panY());
panYAnim->setEndValue(0.0f);
panYAnim->setEasingCurve(QEasingCurve::InOutQuad);
animGroup->addAnimation(panYAnim);
auto* zoomAnim = new QPropertyAnimation(this, "zoom");
zoomAnim->setDuration(300);
zoomAnim->setStartValue(zoom());
zoomAnim->setEndValue(-20.0f);
zoomAnim->setEasingCurve(QEasingCurve::InOutQuad);
animGroup->addAnimation(zoomAnim);
animGroup->start(QAbstractAnimation::DeleteWhenStopped);
}
void Camera::animateRestoreState()
{
auto* animGroup = new QParallelAnimationGroup(this);
auto* xRotAnim = new QPropertyAnimation(this, "xRotation");
xRotAnim->setDuration(300);
xRotAnim->setStartValue(xRotation());
xRotAnim->setEndValue(savedXRot());
xRotAnim->setEasingCurve(QEasingCurve::InOutQuad);
animGroup->addAnimation(xRotAnim);
auto* yRotAnim = new QPropertyAnimation(this, "yRotation");
yRotAnim->setDuration(300);
yRotAnim->setStartValue(yRotation());
yRotAnim->setEndValue(savedYRot());
yRotAnim->setEasingCurve(QEasingCurve::InOutQuad);
animGroup->addAnimation(yRotAnim);
auto* panXAnim = new QPropertyAnimation(this, "panX");
panXAnim->setDuration(300);
panXAnim->setStartValue(panX());
panXAnim->setEndValue(savedPanX());
panXAnim->setEasingCurve(QEasingCurve::InOutQuad);
animGroup->addAnimation(panXAnim);
auto* panYAnim = new QPropertyAnimation(this, "panY");
panYAnim->setDuration(300);
panYAnim->setStartValue(panY());
panYAnim->setEndValue(savedPanY());
panYAnim->setEasingCurve(QEasingCurve::InOutQuad);
animGroup->addAnimation(panYAnim);
auto* zoomAnim = new QPropertyAnimation(this, "zoom");
zoomAnim->setDuration(300);
zoomAnim->setStartValue(zoom());
zoomAnim->setEndValue(savedZoom());
zoomAnim->setEasingCurve(QEasingCurve::InOutQuad);
animGroup->addAnimation(zoomAnim);
connect(animGroup, &QParallelAnimationGroup::finished, this, &Camera::restoreStateAnimationFinished);
animGroup->start(QAbstractAnimation::DeleteWhenStopped);
}