1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2017 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt3D module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL3$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at http://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPLv3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or later as published by the Free |
28 | ** Software Foundation and appearing in the file LICENSE.GPL included in |
29 | ** the packaging of this file. Please review the following information to |
30 | ** ensure the GNU General Public License version 2.0 requirements will be |
31 | ** met: http://www.gnu.org/licenses/gpl-2.0.html. |
32 | ** |
33 | ** $QT_END_LICENSE$ |
34 | ** |
35 | ****************************************************************************/ |
36 | |
37 | #include "qscene2d.h" |
38 | #include "qscene2d_p.h" |
39 | #include <private/qrenderaspect_p.h> |
40 | #include "scene2d_p.h" |
41 | #include "scene2dmanager_p.h" |
42 | #include "scene2devent_p.h" |
43 | |
44 | #include <Qt3DCore/qentity.h> |
45 | |
46 | QT_BEGIN_NAMESPACE |
47 | |
48 | using namespace Qt3DCore; |
49 | |
50 | namespace Qt3DRender { |
51 | |
52 | namespace Quick { |
53 | |
54 | /*! |
55 | \namespace Qt3DRender::Quick |
56 | \inmodule Qt3DScene2D |
57 | \brief Internal namespace to import QML types. |
58 | */ |
59 | |
60 | /*! |
61 | \class Qt3DRender::Quick::QScene2D |
62 | \inheaderfile Qt3DQuickScene2D/QScene2D |
63 | \inmodule Qt3DScene2D |
64 | |
65 | \brief This class enables rendering qml into a texture, which then can be |
66 | used as a part of 3D scene. |
67 | |
68 | This class uses QQuickRenderControl to render the given QQuickItem into an |
69 | offscreen surface, which is attached to a texture provided by the user. This allows the |
70 | component to directly render into the texture without intermediate copy and the user to |
71 | freely specify how the texture is used in the 3D scene. |
72 | |
73 | The entities using the QScene2D can be associated with the class to enable interaction |
74 | with the item; if an entity has a QObjectPicker component, the pick events from that picker |
75 | are sent to the QScene2D and converted to mouse events and finally sent to the item. |
76 | |
77 | \note Only mouse events are supported. The item does not support keyboard input. |
78 | |
79 | \since 5.9 |
80 | */ |
81 | |
82 | /*! |
83 | \qmltype Scene2D |
84 | \inqmlmodule QtQuick.Scene2D |
85 | \since 5.9 |
86 | \instantiates Qt3DRender::Quick::QScene2D |
87 | |
88 | \brief This type enables rendering qml into a texture, which then can be |
89 | used as a part of 3D scene. |
90 | |
91 | This object uses RenderControl to render the given Item into an |
92 | offscreen surface, which is attached to a texture provided by the user. This allows the |
93 | component to directly render into the texture without intermediate copy and the user to |
94 | freely specify how the texture is used in the 3D scene. |
95 | |
96 | The entities using the Scene2D can be associated with the type to enable interaction |
97 | with the item; if an entity has an ObjectPicker component, the pick events from that picker |
98 | are sent to the Scene2D and converted to mouse events and finally sent to the item. |
99 | |
100 | \note Only mouse events are supported. The item does not support keyboard input. |
101 | |
102 | Usage: |
103 | \qml |
104 | Entity { |
105 | id: sceneRoot |
106 | |
107 | // specify Scene2D inside the entity hierarchy |
108 | Scene2D { |
109 | // specify output |
110 | output: RenderTargetOutput { |
111 | attachmentPoint: RenderTargetOutput.Color0 |
112 | texture: Texture2D { |
113 | id: textureId |
114 | width: 1024 |
115 | height: 1024 |
116 | format: Texture.RGBA8_UNorm |
117 | } |
118 | } |
119 | // specify entities |
120 | entities: [entityId] |
121 | |
122 | // specify rendered content |
123 | Rectangle { |
124 | color: "red" |
125 | } |
126 | } |
127 | |
128 | Entity { |
129 | id: entityId |
130 | |
131 | property Material material: TextureMaterial { |
132 | texture: textureId |
133 | } |
134 | property ObjectPicker picker: ObjectPicker { |
135 | hoverEnabled: true |
136 | dragEnabled: true |
137 | } |
138 | ... |
139 | |
140 | \endqml |
141 | */ |
142 | |
143 | /*! |
144 | \enum QScene2D::RenderPolicy |
145 | |
146 | This enum type describes types of render policies available. |
147 | \value Continuous The Scene2D is rendering continuously. This is the default render policy. |
148 | \value SingleShot The Scene2D renders to the texture only once after which the resources |
149 | allocated for rendering are released. |
150 | */ |
151 | |
152 | /*! |
153 | \qmlproperty RenderTargetOutput Qt3D.Render::Scene2D::output |
154 | Holds the RenderTargetOutput, which specifies where the Scene2D is rendering to. |
155 | */ |
156 | |
157 | /*! |
158 | \qmlproperty enumeration Qt3D.Render::Scene2D::renderPolicy |
159 | Holds the render policy of this Scene2D. |
160 | |
161 | \list |
162 | \li Continuous The Scene2D is rendering continuously. This is the default render policy. |
163 | \li SingleShot The Scene2D renders to the texture only once after which the resources |
164 | allocated for rendering are released. |
165 | \endlist |
166 | */ |
167 | /*! |
168 | \qmlproperty Item Qt3D.Render::Scene2D::item |
169 | Holds the Item, which is rendered by Scene2D to the texture. |
170 | */ |
171 | |
172 | /*! |
173 | \qmlproperty bool Qt3D.Render::Scene2D::mouseEnabled |
174 | Holds whether mouse events are enabled for the rendered item. The mouse events are |
175 | generated from object picking events of the entities added to the Scene2D. |
176 | Mouse is enabled by default. |
177 | |
178 | \note Events sent to items are delayed by one frame due to object picking |
179 | happening in the backend. |
180 | */ |
181 | /*! |
182 | \qmlproperty list<Entity> Qt3D.Render::Scene2D::entities |
183 | Holds the list of entities which are associated with the Scene2D object. If the |
184 | entities have ObjectPicker, the pick events from that entity are sent to Scene2D |
185 | and converted to mouse events. |
186 | */ |
187 | |
188 | QScene2DPrivate::QScene2DPrivate() |
189 | : Qt3DCore::QNodePrivate() |
190 | , m_renderManager(new Scene2DManager(this)) |
191 | , m_output(nullptr) |
192 | { |
193 | } |
194 | |
195 | QScene2DPrivate::~QScene2DPrivate() |
196 | { |
197 | m_renderManager->cleanup(); |
198 | delete m_renderManager; |
199 | } |
200 | |
201 | |
202 | /*! |
203 | The constructor creates a new QScene2D instance with the specified \a parent. |
204 | */ |
205 | QScene2D::QScene2D(Qt3DCore::QNode *parent) |
206 | : Qt3DCore::QNode(*new QScene2DPrivate, parent) |
207 | { |
208 | #ifdef QT_STATIC |
209 | static bool isInitialized = false; |
210 | if (!isInitialized) { |
211 | Qt3DRender::QRenderAspectPrivate::configurePlugin(QLatin1String("scene2d" )); |
212 | } |
213 | #endif |
214 | } |
215 | |
216 | /*! |
217 | \property QScene2D::item |
218 | Holds the QQuickItem, which is rendered by QScene2D to the texture. |
219 | */ |
220 | QQuickItem* QScene2D::item() const |
221 | { |
222 | Q_D(const QScene2D); |
223 | return d->m_renderManager->m_item; |
224 | } |
225 | |
226 | void QScene2D::setItem(QQuickItem *item) |
227 | { |
228 | Q_D(QScene2D); |
229 | if (d->m_renderManager->m_initialized) { |
230 | qWarning() << "Unable to set item after initialization." ; |
231 | return; |
232 | } |
233 | if (d->m_renderManager->m_item != item) { |
234 | d->m_renderManager->setItem(item); |
235 | emit itemChanged(item); |
236 | } |
237 | } |
238 | |
239 | /*! |
240 | \property QScene2D::renderPolicy |
241 | |
242 | Holds the render policy of this Scene2D. |
243 | */ |
244 | QScene2D::RenderPolicy QScene2D::renderPolicy() const |
245 | { |
246 | Q_D(const QScene2D); |
247 | return d->m_renderManager->m_renderPolicy; |
248 | } |
249 | |
250 | void QScene2D::setRenderPolicy(QScene2D::RenderPolicy renderPolicy) |
251 | { |
252 | Q_D(const QScene2D); |
253 | if (d->m_renderManager->m_renderPolicy != renderPolicy) { |
254 | d->m_renderManager->m_renderPolicy = renderPolicy; |
255 | emit renderPolicyChanged(policy: renderPolicy); |
256 | } |
257 | } |
258 | |
259 | /*! |
260 | \property QScene2D::output |
261 | Holds the QRenderTargetOutput, which specifies where the QScene2D is |
262 | rendering to. |
263 | */ |
264 | Qt3DRender::QRenderTargetOutput *QScene2D::output() const |
265 | { |
266 | Q_D(const QScene2D); |
267 | return d->m_output; |
268 | } |
269 | |
270 | void QScene2D::setOutput(Qt3DRender::QRenderTargetOutput *output) |
271 | { |
272 | Q_D(QScene2D); |
273 | if (d->m_output != output) { |
274 | if (d->m_output) |
275 | d->unregisterDestructionHelper(node: d->m_output); |
276 | d->m_output = output; |
277 | if (output) |
278 | d->registerDestructionHelper(node: output, func: &QScene2D::setOutput, d->m_output); |
279 | emit outputChanged(output); |
280 | } |
281 | } |
282 | |
283 | Qt3DCore::QNodeCreatedChangeBasePtr QScene2D::createNodeCreationChange() const |
284 | { |
285 | auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QScene2DData>::create(arguments: this); |
286 | auto &data = creationChange->data; |
287 | Q_D(const QScene2D); |
288 | data.renderPolicy = d->m_renderManager->m_renderPolicy; |
289 | data.sharedObject = d->m_renderManager->m_sharedObject; |
290 | data.output = d->m_output ? d->m_output->id() : Qt3DCore::QNodeId(); |
291 | for (Qt3DCore::QEntity *e : d->m_entities) |
292 | data.entityIds.append(t: e->id()); |
293 | data.mouseEnabled = d->m_renderManager->m_mouseEnabled; |
294 | return creationChange; |
295 | } |
296 | |
297 | bool QScene2D::isMouseEnabled() const |
298 | { |
299 | Q_D(const QScene2D); |
300 | return d->m_renderManager->m_mouseEnabled; |
301 | } |
302 | |
303 | /*! |
304 | Retrieve entities associated with the QScene2D. |
305 | */ |
306 | QVector<Qt3DCore::QEntity*> QScene2D::entities() |
307 | { |
308 | Q_D(const QScene2D); |
309 | return d->m_entities; |
310 | } |
311 | |
312 | /*! |
313 | Retrieve entities associated with the QScene2D. |
314 | */ |
315 | QVector<Qt3DCore::QEntity*> QScene2D::entities() const |
316 | { |
317 | Q_D(const QScene2D); |
318 | return d->m_entities; |
319 | } |
320 | |
321 | /*! |
322 | Adds an \a entity to the the QScene2D object. If the entities have QObjectPicker, |
323 | the pick events from that entity are sent to QScene2D and converted to mouse events. |
324 | */ |
325 | void QScene2D::addEntity(Qt3DCore::QEntity *entity) |
326 | { |
327 | Q_D(QScene2D); |
328 | if (!d->m_entities.contains(t: entity)) { |
329 | d->m_entities.append(t: entity); |
330 | |
331 | d->registerDestructionHelper(node: entity, func: &QScene2D::removeEntity, d->m_entities); |
332 | d->updateNode(node: entity, property: "entities" , change: PropertyValueAdded); |
333 | } |
334 | } |
335 | |
336 | /*! |
337 | Removes an \a entity from the the QScene2D object. |
338 | */ |
339 | void QScene2D::removeEntity(Qt3DCore::QEntity *entity) |
340 | { |
341 | Q_D(QScene2D); |
342 | if (d->m_entities.contains(t: entity)) { |
343 | d->m_entities.removeAll(t: entity); |
344 | |
345 | d->unregisterDestructionHelper(node: entity); |
346 | d->updateNode(node: entity, property: "entities" , change: PropertyValueRemoved); |
347 | } |
348 | } |
349 | |
350 | /*! |
351 | \property QScene2D::mouseEnabled |
352 | Holds whether mouse events are enabled for the rendered item. The mouse events are |
353 | generated from object picking events of the entities added to the QScene2D. |
354 | Mouse is enabled by default. |
355 | |
356 | \note Events are delayed by one frame due to object picking happening in the backend. |
357 | */ |
358 | void QScene2D::setMouseEnabled(bool enabled) |
359 | { |
360 | Q_D(QScene2D); |
361 | if (d->m_renderManager->m_mouseEnabled != enabled) { |
362 | d->m_renderManager->m_mouseEnabled = enabled; |
363 | emit mouseEnabledChanged(enabled); |
364 | } |
365 | } |
366 | |
367 | |
368 | } // namespace Quick |
369 | } // namespace Qt3DRender |
370 | |
371 | QT_END_NAMESPACE |
372 | |