1 | // Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause |
3 | |
4 | #include <Qt3DQuickExtras/qt3dquickwindow.h> |
5 | #include <Qt3DExtras/Qt3DWindow> |
6 | #include "qt3dquickwindow_p.h" |
7 | #include <Qt3DQuick/QQmlAspectEngine> |
8 | #include <Qt3DQuickExtras/qt3dquickwindow.h> |
9 | #include <Qt3DInput/qinputaspect.h> |
10 | #include <Qt3DInput/qinputsettings.h> |
11 | #include <Qt3DLogic/qlogicaspect.h> |
12 | #include <Qt3DRender/qcamera.h> |
13 | #include <Qt3DRender/qrenderaspect.h> |
14 | #include <Qt3DRender/qrendersurfaceselector.h> |
15 | #include <Qt3DCore/qcoreaspect.h> |
16 | #include <QtGui/QGuiApplication> |
17 | #include <QtGui/QScreen> |
18 | #include <qopenglcontext.h> |
19 | #include <QtQml/QQmlContext> |
20 | #include <QtQml/qqmlincubator.h> |
21 | |
22 | #include <Qt3DQuickExtras/private/qt3dquickwindowlogging_p.h> |
23 | #include <Qt3DRender/private/qrendersurfaceselector_p.h> |
24 | #include <Qt3DRender/private/qrenderaspect_p.h> |
25 | |
26 | QT_BEGIN_NAMESPACE |
27 | |
28 | namespace Qt3DExtras { |
29 | |
30 | namespace Quick { |
31 | |
32 | namespace { |
33 | |
34 | class : public QObject, public QQmlIncubationController |
35 | { |
36 | Q_OBJECT |
37 | public: |
38 | explicit (QObject *parent = nullptr) |
39 | : QObject(parent) |
40 | , m_incubationTime(std::max(a: 1, b: int(1000 / QGuiApplication::primaryScreen()->refreshRate()) / 3)) |
41 | { |
42 | startTimer(interval: QGuiApplication::primaryScreen()->refreshRate()); |
43 | } |
44 | |
45 | void (QTimerEvent *) override |
46 | { |
47 | incubateFor(msecs: m_incubationTime); |
48 | } |
49 | |
50 | private: |
51 | const int ; |
52 | }; |
53 | |
54 | } // anonymous |
55 | |
56 | Qt3DQuickWindowPrivate::() |
57 | : m_engine(nullptr) |
58 | , m_renderAspect(nullptr) |
59 | , m_inputAspect(nullptr) |
60 | , m_logicAspect(nullptr) |
61 | , m_initialized(false) |
62 | , m_cameraAspectRatioMode(Qt3DQuickWindow::AutomaticAspectRatio) |
63 | , m_incubationController(nullptr) |
64 | { |
65 | } |
66 | |
67 | Qt3DQuickWindow::(QWindow *parent) |
68 | : QWindow(*new Qt3DQuickWindowPrivate(), parent) |
69 | { |
70 | Q_D(Qt3DQuickWindow); |
71 | |
72 | resize(w: 1024, h: 768); |
73 | |
74 | Qt3DExtras::setupWindowSurface(window: this, Qt3DRender::API::RHI); |
75 | |
76 | auto coreAspect = new Qt3DCore::QCoreAspect; |
77 | d->m_renderAspect = new Qt3DRender::QRenderAspect; |
78 | if (parent && parent->screen()) |
79 | static_cast<Qt3DRender::QRenderAspectPrivate*>(Qt3DRender::QRenderAspectPrivate::get(q: d->m_renderAspect))->m_screen = parent->screen(); |
80 | d->m_inputAspect = new Qt3DInput::QInputAspect; |
81 | d->m_logicAspect = new Qt3DLogic::QLogicAspect; |
82 | d->m_engine = new Qt3DCore::Quick::QQmlAspectEngine; |
83 | |
84 | d->m_engine->aspectEngine()->registerAspect(aspect: coreAspect); |
85 | d->m_engine->aspectEngine()->registerAspect(aspect: d->m_renderAspect); |
86 | d->m_engine->aspectEngine()->registerAspect(aspect: d->m_inputAspect); |
87 | d->m_engine->aspectEngine()->registerAspect(aspect: d->m_logicAspect); |
88 | } |
89 | |
90 | Qt3DQuickWindow::() |
91 | { |
92 | Q_D(Qt3DQuickWindow); |
93 | delete d->m_engine; |
94 | } |
95 | |
96 | void Qt3DQuickWindow::(Qt3DCore::QAbstractAspect *aspect) |
97 | { |
98 | Q_ASSERT(!isVisible()); |
99 | Q_D(Qt3DQuickWindow); |
100 | d->m_engine->aspectEngine()->registerAspect(aspect); |
101 | } |
102 | |
103 | void Qt3DQuickWindow::(const QString &name) |
104 | { |
105 | Q_ASSERT(!isVisible()); |
106 | Q_D(Qt3DQuickWindow); |
107 | d->m_engine->aspectEngine()->registerAspect(name); |
108 | } |
109 | |
110 | void Qt3DQuickWindow::(const QUrl &source) |
111 | { |
112 | Q_D(Qt3DQuickWindow); |
113 | d->m_source = source; |
114 | } |
115 | |
116 | Qt3DCore::Quick::QQmlAspectEngine *Qt3DQuickWindow::() const |
117 | { |
118 | Q_D(const Qt3DQuickWindow); |
119 | return d->m_engine; |
120 | } |
121 | |
122 | void Qt3DQuickWindow::(CameraAspectRatioMode mode) |
123 | { |
124 | Q_D(Qt3DQuickWindow); |
125 | if (d->m_cameraAspectRatioMode == mode) |
126 | return; |
127 | |
128 | d->m_cameraAspectRatioMode = mode; |
129 | setCameraAspectModeHelper(); |
130 | emit cameraAspectRatioModeChanged(mode); |
131 | } |
132 | |
133 | Qt3DQuickWindow::CameraAspectRatioMode Qt3DQuickWindow::() const |
134 | { |
135 | Q_D(const Qt3DQuickWindow); |
136 | return d->m_cameraAspectRatioMode; |
137 | } |
138 | |
139 | void Qt3DQuickWindow::(QShowEvent *e) |
140 | { |
141 | Q_D(Qt3DQuickWindow); |
142 | if (!d->m_initialized) { |
143 | |
144 | // Connect to the QQmlAspectEngine's statusChanged signal so that when the QML is loaded |
145 | // and th eobjects hav ebeen instantiated, but before we set them on the QAspectEngine we |
146 | // can swoop in and set the window surface and camera on the framegraph and ensure the camera |
147 | // respects the window's aspect ratio |
148 | connect(sender: d->m_engine, signal: &Qt3DCore::Quick::QQmlAspectEngine::sceneCreated, |
149 | context: this, slot: &Qt3DQuickWindow::onSceneCreated); |
150 | |
151 | d->m_engine->setSource(d->m_source); |
152 | |
153 | // Set the QQmlIncubationController on the window |
154 | // to benefit from asynchronous incubation |
155 | if (!d->m_incubationController) |
156 | d->m_incubationController = new Qt3DQuickWindowIncubationController(this); |
157 | |
158 | d->m_engine->qmlEngine()->setIncubationController(d->m_incubationController); |
159 | |
160 | d->m_initialized = true; |
161 | } |
162 | QWindow::showEvent(e); |
163 | } |
164 | |
165 | void Qt3DQuickWindow::(QObject *rootObject) |
166 | { |
167 | Q_ASSERT(rootObject); |
168 | Q_D(Qt3DQuickWindow); |
169 | |
170 | setWindowSurface(rootObject); |
171 | |
172 | if (d->m_cameraAspectRatioMode == AutomaticAspectRatio) { |
173 | // Set aspect ratio of first camera to match the window |
174 | QList<Qt3DRender::QCamera *> cameras |
175 | = rootObject->findChildren<Qt3DRender::QCamera *>(); |
176 | if (cameras.isEmpty()) { |
177 | qCDebug(QuickWindow) << "No camera found" ; |
178 | } else { |
179 | d->m_camera = cameras.first(); |
180 | setCameraAspectModeHelper(); |
181 | } |
182 | } |
183 | |
184 | // Set ourselves up as a source of input events for the input aspect |
185 | Qt3DInput::QInputSettings *inputSettings = rootObject->findChild<Qt3DInput::QInputSettings *>(); |
186 | if (inputSettings) { |
187 | inputSettings->setEventSource(this); |
188 | } else { |
189 | qCDebug(QuickWindow) << "No Input Settings found, keyboard and mouse events won't be handled" ; |
190 | } |
191 | } |
192 | |
193 | void Qt3DQuickWindow::(QObject *rootObject) |
194 | { |
195 | Qt3DRender::QRenderSurfaceSelector *surfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(rootObject); |
196 | if (surfaceSelector) |
197 | surfaceSelector->setSurface(this); |
198 | } |
199 | |
200 | void Qt3DQuickWindow::() |
201 | { |
202 | Q_D(Qt3DQuickWindow); |
203 | switch (d->m_cameraAspectRatioMode) { |
204 | case AutomaticAspectRatio: |
205 | connect(sender: this, signal: &QWindow::widthChanged, context: this, slot: &Qt3DQuickWindow::updateCameraAspectRatio); |
206 | connect(sender: this, signal: &QWindow::heightChanged, context: this, slot: &Qt3DQuickWindow::updateCameraAspectRatio); |
207 | // Update the aspect ratio the first time the surface is set |
208 | updateCameraAspectRatio(); |
209 | break; |
210 | case UserAspectRatio: |
211 | disconnect(sender: this, signal: &QWindow::widthChanged, receiver: this, slot: &Qt3DQuickWindow::updateCameraAspectRatio); |
212 | disconnect(sender: this, signal: &QWindow::heightChanged, receiver: this, slot: &Qt3DQuickWindow::updateCameraAspectRatio); |
213 | break; |
214 | } |
215 | } |
216 | |
217 | void Qt3DQuickWindow::() |
218 | { |
219 | Q_D(Qt3DQuickWindow); |
220 | if (d->m_camera) { |
221 | d->m_camera->setAspectRatio(static_cast<float>(width()) / |
222 | std::max(a: 1.f, b: static_cast<float>(height()))); |
223 | } |
224 | } |
225 | |
226 | } // Quick |
227 | |
228 | } // Qt3DExtras |
229 | |
230 | QT_END_NAMESPACE |
231 | |
232 | #include "moc_qt3dquickwindow.cpp" |
233 | #include "qt3dquickwindow.moc" |
234 | |