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
46QT_BEGIN_NAMESPACE
47
48using namespace Qt3DCore;
49
50namespace Qt3DRender {
51
52namespace 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
188QScene2DPrivate::QScene2DPrivate()
189 : Qt3DCore::QNodePrivate()
190 , m_renderManager(new Scene2DManager(this))
191 , m_output(nullptr)
192{
193}
194
195QScene2DPrivate::~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 */
205QScene2D::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 */
220QQuickItem* QScene2D::item() const
221{
222 Q_D(const QScene2D);
223 return d->m_renderManager->m_item;
224}
225
226void 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 */
244QScene2D::RenderPolicy QScene2D::renderPolicy() const
245{
246 Q_D(const QScene2D);
247 return d->m_renderManager->m_renderPolicy;
248}
249
250void 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 */
264Qt3DRender::QRenderTargetOutput *QScene2D::output() const
265{
266 Q_D(const QScene2D);
267 return d->m_output;
268}
269
270void 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
283Qt3DCore::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
297bool 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 */
306QVector<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 */
315QVector<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*/
325void 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*/
339void 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 */
358void 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
371QT_END_NAMESPACE
372

source code of qt3d/src/quick3d/quick3dscene2d/items/qscene2d.cpp