feat: Add animated home button to view cube to reset camera
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
@@ -269,6 +269,70 @@ void Camera::animateToPlaneView(int plane)
|
|||||||
animGroup->start(QAbstractAnimation::DeleteWhenStopped);
|
animGroup->start(QAbstractAnimation::DeleteWhenStopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Camera::animateToHomeView()
|
||||||
|
{
|
||||||
|
auto* animGroup = new QParallelAnimationGroup(this);
|
||||||
|
|
||||||
|
const float full_circle = 360.0f * 16.0f;
|
||||||
|
|
||||||
|
float currentXRot = xRotation();
|
||||||
|
float targetXRot = 30 * 16;
|
||||||
|
float diffX = targetXRot - currentXRot;
|
||||||
|
diffX = fmod(diffX, full_circle);
|
||||||
|
if (diffX > full_circle / 2.0f) {
|
||||||
|
diffX -= full_circle;
|
||||||
|
} else if (diffX < -full_circle / 2.0f) {
|
||||||
|
diffX += full_circle;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* xRotAnim = new QPropertyAnimation(this, "xRotation");
|
||||||
|
xRotAnim->setDuration(300);
|
||||||
|
xRotAnim->setStartValue(currentXRot);
|
||||||
|
xRotAnim->setEndValue(currentXRot + diffX);
|
||||||
|
xRotAnim->setEasingCurve(QEasingCurve::InOutQuad);
|
||||||
|
animGroup->addAnimation(xRotAnim);
|
||||||
|
|
||||||
|
float currentYRot = yRotation();
|
||||||
|
float targetYRot = -45 * 16;
|
||||||
|
float diffY = targetYRot - currentYRot;
|
||||||
|
diffY = fmod(diffY, full_circle);
|
||||||
|
if (diffY > full_circle / 2.0f) {
|
||||||
|
diffY -= full_circle;
|
||||||
|
} else if (diffY < -full_circle / 2.0f) {
|
||||||
|
diffY += full_circle;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* yRotAnim = new QPropertyAnimation(this, "yRotation");
|
||||||
|
yRotAnim->setDuration(300);
|
||||||
|
yRotAnim->setStartValue(currentYRot);
|
||||||
|
yRotAnim->setEndValue(currentYRot + diffY);
|
||||||
|
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::startRotation(const QVector3D& pivot)
|
void Camera::startRotation(const QVector3D& pivot)
|
||||||
{
|
{
|
||||||
m_rotationPivot = pivot;
|
m_rotationPivot = pivot;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public:
|
|||||||
|
|
||||||
void animateToPlaneView(int plane);
|
void animateToPlaneView(int plane);
|
||||||
void animateRestoreState();
|
void animateRestoreState();
|
||||||
|
void animateToHomeView();
|
||||||
|
|
||||||
void startRotation(const QVector3D& pivot);
|
void startRotation(const QVector3D& pivot);
|
||||||
void stopRotation();
|
void stopRotation();
|
||||||
|
|||||||
@@ -5,10 +5,12 @@
|
|||||||
#include <QOpenGLShaderProgram>
|
#include <QOpenGLShaderProgram>
|
||||||
#include <QOpenGLTexture>
|
#include <QOpenGLTexture>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
|
#include <QSvgRenderer>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
ViewCube::ViewCube()
|
ViewCube::ViewCube()
|
||||||
{
|
{
|
||||||
|
m_homeButtonRenderer = new QSvgRenderer(QString(":/icons/rectangle.svg"));
|
||||||
for (int i = 0; i < 6; ++i) {
|
for (int i = 0; i < 6; ++i) {
|
||||||
m_faceTextures[i] = nullptr;
|
m_faceTextures[i] = nullptr;
|
||||||
}
|
}
|
||||||
@@ -20,6 +22,7 @@ ViewCube::~ViewCube()
|
|||||||
delete m_faceTextures[i];
|
delete m_faceTextures[i];
|
||||||
}
|
}
|
||||||
delete m_textureShaderProgram;
|
delete m_textureShaderProgram;
|
||||||
|
delete m_homeButtonRenderer;
|
||||||
m_cubeVbo.destroy();
|
m_cubeVbo.destroy();
|
||||||
m_cubeVao.destroy();
|
m_cubeVao.destroy();
|
||||||
m_axesVbo.destroy();
|
m_axesVbo.destroy();
|
||||||
@@ -42,10 +45,9 @@ void ViewCube::paintGL(QOpenGLShaderProgram* simpleShader, int simpleShaderColor
|
|||||||
QRect viewCubeRect(width - viewCubeSize, 0, viewCubeSize, viewCubeSize);
|
QRect viewCubeRect(width - viewCubeSize, 0, viewCubeSize, viewCubeSize);
|
||||||
QPoint physicalMousePos = mousePos * QGuiApplication::primaryScreen()->devicePixelRatio();
|
QPoint physicalMousePos = mousePos * QGuiApplication::primaryScreen()->devicePixelRatio();
|
||||||
|
|
||||||
float opacity = 0.5f;
|
m_isHovered = viewCubeRect.contains(physicalMousePos);
|
||||||
if (viewCubeRect.contains(physicalMousePos)) {
|
|
||||||
opacity = 1.0f;
|
float opacity = m_isHovered ? 1.0f : 0.5f;
|
||||||
}
|
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
@@ -210,3 +212,39 @@ void ViewCube::drawAxes(QOpenGLShaderProgram* simpleShader, int colorLoc, const
|
|||||||
|
|
||||||
glLineWidth(1.0f);
|
glLineWidth(1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewCube::paint2D(QPainter& painter, int widgetWidth, int widgetHeight)
|
||||||
|
{
|
||||||
|
if (!m_isHovered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int viewCubeSize = 150; // logical pixels
|
||||||
|
int buttonSize = 24;
|
||||||
|
int buttonMargin = 8;
|
||||||
|
|
||||||
|
int viewCubeX = widgetWidth - viewCubeSize;
|
||||||
|
int viewCubeY = 0;
|
||||||
|
|
||||||
|
m_homeButtonRect = QRect(viewCubeX - buttonMargin - buttonSize, viewCubeY, buttonSize, buttonSize);
|
||||||
|
|
||||||
|
if (m_homeButtonRenderer && m_homeButtonRenderer->isValid()) {
|
||||||
|
m_homeButtonRenderer->render(&painter, m_homeButtonRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ViewCube::handleMousePress(const QPoint& pos, int widgetWidth, int widgetHeight)
|
||||||
|
{
|
||||||
|
if (!m_isHovered) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int viewCubeSize = 150;
|
||||||
|
int buttonSize = 24;
|
||||||
|
int buttonMargin = 8;
|
||||||
|
int viewCubeX = widgetWidth - viewCubeSize;
|
||||||
|
int viewCubeY = 0;
|
||||||
|
QRect homeButtonRect(viewCubeX - buttonMargin - buttonSize, viewCubeY, buttonSize, buttonSize);
|
||||||
|
|
||||||
|
return homeButtonRect.contains(pos);
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
class QOpenGLShaderProgram;
|
class QOpenGLShaderProgram;
|
||||||
class QOpenGLTexture;
|
class QOpenGLTexture;
|
||||||
|
class QPainter;
|
||||||
|
class QSvgRenderer;
|
||||||
|
|
||||||
class ViewCube : protected QOpenGLFunctions
|
class ViewCube : protected QOpenGLFunctions
|
||||||
{
|
{
|
||||||
@@ -18,6 +20,8 @@ public:
|
|||||||
|
|
||||||
void initializeGL();
|
void initializeGL();
|
||||||
void paintGL(QOpenGLShaderProgram* simpleShader, int simpleShaderColorLoc, const QMatrix4x4& viewMatrix, int width, int height, const QPoint& mousePos);
|
void paintGL(QOpenGLShaderProgram* simpleShader, int simpleShaderColorLoc, const QMatrix4x4& viewMatrix, int width, int height, const QPoint& mousePos);
|
||||||
|
void paint2D(QPainter& painter, int widgetWidth, int widgetHeight);
|
||||||
|
bool handleMousePress(const QPoint& pos, int widgetWidth, int widgetHeight);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createFaceTextures();
|
void createFaceTextures();
|
||||||
@@ -26,6 +30,10 @@ private:
|
|||||||
void drawViewCube(const QMatrix4x4& projection, const QMatrix4x4& view, float opacity);
|
void drawViewCube(const QMatrix4x4& projection, const QMatrix4x4& view, float opacity);
|
||||||
void drawAxes(QOpenGLShaderProgram* simpleShader, int colorLoc, const QMatrix4x4& projection, const QMatrix4x4& view);
|
void drawAxes(QOpenGLShaderProgram* simpleShader, int colorLoc, const QMatrix4x4& projection, const QMatrix4x4& view);
|
||||||
|
|
||||||
|
bool m_isHovered = false;
|
||||||
|
QRect m_homeButtonRect;
|
||||||
|
QSvgRenderer* m_homeButtonRenderer = nullptr;
|
||||||
|
|
||||||
QOpenGLTexture* m_faceTextures[6];
|
QOpenGLTexture* m_faceTextures[6];
|
||||||
|
|
||||||
QOpenGLShaderProgram* m_textureShaderProgram = nullptr;
|
QOpenGLShaderProgram* m_textureShaderProgram = nullptr;
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ void ViewportWidget::paintGL()
|
|||||||
m_sketchGrid->paintAxisLabels(painter, static_cast<SketchGrid::SketchPlane>(m_currentPlane), model, projection);
|
m_sketchGrid->paintAxisLabels(painter, static_cast<SketchGrid::SketchPlane>(m_currentPlane), model, projection);
|
||||||
}
|
}
|
||||||
m_featureBrowser->paint(painter, width(), height());
|
m_featureBrowser->paint(painter, width(), height());
|
||||||
|
m_viewCube->paint2D(painter, width(), height());
|
||||||
|
|
||||||
|
|
||||||
if (m_activeSketchTool) {
|
if (m_activeSketchTool) {
|
||||||
@@ -230,6 +231,12 @@ void ViewportWidget::mousePressEvent(QMouseEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
if (m_viewCube->handleMousePress(event->pos(), width(), height())) {
|
||||||
|
m_camera->animateToHomeView();
|
||||||
|
update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_isSelectingPlane) {
|
if (m_isSelectingPlane) {
|
||||||
if (m_highlightedPlane != SketchPlane::NONE) {
|
if (m_highlightedPlane != SketchPlane::NONE) {
|
||||||
emit planeSelected(m_highlightedPlane);
|
emit planeSelected(m_highlightedPlane);
|
||||||
|
|||||||
Reference in New Issue
Block a user