summaryrefslogtreecommitdiffstats
path: root/src/Authoring/Qt3DStudio/Palettes/scenecamera
diff options
context:
space:
mode:
Diffstat (limited to 'src/Authoring/Qt3DStudio/Palettes/scenecamera')
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraglwidget.cpp208
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraglwidget.h69
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecamerascrollarea.cpp160
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecamerascrollarea.h69
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraview.cpp161
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraview.h80
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/scenecamera/scenecameraview.ui107
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>