summaryrefslogtreecommitdiffstats
path: root/src/runtime/doc/src/scenecppapi.qdoc
blob: 4c0b6225f5f2beeb8d7864ec48686e210ff5f461 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt 3D Studio.
**
** $QT_BEGIN_LICENSE:FDL$
** 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 Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
    \page qt3d-runtime-scenecppapi.html
    \title Advanced Scene Manipulation via the Qt 3D Studio Runtime Private C++ Classes

    In addition to the \l {Qt 3D Studio Runtime C++ Classes}}{public C++ API},
    applications needing direct access to the scenegraph of the presentations
    loaded from \c{.uip} files can use the runtime's private C++ classes.

    \note These classes offer no source or binary compatibility guarantees.

    \note There is no documentation provided for the private classes. Refer to
    the examples, this page, and the header files instead.

    To link against the module, add this line to your \l qmake \c .pro file:

    \badcode
    QT += 3dstudioruntime2-private
    \endcode

    Then add the following include statement to the application sources:

    \badcode
        #include <private/q3dsengine_p.h>
        #include <private/q3dsuippresentation_p.h>
    \endcode

    To access the Q3DSEngine instance, call Q3DSPresentation::engine(). This
    applies also to Qt Quick applications: the Presentation item in the QML
    code is an instance of a subclass of Q3DSPresentation, so once it gets
    passed to C++ code, it can be used as a Q3DSPresentation. Accessing the
    engine is only possible when a presentation is loaded. If the code needing
    access to the scene is not invoked by some user interaction but rather has
    to be done at startup, connect the execution of the C++ logic to a signal
    like Studio3D::presentationLoaded().

    Check out the \l{Qt 3D Studio Runtime: Dynamic Scene Manipulation C++
    Example}{scenemanip example} for a demonstration of manipulating the Qt 3D
    Studio scene from C++ in a Qt Quick application.

    The next step is to get access to the Qt 3D Studio object tree. Query the
    Q3DSUipPresentation via Q3DSEngine::presentation(). There is a separate
    object tree for each subpresentation. Q3DSEngine::presentationCount()
    allows iterating through all of them:

    \badcode
        int presentationCount() const;
        Q3DSUipPresentation *presentation(int index = 0) const;
        Q3DSUipPresentation *presentationByName(const QString &name) const;
    \endcode

    The Q3DSUipPresentation instance owns two object trees: one for the scene
    (that maps mostly 1:1 to the scene, layer, camera, light, model, etc. tree
    in the left side of the Timline in the Qt 3D Studio editor) and one for the
    slides.

    To access these, use the following accessors:

    \badcode
        Q3DSScene *scene() const;
        Q3DSSlide *masterSlide() const;
    \endcode

    Support for dynamically manipulating the slide structure is limited as of
    now. Certain related operations, like adding or removing animation tracks
    at runtime is also limited for the time being. For the rest of this
    document, we will focus on the scene itself.

    The scenegraph is quite similar to the Qt Quick scenegraph and QSGNode when
    it comes to the management of child and sibling nodes. Adding and removing
    child nodes happens using a very similar API. The equivalent of QSGNode in
    the Qt 3D Studio world is Q3DSGraphObject. For application purposes the
    most important member functions are:

    \badcode
        Type type() const
        Q3DSGraphObject *parent() const
        Q3DSGraphObject *firstChild() const
        Q3DSGraphObject *lastChild() const
        Q3DSGraphObject *nextSibling() const
        Q3DSGraphObject *previousSibling() const
        int childCount() const;
        Q3DSGraphObject *childAtIndex(int idx) const;
        void removeChildNode(Q3DSGraphObject *node);
        void removeAllChildNodes();
        void prependChildNode(Q3DSGraphObject *node);
        void appendChildNode(Q3DSGraphObject *node);
        void insertChildNodeBefore(Q3DSGraphObject *node, Q3DSGraphObject *before);
        void insertChildNodeAfter(Q3DSGraphObject *node, Q3DSGraphObject *after);
        void reparentChildNodesTo(Q3DSGraphObject *newParent);

        virtual void applyPropertyChanges(const Q3DSPropertyChangeList &changeList);
        void notifyPropertyChanges(const Q3DSPropertyChangeList &changeList, int changeFlags = -1);

        QVector<QByteArray> propertyNames() const;
        QVector<QVariant> propertyValues() const;

        QVariant property(const char *name);
        bool setProperty(const char *name, const QVariant &v);
        QVector<QByteArray> dynamicPropertyNames() const;
        QVector<QVariant> dynamicPropertyValues() const;

        QVariantMap dynamicProperties() const;
        void clearDynamicProperties();
        Q3DSPropertyChangeList applyDynamicProperties(const QVariantMap &v);
    \endcode

    Q3DSLayerNode, Q3DSCameraNode, Q3DSLightNode, Q3DSModelNode, Q3DSGroupNode,
    Q3DSTextNode are all subclasses of Q3DSNode which in turn is a
    Q3DSGraphObject. The common base (Q3DSNode) provides common properties like
    the transformation (position, rotation, scale).

    To change a property at runtime, first find out the correct name for the
    property from the \l {Attribute Names}{Scene Object Attribute List}.

    Then do either

    \badcode
        node->notifyPropertyChanges({ node->setPosition(QVector3D(1.0f, 0.5f, 3.0f)) });
    \endcode

    or

    \badcode
        Q3DSPropertyChangeList cl { Q3DSPropertyChange::fromVariant("position", QVector3D(1.0f, 0.5f, 3.0f) };
        node->applyPropertyChanges(cl);
        node->notifyPropertyChanges(cl);
    \endcode

    The former is more efficient, while the latter allows constructing change
    lists dynamically with the property names given as strings instead of
    having to call C++ setter functions.

    To get access to an object, for example, the Q3DSModelNode corresponding to
    a Model in the editor, use the Q3DSUipPresentation's object() or
    objectByName() functions. The latter is more useful for applications since
    it works based on the Name (that is defined by the designer in the editor),
    while the former uses the object id that is unique, but invisible to the
    designer in the editor.

    \note Names do not have to be unique. This can cause confusion because some
    names the editor assigns by default are shared between multiple objects. To
    prevent this, rename the objects in the tree view to something unique.

    \badcode
        auto car = presentation->objectByName<Q3DSModelNode>(QLatin1String("FancySportsCar"));
    \endcode

    Besides changing properties, adding or removing objects at runtime is also
    possible. This will lead to the corresponding graphics objects appearing or
    disappearing. For example, to spawn a new model object with the built-in
    cube as its mesh:

    \badcode
        Q3DSModelNode *cube = presentation->newObject<Q3DSModelNode>(QByteArrayLiteral("newCube"));
        cube->setMesh(QLatin1String("#Cube"));
        Q3DSDefaultMaterial *cubeMat = presentation->newObject<Q3DSDefaultMaterial>(QByteArrayLiteral("cubeMaterial"));
        cube->appendChildNode(cubeMat);
        group->appendChildNode(cube);
    \endcode

    appendChildNode() takes ownership and inserts the given object in the
    parent's child list. This is similar to QObject::setParent() but note that
    QSGNode and Q3DSGraphObject are more powerful since they allow not just
    appending but also inserting at arbitrary positions in the child list.

    When a newly created object gets added to a parent that itself is already
    part of a hierarchy under a Q3DSScene, the object becomes active, which
    triggers creating the graphics and 3D resources that are necessary to
    render the object in the associated layer's texture. In the above example
    this point is the last appendChildNode() call, assuming \c group is an
    object already parented into a live Q3DSScene tree.

    To properly disconnect an object from the scene, use
    Q3DSUipPresentation::unlinkObject():

    \badcode
        presentation->unlinkObject(cube);
        delete cube;
    \endcode

    Due to the unlinkObject() call, the cube will disappear from the screen.
    Note that the Q3DSDefaultMaterial child object is unlinked and destroyed as
    well, just like a child QObject is destroyed together with its parent.

    Being part of the scenegraph is not enough to get displayed, however. The
    concept of slides has a great effect on visibility as well. To associate a
    newly created object with a slide, call Q3DSSlide::addObject(). For
    example, assuming the \c{.uip} file loaded has one slide under the master
    slide:

    \badcode
        Q3DSSlide *slide = static_cast<Q3DSSlide *>(presentation->masterSlide()->firstChild());
        slide->addObject(cubeMat);
        slide->addObject(cube);
    \endcode

    The children of the new object have to be managed manually here, hence the
    separate addObject(cubeMat) call. It is not required that all descendants
    of an object belong to the same slide as the object.

    When removing objects, make sure to disconnect them from the slide as well.
    To do this recursively for all objects in the subtree that is about to
    removed, one can do the following:

    \badcode
        Q3DSUipPresentation::forAllObjectsInSubTree(cube, [slide](Q3DSGraphObject *obj) {
            slide->removeObject(obj);
        });
    \endcode

    There are many more possibilities with the Q3DSGraphObject API. Refer to
    the header files for more insight. It is worth nothing that it is also
    possible to build Qt 3D Studio scenes completely from C++, without using
    any \c{.uip} files. Check the demo application under
    \c{tests/manual/standalone} in the runtime's source tree for an example of
    creating and managing interactive scenes this way. It is also a good
    example for performing advanced tasks via the private API, like reacting on
    input events, providing custom mesh data, and dynamically generating
    texture maps.
*/