diff options
Diffstat (limited to 'src/Authoring/Qt3DStudio/Palettes/scenecamera')
7 files changed, 854 insertions, 0 deletions
diff --git a/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraglwidget.cpp b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraglwidget.cpp new file mode 100644 index 00000000..ce7d8e37 --- /dev/null +++ b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraglwidget.cpp @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "Qt3DSCommonPrecompile.h" +#include "scenecameraglwidget.h" +#include "StudioApp.h" +#include "IStudioRenderer.h" +#include "WGLRenderContext.h" +#include "StudioPreferences.h" + +#include <QtGui/qopenglshaderprogram.h> +#include <QtGui/qopengltexture.h> +#include <QtGui/qopenglbuffer.h> +#include <QtGui/qopenglvertexarrayobject.h> + +const QVector4D defaultTextureOffset = QVector4D(0.0f, 0.0f, 1.0f, 1.0f); +const QVector2D defaultGeometryOffset = QVector2D(1.0f, 1.0f); + +SceneCameraGlWidget::SceneCameraGlWidget(QWidget *parent) + : QOpenGLWidget(parent) + , m_textureOffset(defaultTextureOffset) + , m_geometryOffset(defaultGeometryOffset) +{ + QSurfaceFormat format = CWGLRenderContext::selectSurfaceFormat(this); + format.setSamples(1); // We want pixel perfect view, not aliased one + setFormat(format); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +} + +SceneCameraGlWidget::~SceneCameraGlWidget() +{ + cleanup(); +} + +void SceneCameraGlWidget::initializeGL() +{ + initializeOpenGLFunctions(); + QObject::connect(context(), &QOpenGLContext::aboutToBeDestroyed, + this, &SceneCameraGlWidget::cleanup); + + m_program = new QOpenGLShaderProgram(); + if (!m_program->addShaderFromSourceCode( + QOpenGLShader::Vertex, + "#version 330 core\n" + "in vec2 vertexPos;\n" + "in vec2 vertexTexCoord;\n" + "uniform vec4 uTexOffset;\n" + "uniform vec4 uGeomOffset;\n" + "out vec2 texCoord;\n" + "void main(void)\n" + "{\n" + " gl_Position = vec4(uGeomOffset.xy + vertexPos * uGeomOffset.zw, 0.0, 1.0);\n" + " texCoord = vec2(uTexOffset.z * vertexTexCoord.x + uTexOffset.x,\n" + " uTexOffset.w * vertexTexCoord.y + uTexOffset.y);\n" + "}")) { + qWarning() << __FUNCTION__ << "Failed to add vertex shader for scene camera preview"; + return; + } + if (!m_program->addShaderFromSourceCode( + QOpenGLShader::Fragment, + "#version 330 core\n" + "in vec2 texCoord;\n" + "uniform sampler2D uSampler;\n" + "out vec4 fragColor;\n" + "void main(void) {\n" + " vec4 oc = texture(uSampler, texCoord);\n" + " fragColor = vec4(oc);\n" + "}")) { + + qWarning() << __FUNCTION__ << "Failed to add fragment shader for scene camera preview"; + return; + } + if (!m_program->link()) { + qWarning() << __FUNCTION__ << "Failed to link program for scene camera preview"; + return; + } + if (!m_program->bind()) { + qWarning() << __FUNCTION__ << "Failed to bind program for scene camera preview"; + return; + } else { + GLint vertexAtt = GLint(m_program->attributeLocation("vertexPos")); + GLint uvAtt = GLint(m_program->attributeLocation("vertexTexCoord")); + m_uniformTextureOffset = GLint(m_program->uniformLocation("uTexOffset")); + m_uniformGeometryOffset = GLint(m_program->uniformLocation("uGeomOffset")); + m_program->setUniformValue("uSampler", 0); + + m_vao = new QOpenGLVertexArrayObject; + if (m_vao->create()) { + m_vao->bind(); + m_vertexBuffer = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); + if (m_vertexBuffer->create() && m_vertexBuffer->bind()) { + GLfloat vertexBuffer[] = {-1.0f, 1.0f, + -1.0f, -1.0f, + 1.0f, 1.0f, + 1.0f, -1.0f}; + m_vertexBuffer->allocate(vertexBuffer, 8 * sizeof(GLfloat)); + glEnableVertexAttribArray(vertexAtt); + glVertexAttribPointer(vertexAtt, 2, GL_FLOAT, GL_FALSE, 0, (void *)0); + } else { + qWarning() << __FUNCTION__ + << "Failed to create/bind vertex buffer for scene camera preview"; + return; + } + m_uvBuffer = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); + if (m_uvBuffer->create() && m_uvBuffer->bind()) { + GLfloat uvBuffer[] = {0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 1.0f, + 1.0f, 0.0f}; + m_uvBuffer->allocate(uvBuffer, 8 * sizeof(GLfloat)); + glEnableVertexAttribArray(uvAtt); + glVertexAttribPointer(uvAtt, 2, GL_FLOAT, GL_FALSE, 0, (void *)0); + } else { + qWarning() << __FUNCTION__ + << "Failed to create/bind UV buffer for scene camera preview"; + return; + } + + m_vao->release(); + } else { + qWarning() << __FUNCTION__ << "Failed to create/bind vertex array object"; + return; + } + } + + const QColor matteColor = CStudioPreferences::matteColor(); + glClearColor(matteColor.redF(), matteColor.greenF(), matteColor.blueF(), 1.0f); +} + +void SceneCameraGlWidget::paintGL() +{ + Q3DStudio::IStudioRenderer &renderer(g_StudioApp.getRenderer()); + if (renderer.IsInitialized()) { + m_vao->bind(); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + QSize fboSize; + qt3ds::QT3DSU32 textureId; + renderer.getPreviewFbo(fboSize, textureId); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, GLuint(textureId)); + + m_program->setUniformValueArray(m_uniformTextureOffset, &m_textureOffset, 1); + m_program->setUniformValueArray(m_uniformGeometryOffset, &m_geometryOffset, 1); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + m_vao->release(); + } +} + +void SceneCameraGlWidget::resizeGL(int, int) +{ + // We need to update immediately to avoid flicker + update(); +} + +void SceneCameraGlWidget::cleanup() +{ + makeCurrent(); + + delete m_program; + delete m_vertexBuffer; + delete m_uvBuffer; + delete m_vao; + m_program = nullptr; + m_vertexBuffer = nullptr; + m_uvBuffer = nullptr; + m_vao = nullptr; + m_uniformTextureOffset = 0; + m_uniformGeometryOffset = 0; + m_textureOffset = defaultTextureOffset; + m_geometryOffset = defaultGeometryOffset; + + doneCurrent(); +} diff --git a/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraglwidget.h b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraglwidget.h new file mode 100644 index 00000000..93becf19 --- /dev/null +++ b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraglwidget.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SCENE_CAMERA_GLWIDGET_H +#define SCENE_CAMERA_GLWIDGET_H + +#include <QtWidgets/qopenglwidget.h> +#include <QtGui/qopenglfunctions.h> +#include <QtGui/qvector2d.h> +#include <QtGui/qvector4d.h> + +QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram) +QT_FORWARD_DECLARE_CLASS(QOpenGLBuffer) +QT_FORWARD_DECLARE_CLASS(QOpenGLVertexArrayObject) + +class SceneCameraGlWidget : public QOpenGLWidget, QOpenGLFunctions +{ + Q_OBJECT +public: + explicit SceneCameraGlWidget(QWidget *parent = nullptr); + ~SceneCameraGlWidget(); + + void setTextureOffset(const QVector4D &offset) { m_textureOffset = offset; } + void setGeometryOffset(const QVector4D &offset) { m_geometryOffset = offset; } + +protected: + void initializeGL() override; + void paintGL() override; + void resizeGL(int, int) override; + +private: + void cleanup(); + + QOpenGLShaderProgram *m_program = nullptr; + QOpenGLBuffer *m_vertexBuffer = nullptr; + QOpenGLBuffer *m_uvBuffer = nullptr; + QOpenGLVertexArrayObject *m_vao = nullptr; + GLint m_uniformTextureOffset = 0; + GLint m_uniformGeometryOffset = 0; + QVector4D m_textureOffset; + QVector4D m_geometryOffset; +}; + +#endif diff --git a/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecamerascrollarea.cpp b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecamerascrollarea.cpp new file mode 100644 index 00000000..035e242c --- /dev/null +++ b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecamerascrollarea.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "Qt3DSCommonPrecompile.h" +#include "scenecamerascrollarea.h" +#include "scenecameraglwidget.h" +#include "Core.h" + +#include <QtWidgets/qscrollbar.h> +#include <QtGui/qevent.h> + +SceneCameraScrollArea::SceneCameraScrollArea(QWidget *parent) + : QAbstractScrollArea(parent) +{ + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + m_glWidget = new SceneCameraGlWidget(this); +} + +SceneCameraScrollArea::~SceneCameraScrollArea() +{ +} + +void SceneCameraScrollArea::setZoom(qreal zoom, const QPoint &zoomPoint) +{ + // Calculate the actual presentation point + qreal oldH = (horizontalScrollBar()->value() + zoomPoint.x()) / m_zoom; + qreal oldV = (verticalScrollBar()->value() + zoomPoint.y()) / m_zoom; + + m_zoom = zoom; + + recalculateScrollRanges(); + + // Move the scrollbars so that the actual presentation point stays in the same location + horizontalScrollBar()->setValue(qRound(oldH * m_zoom - zoomPoint.x())); + verticalScrollBar()->setValue(qRound(oldV * m_zoom - zoomPoint.y())); + + recalculateOffsets(); + + Q_EMIT needUpdate(); +} + +void SceneCameraScrollArea::setPresentationSize(const QSize &size) +{ + if (m_presentationSize != size) { + m_presentationSize = size; + recalculateScrollRanges(); + recalculateOffsets(); + } +} + +void SceneCameraScrollArea::recalculateScrollRanges() +{ + const QSizeF presSize = zoomedPresentationSize(); + + const QSize viewSize = viewport()->size(); + horizontalScrollBar()->setRange(0, int(presSize.width() - viewSize.width())); + verticalScrollBar()->setRange(0, int(presSize.height() - viewSize.height())); + horizontalScrollBar()->setPageStep(viewSize.width()); + verticalScrollBar()->setPageStep(viewSize.height()); +} + +void SceneCameraScrollArea::recalculateOffsets() +{ + // Texture offset vector contains normalized rect of the viewable area of the texture + const QSize viewSize = viewport()->size(); + const qreal fullWidth = qreal(horizontalScrollBar()->maximum() + viewSize.width()); + const qreal fullHeight = qreal(verticalScrollBar()->maximum() + viewSize.height()); + QVector4D textureOffset( + float(horizontalScrollBar()->value() / fullWidth), + float((verticalScrollBar()->maximum() - verticalScrollBar()->value()) / fullHeight), + float(viewSize.width() / fullWidth), float(viewSize.height() / fullHeight)); + + m_glWidget->setTextureOffset(textureOffset); + + // The geometry offset is adjusted to keep aspect ratio when view area is larger than + // zoomed width/height. Since the geometry of the quad is in range [-1, 1], the width/height of + // the offset is just a direct multiplier to the coordinate. + // XY contain the subpixel offset to ensure we don't get artifacts depending on pixel alignment. + const QSizeF presSize = zoomedPresentationSize(); + float subPixelX = 0.0f; + float subPixelY = 0.0f; + qreal normWidth = 1.0; + qreal normHeight = 1.0; + if (presSize.width() < fullWidth) { + qreal diffX = (fullWidth - qRound(presSize.width())) / 2.0; + subPixelX = float((diffX - qRound(diffX)) / fullWidth); + normWidth = presSize.width() / fullWidth; + } + if (presSize.height() < fullHeight) { + qreal diffY = (fullHeight - qRound(presSize.height())) / 2.0; + subPixelY = float((diffY - qRound(diffY)) / fullHeight); + normHeight = presSize.height() / fullHeight; + } + + QVector4D geometryOffset(subPixelX, subPixelY, float(normWidth), float(normHeight)); + m_glWidget->setGeometryOffset(geometryOffset); +} + +void SceneCameraScrollArea::scrollContentsBy(int, int) +{ + recalculateOffsets(); + Q_EMIT needUpdate(); +} + +void SceneCameraScrollArea::showEvent(QShowEvent *event) +{ + QAbstractScrollArea::showEvent(event); + + recalculateScrollRanges(); + recalculateOffsets(); + resizeGlWidget(); +} + +void SceneCameraScrollArea::resizeGlWidget() +{ + m_glWidget->resize(viewport()->size()); +} + +QSizeF SceneCameraScrollArea::zoomedPresentationSize() +{ + // Multiply QSize components separately to avoid rounding to integers + QSizeF size = QSizeF(m_presentationSize.width() * m_zoom, + m_presentationSize.height() * m_zoom); + return size; +} + +void SceneCameraScrollArea::resizeEvent(QResizeEvent *event) +{ + QAbstractScrollArea::resizeEvent(event); + + recalculateScrollRanges(); + recalculateOffsets(); + resizeGlWidget(); +} diff --git a/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecamerascrollarea.h b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecamerascrollarea.h new file mode 100644 index 00000000..682dc430 --- /dev/null +++ b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecamerascrollarea.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SCENE_CAMERA_SCROLL_AREA +#define SCENE_CAMERA_SCROLL_AREA + +#include <QtWidgets/qabstractscrollarea.h> + +class SceneCameraGlWidget; + +class SceneCameraScrollArea : public QAbstractScrollArea +{ + Q_OBJECT + +public: + SceneCameraScrollArea(QWidget *parent = nullptr); + virtual ~SceneCameraScrollArea(); + + SceneCameraGlWidget *glWidget() const { return m_glWidget; } + + void setZoom(qreal zoom, const QPoint &zoomPoint); + void setPresentationSize(const QSize &size); + void recalculateScrollRanges(); + void recalculateOffsets(); + +Q_SIGNALS: + void needUpdate(); + +protected: + void resizeEvent(QResizeEvent *event) override; + void scrollContentsBy(int, int) override; + void showEvent(QShowEvent *event) override; + +private: + void resizeGlWidget(); + QSizeF zoomedPresentationSize(); + +protected: + SceneCameraGlWidget *m_glWidget = nullptr; + qreal m_zoom = 1.0; + QSize m_presentationSize; +}; + +#endif diff --git a/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraview.cpp b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraview.cpp new file mode 100644 index 00000000..e153c0ad --- /dev/null +++ b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraview.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "scenecameraview.h" +#include "ui_scenecameraview.h" +#include "scenecameraglwidget.h" +#include "StudioApp.h" +#include "Core.h" +#include "StudioProjectSettings.h" +#include "MainFrm.h" +#include "PlayerWnd.h" +#include "MouseCursor.h" +#include "ResourceCache.h" + +#include <QtGui/qevent.h> +#include <QtWidgets/qscrollbar.h> + +const QPoint invalidMousePoint = QPoint(-999999, -999999); + +SceneCameraView::SceneCameraView(CMainFrame *mainFrame, QWidget *parent) : + QWidget(parent) + , m_ui(new Ui::SceneCameraView) + , m_mousePressPointLeft(invalidMousePoint) + , m_mousePressPointRight(invalidMousePoint) +{ + m_ui->setupUi(this); + + m_cursorPan = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_EDIT_CAMERA_PAN); + m_cursorZoom = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_EDIT_CAMERA_ZOOM); + + // Limit the preview framerate a bit to limit amount of updates when dragging the slider + m_updateTimer.setInterval(0); + m_updateTimer.setSingleShot(true); + + connect(m_ui->zoomSlider, &QSlider::valueChanged, + this, &SceneCameraView::handleSliderValueChange); + connect(mainFrame->GetPlayerWnd(), &CPlayerWnd::newFrame, + this, &SceneCameraView::requestUpdate); + connect(m_ui->scrollArea, &SceneCameraScrollArea::needUpdate, + this, &SceneCameraView::requestUpdate); + connect(&m_updateTimer, &QTimer::timeout, this, &SceneCameraView::doUpdate); +} + +SceneCameraView::~SceneCameraView() +{ + delete m_ui; +} + +void SceneCameraView::wheelEvent(QWheelEvent *e) +{ + m_zoomPoint = m_ui->scrollArea->viewport()->mapFrom(this, e->pos()); + int currentZoomValue = m_ui->zoomSlider->value(); + // Adjust amount of change based on zoom level + int divider = qMin(120, 1000 / currentZoomValue); + m_ui->zoomSlider->setValue(currentZoomValue + (e->angleDelta().y() / divider)); +} + +void SceneCameraView::resizeEvent(QResizeEvent *e) +{ + m_zoomPoint = m_ui->scrollArea->viewport()->geometry().center(); + + QWidget::resizeEvent(e); +} + +void SceneCameraView::mousePressEvent(QMouseEvent *e) +{ + // Ignore panning starting outside scrollarea + if (!m_ui->scrollArea->rect().contains(e->pos())) + return; + + // Panning can be done with left or middle button. Left is more natural and we don't need it + // for selection. Alt+middle pans in edit camera mode, so middle button is also supported for + // panning. + if (m_mousePressPointRight == invalidMousePoint + && (e->button() == Qt::LeftButton || e->button() == Qt::MidButton)) { + m_mousePressPointLeft = e->pos(); + m_mousePressScrollValues = QPoint(m_ui->scrollArea->horizontalScrollBar()->value(), + m_ui->scrollArea->verticalScrollBar()->value()); + setCursor(m_cursorPan); + } else if (m_mousePressPointLeft == invalidMousePoint && e->button() == Qt::RightButton) { + m_mousePressPointRight = e->pos(); + m_mousePressZoomValue = m_ui->zoomSlider->value(); + setCursor(m_cursorZoom); + } +} + +void SceneCameraView::mouseMoveEvent(QMouseEvent *e) +{ + if (m_mousePressPointLeft != invalidMousePoint) { + const QPoint delta = e->pos() - m_mousePressPointLeft; + m_ui->scrollArea->horizontalScrollBar()->setValue(m_mousePressScrollValues.x() - delta.x()); + m_ui->scrollArea->verticalScrollBar()->setValue(m_mousePressScrollValues.y() - delta.y()); + } + if (m_mousePressPointRight != invalidMousePoint) { + const qreal delta = qreal(e->pos().y() - m_mousePressPointRight.y()); + m_zoomPoint = m_mousePressPointRight; + m_ui->zoomSlider->setValue(m_mousePressZoomValue - delta / 2.0); + } +} + +void SceneCameraView::mouseReleaseEvent(QMouseEvent *e) +{ + if (m_mousePressPointLeft != invalidMousePoint + && e->button() == Qt::LeftButton || e->button() == Qt::MidButton) { + m_mousePressPointLeft = invalidMousePoint; + setCursor(Qt::ArrowCursor); + } else if (m_mousePressPointRight != invalidMousePoint) { + m_zoomPoint = m_ui->scrollArea->viewport()->geometry().center(); + m_mousePressPointRight = invalidMousePoint; + m_mousePressZoomValue = 0; + setCursor(Qt::ArrowCursor); + } +} + +void SceneCameraView::handleSliderValueChange() +{ + const qreal zoom = qreal(m_ui->zoomSlider->value()) / 10.0; + QString valueString = QString::number(zoom, 'f', 1); + m_ui->slideValueLabel->setText(tr("%1x").arg(valueString)); + m_ui->scrollArea->setZoom(zoom, m_zoomPoint); + m_zoomPoint = m_ui->scrollArea->viewport()->geometry().center(); +} + +void SceneCameraView::doUpdate() +{ + // There is no event for presentation size change, so update every frame to catch the change + m_ui->scrollArea->setPresentationSize( + g_StudioApp.GetCore()->GetStudioProjectSettings()->getPresentationSize()); + m_ui->scrollArea->glWidget()->update(); +} + +void SceneCameraView::requestUpdate() +{ + if (!m_updateTimer.isActive()) + m_updateTimer.start(); +} diff --git a/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraview.h b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraview.h new file mode 100644 index 00000000..e2bfb05b --- /dev/null +++ b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraview.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SCENECAMERAVIEW_H +#define SCENECAMERAVIEW_H + +#include <QtWidgets/qwidget.h> +#include <QtCore/qtimer.h> + +#ifdef QT_NAMESPACE +using namespace QT_NAMESPACE; +#endif + +QT_BEGIN_NAMESPACE +namespace Ui { +class SceneCameraView; +} +QT_END_NAMESPACE + +class CMainFrame; + +class SceneCameraView : public QWidget +{ + Q_OBJECT + +public: + explicit SceneCameraView(CMainFrame *mainFrame, QWidget *parent = 0); + ~SceneCameraView(); + +protected: + void wheelEvent(QWheelEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + +private: + void handleSliderValueChange(); + void doUpdate(); + void requestUpdate(); + + Ui::SceneCameraView *m_ui = nullptr; + + QTimer m_updateTimer; + QPoint m_zoomPoint; + QPoint m_mousePressPointLeft; + QPoint m_mousePressPointRight; + QPoint m_mousePressScrollValues; + int m_mousePressZoomValue = 0; + + QCursor m_cursorPan; + QCursor m_cursorZoom; +}; + +#endif // SCENECAMERAVIEW_H diff --git a/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraview.ui b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraview.ui new file mode 100644 index 00000000..01aefa72 --- /dev/null +++ b/src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraview.ui @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SceneCameraView</class> + <widget class="QWidget" name="SceneCameraView"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="SceneCameraScrollArea" name="scrollArea" native="true"/> + </item> + <item> + <widget class="QWidget" name="widget" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QSlider" name="zoomSlider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>100</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>300</width> + <height>16777215</height> + </size> + </property> + <property name="minimum"> + <number>2</number> + </property> + <property name="maximum"> + <number>200</number> + </property> + <property name="singleStep"> + <number>1</number> + </property> + <property name="value"> + <number>10</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="slideValueLabel"> + <property name="text"> + <string>1.0</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>SceneCameraScrollArea</class> + <extends>QWidget</extends> + <header>scenecamerascrollarea.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> |