summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2018-05-18 10:33:28 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2018-05-18 10:33:34 +0200
commit8bb3378d0d7c82eb1896ac043570ddab7c2edae9 (patch)
treef3fe8bce8b4df108c1cc9766fdbafea95c3bd490
parent78ab305d5ca59a158232a8b47070ef35ae803033 (diff)
parent186e8bf9ec08b1aca289a23b93290bf4cd5521fe (diff)
Merge remote-tracking branch 'origin/2.0'
-rw-r--r--examples/3dstudioruntime2/qmldatainput/doc/images/qmldatainput.pngbin0 -> 163178 bytes
-rw-r--r--examples/3dstudioruntime2/qmldatainput/doc/src/qmldatainput.qdoc55
-rw-r--r--examples/3dstudioruntime2/qmldatainput/presentation/Paper05.pngbin0 -> 321820 bytes
-rw-r--r--examples/3dstudioruntime2/qmldatainput/presentation/datainput.uip22
-rw-r--r--examples/3dstudioruntime2/qmldatainput/qml/qmldatainput/main.qml4
-rw-r--r--examples/3dstudioruntime2/qmldatainput/qmldatainput.qrc1
-rw-r--r--examples/3dstudioruntime2/simpleoffscreen/doc/images/simpleoffscreen.pngbin0 -> 273228 bytes
-rw-r--r--examples/3dstudioruntime2/simpleoffscreen/doc/src/simpleoffscreen.qdoc47
-rw-r--r--examples/3dstudioruntime2/simpleqml/doc/images/simpleqml.pngbin0 -> 312906 bytes
-rw-r--r--examples/3dstudioruntime2/simpleqml/doc/src/simpleqml.qdoc51
-rw-r--r--examples/3dstudioruntime2/simpleqml/main.cpp4
-rw-r--r--examples/3dstudioruntime2/simpleqml/main.qml32
-rw-r--r--examples/3dstudioruntime2/simpleqml/presentation/barrel.uia1
-rw-r--r--examples/3dstudioruntime2/simpleqml/presentation/barrel.uip3
-rw-r--r--examples/3dstudioruntime2/simplewidget/doc/images/simplewidget.pngbin0 -> 233143 bytes
-rw-r--r--examples/3dstudioruntime2/simplewidget/doc/src/simplewidget.qdoc48
-rw-r--r--examples/3dstudioruntime2/simplewidget/main.cpp12
-rw-r--r--examples/3dstudioruntime2/simplewidget/presentation/SampleProject.uia16
-rw-r--r--examples/3dstudioruntime2/simplewidget/presentation/SampleProject.uip77
-rw-r--r--examples/3dstudioruntime2/simplewidget/presentation/maps/materials/shadow.pngbin0 -> 334 bytes
-rw-r--r--examples/3dstudioruntime2/simplewidget/presentation/maps/materials/spherical_checker.pngbin0 -> 11066 bytes
-rw-r--r--examples/3dstudioruntime2/simplewidget/presentation/materials/simple_glass.material197
-rw-r--r--examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/Speedometer.import39
-rw-r--r--examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/maps/Speed.pngbin0 -> 485677 bytes
-rw-r--r--examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/meshes/NeedleSpeed.meshbin0 -> 10880 bytes
-rw-r--r--examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/meshes/Speedometer.meshbin0 -> 484416 bytes
-rw-r--r--examples/3dstudioruntime2/simplewidget/simplewidget.qrc16
-rw-r--r--examples/3dstudioruntime2/simplewindow/doc/images/simplewindow.pngbin0 -> 246472 bytes
-rw-r--r--examples/3dstudioruntime2/simplewindow/doc/src/simplewindow.qdoc51
-rw-r--r--examples/3dstudioruntime2/simplewindow/main.cpp12
-rw-r--r--src/doc/doc.pro8
-rw-r--r--src/doc/qt3d-runtime-project.qdocconf55
-rw-r--r--src/doc/style/qt5-sidebar.html13
-rw-r--r--src/imports/studio3d/q3dsstudio3ditem.cpp88
-rw-r--r--src/imports/studio3d/q3dssubpresentationsettings.cpp82
-rw-r--r--src/runtime/api/q3dsdatainput.cpp87
-rw-r--r--src/runtime/api/q3dsdatainput.h1
-rw-r--r--src/runtime/api/q3dselement.cpp138
-rw-r--r--src/runtime/api/q3dselement.h1
-rw-r--r--src/runtime/api/q3dspresentation.cpp356
-rw-r--r--src/runtime/api/q3dssceneelement.cpp214
-rw-r--r--src/runtime/api/q3dssceneelement.h1
-rw-r--r--src/runtime/api/q3dssurfaceviewer.cpp139
-rw-r--r--src/runtime/api/q3dsviewersettings.cpp51
-rw-r--r--src/runtime/api/q3dswidget.cpp53
-rw-r--r--src/runtime/behaviorapi/q3dsbehaviorobject.cpp166
-rw-r--r--src/runtime/doc/doc.pri6
-rw-r--r--src/runtime/doc/online/qt3dstudioruntime2.qdocconf (renamed from src/doc/online/Qt3DStudioRuntime2.qdocconf)0
-rw-r--r--src/runtime/doc/qt3d-runtime-project.qdocconf61
-rw-r--r--src/runtime/doc/qt3dstudioruntime2.qdocconf (renamed from src/doc/Qt3DStudioRuntime2.qdocconf)0
-rw-r--r--src/runtime/doc/src/attributenames.html911
-rw-r--r--src/runtime/doc/src/attributenames.qdoc71
-rw-r--r--src/runtime/doc/src/copyright.qdoc (renamed from src/doc/src/copyright.qdoc)0
-rw-r--r--src/runtime/doc/src/embedded.qdoc (renamed from src/doc/src/embedded.qdoc)1
-rw-r--r--src/runtime/doc/src/examples.qdoc (renamed from src/doc/src/examples.qdoc)21
-rw-r--r--src/runtime/doc/src/gettingstarted.qdoc107
-rw-r--r--src/runtime/doc/src/images/intro-app.pngbin0 -> 368639 bytes
-rw-r--r--src/runtime/doc/src/images/intro-editor.pngbin0 -> 289164 bytes
-rw-r--r--src/runtime/doc/src/images/intro-viewer-profile.pngbin0 -> 697498 bytes
-rw-r--r--src/runtime/doc/src/images/intro-viewer.pngbin0 -> 508715 bytes
-rw-r--r--src/runtime/doc/src/index.qdoc (renamed from src/doc/src/index.qdoc)13
-rw-r--r--src/runtime/doc/src/mobile.qdoc (renamed from src/doc/src/mobile.qdoc)1
-rw-r--r--src/runtime/doc/src/module.qdoc (renamed from src/doc/src/module.qdoc)0
-rw-r--r--src/runtime/doc/src/requirements.qdoc108
-rw-r--r--src/runtime/doc/src/toc.qdoc (renamed from src/doc/src/gettingstarted.qdoc)13
-rw-r--r--src/runtime/doc/style/qt5-sidebar.html28
-rw-r--r--src/runtime/q3dsanimationmanager.cpp19
-rw-r--r--src/runtime/q3dsanimationmanager_p.h3
-rw-r--r--src/runtime/q3dsengine.cpp108
-rw-r--r--src/runtime/q3dsengine_p.h1
-rw-r--r--src/runtime/q3dsgraphexplorer.cpp2
-rw-r--r--src/runtime/q3dsruntimeglobal_p.h4
-rw-r--r--src/runtime/q3dsscenemanager.cpp121
-rw-r--r--src/runtime/q3dsscenemanager_p.h5
-rw-r--r--src/runtime/q3dsslideplayer.cpp283
-rw-r--r--src/runtime/q3dsslideplayer_p.h3
-rw-r--r--src/runtime/q3dsuippresentation.cpp8
-rw-r--r--src/runtime/q3dsuippresentation_p.h10
-rw-r--r--src/runtime/runtime.pro2
-rw-r--r--src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp73
-rw-r--r--src/src.pro3
-rw-r--r--tests/auto/behaviors/tst_q3dsbehaviors.cpp2
-rw-r--r--tests/auto/documents/tst_q3dsdocuments.cpp2
-rw-r--r--tests/auto/q3dslancelot/scenegrabber/main.cpp2
-rw-r--r--tests/auto/slideplayer/tst_q3dsslideplayer.cpp2
-rw-r--r--tests/auto/slides/tst_q3dsslides.cpp2
-rw-r--r--tests/manual/qt3dsexplorer/main.cpp2
-rw-r--r--tools/q3dsviewer/main.cpp22
-rw-r--r--tools/q3dsviewer/q3dsmainwindow.cpp8
89 files changed, 3689 insertions, 480 deletions
diff --git a/examples/3dstudioruntime2/qmldatainput/doc/images/qmldatainput.png b/examples/3dstudioruntime2/qmldatainput/doc/images/qmldatainput.png
new file mode 100644
index 0000000..e0567ee
--- /dev/null
+++ b/examples/3dstudioruntime2/qmldatainput/doc/images/qmldatainput.png
Binary files differ
diff --git a/examples/3dstudioruntime2/qmldatainput/doc/src/qmldatainput.qdoc b/examples/3dstudioruntime2/qmldatainput/doc/src/qmldatainput.qdoc
new file mode 100644
index 0000000..58e6ae5
--- /dev/null
+++ b/examples/3dstudioruntime2/qmldatainput/doc/src/qmldatainput.qdoc
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the 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$
+**
+****************************************************************************/
+
+/*!
+ \example qmldatainput
+ \title Qt 3D Studio Runtime: QML DataInput Example
+ \ingroup qt3dstudioruntime2-examples-qml
+ \brief Demonstrates using DataInput elements in QML
+
+ \image qmldatainput.png
+
+ \e {This example demonstrates using DataInput elements with QML in Studio}
+
+ \include examples-run.qdocinc
+
+ \section1 Description
+
+ The presentation consists of a static text element serving as a label and a rotating text
+ element for showing the input data as text. There is also a data input of type \e{Ranged Number}
+ in the presentation. This data input is used to control both the rotation animation time and
+ the text shown on the second text element.
+ The range is specified as [0 .. 360] in the presentation, where zero maps
+ to the beginning of the animation and 360 maps to the end of the animation.
+
+ The \l {qmldatainput/qml/qmldatainput/main.qml}{qml main} loads the presentation and animates
+ a number property. The value of the animated property is bound to the
+ \l{DataInput::value}{value} property of the DataInput element, making the value show up in the
+ linked text element in the presentation. The same value is used to control the animation time:
+
+ \snippet qmldatainput/qml/qmldatainput/main.qml 1
+*/
diff --git a/examples/3dstudioruntime2/qmldatainput/presentation/Paper05.png b/examples/3dstudioruntime2/qmldatainput/presentation/Paper05.png
new file mode 100644
index 0000000..e70749d
--- /dev/null
+++ b/examples/3dstudioruntime2/qmldatainput/presentation/Paper05.png
Binary files differ
diff --git a/examples/3dstudioruntime2/qmldatainput/presentation/datainput.uip b/examples/3dstudioruntime2/qmldatainput/presentation/datainput.uip
index 6b47e44..901e994 100644
--- a/examples/3dstudioruntime2/qmldatainput/presentation/datainput.uip
+++ b/examples/3dstudioruntime2/qmldatainput/presentation/datainput.uip
@@ -24,16 +24,21 @@
</Model>
<Text id="Text3" />
<Text id="Text4" />
+ <Model id="Rectangle" >
+ <Material id="Default_001" name="Default" >
+ <Image id="Default_001_diffusemap" />
+ </Material>
+ </Model>
</Layer>
</Scene>
</Graph>
<Logic >
<State name="Master Slide" component="#Scene" >
- <Add ref="#Layer" multisampleaa="None" progressiveaa="4x" temporalaa="True" />
- <Add ref="#Camera" controlledproperty="$cameraRotInput rotation" pivot="0 0 0" rotation="0 0 0" />
- <Add ref="#Light" castshadow="True" controlledproperty="$colorInput lightdiffuse" lightdiffuse="1 0 0" position="-350.984 -229.258 -30" />
+ <Add ref="#Layer" multisampleaa="SSAA" progressiveaa="8x" />
+ <Add ref="#Camera" controlledproperty="$cameraRotInput rotation" pivot="0 0 0" position="0 0 -800" rotation="0 0 0" />
+ <Add ref="#Light" castshadow="True" controlledproperty="$colorInput lightdiffuse" lightdiffuse="1 0 0" lighttype="Point" position="-300.444 70.829 -30" shdwfactor="11.89" shdwfilter="6.94" shdwmapres="11" />
<State id="Scene-Slide1" name="Slide1" initialplaystate="Pause" >
- <Add ref="#Text" name="Text" font="TitilliumWeb-Regular" position="216.513 76.6172 -113.498" scale="1 1 1" size="24" textstring="0" >
+ <Add ref="#Text" name="Text" controlledproperty="$stringInput textstring" font="TitilliumWeb-Regular" position="216.513 76.6172 -113.498" scale="1 1 1" size="24" textstring="0" >
<AnimationTrack property="rotation.x" type="EaseInOut" >0 0 0 0 10 0 0 0</AnimationTrack>
<AnimationTrack property="rotation.y" type="EaseInOut" >0 0 0 0 10 0 0 0</AnimationTrack>
<AnimationTrack property="rotation.z" type="EaseInOut" >0 0 0 0 10 -360 0 0</AnimationTrack>
@@ -42,13 +47,16 @@
<Add ref="#Cone" name="Cone" controlledproperty="$scaleInput scale" position="-417.135 -225.166 0" sourcepath="#Cone" />
<Add ref="#Default" />
<Add ref="#Cylinder" name="Cylinder" controlledproperty="$variantInput opacity" position="131.347 -180.422 0" sourcepath="#Cylinder" />
- <Add ref="#Default_002" />
+ <Add ref="#Default_002" diffuse="0.666667 1 0.498039" />
<Add ref="#Text6" name="Text6" font="TitilliumWeb-Regular" position="135.678 -300.019 -8.28656" size="16" textstring="Opacity control&#10;(Variant type)" />
<Add ref="#Text8" name="Text8" font="TitilliumWeb-Regular" position="-428.683 -290.118 0" size="16" textstring="Scale control" />
- <Add ref="#Cube2" name="Cube2" controlledproperty="$vec3Input rotation" position="409.919 -177.535 0" sourcepath="#Cube" />
+ <Add ref="#Cube2" name="Cube2" controlledproperty="$cameraRotInput rotation" position="409.919 -177.535 0" sourcepath="#Cube" />
<Add ref="#Default_003" controlledproperty="$vec3Input2 diffuse" />
<Add ref="#Text3" name="Text3" font="TitilliumWeb-Regular" position="434.456 -304.552 0" size="16" textstring="Rotation control&#10;Diffuse color control" />
- <Add ref="#Text4" name="Text4" font="TitilliumWeb-Regular" position="-381.051 290.118 0" size="18" textstring="Directional light color and Camera xy &#10;rotation controlled via Datainput" />
+ <Add ref="#Text4" name="Text4" font="TitilliumWeb-Regular" position="-381.051 290.118 0" size="18" textstring="Directional light color control&#10;Camera xy rotation control" />
+ <Add ref="#Rectangle" name="Rectangle" position="0 -400 20" rotation="90.5 0 0" scale="11.0468 7.99191 9.12813" sourcepath="#Rectangle" />
+ <Add ref="#Default_001" diffuse="0.623529 0.623529 0.623529" diffusemap="#Default_001_diffusemap" />
+ <Add ref="#Default_001_diffusemap" sourcepath="Paper05.png" />
</State>
</State>
</Logic>
diff --git a/examples/3dstudioruntime2/qmldatainput/qml/qmldatainput/main.qml b/examples/3dstudioruntime2/qmldatainput/qml/qmldatainput/main.qml
index ef7d0e7..c0757e2 100644
--- a/examples/3dstudioruntime2/qmldatainput/qml/qmldatainput/main.qml
+++ b/examples/3dstudioruntime2/qmldatainput/qml/qmldatainput/main.qml
@@ -83,14 +83,14 @@ Item {
property: "inputScaleVec3"
duration: 12000
from: Qt.vector3d(0.3, 0.5, 0.5)
- to: Qt.vector3d(1.0, 1.0, 1.0)
+ to: Qt.vector3d(4.0, 4.0, 1.0)
loops: Animation.Infinite
running: true
}
Vector3dAnimation {
target: studio3D
property: "inputColorVec3"
- duration: 2000
+ duration: 6000
from: Qt.vector3d(0.1, 0.1, 0.3)
to: Qt.vector3d(1.0, 0.5, 1.0)
loops: Animation.Infinite
diff --git a/examples/3dstudioruntime2/qmldatainput/qmldatainput.qrc b/examples/3dstudioruntime2/qmldatainput/qmldatainput.qrc
index 6fb7388..97aaeaa 100644
--- a/examples/3dstudioruntime2/qmldatainput/qmldatainput.qrc
+++ b/examples/3dstudioruntime2/qmldatainput/qmldatainput.qrc
@@ -3,5 +3,6 @@
<file>qml/qmldatainput/main.qml</file>
<file>presentation/datainput.uia</file>
<file>presentation/datainput.uip</file>
+ <file>presentation/Paper05.png</file>
</qresource>
</RCC>
diff --git a/examples/3dstudioruntime2/simpleoffscreen/doc/images/simpleoffscreen.png b/examples/3dstudioruntime2/simpleoffscreen/doc/images/simpleoffscreen.png
new file mode 100644
index 0000000..f406b3a
--- /dev/null
+++ b/examples/3dstudioruntime2/simpleoffscreen/doc/images/simpleoffscreen.png
Binary files differ
diff --git a/examples/3dstudioruntime2/simpleoffscreen/doc/src/simpleoffscreen.qdoc b/examples/3dstudioruntime2/simpleoffscreen/doc/src/simpleoffscreen.qdoc
new file mode 100644
index 0000000..ecc0da8
--- /dev/null
+++ b/examples/3dstudioruntime2/simpleoffscreen/doc/src/simpleoffscreen.qdoc
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the 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$
+**
+****************************************************************************/
+
+/*!
+ \example simpleoffscreen
+ \title Qt 3D Studio Runtime: Simple Offscreen Example
+ \ingroup qt3dstudioruntime2-examples-cpp
+ \brief Demonstrates using the Q3DSSurfaceViewer class render frames into image files
+
+ \image simpleoffscreen.png
+
+ \e {This example demonstrates offscreen usage of the Q3DSSurfaceViewer class}
+
+ \include examples-run.qdocinc
+
+ \section1 Description
+
+ In this example there is no on-screen user interface. Instead, an
+ OpenGL framebuffer object is created. With the help of a
+ QOffscreenSurface the Qt 3D Studio presentation is rendered into
+ the OpenGL texture. The contents is then read back into a QImage
+ and saved into image files.
+*/
diff --git a/examples/3dstudioruntime2/simpleqml/doc/images/simpleqml.png b/examples/3dstudioruntime2/simpleqml/doc/images/simpleqml.png
new file mode 100644
index 0000000..a22b467
--- /dev/null
+++ b/examples/3dstudioruntime2/simpleqml/doc/images/simpleqml.png
Binary files differ
diff --git a/examples/3dstudioruntime2/simpleqml/doc/src/simpleqml.qdoc b/examples/3dstudioruntime2/simpleqml/doc/src/simpleqml.qdoc
new file mode 100644
index 0000000..dfd0f16
--- /dev/null
+++ b/examples/3dstudioruntime2/simpleqml/doc/src/simpleqml.qdoc
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the 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$
+**
+****************************************************************************/
+
+/*!
+ \example simpleqml
+ \title Qt 3D Studio Runtime: Simple QML Example
+ \ingroup qt3dstudioruntime2-examples-qml
+ \brief Demonstrates using the Studio3D element in a Qt Quick application
+
+ \image simpleqml.png
+
+ \e {This example demonstrates basic usage of the Studio3D element in Qt Quick applications}
+
+ \include examples-run.qdocinc
+
+ \section1 Description
+
+ This example consists of a simple C++ main() function that sets up
+ a QQuickView and a QML scene demonstrating the usage of the \l
+ Studio3D, \l Presentation, \l DataInput, \l SceneElement, and \l
+ Element QML types.
+
+ Besides displaying the presentation designed in the Qt 3D Studio
+ application, a few simple cases of interacting with the scene
+ (such as, changing 3D object properties via data input, changing
+ slides, controlling the timeline) are also demonstrated.
+*/
diff --git a/examples/3dstudioruntime2/simpleqml/main.cpp b/examples/3dstudioruntime2/simpleqml/main.cpp
index 897b59a..a0a3de3 100644
--- a/examples/3dstudioruntime2/simpleqml/main.cpp
+++ b/examples/3dstudioruntime2/simpleqml/main.cpp
@@ -56,6 +56,10 @@ int main(int argc, char *argv[])
{
qputenv("QSG_INFO", "1");
QApplication app(argc, argv);
+
+ // Use the ideal format (i.e. OpenGL version and profile) recommended by
+ // the Qt 3D Studio runtime. Without this the format set on the QQuickView
+ // would be used instead.
QSurfaceFormat::setDefaultFormat(Q3DS::surfaceFormat());
QQuickView viewer;
diff --git a/examples/3dstudioruntime2/simpleqml/main.qml b/examples/3dstudioruntime2/simpleqml/main.qml
index 4d47a47..0490a5a 100644
--- a/examples/3dstudioruntime2/simpleqml/main.qml
+++ b/examples/3dstudioruntime2/simpleqml/main.qml
@@ -98,33 +98,6 @@ Rectangle {
id: barrelRef
elementPath: "Barrel" // or Scene.Layer.Barrel but as long as it's unique the name's good enough
}
-
- // Let's try out a QML subpresentation defined in-line, i.e. no separate .qml file.
- SubPresentationSettings {
- qmlStreams: [
- QmlStream {
- presentationId: "embeddedQmlScene"
- Rectangle {
- color: "white"
- Rectangle {
- color: "red"
- width: parent.width * 0.8
- height: parent.height * 0.8
- anchors.centerIn: parent
- Text {
- anchors.centerIn: parent
- text: "Hello from\nembedded Qt Quick"
- color: "white"
- }
- NumberAnimation on rotation {
- from: 0; to: 360; duration: 10000
- loops: Animation.Infinite
- }
- }
- }
- }
- ]
- }
}
ignoredEvents: mouseEvCb.checked ? Studio3D.EnableAllEvents : (Studio3D.IgnoreMouseEvents | Studio3D.IgnoreWheelEvents)
onRunningChanged: console.log("running: " + s3d.running)
@@ -214,11 +187,6 @@ Rectangle {
focusPolicy: Qt.NoFocus
}
Button {
- text: "Fire event"
- onClicked: s3dpres.fireEvent("Scene.Layer.Camera", "customCameraEvent") // in actionevent.uip this will change the sphere's color
- focusPolicy: Qt.NoFocus
- }
- Button {
text: "Toggle camera"
onClicked: {
var v = s3dpres.getAttribute("Scene.Layer.Camera", "eyeball")
diff --git a/examples/3dstudioruntime2/simpleqml/presentation/barrel.uia b/examples/3dstudioruntime2/simpleqml/presentation/barrel.uia
index 71d8e26..d936e42 100644
--- a/examples/3dstudioruntime2/simpleqml/presentation/barrel.uia
+++ b/examples/3dstudioruntime2/simpleqml/presentation/barrel.uia
@@ -3,7 +3,6 @@
<assets initial="barrel">
<dataInput name="di_text" type="String"/>
<presentation id="barrel" src="barrel.uip"/>
- <presentation-qml id="embeddedQmlScene" args="dummy"/>
</assets>
<statemachine ref="#logic">
<visual-states>
diff --git a/examples/3dstudioruntime2/simpleqml/presentation/barrel.uip b/examples/3dstudioruntime2/simpleqml/presentation/barrel.uip
index 66b40c2..9299f39 100644
--- a/examples/3dstudioruntime2/simpleqml/presentation/barrel.uip
+++ b/examples/3dstudioruntime2/simpleqml/presentation/barrel.uip
@@ -6,7 +6,6 @@
</ProjectSettings>
<Graph >
<Scene id="Scene" >
- <Layer id="splayer" />
<Layer id="Layer" >
<Camera id="Camera" />
<Light id="Light" />
@@ -25,10 +24,10 @@
</Graph>
<Logic >
<State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
<Add ref="#Camera" />
<Add ref="#Light" />
<State id="Scene-Slide1" name="Slide1" playmode="Looping" >
- <Add ref="#splayer" name="splayer" height="30" sourcepath="embeddedQmlScene" top="50" width="30" />
<Add ref="#Barrel" name="Barrel" position="0 -42 -483" rotation="90 0 0" scale="100 100 100" sourcepath=".\barrel\meshes\Barrel.mesh#1" >
<AnimationTrack property="opacity" type="EaseInOut" />
<AnimationTrack property="rotation.x" type="EaseInOut" >0 90 100 100 5 64 100 100 10 90 100 100</AnimationTrack>
diff --git a/examples/3dstudioruntime2/simplewidget/doc/images/simplewidget.png b/examples/3dstudioruntime2/simplewidget/doc/images/simplewidget.png
new file mode 100644
index 0000000..a975c73
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewidget/doc/images/simplewidget.png
Binary files differ
diff --git a/examples/3dstudioruntime2/simplewidget/doc/src/simplewidget.qdoc b/examples/3dstudioruntime2/simplewidget/doc/src/simplewidget.qdoc
new file mode 100644
index 0000000..ab02d59
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewidget/doc/src/simplewidget.qdoc
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the 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$
+**
+****************************************************************************/
+
+/*!
+ \example simplewidget
+ \title Qt 3D Studio Runtime: Simple Widget Example
+ \ingroup qt3dstudioruntime2-examples-cpp
+ \brief Demonstrates using the Q3DSWidget widget in a Qt C++ application
+
+ \image simplewidget.png
+
+ \e {This example demonstrates basic usage of the Q3DSWidget class}
+
+ \include examples-run.qdocinc
+
+ \section1 Description
+
+ This example consists of a simple widget UI that includes a
+ Q3DSWidget. This QOpenGLWidget subclass displays and controls Qt
+ 3D Studio presentations. Changing the value of a text node via
+ data input, basic error handling, and the means of reloading or
+ opening presentations, as well as toggling the in-scene profiling
+ pane are also demonstrated.
+*/
diff --git a/examples/3dstudioruntime2/simplewidget/main.cpp b/examples/3dstudioruntime2/simplewidget/main.cpp
index 50b3fac..6d02374 100644
--- a/examples/3dstudioruntime2/simplewidget/main.cpp
+++ b/examples/3dstudioruntime2/simplewidget/main.cpp
@@ -59,7 +59,6 @@
#include <q3dsruntimeglobal.h>
#include <Q3DSWidget>
#include <Q3DSPresentation>
-#include <Q3DSDataInput>
int main(int argc, char *argv[])
{
@@ -81,17 +80,8 @@ int main(int argc, char *argv[])
QMessageBox::critical(&w, QLatin1String("Failed to load presentation"), msg, QLatin1String("Ok"));
});
- // The presentation has a data input entry "di_text" for the textstring
- // property of one of the Text nodes. Provide a custom value. Do this in a
- // manner so that the value is set even when doing a Reload or changing the
- // presentation object's source.
- Q3DSDataInput dataInput(w3DS->presentation(), QLatin1String("di_text"));
- QObject::connect(w3DS, &Q3DSWidget::presentationLoaded, w3DS, [&dataInput] {
- dataInput.setValue(QLatin1String("Hello world"));
- });
-
w3DS->presentation()->setProfilingEnabled(true);
- w3DS->presentation()->setSource(QUrl(QLatin1String("qrc:/barrel.uip")));
+ w3DS->presentation()->setSource(QUrl(QLatin1String("qrc:/presentation/SampleProject.uia")));
layout->addWidget(w3DS);
QPushButton *openBtn = new QPushButton(QLatin1String("Open"));
diff --git a/examples/3dstudioruntime2/simplewidget/presentation/SampleProject.uia b/examples/3dstudioruntime2/simplewidget/presentation/SampleProject.uia
new file mode 100644
index 0000000..d59165e
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewidget/presentation/SampleProject.uia
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application xmlns="http://qt.io/qt3dstudio/uia">
+ <assets initial="SampleProject">
+ <presentation id="SampleProject" src="SampleProject.uip"/>
+ </assets>
+
+ <statemachine ref="#logic">
+ <visual-states>
+ <state ref="Initial">
+ <enter>
+ <goto-slide element="main:Scene" rel="next"/>
+ </enter>
+ </state>
+ </visual-states>
+ </statemachine>
+</application>
diff --git a/examples/3dstudioruntime2/simplewidget/presentation/SampleProject.uip b/examples/3dstudioruntime2/simplewidget/presentation/SampleProject.uip
new file mode 100644
index 0000000..4c1325e
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewidget/presentation/SampleProject.uip
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="800" maintainAspect="True" >
+ <CustomColors count="16" >#ff5500 #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors>
+ </ProjectSettings>
+ <Classes >
+ <CustomMaterial id="simple_glass" name="simple_glass" sourcepath="materials/simple_glass.material" />
+ </Classes>
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer2" >
+ <Camera id="Camera_001" />
+ <Light id="Light_001" />
+ <Model id="NeedleSpeed_001" name="NeedleSpeed" importid="NeedleSpeed" orientation="Right Handed" position="0 0 -0" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="models/Speedometer/meshes/NeedleSpeed.mesh" >
+ <Material id="NeedleBlack_002" name="NeedleBlack" blendmode="Normal" diffuse="0 0 0" emissivepower="0" importid="NeedleBlack" opacity="100" specularamount="0" specularroughness="9.41177" />
+ <Material id="NeedleWhite_002" />
+ </Model>
+ </Layer>
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Group id="Speedometer" importid="__import__root__" >
+ <Group id="Group_Speedometer_Master" name="Group_Speedometer_Master" importid="Group_Speedometer_Master" orientation="Right Handed" position="0 0 -0" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" >
+ <Model id="Speedometer_001" name="Speedometer" importid="Speedometer" orientation="Right Handed" position="0 0 -0" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="models/Speedometer/meshes/Speedometer.mesh" >
+ <CustomMaterial id="BaseMetal" class="#simple_glass" />
+ <ReferencedMaterial id="HighLight" />
+ <Material id="NeedleWhite_001" name="NeedleWhite" blendmode="Normal" diffuse="0.8 0.8 0.8" emissivepower="0" importid="NeedleWhite_0005" opacity="100" specularamount="0" specularroughness="27.451" />
+ <Material id="BlackMetalRing" name="BlackMetalRing" blendmode="Normal" diffuse="0.0578313 0.0578313 0.0578313" emissivepower="0" importid="BlackMetalRing" opacity="100" specularamount="0" specularroughness="99.8039" />
+ <Material id="NeedleBlack_001" name="NeedleBlack" blendmode="Normal" diffuse="0 0 0" emissivepower="0" importid="NeedleBlack_0006" opacity="100" specularamount="0" specularroughness="9.41177" />
+ <Material id="SpeedometerBg" name="SpeedometerBg" blendmode="Normal" diffuse="1 1 1" diffusemap="#SpeedometerBg_diffusemap" emissivepower="0" importid="SpeedometerBg" opacity="100" specularamount="0" specularroughness="9.41177" >
+ <Image id="SpeedometerBg_diffusemap" name="SpeedometerBg_diffusemap" importid="SpeedometerBg_diffusemap" sourcepath="models/Speedometer/maps/Speed.png" />
+ </Material>
+ </Model>
+ </Group>
+ </Group>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" multisampleaa="SSAA" probebright="500" />
+ <Add ref="#Camera" fov="30" position="0 0 -400" />
+ <Add ref="#Light" brightness="200" lightdiffuse="1 1 1" lightspecular="0 0.666667 1" lighttype="Point" pivot="100 0 0" position="0 0 -50" >
+ <AnimationTrack property="rotation.x" type="EaseInOut" >0 0 100 100 5 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.y" type="EaseInOut" >0 0 100 100 5 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.z" type="EaseInOut" >0 45 100 100 5 -225 100 100</AnimationTrack>
+ </Add>
+ <State id="Scene-Slide1" name="Slide1" playmode="PingPong" playthroughto="Next" >
+ <Set ref="#Layer" endtime="5000" />
+ <Set ref="#Camera" endtime="5000" />
+ <Set ref="#Light" endtime="5000" />
+ <Add ref="#Layer2" name="Layer2" endtime="5000" multisampleaa="None" progressiveaa="8x" />
+ <Add ref="#Camera_001" endtime="5000" fov="30" position="0 0 -600" />
+ <Add ref="#Light_001" endtime="5000" />
+ <Add ref="#NeedleSpeed_001" name="NeedleSpeed" endtime="5000" importfile="models/Speedometer/Speedometer.import" pivot="5 5 0" >
+ <AnimationTrack property="rotation.x" type="EaseInOut" >0 0 100 100 2.13 0 0 0 5 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.y" type="EaseInOut" >0 0 100 100 2.13 0 0 0 5 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.z" type="EaseInOut" >0 0 100 100 2.13 -105.249 0 0 5 -270 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#NeedleBlack_002" diffuse="0 0.333333 1" importfile="models/Speedometer/Speedometer.import" />
+ <Add ref="#NeedleWhite_002" name="NeedleWhite" diffuse="1 1 1" specularamount="0" />
+ <Add ref="#Speedometer" name="Speedometer" endtime="5000" importfile="models/Speedometer/Speedometer.import" position="0 0 0" scale="0.7 0.7 0.7" sourcepath="models/Speedometer/Speedometer.import" />
+ <Add ref="#Group_Speedometer_Master" endtime="5000" importfile="models/Speedometer/Speedometer.import" />
+ <Add ref="#Speedometer_001" endtime="5000" importfile="models/Speedometer/Speedometer.import" />
+ <Add ref="#BaseMetal" name="BaseMetal" glass_color="0 0.333333 1" />
+ <Add ref="#HighLight" name="HighLight" endtime="5000" referencedmaterial="#BaseMetal" />
+ <Add ref="#NeedleWhite_001" importfile="models/Speedometer/Speedometer.import" />
+ <Add ref="#BlackMetalRing" diffuse="0 0.0862745 0.596078" importfile="models/Speedometer/Speedometer.import" specularamount="0" />
+ <Add ref="#NeedleBlack_001" importfile="models/Speedometer/Speedometer.import" />
+ <Add ref="#SpeedometerBg" diffuse="0.270588 0.501961 1" importfile="models/Speedometer/Speedometer.import" specularamount="0.1" specularroughness="1" speculartint="0.529412 0.772549 1" />
+ <Add ref="#SpeedometerBg_diffusemap" importfile="models/Speedometer/Speedometer.import" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/examples/3dstudioruntime2/simplewidget/presentation/maps/materials/shadow.png b/examples/3dstudioruntime2/simplewidget/presentation/maps/materials/shadow.png
new file mode 100644
index 0000000..599b1cc
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewidget/presentation/maps/materials/shadow.png
Binary files differ
diff --git a/examples/3dstudioruntime2/simplewidget/presentation/maps/materials/spherical_checker.png b/examples/3dstudioruntime2/simplewidget/presentation/maps/materials/spherical_checker.png
new file mode 100644
index 0000000..e42394d
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewidget/presentation/maps/materials/spherical_checker.png
Binary files differ
diff --git a/examples/3dstudioruntime2/simplewidget/presentation/materials/simple_glass.material b/examples/3dstudioruntime2/simplewidget/presentation/materials/simple_glass.material
new file mode 100644
index 0000000..a6b4ee0
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewidget/presentation/materials/simple_glass.material
@@ -0,0 +1,197 @@
+<Material name="simple_glass" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" description="Environment texture for the material" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" description="Enable environment mapping" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" description="Baked shadow texture for the material" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" description="Enable shadow mapping" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Fresnel Power" name="uFresnelPower" description="Fresnel power of the material" type="Float" default="1.0" category="Material"/>
+ <Property formalName="Minimum Opacity" name="uMinOpacity" description="Minimum opacity of the material" type="Float" default="0.5" category="Material"/>
+ <Property formalName="Reflectivity" name="reflectivity_amount" type="Float" min="0.000000" max="1.000000" default="1.000000" description="Reflectivity factor" category="Material"/>
+ <Property formalName="Glass ior" name="glass_ior" hidden="True" type="Float" default="1.100000" description="Index of refraction of the material" category="Material"/>
+ <Property formalName="Glass Color" name="glass_color" type="Color" default="0.9 0.9 0.9" description="Color of the material" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define QT3DS_ENABLE_UV0 1
+#define QT3DS_ENABLE_WORLD_POSITION 1
+#define QT3DS_ENABLE_TEXTAN 1
+#define QT3DS_ENABLE_BINORMAL 0
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+vec3 ftmp0;
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "abbeNumberIOR.glsllib"
+#include "fresnelLayer.glsllib"
+#include "refraction.glsllib"
+
+bool evalTwoSided()
+{
+ return( true );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if QT3DS_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.000000, 0.000000, scatter_reflect_transmit );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if QT3DS_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, 0.000000, 0.000000 );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !QT3DS_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, 0.000000, 0.000000, scatter_reflect_transmit );
+
+#else
+ layers[0].base += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, 0.000000, 0.000000 );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if QT3DS_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if QT3DS_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !QT3DS_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( true ? 1.0 : luminance( vec3( abbeNumberIOR(glass_ior, 0.000000 ) ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ ftmp0 = vec3( reflectivity_amount );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = layers[0].base * vec4( ftmp0, 1.0);
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( tangentFrame( normal, varWorldPos ) );
+}
+
+vec4 computeGlass(in vec3 normal, in float materialIOR, in float alpha, in vec4 color)
+{
+ vec4 rgba = color;
+ float ratio = simpleFresnel( normal, materialIOR, uFresnelPower );
+ vec3 absorb_color = ( log( glass_color )/-1.000000 );
+ // prevent log(0) -> inf number issue
+ if ( isinf(absorb_color.r) ) absorb_color.r = 1.0;
+ if ( isinf(absorb_color.g) ) absorb_color.g = 1.0;
+ if ( isinf(absorb_color.b) ) absorb_color.b = 1.0;
+ rgba.rgb = mix(vec3(1.0) - absorb_color, rgba.rgb * (vec3(1.0) - absorb_color), ratio);
+ rgba.a = mix(uMinOpacity, alpha, ratio);
+ return rgba;
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="36"/>
+ <LayerKey count="1"/>
+ <Pass >
+ <Blending source="SrcAlpha" dest="OneMinusSrcAlpha"/>
+ <RenderState name="CullFace"/>
+ </Pass>
+</Passes>
+</Material>
diff --git a/examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/Speedometer.import b/examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/Speedometer.import
new file mode 100644
index 0000000..d74ef62
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/Speedometer.import
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP Version="1" >
+ <Project Revision="1" >
+ <Graph >
+ <Group id="__import__root__" >
+ <Group id="Group_Speedometer_Master" name="Group_Speedometer_Master" orientation="Right Handed" position="0 0 -0" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" >
+ <Model id="NeedleSpeed" name="NeedleSpeed" orientation="Right Handed" position="0 0 -0" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="meshes/NeedleSpeed.mesh" >
+ <Material id="NeedleBlack" name="NeedleBlack" blendmode="Normal" diffuse="0 0 0" emissivepower="0" opacity="100" specularamount="0" specularroughness="9.41177" />
+ <Material id="NeedleWhite" name="NeedleWhite" blendmode="Normal" diffuse="0.8 0.8 0.8" emissivepower="0" opacity="100" specularamount="0" specularroughness="27.451" />
+ </Model>
+ <Model id="Speedometer" name="Speedometer" orientation="Right Handed" position="0 0 -0" rotation="0 -0 0" rotationorder="XYZr" scale="1 1 1" sourcepath="meshes/Speedometer.mesh" >
+ <Material id="BaseMetal" name="BaseMetal" blendmode="Normal" diffuse="0.01728 0.01728 0.01728" emissivepower="0" opacity="100" specularamount="0" specularroughness="11.3725" />
+ <Material id="HighLight" name="HighLight" blendmode="Normal" diffuse="0.298 0.54088 0.8" emissivepower="0" opacity="66.8675" specularamount="0" specularroughness="100" />
+ <Material id="NeedleWhite_0005" name="NeedleWhite" blendmode="Normal" diffuse="0.8 0.8 0.8" emissivepower="0" opacity="100" specularamount="0" specularroughness="27.451" />
+ <Material id="BlackMetalRing" name="BlackMetalRing" blendmode="Normal" diffuse="0.0578313 0.0578313 0.0578313" emissivepower="0" opacity="100" specularamount="0" specularroughness="99.8039" />
+ <Material id="NeedleBlack_0006" name="NeedleBlack" blendmode="Normal" diffuse="0 0 0" emissivepower="0" opacity="100" specularamount="0" specularroughness="9.41177" />
+ <Material id="SpeedometerBg" name="SpeedometerBg" blendmode="Normal" diffuse="1 1 1" diffusemap="SpeedometerBg_diffusemap" emissivepower="0" opacity="100" specularamount="0" specularroughness="9.41177" >
+ <Image id="SpeedometerBg_diffusemap" name="SpeedometerBg_diffusemap" sourcepath="maps/Speed.png" />
+ </Material>
+ </Model>
+ </Group>
+ </Group>
+ </Graph>
+ <Import SrcFile="" ImageDir="Images" MeshDir="Meshes" >
+ <Image >
+ <Source >Speed.png</Source>
+ <Dest >maps/Speed.png</Dest>
+ </Image>
+ <Mesh >
+ <Source >Speedometer</Source>
+ <Dest >meshes/Speedometer.mesh</Dest>
+ </Mesh>
+ <Mesh >
+ <Source >NeedleSpeed</Source>
+ <Dest >meshes/NeedleSpeed.mesh</Dest>
+ </Mesh>
+ </Import>
+ </Project>
+</UIP>
diff --git a/examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/maps/Speed.png b/examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/maps/Speed.png
new file mode 100644
index 0000000..84b7e4d
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/maps/Speed.png
Binary files differ
diff --git a/examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/meshes/NeedleSpeed.mesh b/examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/meshes/NeedleSpeed.mesh
new file mode 100644
index 0000000..72220cd
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/meshes/NeedleSpeed.mesh
Binary files differ
diff --git a/examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/meshes/Speedometer.mesh b/examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/meshes/Speedometer.mesh
new file mode 100644
index 0000000..9f7ba34
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewidget/presentation/models/Speedometer/meshes/Speedometer.mesh
Binary files differ
diff --git a/examples/3dstudioruntime2/simplewidget/simplewidget.qrc b/examples/3dstudioruntime2/simplewidget/simplewidget.qrc
index e9b7006..3f6f2fa 100644
--- a/examples/3dstudioruntime2/simplewidget/simplewidget.qrc
+++ b/examples/3dstudioruntime2/simplewidget/simplewidget.qrc
@@ -1,12 +1,12 @@
<RCC>
<qresource prefix="/">
- <file alias="barrel.uia">../simpleqml/presentation/barrel.uia</file>
- <file alias="barrel.uip">../simpleqml/presentation/barrel.uip</file>
- <file alias="barrel/meshes/Barrel.mesh">../simpleqml/presentation/barrel/meshes/Barrel.mesh</file>
- <file alias="fonts/Arimo-Regular.ttf">../simpleqml/presentation/fonts/Arimo-Regular.ttf</file>
- <file alias="maps/barrel_barrel_Diffuse.png">../simpleqml/presentation/maps/barrel_barrel_Diffuse.png</file>
- <file alias="maps/barrel_barrel_Emissive.png">../simpleqml/presentation/maps/barrel_barrel_Emissive.png</file>
- <file alias="maps/barrel_barrel_Normal.png">../simpleqml/presentation/maps/barrel_barrel_Normal.png</file>
- <file alias="maps/barrel_barrel_Specular.png">../simpleqml/presentation/maps/barrel_barrel_Specular.png</file>
+ <file>presentation/SampleProject.uia</file>
+ <file>presentation/SampleProject.uip</file>
+ <file>presentation/maps/materials/spherical_checker.png</file>
+ <file>presentation/maps/materials/shadow.png</file>
+ <file>presentation/materials/simple_glass.material</file>
+ <file>presentation/models/Speedometer/maps/Speed.png</file>
+ <file>presentation/models/Speedometer/meshes/Speedometer.mesh</file>
+ <file>presentation/models/Speedometer/meshes/NeedleSpeed.mesh</file>
</qresource>
</RCC>
diff --git a/examples/3dstudioruntime2/simplewindow/doc/images/simplewindow.png b/examples/3dstudioruntime2/simplewindow/doc/images/simplewindow.png
new file mode 100644
index 0000000..37550c7
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewindow/doc/images/simplewindow.png
Binary files differ
diff --git a/examples/3dstudioruntime2/simplewindow/doc/src/simplewindow.qdoc b/examples/3dstudioruntime2/simplewindow/doc/src/simplewindow.qdoc
new file mode 100644
index 0000000..b00bc3e
--- /dev/null
+++ b/examples/3dstudioruntime2/simplewindow/doc/src/simplewindow.qdoc
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the 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$
+**
+****************************************************************************/
+
+/*!
+ \example simplewindow
+ \title Qt 3D Studio Runtime: Simple Window Example
+ \ingroup qt3dstudioruntime2-examples-cpp
+ \brief Demonstrates using the Q3DSSurfaceViewer class in order to render in a QWindow
+
+ \image simplewindow.png
+
+ \e {This example demonstrates basic usage of the Q3DSSurfaceViewer class}
+
+ \include examples-run.qdocinc
+
+ \section1 Description
+
+ This example consists of an OpenGL-based QWindow. The contents is
+ provided by a Q3DSSurfaceViewer instance by loading up a simple Qt
+ 3D Studio presentation.
+
+ When targeting a QWindow, the application can choose whether it
+ wants to be in control of updates (i.e. manually requesting the
+ next frame by calling Q3DSSurfaceViewer::update()). By passing
+ the \c{--multi} command-line argument the example demonstrates
+ both types of usages.
+*/
diff --git a/examples/3dstudioruntime2/simplewindow/main.cpp b/examples/3dstudioruntime2/simplewindow/main.cpp
index 15796b4..3fea28b 100644
--- a/examples/3dstudioruntime2/simplewindow/main.cpp
+++ b/examples/3dstudioruntime2/simplewindow/main.cpp
@@ -80,13 +80,13 @@ int main(int argc, char *argv[])
});
// The presentation has a data input entry "di_text" for the textstring
- // property of one of the Text nodes. Provide a custom value.
+ // property of one of the Text nodes. Provide a custom value. Do this in a
+ // manner so that the value is set even when doing a Reload or changing the
+ // presentation object's source.
Q3DSDataInput dataInput(viewer.presentation(), QLatin1String("di_text"));
- // Assuming the source is never changed or reloaded, a plain setValue()
- // call is good enough. Otherwise, we would need to connect to the
- // presentationLoaded() signal and set the value whenever a new
- // presentation is loaded.
- dataInput.setValue(QLatin1String("Hello world"));
+ QObject::connect(&viewer, &Q3DSSurfaceViewer::presentationLoaded, &viewer, [&dataInput] {
+ dataInput.setValue(QLatin1String("Hello world"));
+ });
viewer.presentation()->setSource(QUrl(QLatin1String("qrc:/barrel.uip")));
viewer.create(&w, w.context());
diff --git a/src/doc/doc.pro b/src/doc/doc.pro
deleted file mode 100644
index eba9ea3..0000000
--- a/src/doc/doc.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-TEMPLATE = aux
-
-build_online_docs: \
- QMAKE_DOCS = $$PWD/online/Qt3DStudioRuntime2.qdocconf
-else: \
- QMAKE_DOCS = $$PWD/Qt3DStudioRuntime2.qdocconf
-
-OTHER_FILES += $$PWD/src/*.qdoc
diff --git a/src/doc/qt3d-runtime-project.qdocconf b/src/doc/qt3d-runtime-project.qdocconf
deleted file mode 100644
index 1c69bf4..0000000
--- a/src/doc/qt3d-runtime-project.qdocconf
+++ /dev/null
@@ -1,55 +0,0 @@
-project = Qt3DStudioRuntime2
-description = Qt 3D Studio Runtime Reference Manual
-version = $QT_VERSION
-
-sourcedirs += ./src
-imagedirs += ./src/images
-
-sourcedirs += ../runtime/api
-headerdirs += ../runtime/api
-
-sourcedirs += ../imports/studio3d
-headerdirs += ../imports/studio3d
-
-depends = qtcore qtgui qtwidgets qtqml qtquick qtdoc qt3dcore qt3drender qt3dlogic qt3danimation
-
-qhp.projects = 3dstudioruntime2
-
-qhp.3dstudioruntime2.file = Qt3DStudioRuntime2.qhp
-qhp.3dstudioruntime2.namespace = io.qt.qt3dstudioruntime2.$QT_VERSION_TAG
-qhp.3dstudioruntime2.virtualFolder = Qt3DStudioRuntime2
-qhp.3dstudioruntime2.indexTitle = Qt 3D Studio Runtime
-qhp.3dstudioruntime2.indexRoot =
-
-qhp.3dstudioruntime2.filterAttributes = Qt3DStudioRuntime2 $QT_VERSION
-qhp.3dstudioruntime2.customFilters.Qt.name = Qt3DStudioRuntime2 $QT_VERSION
-qhp.3dstudioruntime2.customFilters.Qt.filterAttributes = Qt3DStudioRuntime2 $QT_VERSION
-
-qhp.3dstudioruntime2.subprojects = manual qmltypes classes
-
-qhp.3dstudioruntime2.subprojects.manual.title = Qt 3D Studio Runtime
-qhp.3dstudioruntime2.subprojects.manual.indexTitle = Qt 3D Studio Runtime TOC
-qhp.3dstudioruntime2.subprojects.manual.type = manual
-
-qhp.3dstudioruntime2.subprojects.qmltypes.title = QML Types
-qhp.3dstudioruntime2.subprojects.qmltypes.indexTitle = Qt 3D Studio Runtime QML Types
-qhp.3dstudioruntime2.subprojects.qmltypes.selectors = qmltype
-qhp.3dstudioruntime2.subprojects.qmltypes.sortPages = true
-
-qhp.3dstudioruntime2.subprojects.classes.title = C++ Classes
-qhp.3dstudioruntime2.subprojects.classes.indexTitle = Qt 3D Studio Runtime C++ Classes
-qhp.3dstudioruntime2.subprojects.classes.selectors = class fake:headerfile
-qhp.3dstudioruntime2.subprojects.classes.sortPages = true
-
-# Add an .html file with sidebar content, used in the online style
-HTML.stylesheets += style/qt5-sidebar.html
-
-navigation.homepage = Qt 3D Studio Runtime
-navigation.cppclassespage = Qt 3D Studio Runtime C++ Classes
-navigation.qmltypespage = Qt 3D Studio Runtime QML Types
-buildversion = "Qt 3D Studio Runtime $QT_VER Manual"
-
-examplesinstallpath = 3dstudioruntime2
-exampledirs += ../../examples/3dstudioruntime2
-
-Cpp.ignoretokens += Q3DSV_EXPORT
diff --git a/src/doc/style/qt5-sidebar.html b/src/doc/style/qt5-sidebar.html
deleted file mode 100644
index 89b8c0d..0000000
--- a/src/doc/style/qt5-sidebar.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<div class="sectionlist normallist">
- <div class="heading">
- <a name="reference"></a>
- <h2 id="reference">Qt 3D Studio Runtime</h2>
- </div>
- <div class="indexboxcont indexboxbar">
- <ul>
- <li><a href="getting-started.html">Getting Started</a></li>
- <li><a href="qt3dstudio-studio.html">Studio</a></li>
- <li><a href="qtstudio3d-qml-examples.html">Examples</a></li>
- <li><a href="copyright-notices.html">Copyright Notices</a></li>
- </ul>
- </div>
diff --git a/src/imports/studio3d/q3dsstudio3ditem.cpp b/src/imports/studio3d/q3dsstudio3ditem.cpp
index 2326d1f..b585122 100644
--- a/src/imports/studio3d/q3dsstudio3ditem.cpp
+++ b/src/imports/studio3d/q3dsstudio3ditem.cpp
@@ -58,9 +58,67 @@ QT_BEGIN_NAMESPACE
\inqmlmodule QtStudio3D
\ingroup 3dstudioruntime2
\inherits Item
- \brief blah
- blah
+ \brief Qt 3D Studio presentation viewer.
+
+ This type enables developers to embed Qt 3D Studio presentations in Qt
+ Quick.
+
+ \section2 Example usage
+
+ \qml
+ Studio3D {
+ id: studio3D
+ Presentation {
+ source: "qrc:///presentation.uia"
+ SceneElement {
+ id: scene
+ elementPath: "Scene"
+ currentSlideIndex: 2
+ }
+ Element {
+ id: textLabel
+ elementPath: "Scene.Layer.myLabel"
+ }
+ }
+ ViewerSettings {
+ showRenderStats: true
+ }
+ onRunningChanged: {
+ console.log("Presentation ready!");
+ }
+ }
+ \endqml
+*/
+
+/*!
+ \qmlsignal Studio3D::frameUpdate()
+
+ This signal is emitted each time a frame has been updated regardless of
+ visibility. This allows a hidden Studio3D element to still process
+ information every frame, even though the renderer is not rendering.
+
+ The corresponding handler is \c onFrameUpdate.
+
+ To prevent expensive handlers from being processed when hidden, add an
+ early return to the top like:
+
+ \qml
+ onFrameUpdate: {
+ if (!visible) return;
+ ...
+ }
+ \endqml
+*/
+
+/*!
+ \qmlsignal Studio3D::presentationReady()
+
+ This signal is emitted when the viewer has been initialized and the
+ presentation is ready to be shown. The difference to \c running property is
+ that the viewer has to be visible for \c running to get \c{true}. This
+ signal is useful for displaying splash screen while viewer is getting
+ initialized.
*/
static bool engineCleanerRegistered = false;
@@ -94,11 +152,30 @@ Q3DSStudio3DItem::~Q3DSStudio3DItem()
{
}
+/*!
+ \qmlproperty Presentation Studio3D::presentation
+
+ Accessor for the presentation. Applications are expected to create a single
+ Presentation child object for Studio3D. If this is omitted, a presentation
+ is created automatically.
+
+ This property is read-only.
+*/
+
Q3DSPresentationItem *Q3DSStudio3DItem::presentation() const
{
return m_presentation;
}
+/*!
+ \qmlproperty bool Studio3D::running
+
+ The value of this property is \c true when the viewer has been initialized
+ and the presentation is running.
+
+ This property is read-only.
+*/
+
bool Q3DSStudio3DItem::isRunning() const
{
return m_running;
@@ -214,6 +291,13 @@ void Q3DSStudio3DItem::createEngine()
return;
}
+ const QSurfaceFormat wformat = w->format();
+ const QSurfaceFormat eformat = Q3DS::surfaceFormat();
+ if (wformat.version() != eformat.version() || wformat.profile() != eformat.profile()) {
+ qCDebug(lcStudio3D) << "Adopting surface format from QQuickWindow:" << wformat;
+ Q3DS::adoptSurfaceFormat(wformat);
+ }
+
m_engine = new Q3DSEngine;
engineTracker.insert(m_engine);
diff --git a/src/imports/studio3d/q3dssubpresentationsettings.cpp b/src/imports/studio3d/q3dssubpresentationsettings.cpp
index 0eabd1f..e8ffcea 100644
--- a/src/imports/studio3d/q3dssubpresentationsettings.cpp
+++ b/src/imports/studio3d/q3dssubpresentationsettings.cpp
@@ -47,4 +47,86 @@ QQmlListProperty<Q3DSInlineQmlSubPresentation> Q3DSSubPresentationSettings::qmlS
return QQmlListProperty<Q3DSInlineQmlSubPresentation>(this, m_list);
}
+/*!
+ \qmltype SubPresentationSettings
+ \inqmlmodule QtStudio3D
+ \ingroup 3dstudioruntime2
+ \brief Settings for sub-presentations.
+
+ This type enables specifying a QML sub-presentation directly in the QML.
+
+ A QML sub-presentation is a Qt Quick scene that is rendered to a texture
+ and then used either as the contents of Qt 3D Studio layer or as a texture
+ map. The contents of such a sub-presentation can be provided in two ways:
+ by a separate \c{.qml} file, or directly under the Studio3D element.
+ SubPresentationSettings is the enabler for the latter.
+
+ \section2 Usage
+
+ \qml
+ Studio3D {
+ id: studio3D
+ Presentation {
+ source: "file:///presentation.uia"
+ SubPresentationSettings {
+ qmlStreams: [
+ QmlStream {
+ presentationId: "sub-presentation-id"
+ Item {
+ width: 1024
+ height: 1024
+ // ... other Qt Quick items
+ }
+ }
+ ]
+ }
+ }
+ }
+ \endqml
+ */
+
+/*!
+ \qmlproperty list<QmlStream> SubPresentationSettings::qmlStreams
+
+ Holds the list of QmlStream children.
+ */
+
+/*!
+ \qmltype QmlStream
+ \inqmlmodule QtStudio3D
+ \ingroup 3dstudioruntime2
+ \brief QML stream.
+
+ This type allows attaching QML sub-presentation with a quick item. The item is rendered to a
+ texture and used as a part of a Qt 3D Studio presentation.
+
+ The sub-presentation element must be specified in the \e assets element of the presentation
+ .uia file:
+
+ \badcode
+ <assets ...>
+ <presentation-qml id="presentation-id" args="preview-presentation.qml" />
+ </assets>
+ \endcode
+
+ The \c presentation-id attribute must contain a unique ID of the sub-presentation.
+ The \c args attribute may contain an optional preview version of the item, which is only
+ used in the Viewer application.
+ */
+
+/*!
+ \qmlproperty string QmlStream::presentationId
+
+ Holds the string ID of the sub-presentation the item is attached to. The id must be one of
+ the \c presentation-qml IDs specified in the .uia file.
+ */
+
+/*!
+ \qmlproperty Item QmlStream::item
+
+ Holds the item attached to the sub-presentation. The item size is used as the the size of the
+ texture the item is rendered to. Default values \c{(256, 256)} are used if the item doesn't
+ specify a size.
+ */
+
QT_END_NAMESPACE
diff --git a/src/runtime/api/q3dsdatainput.cpp b/src/runtime/api/q3dsdatainput.cpp
index 9341c04..69cafe3 100644
--- a/src/runtime/api/q3dsdatainput.cpp
+++ b/src/runtime/api/q3dsdatainput.cpp
@@ -32,18 +32,31 @@
QT_BEGIN_NAMESPACE
-Q3DSDataInput::Q3DSDataInput(QObject *parent)
- : QObject(*new Q3DSDataInputPrivate, parent)
-{
-}
+/*!
+ \class Q3DSDataInput
+ \inmodule 3dstudioruntime2
+ \since Qt 3D Studio 2.0
+
+ \brief Controls a data input entry in a Qt 3D Studio presentation.
+
+ This class is a convenience class for controlling a data input in a presentation.
-Q3DSDataInput::Q3DSDataInput(const QString &name, QObject *parent)
+ \sa Q3DSPresentation
+*/
+
+/*!
+ \internal
+ */
+Q3DSDataInput::Q3DSDataInput(QObject *parent)
: QObject(*new Q3DSDataInputPrivate, parent)
{
- Q_D(Q3DSDataInput);
- d->name = name;
}
+/*!
+ Constructs a Q3DSDataInput instance and initializes the \a name. The
+ constructed instance is automatically associated with the specified \a
+ presentation. An optional \a parent object can be specified.
+ */
Q3DSDataInput::Q3DSDataInput(Q3DSPresentation *presentation, const QString &name, QObject *parent)
: QObject(*new Q3DSDataInputPrivate, parent)
{
@@ -52,15 +65,29 @@ Q3DSDataInput::Q3DSDataInput(Q3DSPresentation *presentation, const QString &name
d->presentation = presentation;
}
+/*!
+ \internal
+ */
Q3DSDataInput::Q3DSDataInput(Q3DSDataInputPrivate &dd, QObject *parent)
: QObject(dd, parent)
{
}
+/*!
+ Destructor.
+ */
Q3DSDataInput::~Q3DSDataInput()
{
}
+/*!
+ \property Q3DSDataInput::name
+
+ Specifies the name of the controlled data input element in the
+ presentation. This property must be set before setting the value property.
+ The initial value is provided via the constructor in practice, but the name
+ can also be changed later on, if desired.
+ */
QString Q3DSDataInput::name() const
{
Q_D(const Q3DSDataInput);
@@ -76,6 +103,19 @@ void Q3DSDataInput::setName(const QString &name)
}
}
+/*!
+ \property Q3DSDataInput::value
+
+ Specifies the value of the controlled data input element in the
+ presentation.
+
+ The value of this property only accounts for changes done via the same
+ Q3DSDataInput instance. If the value of the same data input in the
+ presentation is changed elsewhere, for example via presentation scripting,
+ those changes are not reflected in the value of this property. Due to this
+ uncertainty, this property treats all value sets as changes even if the
+ newly set value is the same value as the previous value.
+*/
QVariant Q3DSDataInput::value() const
{
Q_D(const Q3DSDataInput);
@@ -104,4 +144,37 @@ void Q3DSDataInputPrivate::sendValue()
presentation->setDataInputValue(name, value);
}
+/*!
+ \qmltype DataInput
+ \instantiates Q3DSDataInput
+ \inqmlmodule QtStudio3D
+ \ingroup 3dstudioruntime2
+ \brief Control type for data inputs in a Qt 3D Studio presentation.
+
+ This type is a convenience type for controlling a data input in a presentation.
+
+ \sa Studio3D, Presentation
+*/
+
+/*!
+ \qmlproperty string DataInput::name
+
+ Specifies the name of the controlled data input element in the presentation.
+ This property must be set as part of DataInput declaration.
+*/
+
+/*!
+ \qmlproperty variant DataInput::value
+
+ Specifies the value of the controlled data input element in the presentation.
+ The changes to the value property are queued and handled asynchronously before the
+ next frame is displayed.
+
+ The value of this property only accounts for changes done via the same DataInput instance.
+ If the value of the same data input in the presentation is changed elsewhere,
+ for example via presentation scripting, those changes are not reflected in
+ the value of this property. Due to this uncertainty, this property treats all value sets as
+ changes even if the newly set value is the same value as the previous value.
+*/
+
QT_END_NAMESPACE
diff --git a/src/runtime/api/q3dsdatainput.h b/src/runtime/api/q3dsdatainput.h
index e685f78..c869c9e 100644
--- a/src/runtime/api/q3dsdatainput.h
+++ b/src/runtime/api/q3dsdatainput.h
@@ -52,7 +52,6 @@ class Q3DSV_EXPORT Q3DSDataInput : public QObject
public:
explicit Q3DSDataInput(QObject *parent = nullptr);
- explicit Q3DSDataInput(const QString &name, QObject *parent = nullptr);
Q3DSDataInput(Q3DSPresentation *presentation, const QString &name, QObject *parent = nullptr);
~Q3DSDataInput();
diff --git a/src/runtime/api/q3dselement.cpp b/src/runtime/api/q3dselement.cpp
index ae119ae..3e72e83 100644
--- a/src/runtime/api/q3dselement.cpp
+++ b/src/runtime/api/q3dselement.cpp
@@ -32,18 +32,38 @@
QT_BEGIN_NAMESPACE
+/*!
+ \class Q3DSElement
+ \inmodule 3dstudioruntime2
+ \since Qt 3D Studio 2.0
+
+ \brief Controls a scene object in a Qt 3D Studio presentation.
+
+ This class is a convenience class for controlling the properties of a scene
+ object (such as, model, material, camera, layer) in a Qt 3D Studio
+ presentation.
+
+ \note The functionality of Q3DSElement is equivalent to
+ Q3DSPresentation::setAttribute(), Q3DSPresentation::getAttribute(), and
+ Q3DSPresentation::fireEvent().
+
+ \sa Q3DSPresentation, Q3DSWidget, Q3DSSurfaceViewer, Q3DSSceneElement
+ */
+
+/*!
+ \internal
+ */
Q3DSElement::Q3DSElement(QObject *parent)
: QObject(*new Q3DSElementPrivate, parent)
{
}
-Q3DSElement::Q3DSElement(const QString &elementPath, QObject *parent)
- : QObject(*new Q3DSElementPrivate, parent)
-{
- Q_D(Q3DSElement);
- d->elementPath = elementPath;
-}
-
+/*!
+ Constructs a Q3DSElement instance controlling the scene object specified by
+ \a elementPath. An optional \a parent object can be specified. The
+ constructed instance is automatically associated with the specified \a
+ presentation. An optional \a parent object can be specified.
+ */
Q3DSElement::Q3DSElement(Q3DSPresentation *presentation, const QString &elementPath, QObject *parent)
: QObject(*new Q3DSElementPrivate, parent)
{
@@ -52,15 +72,47 @@ Q3DSElement::Q3DSElement(Q3DSPresentation *presentation, const QString &elementP
d->presentation = presentation;
}
+/*!
+ \internal
+ */
Q3DSElement::Q3DSElement(Q3DSElementPrivate &dd, QObject *parent)
: QObject(dd, parent)
{
}
+/*!
+ Destructor.
+ */
Q3DSElement::~Q3DSElement()
{
}
+/*!
+ \property Q3DSElement::elementPath
+
+ Holds the element path of the presentation element.
+
+ An element path refers to an object in the scene either by name or id. The
+ latter is rarely used in application code since the unique IDs are not
+ exposed in the Qt 3D Studio application. To refer to an object by id,
+ prepend \c{#} to the name. Applications will typically refer to objects by
+ name.
+
+ Names are not necessarily unique, however. To access an object with a
+ non-unique name, the path can be specified, for example,
+ \c{Scene.Layer.Camera}. Here the right camera object gets chosen even if
+ the scene contains other layers with the default camera names (for instance
+ \c{Scene.Layer2.Camera}).
+
+ If the object is renamed to a unique name in the Qt 3D Studio application's
+ Timeline view, the path can be omitted. For example, if the camera in
+ question was renamed to \c MyCamera, applications can then simply pass \c
+ MyCamera as the element path.
+
+ To access an object in a sub-presentation, prepend the name of the
+ sub-presentation followed by a colon, for example,
+ \c{SubPresentationOne:Scene.Layer.Camera}.
+ */
QString Q3DSElement::elementPath() const
{
Q_D(const Q3DSElement);
@@ -76,6 +128,12 @@ void Q3DSElement::setElementPath(const QString &elementPath)
}
}
+/*!
+ Returns the current value of an attribute (property) of the scene
+ object specified by elementPath.
+
+ The \a attributeName is the \l{Attribute Names}{scripting name} of the attribute.
+ */
QVariant Q3DSElement::getAttribute(const QString &attributeName) const
{
Q_D(const Q3DSElement);
@@ -85,6 +143,12 @@ QVariant Q3DSElement::getAttribute(const QString &attributeName) const
return QVariant();
}
+/*!
+ Sets the \a value of an attribute (property) of the scene object
+ specified by elementPath.
+
+ The \a attributeName is the \l{Attribute Names}{scripting name} of the attribute.
+ */
void Q3DSElement::setAttribute(const QString &attributeName, const QVariant &value)
{
Q_D(Q3DSElement);
@@ -92,6 +156,14 @@ void Q3DSElement::setAttribute(const QString &attributeName, const QVariant &val
d->presentation->setAttribute(d->elementPath, attributeName, value);
}
+/*!
+ Dispatches an event with \a eventName on the scene object
+ specified by elementPath.
+
+ Appropriate actions created in Qt 3D Studio or callbacks registered using
+ the registerForEvent() method in attached (behavior) scripts will be
+ executed in response to the event.
+ */
void Q3DSElement::fireEvent(const QString &eventName)
{
Q_D(Q3DSElement);
@@ -104,4 +176,56 @@ void Q3DSElementPrivate::setPresentation(Q3DSPresentation *pres)
presentation = pres;
}
+/*!
+ \qmltype Element
+ \instantiates Q3DSElement
+ \inqmlmodule QtStudio3D
+ \ingroup 3dstudioruntime2
+ \brief Control type for elements in a Qt 3D Studio presentation.
+
+ This type is a convenience type for managing a presentation element.
+
+ All methods provided by this type are queued and handled asynchronously before the next
+ frame is displayed.
+
+ \sa Studio3D, Presentation, SceneElement
+*/
+
+/*!
+ \qmlproperty string Element::elementPath
+
+ Holds the element path of the presentation element.
+ This property must be set as part of Element declaration.
+ You can specify an element of a sub-presentation by adding "SubPresentationId:"
+ in front of the element path, for example \c{"SubPresentationOne:Scene"}.
+*/
+
+/*!
+ \qmlmethod void Element::setAttribute(string attributeName, variant value)
+
+ Sets the \a value of an attribute on an element specified by this instance.
+ The \a attributeName is the \l{Attribute Names}{scripting name} of the attribute.
+
+ The attribute must be preserved for scripting to be set by this function, or else it will fail.
+ An attribute is preserved if it is either \e{animated}, or
+ \e{an attribute on a master element that is unlinked and changed per-slide}.
+*/
+
+/*!
+ \qmlmethod void Element::fireEvent(string eventName)
+
+ Dispatches an event with \a eventName on the element specified by this instance.
+ Appropriate actions created in Qt 3D Studio or callbacks registered using the registerForEvent()
+ method in attached scripts will be executed in response to the event.
+*/
+
+/*!
+ \qmlsignal Element::elementPathChanged(string elementPath)
+
+ This signal is emitted when the element path property changes.
+ The new value is provided in the \a elementPath parameter.
+
+ The corresponding handler is \c onElementPathChanged.
+*/
+
QT_END_NAMESPACE
diff --git a/src/runtime/api/q3dselement.h b/src/runtime/api/q3dselement.h
index ec62590..7e5d0b8 100644
--- a/src/runtime/api/q3dselement.h
+++ b/src/runtime/api/q3dselement.h
@@ -51,7 +51,6 @@ class Q3DSV_EXPORT Q3DSElement : public QObject
public:
explicit Q3DSElement(QObject *parent = nullptr);
- explicit Q3DSElement(const QString &elementPath, QObject *parent = nullptr);
Q3DSElement(Q3DSPresentation *presentation, const QString &elementPath, QObject *parent = nullptr);
~Q3DSElement();
diff --git a/src/runtime/api/q3dspresentation.cpp b/src/runtime/api/q3dspresentation.cpp
index 0f0cf89..0a797b2 100644
--- a/src/runtime/api/q3dspresentation.cpp
+++ b/src/runtime/api/q3dspresentation.cpp
@@ -31,6 +31,40 @@
QT_BEGIN_NAMESPACE
+/*!
+ \class Q3DSPresentation
+ \inmodule 3dstudioruntime2
+ \since Qt 3D Studio 2.0
+
+ \brief Represents a Qt 3D Studio presentation.
+
+ This class provides properties and methods for controlling a
+ presentation.
+
+ Qt 3D Studio supports multiple presentations in one project. There
+ is always a main presentation and zero or more
+ sub-presentations. The sub-presentations are composed into the
+ main presentations either as contents of Qt 3D Studio layers or as
+ texture maps.
+
+ In the filesystem each presentation corresponds to one \c{.uip}
+ file. When present, the \c{.uia} file ties these together by
+ specifying a name for each of the (sub-)presentations and
+ specifies which one is the main one.
+
+ From the API point of view Q3DSPresentation corresponds to the
+ main presentation. The source property can refer either to a
+ \c{.uia} or \c{.uip} file. When specifying a file with \c{.uip}
+ extension and a \c{.uia} is present with the same name, the
+ \c{.uia} is loaded automatically and thus sub-presentation
+ information is available regardless.
+
+ \note This class should not be instantiated directly when working with the
+ C++ APIs. Q3DSSurfaceViewer and Q3DSWidget create a Q3DSPresentation
+ instance implicitly. This can be queried via
+ Q3DSSurfaceViewer::presentation() or Q3DSWidget::presentation().
+ */
+
// Unlike in 3DS1, Q3DSPresentation here does not own the engine. This is due
// to the delicate lifetime management needs due to Qt 3D under the hood: for
// instance the Studio3D element has to carefully manage the underlying
@@ -40,20 +74,41 @@ QT_BEGIN_NAMESPACE
// Q3DSPresentationController (for common functionality), or individually by
// Studio3D, Q3DSWidget, or Q3DSSurfaceViewer.
+/*!
+ Constructs a new Q3DSPresentation with the given \a parent.
+ */
Q3DSPresentation::Q3DSPresentation(QObject *parent)
: QObject(*new Q3DSPresentationPrivate, parent)
{
}
+/*!
+ \internal
+ */
Q3DSPresentation::Q3DSPresentation(Q3DSPresentationPrivate &dd, QObject *parent)
: QObject(dd, parent)
{
}
+/*!
+ Destructor.
+ */
Q3DSPresentation::~Q3DSPresentation()
{
}
+/*!
+ \property Q3DSPresentation::source
+
+ Holds the name of the main presentation file (\c{*.uia} or
+ \c{*.uip}). This may be either a local file or qrc URL.
+
+ The names of all further assets (image files for texture maps, qml
+ behavior scripts, mesh files) will be resolved relative to the
+ location of the presentation, unless they use absolute paths. This
+ allows bundling all assets next to the presentation in the Qt
+ resource system.
+*/
QUrl Q3DSPresentation::source() const
{
Q_D(const Q3DSPresentation);
@@ -128,6 +183,9 @@ void Q3DSPresentation::setProfileUiScale(float scale)
}
}
+/*!
+ Reloads the presentation.
+ */
void Q3DSPresentation::reload()
{
Q_D(Q3DSPresentation);
@@ -135,6 +193,21 @@ void Q3DSPresentation::reload()
d->controller->handlePresentationReload();
}
+/*!
+ Sets the \a value of a data input element \a name in the presentation.
+
+ Data input provides a higher level, designer-driven alternative to
+ Q3DSElement and setAttribute(). Instead of exposing a large set of
+ properties with their intenal engine names, data input allows designers to
+ decide which properties should be writable by the application, and can
+ assign custom names to these data input entries, thus forming a
+ well-defined contract between the designer and the developer.
+
+ In addition, data input also allows controlling the time line and the
+ current slide for time context objects (Scene or Component). Therefore it
+ is also an alternative to the goToSlide() and goToTime() family of APIs and
+ to Q3DSSceneElement.
+ */
void Q3DSPresentation::setDataInputValue(const QString &name, const QVariant &value)
{
Q_D(Q3DSPresentation);
@@ -142,6 +215,14 @@ void Q3DSPresentation::setDataInputValue(const QString &name, const QVariant &va
d->controller->handleDataInputValue(name, value);
}
+/*!
+ Dispatches an event with \a eventName on a specific element found in \a
+ elementPath. Appropriate actions created in Qt 3D Studio or callbacks
+ registered using the registerForEvent() method in attached (behavior)
+ scripts will be executed in response to the event.
+
+ See setAttribute() for a description of \a elementPath.
+ */
void Q3DSPresentation::fireEvent(const QString &elementPath, const QString &eventName)
{
Q_D(Q3DSPresentation);
@@ -149,6 +230,32 @@ void Q3DSPresentation::fireEvent(const QString &elementPath, const QString &even
d->controller->handleFireEvent(elementPath, eventName);
}
+/*!
+ Moves the timeline for a time context (a Scene or a Component element) to a
+ specific position. The position is given in seconds in \a timeSeconds.
+
+ If \a elementPath points to a time context, that element is
+ controlled. For all other element types the time context owning
+ that element is controlled instead. You can target the command to
+ a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example
+ \c{"SubPresentationOne:Scene"}.
+
+ The behavior when specifying a time before 0 or after the end time
+ for the current slide depends on the play mode of the slide:
+
+ \list
+ \li \c{Stop at End} - values outside the valid time range instead clamp to the boundaries.
+ For example, going to time -5 is the same as going to time 0.
+ \li \c{Looping} - values outside the valid time range mod into the valid range. For example,
+ going to time -4 on a 10 second slide is the same as going to time 6.
+ \li \c{Ping Pong} - values outside the valid time range bounce off the ends. For example,
+ going to time -4 is the same as going to time 4 (assuming the time context is at least 4 seconds
+ long), while going to time 12 on a 10 second slide is the same as going to time 8.
+ \li \c{Ping} - values less than 0 are treated as time 0, while values greater than the endtime
+ bounce off the end (eventually hitting 0.)
+ \endlist
+ */
void Q3DSPresentation::goToTime(const QString &elementPath, float timeSeconds)
{
Q_D(Q3DSPresentation);
@@ -156,6 +263,17 @@ void Q3DSPresentation::goToTime(const QString &elementPath, float timeSeconds)
d->controller->handleGoToTime(elementPath, timeSeconds);
}
+/*!
+ Requests a time context (a Scene or a Component object) to change
+ to a specific slide by \a name. If the context is already on that
+ slide, playback will start over.
+
+ If \a elementPath points to a time context, that element is
+ controlled. For all other element types the time context owning
+ that element is controlled instead. You can target the command to
+ a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+ */
void Q3DSPresentation::goToSlide(const QString &elementPath, const QString &name)
{
Q_D(Q3DSPresentation);
@@ -163,6 +281,17 @@ void Q3DSPresentation::goToSlide(const QString &elementPath, const QString &name
d->controller->handleGoToSlideByName(elementPath, name);
}
+/*!
+ Requests a time context (a Scene or a Component object) to change
+ to a specific slide by \a index. If the context is already on that
+ slide, playback will start over.
+
+ If \a elementPath points to a time context, that element is
+ controlled. For all other element types the time context owning
+ that element is controlled instead. You can target the command to
+ a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+ */
void Q3DSPresentation::goToSlide(const QString &elementPath, int index)
{
Q_D(Q3DSPresentation);
@@ -170,6 +299,18 @@ void Q3DSPresentation::goToSlide(const QString &elementPath, int index)
d->controller->handleGoToSlideByIndex(elementPath, index);
}
+/*!
+ Requests a time context (a Scene or a Component object) to change to the
+ next or previous slide, depending on the value of \a next. If the context
+ is already at the last or first slide, \a wrap defines if wrapping over to
+ the first or last slide, respectively, occurs.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled
+ instead. You can target the command to a specific sub-presentation by
+ adding "SubPresentationId:" in front of the element path, for example
+ \c{"SubPresentationOne:Scene"}.
+ */
void Q3DSPresentation::goToSlide(const QString &elementPath, bool next, bool wrap)
{
Q_D(Q3DSPresentation);
@@ -177,6 +318,15 @@ void Q3DSPresentation::goToSlide(const QString &elementPath, bool next, bool wra
d->controller->handleGoToSlideByDirection(elementPath, next, wrap);
}
+/*!
+ Returns the value of an attribute (property) on the object specified by \a
+ elementPath. The \a attributeName is the \l{Attribute Names}{scripting
+ name} of the attribute.
+
+ See setAttribute() for a description of \a elementPath.
+
+ \sa setAttribute
+ */
QVariant Q3DSPresentation::getAttribute(const QString &elementPath, const QString &attributeName)
{
Q_D(Q3DSPresentation);
@@ -186,6 +336,34 @@ QVariant Q3DSPresentation::getAttribute(const QString &elementPath, const QStrin
return QVariant();
}
+/*!
+ Sets the \a value of an attribute (property) on the object specified by
+ \a elementPath. The \a attributeName is the \l{Attribute Names}{scripting
+ name} of the attribute.
+
+ An element path refers to an object in the scene either by name or id. The
+ latter is rarely used in application code since the unique IDs are not
+ exposed in the Qt 3D Studio application. To refer to an object by id,
+ prepend \c{#} to the name. Applications will typically refer to objects by
+ name.
+
+ Names are not necessarily unique, however. To access an object with a
+ non-unique name, the path can be specified, for example,
+ \c{Scene.Layer.Camera}. Here the right camera object gets chosen even if
+ the scene contains other layers with the default camera names (for instance
+ \c{Scene.Layer2.Camera}).
+
+ If the object is renamed to a unique name in the Qt 3D Studio application's
+ Timeline view, the path can be omitted. For example, if the camera in
+ question was renamed to \c MyCamera, applications can then simply pass \c
+ MyCamera as the element path.
+
+ To access an object in a sub-presentation, prepend the name of the
+ sub-presentation followed by a colon, for example,
+ \c{SubPresentationOne:Scene.Layer.Camera}.
+
+ \sa getAttribute
+ */
void Q3DSPresentation::setAttribute(const QString &elementPath, const QString &attributeName, const QVariant &value)
{
Q_D(Q3DSPresentation);
@@ -292,4 +470,182 @@ void Q3DSPresentationPrivate::registerInlineQmlSubPresentations(const QVector<Q3
inlineQmlSubPresentations += list;
}
+/*!
+ \qmltype Presentation
+ \instantiates Q3DSPresentation
+ \inqmlmodule QtStudio3D
+ \ingroup 3dstudioruntime2
+
+ \brief Control type for Qt 3D Studio presentations.
+
+ This type provides properties and methods for controlling a presentation.
+
+ All methods provided by this type are queued and handled asynchronously before the next
+ frame is displayed.
+
+ \sa Studio3D
+*/
+
+/*!
+ \qmlproperty url Presentation::source
+
+ Holds the presentation source (\c{*.uia} or \c{*.uip}) file location.
+ May be either a file URL or a qrc URL.
+*/
+
+/*!
+ \qmlproperty SubPresentationSettings Presentation::subPresentationSettings
+
+ Holds the settings for the subpresentations in the Qt 3D Studio presentation.
+
+ This property is read-only.
+*/
+
+/*!
+ \qmlmethod void Presentation::goToSlide(string elementPath, string name)
+
+ Requests a time context (a Scene or a Component element) to change to a specific slide
+ by \a name. If the context is already on that slide playback will start over.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled instead.
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+*/
+
+/*!
+ \qmlmethod void Presentation::goToSlide(string elementPath, int index)
+
+ Requests a time context (a Scene or a Component element) to change to a specific slide by
+ index \a index. If the context is already on that slide playback will start over.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled instead.
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+*/
+
+/*!
+ \qmlmethod void Presentation::goToSlide(string elementPath, bool next, bool wrap)
+
+ Requests a time context (a Scene or a Component element) to change to the next or the
+ previous slide, depending on the value of \a next. If the context is already at the
+ last or first slide, \a wrap defines if change occurs to the opposite end.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled instead.
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+*/
+
+/*!
+ \qmlmethod void Presentation::goToTime(string elementPath, real time)
+
+ Sets a time context (a Scene or a Component element) to a specific playback \a time in seconds.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled instead.
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+
+ The behavior when specifying a time before 0 or after the end time for the current slide depends
+ on the play mode of the slide:
+ \list
+ \li \c{Stop at End} - values outside the valid time range instead clamp to the boundaries.
+ For example, going to time -5 is the same as going to time 0.
+ \li \c{Looping} - values outside the valid time range mod into the valid range. For example,
+ going to time -4 on a 10 second slide is the same as going to time 6.
+ \li \c{Ping Pong} - values outside the valid time range ‘bounce’ off the ends. For example,
+ going to time -4 is the same as going to time 4 (assuming the time context is at least 4 seconds
+ long), while going to time 12 on a 10 second slide is the same as going to time 8.
+ \li \c{Ping} - values less than 0 are treated as time 0, while values greater than the endtime
+ bounce off the end (eventually hitting 0.)
+ \endlist
+*/
+
+/*!
+ \qmlmethod void Presentation::setAttribute(string elementPath, string attributeName,
+ variant value)
+
+ Sets the \a value of an attribute on an element found at \a elementPath. The \a attributeName is
+ the \l{Attribute Names}{scripting name} of the attribute.
+
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene.Mesh.Material"}.
+
+ The attribute must be preserved for scripting to be set by this function, or else it will fail.
+ An attribute is preserved if it is either \e{animated}, or
+ \e{an attribute on a master element that is unlinked and changed per-slide}.
+*/
+
+/*!
+ \qmlmethod void Presentation::setPresentationActive(string id, bool active)
+
+ Stops or starts updates to a sub-presentation based on the \a active flag. The presentation is
+ referenced to by the \a id, which is the name of the presentation without the \c{.uip}.
+
+ Making a presentation inactive prevents any elements, behaviors, and animations within it from
+ updating. It also prevents any events within that presentation from being processed. It does
+ not, however, prevent the presentation from rendering. An inactive presentation will continue
+ to render using its last-updated information.
+
+ Explicitly inactivating presentations can provide a significant performance increase, depending
+ on the number and size of the presentations that are inactive. Inactive presentations are not
+ ‘paused’. When the presentation is re-activated, animations will resume at the time they should
+ be had they been running, not where they were when the presentation was made inactive.
+*/
+
+/*!
+ \qmlmethod void Presentation::fireEvent(string elementPath, string eventName)
+
+ Dispatches an event with \a eventName on a specific element found in \a elementPath. Appropriate
+ Appropriate actions created in Qt 3D Studio or callbacks registered using the registerForEvent()
+ method in attached scripts will be executed in response to the event.
+
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene.Mesh"}.
+*/
+
+/*!
+ \qmlmethod void Presentation::setGlobalAnimationTime(int64 milliseconds)
+
+ Sets the global animation time to \a milliseconds. Setting the global animation time to a
+ non-zero value will disable the automatic animation timer. Setting the value to zero
+ resumes automatic animation timer.
+*/
+
+/*!
+ \qmlmethod void Presentation::setDataInputValue(string name, variant value)
+ \since QtStudio3D 1.1
+
+ Sets the \a value of a data input element \a name in the presentation.
+*/
+
+/*!
+ \qmlsignal Presentation::slideEntered(string elementPath, int index, string name)
+
+ This signal is emitted when a slide is entered in the presentation.
+ The \a elementPath specifies the time context (a Scene or a Component element) owning the
+ entered slide.
+ The \a index and \a name contain the index and the name of the entered slide.
+*/
+
+/*!
+ \qmlsignal Presentation::slideExited(string elementPath, int index, string name)
+
+ This signal is emitted when a slide is exited in the presentation.
+ The \a elementPath specifies the time context (a Scene or a Component element) owning the
+ exited slide.
+ The \a index and \a name contain the index and the name of the exited slide.
+*/
+
+/*!
+ \qmlsignal Presentation::sourceChanged(url source)
+
+ This signal is emitted when the source property has changed.
+ The new value is provided in the \a source parameter.
+
+ The corresponding handler is \c onSourceChanged.
+*/
+
QT_END_NAMESPACE
diff --git a/src/runtime/api/q3dssceneelement.cpp b/src/runtime/api/q3dssceneelement.cpp
index f8b3e23..6b3c161 100644
--- a/src/runtime/api/q3dssceneelement.cpp
+++ b/src/runtime/api/q3dssceneelement.cpp
@@ -32,18 +32,39 @@
QT_BEGIN_NAMESPACE
-Q3DSSceneElement::Q3DSSceneElement(QObject *parent)
- : Q3DSElement(*new Q3DSSceneElementPrivate, parent)
-{
-}
+/*!
+ \class Q3DSSceneElement
+ \inherits Q3DSElement
+ \inmodule 3dstudioruntime2
+ \since Qt 3D Studio 2.0
+
+ \brief Controls the special Scene or Component scene objects in a Qt 3D
+ Studio presentation.
+
+ This class is a convenience class for controlling the properties of Scene
+ and Component objects in the scene. These are special since they have a
+ time context, meaning they control a timline and a set of associated
+ slides.
+
+ \note The functionality of Q3DSSceneElement is equivalent to
+ Q3DSPresentation::goToTime() and Q3DSPresentation::goToSlide().
+
+ \sa Q3DSPresentation, Q3DSWidget, Q3DSSurfaceViewer, Q3DSElement
+ */
-Q3DSSceneElement::Q3DSSceneElement(const QString &elementPath, QObject *parent)
+/*!
+ \internal
+ */
+Q3DSSceneElement::Q3DSSceneElement(QObject *parent)
: Q3DSElement(*new Q3DSSceneElementPrivate, parent)
{
- Q_D(Q3DSSceneElement);
- d->elementPath = elementPath;
}
+/*!
+ Constructs a Q3DSSceneElement instance and associated it with the object
+ specified by \a elementPath and the given \a presentation. An optional \a
+ parent object can be specified.
+ */
Q3DSSceneElement::Q3DSSceneElement(Q3DSPresentation *presentation, const QString &elementPath, QObject *parent)
: Q3DSElement(*new Q3DSSceneElementPrivate, parent)
{
@@ -52,33 +73,77 @@ Q3DSSceneElement::Q3DSSceneElement(Q3DSPresentation *presentation, const QString
d->presentation = presentation;
}
+/*!
+ \internal
+ */
Q3DSSceneElement::Q3DSSceneElement(Q3DSSceneElementPrivate &dd, QObject *parent)
: Q3DSElement(dd, parent)
{
}
+/*!
+ Destructor.
+ */
Q3DSSceneElement::~Q3DSSceneElement()
{
}
+/*!
+ \property Q3DSSceneElement::currentSlideIndex
+
+ Holds the index of the currently active slide of the tracked time context.
+
+ \note If this property is set to something else than the default slide for
+ the scene at the initial declaration of SceneElement, a changed signal for
+ the default slide may stil be emitted before the slide changes to the
+ desired one. This happens in order to ensure we end up with the index of
+ the slide that is actually shown even if the slide specified in the initial
+ declaration is invalid.
+*/
int Q3DSSceneElement::currentSlideIndex() const
{
Q_D(const Q3DSSceneElement);
return d->currentSlideIndex;
}
+/*!
+ \property Q3DSSceneElement::previousSlideIndex
+
+ Holds the index of the previously active slide of the tracked time context.
+
+ This property is read-only.
+*/
int Q3DSSceneElement::previousSlideIndex() const
{
Q_D(const Q3DSSceneElement);
return d->previousSlideIndex;
}
+/*!
+ \property Q3DSSceneElement::currentSlideName
+
+ Holds the name of the currently active slide of the tracked time context.
+
+ \note If this property is set to something else than the default slide for
+ the scene at the initial declaration of SceneElement, a changed signal for
+ the default slide may stil be emitted before the slide changes to the
+ desired one. This happens in order to ensure we end up with the index of
+ the slide that is actually shown even if the slide specified in the initial
+ declaration is invalid.
+*/
QString Q3DSSceneElement::currentSlideName() const
{
Q_D(const Q3DSSceneElement);
return d->currentSlideName;
}
+/*!
+ \property Q3DSSceneElement::previousSlideName
+
+ Holds the name of the previously active slide of the tracked time context.
+
+ This property is read-only.
+*/
QString Q3DSSceneElement::previousSlideName() const
{
Q_D(const Q3DSSceneElement);
@@ -105,6 +170,12 @@ void Q3DSSceneElement::setCurrentSlideName(const QString &currentSlideName)
d->pendingSlideSetName = currentSlideName; // defer to sendPendingValues()
}
+/*!
+ Requests a time context (a Scene or a Component object) to change to the
+ next or previous slide, depending on the value of \a next. If the context
+ is already at the last or first slide, \a wrap defines if wrapping over to
+ the first or last slide, respectively, occurs.
+ */
void Q3DSSceneElement::goToSlide(bool next, bool wrap)
{
Q_D(Q3DSSceneElement);
@@ -112,6 +183,10 @@ void Q3DSSceneElement::goToSlide(bool next, bool wrap)
d->presentation->goToSlide(d->elementPath, next, wrap);
}
+/*!
+ Moves the timeline for a time context (a Scene or a Component element) to a
+ specific position. The position is given in seconds in \a timeSeconds.
+ */
void Q3DSSceneElement::goToTime(float timeSeconds)
{
Q_D(Q3DSSceneElement);
@@ -171,6 +246,131 @@ void Q3DSSceneElementPrivate::setPresentation(Q3DSPresentation *pres)
q, SLOT(_q_onSlideEntered(QString,int,QString)));
}
+/*!
+ \qmltype SceneElement
+ \instantiates Q3DSSceneElement
+ \inherits Element
+ \inqmlmodule QtStudio3D
+ \ingroup 3dstudioruntime2
+ \brief Control type for scene and component elements in a Qt 3D Studio presentation.
+
+ This type is a convenience type for managing the slides of a single
+ time context (a Scene or a Component element) of a presentation.
+
+ All methods provided by this type are queued and handled asynchronously before the next
+ frame is displayed.
+
+ \sa Studio3D, Presentation, Element
+*/
+
+/*!
+ \qmlproperty int SceneElement::currentSlideIndex
+
+ Holds the index of the currently active slide of the tracked time context.
+
+ Changing the current slide via this property is asynchronous. The property
+ value will not actually change until the next frame has been processed, and
+ even then only if the new slide was valid.
+
+ \note If this property is set to something else than the default slide for the scene at the
+ initial declaration of SceneElement, you will still get an extra changed signal for the
+ default slide before the slide changes to the desired one. This happens in order to ensure
+ we end up with the index of the slide that is actually shown even if the slide specified in the
+ initial declaration is invalid.
+*/
+
+/*!
+ \qmlproperty int SceneElement::previousSlideIndex
+
+ Holds the index of the previously active slide of the tracked time context.
+
+ This property is read-only.
+*/
+
+/*!
+ \qmlproperty string SceneElement::currentSlideName
+
+ Holds the name of the currently active slide of the tracked time context.
+
+ Changing the current slide via this property is asynchronous. The property
+ value will not actually change until the next frame has been processed, and
+ even then only if the new slide was valid.
+
+ \note If this property is set to something else than the default slide for the scene at the
+ initial declaration of SceneElement, you will still get an extra changed signal for the
+ default slide before the slide changes to the desired one. This happens in order to ensure
+ we end up with the name of the slide that is actually shown even if the slide specified in the
+ initial declaration is invalid.
+*/
+
+/*!
+ \qmlproperty string SceneElement::previousSlideName
+
+ Holds the name of the previously active slide of the tracked time context.
+
+ This property is read-only.
+*/
+
+/*!
+ \qmlsignal SceneElement::currentSlideIndexChanged(int currentSlideIndex)
+
+ This signal is emitted when the current slide changes.
+ The new value is provided in the \a currentSlideIndex parameter.
+
+ This signal is always emitted with currentSlideNameChanged.
+
+ The corresponding handler is \c onCurrentSlideIndexChanged.
+*/
+
+/*!
+ \qmlsignal SceneElement::previousSlideIndexChanged(int previousSlideIndex)
+
+ This signal is emitted when the previous slide changes.
+ The new value is provided in the \a previousSlideIndex parameter.
+
+ This signal is always emitted with previousSlideNameChanged.
+
+ The corresponding handler is \c onPreviousSlideIndexChanged.
+*/
+
+/*!
+ \qmlsignal SceneElement::currentSlideNameChanged(string currentSlideName)
+
+ This signal is emitted when the current slide changes.
+ The new value is provided in the \a currentSlideName parameter.
+
+ This signal is always emitted with currentSlideIndexChanged.
+
+ The corresponding handler is \c onCurrentSlideNameChanged.
+*/
+
+/*!
+ \qmlsignal SceneElement::previousSlideNameChanged(string previousSlideName)
+
+ This signal is emitted when the previous slide changes.
+ The new value is provided in the \a previousSlideName parameter.
+
+ This signal is always emitted with previousSlideIndexChanged.
+
+ The corresponding handler is \c onPreviousSlideNameChanged.
+*/
+
+/*!
+ \qmlmethod void SceneElement::goToSlide(bool next, bool wrap)
+
+ Requests a time context (a Scene or a Component element) to change to the next or the
+ previous slide, depending on the value of \a next. If the context is already at the
+ last or first slide, \a wrap defines if change occurs to the opposite end.
+*/
+
+/*!
+ \qmlmethod void SceneElement::goToTime(string elementPath, real time)
+
+ Sets a time context (a Scene or a Component element) to a specific playback \a time in seconds.
+
+ For behavior details, see Presentation::goToTime() documentation.
+*/
+
QT_END_NAMESPACE
#include "moc_q3dssceneelement.cpp"
diff --git a/src/runtime/api/q3dssceneelement.h b/src/runtime/api/q3dssceneelement.h
index d8eba18..b7726d3 100644
--- a/src/runtime/api/q3dssceneelement.h
+++ b/src/runtime/api/q3dssceneelement.h
@@ -52,7 +52,6 @@ class Q3DSV_EXPORT Q3DSSceneElement : public Q3DSElement
public:
explicit Q3DSSceneElement(QObject *parent = nullptr);
- explicit Q3DSSceneElement(const QString &elementPath, QObject *parent = nullptr);
Q3DSSceneElement(Q3DSPresentation *presentation, const QString &elementPath, QObject *parent = nullptr);
~Q3DSSceneElement();
diff --git a/src/runtime/api/q3dssurfaceviewer.cpp b/src/runtime/api/q3dssurfaceviewer.cpp
index 853b96b..8ecb6c3 100644
--- a/src/runtime/api/q3dssurfaceviewer.cpp
+++ b/src/runtime/api/q3dssurfaceviewer.cpp
@@ -45,6 +45,56 @@
QT_BEGIN_NAMESPACE
+/*!
+ \class Q3DSSurfaceViewer
+ \inmodule 3dstudioruntime2
+ \since Qt 3D Studio 2.0
+
+ \brief Renders a Qt 3D Studio presentation on a QWindow or an offscreen
+ render target using OpenGL.
+
+ Q3DSSurfaceViewer is used to render Qt 3D Studio presentations onto a
+ QSurface. In practice this means two types of uses: rendering to an
+ on-screen QWindow, or rendering to an offscreen render target (typically an
+ OpenGL texture via a framebuffer object and a QOffscreenSurface).
+
+ \section2 Example Usage
+
+ \code
+ int main(int argc, char *argv[])
+ {
+ QGuiApplication app(argc, argv);
+
+ QOpenGLContext context;
+ context.create();
+
+ QWindow window;
+ window.setSurfaceType(QSurface::OpenGLSurface);
+ window.setFormat(context.format());
+ window.create();
+
+ Q3DSSurfaceViewer viewer;
+ viewer.presentation()->setSource(QUrl(QStringLiteral("qrc:/my_presentation.uip")));
+ viewer.setUpdateInterval(0); // enable automatic updates
+
+ // Register a scene object for slide management (optional)
+ Q3DSSceneElement scene(viewer.presentation(), QStringLiteral("Scene"));
+
+ // Register an element object for attribute setting (optional)
+ Q3DSElement element(viewer.presentation(), QStringLiteral("myCarModel"));
+
+ viewer.create(&window, &context);
+
+ w.resize(1024, 768);
+ w.show();
+
+ return app.exec();
+ }
+ \endcode
+
+ \sa Q3DSWidget
+ */
+
Q3DSSurfaceViewer::Q3DSSurfaceViewer(QObject *parent)
: QObject(*new Q3DSSurfaceViewerPrivate, parent)
{
@@ -67,12 +117,35 @@ Q3DSSurfaceViewer::~Q3DSSurfaceViewer()
// "use this custom FBO as-is". Changing to int would be wrong too since the ID
// is a GLuint in practice.
+/*!
+ Initializes Q3DSSurfaceViewer to render the presentation to the given
+ \a surface using the \a context.
+
+ The source property of the attached presentation must be set before the
+ viewer can be initialized.
+
+ Returns whether the initialization succeeded.
+
+ \sa running, Q3DSPresentation::source, presentation()
+*/
bool Q3DSSurfaceViewer::create(QSurface *surface, QOpenGLContext *context)
{
Q_D(Q3DSSurfaceViewer);
return d->doCreate(surface, context, 0, false);
}
+/*!
+ Initializes Q3DSSurfaceViewer to render the presentation to the given
+ \a surface using the \a context and optional framebuffer id (\a fboId). If
+ \a fboId is omitted, it defaults to zero.
+
+ The source property of the attached presentation must be set before the
+ viewer can be initialized.
+
+ Returns whether the initialization succeeded.
+
+ \sa running, Q3DSPresentation::source, presentation()
+*/
bool Q3DSSurfaceViewer::create(QSurface *surface, QOpenGLContext *context, uint fboId)
{
Q_D(Q3DSSurfaceViewer);
@@ -114,12 +187,18 @@ void Q3DSSurfaceViewer::destroy()
d->fbo = 0;
}
+/*!
+ Returns the presentation object used by the Q3DSSurfaceViewer.
+*/
Q3DSPresentation *Q3DSSurfaceViewer::presentation() const
{
Q_D(const Q3DSSurfaceViewer);
return d->presentation;
}
+/*!
+ Returns the settings object used by the Q3DSSurfaceViewer.
+*/
Q3DSViewerSettings *Q3DSSurfaceViewer::settings() const
{
Q_D(const Q3DSSurfaceViewer);
@@ -132,6 +211,14 @@ QString Q3DSSurfaceViewer::error() const
return d->error;
}
+/*!
+ \property Q3DSSurfaceViewer::running
+
+ The value of this property is \c true when the viewer has been initialized
+ and the presentation is running.
+
+ This property is read-only.
+*/
bool Q3DSSurfaceViewer::isRunning() const
{
Q_D(const Q3DSSurfaceViewer);
@@ -153,6 +240,22 @@ void Q3DSSurfaceViewer::setSize(const QSize &size)
}
}
+/*!
+ \property Q3DSSurfaceViewer::autoSize
+
+ Specifies whether the viewer should change the size of the presentation
+ automatically to match the surface size when surface size changes. The
+ \l{Q3DSSurfaceViewer::size}{size} property is updated automatically
+ whenever the viewer is \l{Q3DSSurfaceViewer::update()}{updated} if this
+ property value is \c{true}.
+
+ When rendering offscreen, via a QOffscreenSurface, this property must be
+ set to \c{false} by the application since it is then up to the application
+ to provide a QOpenGLFramebufferObject with the desired size. The size of
+ the Q3DSSurfaceViewer must be set to the same value.
+
+ The default value is \c{true}.
+*/
bool Q3DSSurfaceViewer::autoSize() const
{
Q_D(const Q3DSSurfaceViewer);
@@ -168,6 +271,17 @@ void Q3DSSurfaceViewer::setAutoSize(bool autoSize)
}
}
+/*!
+ \property Q3DSSurfaceViewer::updateInterval
+
+ Holds the viewer update interval in milliseconds. If the value is negative,
+ the viewer doesn't update the presentation automatically.
+
+ The default value is -1, meaning there are no automatic updates and
+ update() must be called manually.
+
+ \sa update()
+*/
int Q3DSSurfaceViewer::updateInterval() const
{
Q_D(const Q3DSSurfaceViewer);
@@ -190,18 +304,33 @@ void Q3DSSurfaceViewer::setUpdateInterval(int interval)
}
}
+/*!
+ Returns the framebuffer id given in initialization.
+
+ \sa create()
+*/
uint Q3DSSurfaceViewer::fboId() const
{
Q_D(const Q3DSSurfaceViewer);
return d->fbo;
}
+/*!
+ Returns the surface given in initialization.
+
+ \sa create()
+*/
QSurface *Q3DSSurfaceViewer::surface() const
{
Q_D(const Q3DSSurfaceViewer);
return d->surface;
}
+/*!
+ Returns the context given in initialization.
+
+ \sa create()
+*/
QOpenGLContext *Q3DSSurfaceViewer::context() const
{
Q_D(const Q3DSSurfaceViewer);
@@ -210,6 +339,9 @@ QOpenGLContext *Q3DSSurfaceViewer::context() const
extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+/*!
+ Updates the surface viewer with a new frame.
+*/
void Q3DSSurfaceViewer::update()
{
Q_D(Q3DSSurfaceViewer);
@@ -272,6 +404,13 @@ void Q3DSSurfaceViewer::update()
emit frameUpdate();
}
+/*!
+ Grabs the data rendered to the framebuffer into an image using the given \a
+ rect. The \a rect parameter is optional. If it is omitted, the whole
+ framebuffer is captured.
+
+ \note This is a potentially expensive operation.
+*/
QImage Q3DSSurfaceViewer::grab(const QRect &rect)
{
Q_D(Q3DSSurfaceViewer);
diff --git a/src/runtime/api/q3dsviewersettings.cpp b/src/runtime/api/q3dsviewersettings.cpp
index ba1249a..a0d91ea 100644
--- a/src/runtime/api/q3dsviewersettings.cpp
+++ b/src/runtime/api/q3dsviewersettings.cpp
@@ -32,6 +32,26 @@
QT_BEGIN_NAMESPACE
+/*!
+ \class Q3DSViewerSettings
+ \inmodule 3dstudioruntime2
+ \since Qt 3D Studio 2.0
+
+ \brief Qt 3D Studio presentation viewer settings.
+
+ Q3DSViewerSettings provides properties to define presentation independent
+ viewer settings.
+
+ \note As of Qt 3D Studio 2.0 this class is provided mainly for
+ compatibility reasons. Most functions are not applicable or are not
+ currently supported and will be silently ignored.
+
+ \note This class should not be instantiated directly when working with the
+ C++ APIs. Q3DSSurfaceViewer and Q3DSWidget create a Q3DSViewerSettings
+ instance implicitly. This can be queried via Q3DSSurfaceViewer::settings()
+ or Q3DSWidget::settings().
+ */
+
Q3DSViewerSettings::Q3DSViewerSettings(QObject *parent)
: QObject(*new Q3DSViewerSettingsPrivate, parent)
{
@@ -52,6 +72,17 @@ QColor Q3DSViewerSettings::matteColor() const
return d->matteColor;
}
+/*!
+ \property Q3DSViewerSettings::showRenderStats
+
+ If this property is set to \c{true}, the interactive statistics and profile
+ view is displayed in-scene, on top of the 3D content.
+
+ \note This feature can be disabled at build time, in which case this
+ property has no effect.
+
+ Default value is \c{false}.
+*/
bool Q3DSViewerSettings::isShowingRenderStats() const
{
Q_D(const Q3DSViewerSettings);
@@ -129,4 +160,24 @@ void Q3DSViewerSettings::load(const QString &group,
qWarning() << Q_FUNC_INFO << "not implemented";
}
+/*!
+ \qmltype ViewerSettings
+ \instantiates Q3DSViewerSettings
+ \inqmlmodule QtStudio3D
+ \ingroup 3dstudioruntime2
+ \brief Qt 3D Studio presentation viewer settings.
+
+ This type provides properties to define presentation independent viewer settings.
+
+ \sa Studio3D
+*/
+
+/*!
+ \qmlproperty bool ViewerSettings::showRenderStats
+
+ If this property is set to \c{true}, render statistics are displayed on the upper part
+ of the viewer.
+ Default value is \c{false}.
+*/
+
QT_END_NAMESPACE
diff --git a/src/runtime/api/q3dswidget.cpp b/src/runtime/api/q3dswidget.cpp
index 6fb6d3e..8cdd898 100644
--- a/src/runtime/api/q3dswidget.cpp
+++ b/src/runtime/api/q3dswidget.cpp
@@ -44,12 +44,35 @@ QT_BEGIN_NAMESPACE
/*!
\class Q3DSWidget
-
\inmodule 3dstudioruntime2
+ \since Qt 3D Studio 2.0
+ \inherits QOpenGLWidget
+
+ \brief A widget that renders Qt 3D Studio presentations using OpenGL.
+
+ Q3DSWidget is a widget that can be used to embed Qt 3D Studio presentations
+ into QWidget-based applications.
+
+ Q3DSWidget is used to specify a render widget for Qt 3D Studio
+ presentation. It subclasses QOpenGLWidget, which means all considerations
+ that should be taken when working with QOpenGLWidget apply to Q3DSWidget as
+ well. Refer to the QOpenGLWidget documentation for details.
+
+ \section2 Example Usage
- \brief Widget
+ \code
+ Q3DSWidget *viewer = new Q3DSWidget(parentWidget);
+ viewer->presentation()->setSource(QUrl(QStringLiteral("qrc:/my_presentation.uip")));
+ viewer->setUpdateInterval(0);
- blah
+ // Register a scene element object for slide management (optional)
+ Q3DSSceneElement scene(viewer->presentation(), QStringLiteral("Scene"));
+
+ // Register an element object for attribute setting (optional)
+ Q3DSElement element(viewer->presentation(), QStringLiteral("myCarModel"));
+ \endcode
+
+ \sa Q3DSSurfaceViewer
*/
Q3DSWidget::Q3DSWidget(QWidget *parent)
@@ -65,12 +88,18 @@ Q3DSWidget::~Q3DSWidget()
delete d_ptr;
}
+/*!
+ Returns the presentation object used by the Q3DSWidget.
+ */
Q3DSPresentation *Q3DSWidget::presentation() const
{
Q_D(const Q3DSWidget);
return d->presentation;
}
+/*!
+ Returns the settings object used by the Q3DSWidget.
+ */
Q3DSViewerSettings *Q3DSWidget::settings() const
{
Q_D(const Q3DSWidget);
@@ -83,12 +112,30 @@ QString Q3DSWidget::error() const
return d->error;
}
+/*!
+ \property Q3DSWidget::running
+
+ The value of this property is \c true when the viewer has been initialized
+ and the presentation is running.
+
+ This property is read-only.
+*/
bool Q3DSWidget::isRunning() const
{
Q_D(const Q3DSWidget);
return d->engine && d->sourceLoaded;
}
+/*!
+ \property Q3DSWidget::updateInterval
+
+ Holds the viewer update interval in milliseconds. If the value is negative,
+ the viewer doesn't update the presentation automatically.
+
+ The default value is 0, meaning automatic updates are enabled.
+
+ \sa QWidget::update()
+*/
int Q3DSWidget::updateInterval() const
{
Q_D(const Q3DSWidget);
diff --git a/src/runtime/behaviorapi/q3dsbehaviorobject.cpp b/src/runtime/behaviorapi/q3dsbehaviorobject.cpp
index 75ac946..9a31ce8 100644
--- a/src/runtime/behaviorapi/q3dsbehaviorobject.cpp
+++ b/src/runtime/behaviorapi/q3dsbehaviorobject.cpp
@@ -265,4 +265,170 @@ void Q3DSBehaviorObject::setDataInputValue(const QString &name, const QVariant &
m_engine->setDataInputValue(name, value);
}
+/*!
+ \qmltype Behavior
+ \inqmlmodule QtStudio3D
+ \ingroup 3dstudioruntime2
+
+ \brief Technology Preview Behavior Integration
+
+ This is a technology preview (API may change in upcoming version) of how
+ Qt 3D Studio could support writing custom behavior scripts using QML and
+ JavaScript. It enables interacting with the runtime using the Behavior
+ QML class exposed to each behavior script.
+
+ In QML behavior script, the integration to Qt 3D Studio is established by using
+ the metadata tag system similar to the \l {file-formats-effects.html}{effect}
+ and \l {file-formats-material.html}{material} files.
+
+ \badcode
+[[
+<Property name="somePropertyName" ... />
+
+<Handler name="someHandlerName" ... />
+
+<Event name="onSomeEvent" ... />
+...
+]]
+ \endcode
+
+ Secondly, the QML behavior script needs access to the QML module.
+ \badcode
+import QtStudio3D.Behavior 2.0
+ \endcode
+
+ Finally, the Behavior type needs to be implemented in the qml script.
+ \badcode
+Behavior {
+ id: mybehavior
+
+ function onInitialize() {
+ ...
+ }
+
+ function onActivate() {
+ ...
+ }
+
+ function onUpdate() {
+ ...
+ }
+
+ function onDeactivate() {
+ ...
+ }
+
+ function someHandlerName() {
+ ...
+ fireEvent("onSomeEvent")
+ }
+}
+ \endcode
+*/
+
+/*!
+ \qmlmethod float Behavior::getDeltaTime()
+
+ Returns the delta time between this and previous frame in milliseconds.
+*/
+
+/*!
+ \qmlmethod var Behavior::getAttribute(string attribute)
+
+ Returns the value of the given \a attribute.
+*/
+
+/*!
+ \qmlmethod var Behavior::getAttribute(string handle, string attribute)
+
+ Returns the value of the given \a attribute for a given \a handle.
+*/
+
+/*!
+ \qmlmethod void Behavior::setAttribute(string attribute, var value)
+
+ Sets the \a value of the given \a attribute.
+*/
+
+/*!
+ \qmlmethod void Behavior::setAttribute(string handle, string attribute, var value)
+
+ Sets the \a value of the given \a attribute for a given \a handle.
+*/
+
+/*!
+ \qmlmethod void Behavior::fireEvent(string event)
+
+ Fires the given \a event.
+*/
+
+/*!
+ \qmlmethod void Behavior::registerForEvent(string event, QJSValue function)
+
+ Registers the script for an \a event with the handler \a function.
+*/
+
+/*!
+ \qmlmethod void Behavior::registerForEvent(string handle, string event, QJSValue function)
+
+ Registers the script for an \a event with the handler \a function for a given \a handle.
+*/
+
+/*!
+ \qmlmethod void Behavior::unregisterForEvent(string event)
+
+ Unregisters the script from an \a event.
+*/
+
+/*!
+ \qmlmethod void Behavior::unregisterForEvent(string handle, string event)
+
+ Unregisters the script from an \a event for a given \a handle.
+*/
+
+/*!
+ \qmlmethod void Behavior::setDataInputValue(string name, variant value)
+
+ Sets the \a value of the data input identified with the \a name.
+ */
+
+/*!
+ \qmlsignal void Behavior::onInitialize()
+
+ This signal is emitted when the script becomes active the first time.
+ If multiple behaviors match this, the signal for parent elements will
+ occur before their children/descendants. \note Each behavior will
+ only have its \c{onInitialize} signaled once, even if it is deactivated and
+ later reactivated.
+ */
+
+/*!
+ \qmlsignal void Behavior::onActivate()
+
+ This signal is emitted when the script becomes active.
+ Any behaviors which were not active last frame that are active
+ this frame will have their \c{onActivate} signaled. If
+ multiple behaviors match this, the signal for parent elements will
+ occur before their descendants.
+ */
+
+/*!
+ \qmlsignal void Behavior::onDeactivate()
+
+ This signal is emitted when the script becomes inactive.
+ Any behaviors which were active last frame that are not active
+ this frame will have their \c{onDeactivate} signaled. If
+ multiple behaviors match this, the signal for parent elements will
+ occur before their descendants.
+ */
+
+/*!
+ \qmlsignal void Behavior::onUpdate()
+
+ This signal is emitted on each frame when the script is active.
+ Any behaviors that are active this frame will have their
+ \c{onUpdate} signaled. If multiple behaviors match this, the signal
+ for parent elements will occur before their descendants.
+ */
+
QT_END_NAMESPACE
diff --git a/src/runtime/doc/doc.pri b/src/runtime/doc/doc.pri
new file mode 100644
index 0000000..6c5dd55
--- /dev/null
+++ b/src/runtime/doc/doc.pri
@@ -0,0 +1,6 @@
+build_online_docs: \
+ QMAKE_DOCS = $$PWD/online/qt3dstudioruntime2.qdocconf
+else: \
+ QMAKE_DOCS = $$PWD/qt3dstudioruntime2.qdocconf
+
+OTHER_FILES += $$PWD/src/*.qdoc
diff --git a/src/doc/online/Qt3DStudioRuntime2.qdocconf b/src/runtime/doc/online/qt3dstudioruntime2.qdocconf
index 4602372..4602372 100644
--- a/src/doc/online/Qt3DStudioRuntime2.qdocconf
+++ b/src/runtime/doc/online/qt3dstudioruntime2.qdocconf
diff --git a/src/runtime/doc/qt3d-runtime-project.qdocconf b/src/runtime/doc/qt3d-runtime-project.qdocconf
new file mode 100644
index 0000000..5cf0998
--- /dev/null
+++ b/src/runtime/doc/qt3d-runtime-project.qdocconf
@@ -0,0 +1,61 @@
+project = Qt3DStudioRuntime2
+description = Qt 3D Studio Runtime Reference Manual
+version = 2.0
+
+# url is relative to the parent project
+url = runtime
+
+sourcedirs += ./src
+imagedirs += ./src/images
+
+sourcedirs += ../api
+headerdirs += ../api
+
+sourcedirs += ../../imports/studio3d
+headerdirs += ../../imports/studio3d
+
+sourcedirs += ../behaviorapi
+headerdirs += ../behaviorapi
+
+depends = qtcore qtgui qtwidgets qtqml qtquick qtdoc qt3dcore qt3drender qt3dlogic qt3danimation
+
+qhp.projects = Qt3DStudioRuntime2
+
+qhp.Qt3DStudioRuntime2.file = qt3dstudioruntime2.qhp
+qhp.Qt3DStudioRuntime2.namespace = io.qt.qt3dstudioruntime2.20
+qhp.Qt3DStudioRuntime2.virtualFolder = qt3dstudioruntime2
+qhp.Qt3DStudioRuntime2.indexTitle = Qt 3D Studio Runtime
+qhp.Qt3DStudioRuntime2.indexRoot =
+
+qhp.Qt3DStudioRuntime2.filterAttributes = qt3dstudioruntime2 2.0
+qhp.Qt3DStudioRuntime2.customFilters.Qt.name = Qt3DStudioRuntime2 2.0
+qhp.Qt3DStudioRuntime2.customFilters.Qt.filterAttributes = qt3dstudioruntime2 2.0
+
+qhp.Qt3DStudioRuntime2.subprojects = manual qmltypes classes
+
+qhp.Qt3DStudioRuntime2.subprojects.manual.title = Qt 3D Studio Runtime
+qhp.Qt3DStudioRuntime2.subprojects.manual.indexTitle = Qt 3D Studio Runtime TOC
+qhp.Qt3DStudioRuntime2.subprojects.manual.type = manual
+
+qhp.Qt3DStudioRuntime2.subprojects.qmltypes.title = QML Types
+qhp.Qt3DStudioRuntime2.subprojects.qmltypes.indexTitle = Qt 3D Studio Runtime QML Types
+qhp.Qt3DStudioRuntime2.subprojects.qmltypes.selectors = qmltype
+qhp.Qt3DStudioRuntime2.subprojects.qmltypes.sortPages = true
+
+qhp.Qt3DStudioRuntime2.subprojects.classes.title = C++ Classes
+qhp.Qt3DStudioRuntime2.subprojects.classes.indexTitle = Qt 3D Studio Runtime C++ Classes
+qhp.Qt3DStudioRuntime2.subprojects.classes.selectors = class fake:headerfile
+qhp.Qt3DStudioRuntime2.subprojects.classes.sortPages = true
+
+# Add an .html file with sidebar content, used in the online style
+HTML.stylesheets += style/qt5-sidebar.html
+
+navigation.homepage = Qt 3D Studio Runtime
+navigation.cppclassespage = Qt 3D Studio Runtime C++ Classes
+navigation.qmltypespage = Qt 3D Studio Runtime QML Types
+buildversion = "Qt 3D Studio Runtime 2.0 Manual"
+
+examplesinstallpath = 3dstudioruntime2
+exampledirs += ../../../examples/3dstudioruntime2
+
+Cpp.ignoretokens += Q3DSV_EXPORT
diff --git a/src/doc/Qt3DStudioRuntime2.qdocconf b/src/runtime/doc/qt3dstudioruntime2.qdocconf
index 6f5f526..6f5f526 100644
--- a/src/doc/Qt3DStudioRuntime2.qdocconf
+++ b/src/runtime/doc/qt3dstudioruntime2.qdocconf
diff --git a/src/runtime/doc/src/attributenames.html b/src/runtime/doc/src/attributenames.html
new file mode 100644
index 0000000..422c617
--- /dev/null
+++ b/src/runtime/doc/src/attributenames.html
@@ -0,0 +1,911 @@
+\raw HTML
+<table id='scripting-attributes'>
+<tbody></tbody>
+<tr><th colspan="4">Scenes</td></tr>
+<tr>
+<td class='formal'>Name</td>
+<td class='scripting'>name</td>
+<td class='type'>string</td>
+</tr>
+<tr>
+<td class='formal'>Enable Background Color</td>
+<td class='scripting'>bgcolorenable</td>
+<td class='type'>boolean</td>
+</tr>
+<tr>
+<td class='formal'>Background Color R</td>
+<td class='scripting'>backgroundcolor.r</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Background Color G</td>
+<td class='scripting'>backgroundcolor.g</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Background Color B</td>
+<td class='scripting'>backgroundcolor.b</td>
+<td class='type'>number</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Elements other than Scenes</td></tr>
+<tr>
+<td class='formal'>Element Name</td>
+<td class='scripting'>name</td>
+<td class='type'>string</td>
+</tr>
+<tr>
+<td class='formal'>(Eyeball)</td>
+<td class='scripting'>eyeball</td>
+<td class='type'>boolean</td>
+</tr>
+<tr>
+<td class='formal'>Timebar Start</td>
+<td class='scripting'>starttime</td>
+<td class='type'>number</td>
+<td class='note'>
+in integer milliseconds
+</td>
+</tr>
+<tr>
+<td class='formal'>Timebar End</td>
+<td class='scripting'>endtime</td>
+<td class='type'>number</td>
+<td class='note'>
+in integer milliseconds
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Layers</td></tr>
+<tr>
+<td class='formal'>Disable Depth Test</td>
+<td class='scripting'>disabledepthtest</td>
+<td class='type'>boolean</td>
+</tr>
+<tr>
+<td class='formal'>Progressive AA</td>
+<td class='scripting'>progressiveaa</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'None'</code>, <code>'2x'</code>, <code>'4x'</code>, <code>'8x'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Multisample AA</td>
+<td class='scripting'>multisampleaa</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'None'</code>, <code>'2x'</code>, <code>'4x'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Temporal AA</td>
+<td class='scripting'>temporalaa</td>
+<td class='type'>boolean</td>
+</tr>
+<tr>
+<td class='formal'>Layer Background</td>
+<td class='scripting'>background</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Transparent'</code>, <code>'Unspecified'</code>, <code>'SolidColor'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Background Color R</td>
+<td class='scripting'>backgroundcolor.r</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Background Color G</td>
+<td class='scripting'>backgroundcolor.g</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Background Color B</td>
+<td class='scripting'>backgroundcolor.b</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Blend Type</td>
+<td class='scripting'>blendtype</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Normal'</code>, <code>'Screen'</code>, <code>'Multiply'</code>, <code>'Add'</code>, <code>'*Overlay'</code>, <code>'*ColorBurn'</code>, <code>'*ColorDodge'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Horizontal Fields</td>
+<td class='scripting'>horzfields</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Left/Width'</code>, <code>'Left/Right'</code>, <code>'Width/Right'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Left</td>
+<td class='scripting'>left</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Left Units</td>
+<td class='scripting'>leftunits</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'pixels'</code>, <code>'percent'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Width</td>
+<td class='scripting'>width</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Width Units</td>
+<td class='scripting'>widthunits</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'pixels'</code>, <code>'percent'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Right</td>
+<td class='scripting'>right</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Right Units</td>
+<td class='scripting'>rightunits</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'pixels'</code>, <code>'percent'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Vertical Fields</td>
+<td class='scripting'>vertfields</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Top/Height'</code>, <code>'Top/Bottom'</code>, <code>'Height/Bottom'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Top</td>
+<td class='scripting'>top</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Top Units</td>
+<td class='scripting'>topunits</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'pixels'</code>, <code>'percent'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Height</td>
+<td class='scripting'>height</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Height Units</td>
+<td class='scripting'>heightunits</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'pixels'</code>, <code>'percent'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Bottom</td>
+<td class='scripting'>bottom</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Bottom Units</td>
+<td class='scripting'>bottomunits</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'pixels'</code>, <code>'percent'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Ambient Occlusion</td>
+<td class='scripting'>aostrength</td>
+<td class='type'>number</td>
+<td class='note'>
+values between 0 and 100
+</td>
+</tr>
+<tr>
+<td class='formal'>AO Distance</td>
+<td class='scripting'>aodistance</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>AO Softness</td>
+<td class='scripting'>aosoftness</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>AO Threshold</td>
+<td class='scripting'>aobias</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>AO Sampling Rate</td>
+<td class='scripting'>aosamplerate</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>AO Dithering</td>
+<td class='scripting'>aodither</td>
+<td class='type'>boolean</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Strength</td>
+<td class='scripting'>shadowstrength</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Distance</td>
+<td class='scripting'>shadowdist</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Softness</td>
+<td class='scripting'>shadowsoftness</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Threshold</td>
+<td class='scripting'>shadowbias</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Light Probe</td>
+<td class='scripting'>lightprobe</td>
+<td class='type'>image element</td>
+</tr>
+<tr>
+<td class='formal'>IBL Horizon Cutoff</td>
+<td class='scripting'>probehorizon</td>
+<td class='type'>number</td>
+<td class='note'>
+values from -1 (no horizon) to -0.001 (hard edge)
+</td>
+</tr>
+<tr>
+<td class='formal'>Sub-Presentation</td>
+<td class='scripting'>sourcepath</td>
+<td class='type'>string</td>
+<td class='note'>
+id of the sub-presentation to display
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Nodes</td></tr>
+<tr>
+<td class='formal'>Position X</td>
+<td class='scripting'>position.x</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Position Y</td>
+<td class='scripting'>position.y</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Position Z</td>
+<td class='scripting'>position.z</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Rotation X</td>
+<td class='scripting'>rotation.x</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Rotation Y</td>
+<td class='scripting'>rotation.y</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Rotation Z</td>
+<td class='scripting'>rotation.z</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Scale X</td>
+<td class='scripting'>scale.x</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Scale Y</td>
+<td class='scripting'>scale.y</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Scale Z</td>
+<td class='scripting'>scale.z</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Pivot X</td>
+<td class='scripting'>pivot.x</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Pivot Y</td>
+<td class='scripting'>pivot.y</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Pivot Z</td>
+<td class='scripting'>pivot.z</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Opacity</td>
+<td class='scripting'>opacity</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'></td>
+<td class='scripting'>orientation</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Left Handed'</code>, <code>'Right Handed'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'></td>
+<td class='scripting'>rotationorder</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'XYZ'</code>, <code>'YZX'</code>, <code>'ZXY'</code>, <code>'XZY'</code>, <code>'YXZ'</code>, <code>'ZYX'</code>, <code>'XYZr'</code>, <code>'YZXr'</code>, <code>'ZXYr'</code>, <code>'XZYr'</code>, <code>'YXZr'</code>, <code>'ZYXr'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'></td>
+<td class='scripting'>ignoresparent</td>
+<td class='type'>boolean</td>
+<td class='note'>
+prevents parent transformation from being applied [ignored as of 2.0]
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Aliases</td></tr>
+<tr>
+<td class='formal'>Reference</td>
+<td class='scripting'>referencednode</td>
+<td class='type'>string</td>
+<td class='note'>
+relative or absolute element path
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Cameras</td></tr>
+<tr>
+<td class='formal'>Orthographic</td>
+<td class='scripting'>orthographic</td>
+<td class='type'>boolean</td>
+</tr>
+<tr>
+<td class='formal'>Field of View</td>
+<td class='scripting'>fov</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Clipping Start</td>
+<td class='scripting'>clipnear</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Clipping End</td>
+<td class='scripting'>clipfar</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Runtime Scale Mode</td>
+<td class='scripting'>scalemode</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Fit'</code>, <code>'Same Size'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Runtime Scale Anchor</td>
+<td class='scripting'>scaleanchor</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Center'</code>, <code>'NW'</code>, <code>'N'</code>, <code>'NE'</code>, <code>'E'</code>, <code>'SE'</code>, <code>'S'</code>, <code>'SW'</code>, <code>'W'</code>
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Lights</td></tr>
+<tr>
+<td class='formal'>Scope</td>
+<td class='scripting'>scope</td>
+<td class='type'>string</td>
+<td class='note'>
+full path to the element
+</td>
+</tr>
+<tr>
+<td class='formal'>Light Type</td>
+<td class='scripting'>lighttype</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Directional'</code>, <code>'Point'</code>, <code>'Area'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Light Color R</td>
+<td class='scripting'>lightdiffuse.r</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Light Color G</td>
+<td class='scripting'>lightdiffuse.g</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Light Color B</td>
+<td class='scripting'>lightdiffuse.b</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Specular Color R</td>
+<td class='scripting'>lightspecular.r</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Specular Color G</td>
+<td class='scripting'>lightspecular.g</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Specular Color B</td>
+<td class='scripting'>lightspecular.b</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Ambient Color R</td>
+<td class='scripting'>lightambient.r</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Ambient Color G</td>
+<td class='scripting'>lightambient.g</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Ambient Color B</td>
+<td class='scripting'>lightambient.b</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Brightness</td>
+<td class='scripting'>brightness</td>
+<td class='type'>number</td>
+<td class='note'>
+only applies to point lights
+</td>
+</tr>
+<tr>
+<td class='formal'>Linear Fade</td>
+<td class='scripting'>linearfade</td>
+<td class='type'>number</td>
+<td class='note'>
+only applies to point lights
+</td>
+</tr>
+<tr>
+<td class='formal'>Exponential Fade</td>
+<td class='scripting'>expfade</td>
+<td class='type'>number</td>
+<td class='note'>
+only applies to point lights
+</td>
+</tr>
+<tr>
+<td class='formal'>Cast Shadows?</td>
+<td class='scripting'>castshadow</td>
+<td class='type'>boolean</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Darkness</td>
+<td class='scripting'>shdwfactor</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Softness</td>
+<td class='scripting'>shdwfilter</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Resolution</td>
+<td class='scripting'>shdwmapres</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'256'</code>, <code>'512'</code>, <code>'1024'</code>, <code>'2048'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Depth Bias</td>
+<td class='scripting'>shdwbias</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Far Clip</td>
+<td class='scripting'>shdwmapfar</td>
+<td class='type'>number</td>
+<tr>
+<td class='formal'>Shadow Field of View</td>
+<td class='scripting'>shdwmapfov</td>
+<td class='type'>number</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Groups</td></tr>
+<tr>
+<td class='formal'>Import</td>
+<td class='scripting'>sourcepath</td>
+<td class='type'>string</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Text</td></tr>
+<tr>
+<td class='formal'>Text String</td>
+<td class='scripting'>textstring</td>
+<td class='type'>string</td>
+</tr>
+<tr>
+<td class='formal'>Text Color R</td>
+<td class='scripting'>textcolor.r</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Text Color G</td>
+<td class='scripting'>textcolor.g</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Text Color B</td>
+<td class='scripting'>textcolor.b</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Font</td>
+<td class='scripting'>font</td>
+<td class='type'>string</td>
+</tr>
+<tr>
+<td class='formal'>Font Size</td>
+<td class='scripting'>size</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Horizontal Alignment</td>
+<td class='scripting'>horzalign</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Left'</code>, <code>'Center'</code>, <code>'Right'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Vertical Alignment</td>
+<td class='scripting'>vertalign</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Top'</code>, <code>'Middle'</code>, <code>'Bottom'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Leading</td>
+<td class='scripting'>leading</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Tracking</td>
+<td class='scripting'>tracking</td>
+<td class='type'>number</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Models</td></tr>
+<tr>
+<td class='formal'>Mesh</td>
+<td class='scripting'>sourcepath</td>
+<td class='type'>string</td>
+</tr>
+<tr>
+<td class='formal'>Tessellation Mode</td>
+<td class='scripting'>tessellation</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'None'</code>, <code>'Linear'</code>, <code>'Phong'</code>, <code>'NPatch'</code> [ignored as of 2.0]
+</td>
+</tr>
+<tr>
+<td class='formal'>Edge Tessellation Value</td>
+<td class='scripting'>edgetess</td>
+<td class='type'>number</td>
+<td class='note'>
+[ignored as of 2.0]
+</td>
+</tr>
+<tr>
+<td class='formal'>Inner Tessellation Value</td>
+<td class='scripting'>innertess</td>
+<td class='type'>number</td>
+<td class='note'>
+[ignored as of 2.0]
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Standard Materials</td></tr>
+<tr>
+<td class='formal'>Lighting</td>
+<td class='scripting'>shaderlighting</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Vertex'</code>, <code>'Pixel'</code>, <code>'None'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Blending Mode</td>
+<td class='scripting'>blendmode</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Normal'</code>, <code>'Screen'</code>, <code>'Multiply'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Diffuse Color R</td>
+<td class='scripting'>diffuse.r</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Diffuse Color G</td>
+<td class='scripting'>diffuse.g</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Diffuse Color B</td>
+<td class='scripting'>diffuse.b</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Diffuse Map</td>
+<td class='scripting'>diffusemap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Diffuse Map 2</td>
+<td class='scripting'>diffusemap2</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Diffuse Map 3</td>
+<td class='scripting'>diffusemap3</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Reflection</td>
+<td class='scripting'>specularreflection</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Tint R</td>
+<td class='scripting'>speculartint.r</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Specular Tint G</td>
+<td class='scripting'>speculartint.g</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Specular Tint B</td>
+<td class='scripting'>speculartint.b</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Specular Amount</td>
+<td class='scripting'>specularamount</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Specular Map</td>
+<td class='scripting'>specularmap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Model</td>
+<td class='scripting'>specularmodel</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Default'</code>, <code>'KGGX'</code>, <code>'KWard'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Fresnel Power</td>
+<td class='scripting'>fresnelPower</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Index of Refraction</td>
+<td class='scripting'>ior</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Specular Roughness</td>
+<td class='scripting'>specularroughness</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Bump Map</td>
+<td class='scripting'>bumpmap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Normal Map</td>
+<td class='scripting'>normalmap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Bump Amount</td>
+<td class='scripting'>bumpamount</td>
+<td class='type'>number</td>
+<td class='note'>
+affects both bump and normal maps
+</td>
+</tr>
+<tr>
+<td class='formal'>Displacement Map</td>
+<td class='scripting'>displacementmap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Displacement Amount</td>
+<td class='scripting'>displaceamount</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Opacity</td>
+<td class='scripting'>opacity</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Opacity Map</td>
+<td class='scripting'>opacitymap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Emissive Power</td>
+<td class='scripting'>emissivepower</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Emissive Map</td>
+<td class='scripting'>emissivemap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Material References</td></tr>
+<tr>
+<td class='formal'>Referenced Material</td>
+<td class='scripting'>referencedmaterial</td>
+<td class='type'>string</td>
+<td class='note'>
+relative or absolute element path
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Images</td></tr>
+<tr>
+<td class='formal'>U Repeat</td>
+<td class='scripting'>scaleu</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>V Repeat</td>
+<td class='scripting'>scalev</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Texture Mapping</td>
+<td class='scripting'>mappingmode</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'UV Mapping'</code>, <code>'Environmental Mapping'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>U Tiling</td>
+<td class='scripting'>tilingmodehorz</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Tiled'</code>, <code>'Mirrored'</code>, <code>'No Tiling'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>V Tiling</td>
+<td class='scripting'>tilingmodevert</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Tiled'</code>, <code>'Mirrored'</code>, <code>'No Tiling'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>UV Rotation</td>
+<td class='scripting'>rotationuv</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>U Position</td>
+<td class='scripting'>positionu</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>V Position</td>
+<td class='scripting'>positionv</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>U Pivot</td>
+<td class='scripting'>pivotu</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>V Pivot</td>
+<td class='scripting'>pivotv</td>
+<td class='type'>number</td>
+</tr>
+<tr>
+<td class='formal'>Sub-Presentation</td>
+<td class='scripting'>subpresentation</td>
+<td class='type'>string</td>
+<td class='note'>
+id of the sub-presentation to display
+</td>
+</tr>
+<tr>
+<td class='formal'>Source Path</td>
+<td class='scripting'>sourcepath</td>
+<td class='type'>string</td>
+<td class='note'>
+path to the image
+</td>
+</tr>
+</table>
+\endraw
diff --git a/src/runtime/doc/src/attributenames.qdoc b/src/runtime/doc/src/attributenames.qdoc
new file mode 100644
index 0000000..18282de
--- /dev/null
+++ b/src/runtime/doc/src/attributenames.qdoc
@@ -0,0 +1,71 @@
+!/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** 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$
+**
+****************************************************************************/
+
+// Pull in attributenames.html into qdoc. Note that attributenames.html is
+// manually maintained since 2.0 and is not auto-generated.
+
+/*!
+ \page qt3d-runtime-attribute-names.html
+ \title Attribute Names
+ \keyword Attributes
+
+ Below is a list of the attributes that can be set on the various scene
+ objects via Q3DSPresentation::setAttribute() or Q3DSElement::setAttribute().
+
+ \note vector (e.g. a group's or model's \c rotation) and color (e.g. a
+ material's \c diffuse) attributes allow setting/getting all components in
+ one operation, and are mapped to QVector3D and QColor, respectively.
+
+ \note As of Qt 3D Studio 2.0 not all properties can be changed on the fly at
+ run time. As a general rule attributes that are animatable in the Qt 3D
+ Studio application are freely changeable by the applications during run time
+ as well.
+
+ \note When possible, applications are recommended to rely on the \c{data
+ input} functionality of Qt 3D Studio instead. This avoids the need to refer
+ to hard-coded attribute names, and instead allows the designers to expose
+ the interesting attributes with arbitrary data input names to the
+ application developers, thus offering a fixed, well-known interface from the
+ 3D presentation to the application code. See \l Q3DSDataInput and
+ \l DataInput for more information.
+
+ \include attributenames.html
+
+ Custom materials and effects have their custom set of properties that are
+ defined in the \c{.material} or \c{.effect} file. For example, an instances
+ of an effect with the following metadata will have an attribute \c HBlurBias
+ with the type \c number that can be set and queried as if it was a built-in
+ attribute.
+
+ \badcode
+ <Effect>
+ <MetaData>
+ <Property name="HBlurBias" formalName="Horizontal Blur" min="0" max="10" default="2" description="Amount of corona horizontally."/>
+ ...
+ \endcode
+*/
diff --git a/src/doc/src/copyright.qdoc b/src/runtime/doc/src/copyright.qdoc
index 01275f1..01275f1 100644
--- a/src/doc/src/copyright.qdoc
+++ b/src/runtime/doc/src/copyright.qdoc
diff --git a/src/doc/src/embedded.qdoc b/src/runtime/doc/src/embedded.qdoc
index f665582..095a46d 100644
--- a/src/doc/src/embedded.qdoc
+++ b/src/runtime/doc/src/embedded.qdoc
@@ -29,5 +29,4 @@
\page qt3d-runtime-embedded.html
\title Using the Runtime on Embedded Devices
- embedded stuff (eglfs etc.)
*/
diff --git a/src/doc/src/examples.qdoc b/src/runtime/doc/src/examples.qdoc
index 86cab63..3d70a2c 100644
--- a/src/doc/src/examples.qdoc
+++ b/src/runtime/doc/src/examples.qdoc
@@ -33,4 +33,25 @@
Included in Qt 3D Studio Runtime you will find a set of examples. These are
located in the \c {examples} folder in the installation folder.
+
+ \section1 QML Examples
+
+ \list
+ \li \l {Qt 3D Studio Runtime: Simple QML Example}
+ \li \l {Qt 3D Studio Runtime: QML DataInput Example}
+ \endlist
+
+ \section1 C++ Examples
+
+ \list
+ \li \l {Qt 3D Studio Runtime: Simple Window Example}
+ \li \l {Qt 3D Studio Runtime: Simple Widget Example}
+ \li \l {Qt 3D Studio Runtime: Simple Offscreen Example}
+ \endlist
+
+ \section1 More Examples
+
+ You can find more examples from
+ \l{https://git.qt.io/public-demos/qt3dstudio}, these examples are more
+ visually appealing and suitable to use as demos for example.
*/
diff --git a/src/runtime/doc/src/gettingstarted.qdoc b/src/runtime/doc/src/gettingstarted.qdoc
new file mode 100644
index 0000000..a0cef3f
--- /dev/null
+++ b/src/runtime/doc/src/gettingstarted.qdoc
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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-gettingstarted.html
+ \title Getting Started
+
+ The Qt 3D Studio Runtime provides C++ and QML APIs for integrating Qt 3D
+ Studio scenes into Qt applications, as well as the viewer application that
+ is used in combination with the Qt 3D Studio application during the design
+ phase.
+
+ Below is an example scene in the Qt 3D Studio application.
+
+ \image intro-editor.png
+
+ During the design phase, the standalone viewer is typically launched from
+ the editor several times to check and verify the presentation in the
+ runtime.
+
+ \image intro-viewer.png
+
+ Once the design is done and the \c{.uia}, \c{.uip}, and other asset files
+ are available, these can be loaded, rendered, and manipulated in Qt
+ applications. This is done via the APIs provided in the \c 3dstudioruntime2
+ module and the \c QtStudio3D QML plugin.
+
+ Below is the same scene loaded into a simple Qt Quick application
+ (the \l{Qt 3D Studio Runtime: Simple QML Example}{simpleqml
+ example}) that composes the 3D content with the other Qt Quick
+ items, for example the ones provided by \l{Qt Quick Controls
+ 2}. In addition to displaying the presentation, the application
+ can also control many aspects of it (slides, timeline, object
+ properties) and can react on certain conditions, such as when a 3D
+ object is clicked on (picked) by mouse or touch input.
+
+ \image intro-app.png
+
+ To profile, debug, and tune the presentation, the runtime provides a
+ built-in, in-scene debug pane that can be toggled both from the viewer and,
+ optionally, from applications as well.
+
+ \image intro-viewer-profile.png
+
+ \section1 Rendering Scenes
+
+ APIs are provided for the following Qt UI technologies:
+
+ \list
+
+ \li Qt Quick: here applications import QtStudio3D 2.0 which provides the
+ \l Studio3D QML type, a Qt Quick item that can be added to Qt Quick scenes.
+ Under the hood this is similar to adding a \l Scene3D (when working
+ directly with the lower level Qt 3D framework) or a custom item based on
+ \l QQuickFramebufferObject into the scene.
+
+ \li Widgets: Q3DSWidget is a QOpenGLWidget subclass that displays Qt 3D
+ Studio scenes.
+
+ \li QWindow or offscreen render targets (OpenGL texture): Q3DSSurfaceViewer
+ can be used both to render to an on-screen QWindow, as well as off-screen
+ into an OpenGL texture. The latter allows reading back and saving the
+ frames, to generate pre-rendered video sequences for example.
+
+ \endlist
+
+ \section1 Manipulating Scenes
+
+ Rendering Qt 3D Studio scenes is only part of the story since many scenes
+ are not static and will not just display all their contents as they were
+ done by designers in the Qt 3D Studio application. Rather, properties of
+ scene objects (for example, the rotation property of a 3D model, or the
+ diffuse color of the material associated with such a model) may need to be
+ changed dynamically, at run time. The timeline or the current slide may
+ also need to be adjusted based on the user's actions or other application
+ state.
+
+ As of Qt 3D Studio 2.0 such functionality is exposed via the
+ Q3DSPresentation (\l Presentation), Q3DSElement (\l Element),
+ Q3DSSceneElement (\l SceneElement), and Q3DSDataInput (\l DataInput)
+ objects. Advanced scene manipulation (for instance dynamically spawning and
+ removing objects in the 3D scene) will be introduced in future versions.
+*/
diff --git a/src/runtime/doc/src/images/intro-app.png b/src/runtime/doc/src/images/intro-app.png
new file mode 100644
index 0000000..3658190
--- /dev/null
+++ b/src/runtime/doc/src/images/intro-app.png
Binary files differ
diff --git a/src/runtime/doc/src/images/intro-editor.png b/src/runtime/doc/src/images/intro-editor.png
new file mode 100644
index 0000000..52e5a69
--- /dev/null
+++ b/src/runtime/doc/src/images/intro-editor.png
Binary files differ
diff --git a/src/runtime/doc/src/images/intro-viewer-profile.png b/src/runtime/doc/src/images/intro-viewer-profile.png
new file mode 100644
index 0000000..24d23ad
--- /dev/null
+++ b/src/runtime/doc/src/images/intro-viewer-profile.png
Binary files differ
diff --git a/src/runtime/doc/src/images/intro-viewer.png b/src/runtime/doc/src/images/intro-viewer.png
new file mode 100644
index 0000000..f36d57b
--- /dev/null
+++ b/src/runtime/doc/src/images/intro-viewer.png
Binary files differ
diff --git a/src/doc/src/index.qdoc b/src/runtime/doc/src/index.qdoc
index a2c5282..43d8b18 100644
--- a/src/doc/src/index.qdoc
+++ b/src/runtime/doc/src/index.qdoc
@@ -26,22 +26,21 @@
****************************************************************************/
/*!
-\keyword Qt 3D Studio Runtime
-\title Qt 3D Studio Runtime Index
-\page index.html
+\title Qt 3D Studio Runtime
+\page qt3d-runtime-index.html
\section1 Table of Contents
\list
\li \l {Getting Started}
- \li \l {Qt 3D Studio Runtime C++ Classes}
- \li \l {Qt 3D Studio Runtime QML Types}
+ \li \l {System and Application Requirements}
\li \l {Using the Runtime on Android/iOS Devices}
\li \l {Using the Runtime on Embedded Devices}
+ \li \l {Qt 3D Studio Runtime C++ Classes}
+ \li \l {Qt 3D Studio Runtime QML Types}
+ \li \l {Attribute Names}{Scene object attribute list}
\li \l {Examples}
\li \l {Copyright Notices}
\endlist
-blah blah blah
-
*/
diff --git a/src/doc/src/mobile.qdoc b/src/runtime/doc/src/mobile.qdoc
index 1787b63..45fd6a0 100644
--- a/src/doc/src/mobile.qdoc
+++ b/src/runtime/doc/src/mobile.qdoc
@@ -29,5 +29,4 @@
\page qt3d-runtime-mobile.html
\title Using the Runtime on Android/iOS Devices
- mobile stuff
*/
diff --git a/src/doc/src/module.qdoc b/src/runtime/doc/src/module.qdoc
index d37417f..d37417f 100644
--- a/src/doc/src/module.qdoc
+++ b/src/runtime/doc/src/module.qdoc
diff --git a/src/runtime/doc/src/requirements.qdoc b/src/runtime/doc/src/requirements.qdoc
new file mode 100644
index 0000000..1bec57e
--- /dev/null
+++ b/src/runtime/doc/src/requirements.qdoc
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** 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-requirements.html
+ \title System and Application Requirements
+
+ \section1 OpenGL Requirements
+
+ Qt 3D Studio requires OpenGL or OpenGL ES. The recommended minimum versions
+ are \c{3.3 core profile} and \c{3.0}, respectively.
+
+ When it comes to OpenGL ES, a limited subset of the functionality is
+ available when running on plain \c{OpenGL ES 2.0} implementations. In
+ practice this means losing shadow mapping, image based lighting, and many
+ other advanced features and is therefore not recommended. On the other hand,
+ this allows bringing up Qt 3D Studio scenes on boards like the Raspberry Pi
+ (with the original proprietary graphics stack) or the Beaglebone Black, or
+ in hypervisor-based virtualized environments where the GPU virtualization
+ only supports GLES 2.0, and can therefore still be valuable in certain
+ special situations.
+
+ Non-native implementations, like \c ANGLE or software implementations like
+ \c{Mesa's llvmpipe} may work but are not tested and can fail in unexpected
+ ways.
+
+ As of version 2.0 the Qt 3D Studio Runtime is implemented on top of Qt
+ 3D. This means that most graphics API and windowing system bits are
+ abstracted and hidden from the runtime. However, there are still direct
+ OpenGL dependencies in a few places and, more importantly, the standard
+ material, custom materials, and effects all rely on GLSL. Therefore other
+ graphics APIs, such as, Vulkan or Direct 3D, cannot be supported at this
+ time.
+
+ \section1 Application Integration Notes
+
+ \section2 C++
+
+ A typical Qt C++ application using the Qt 3D Studio Runtime is expected to
+ query and honor the runtime's \c{ideal surface format}. This way the OpenGL
+ contexts will all be created with the OpenGL version and profile that best
+ match the runtime's needs:
+
+ \badcode
+ #include <Q3DSWidget> // or <q3dsruntimeglobal.h> if only Q3DS::surfaceFormat() is interesting for main()
+
+ int main(int argc, char *argv[])
+ {
+ QApplication app(argc, argv);
+
+ QSurfaceFormat::setDefaultFormat(Q3DS::surfaceFormat());
+
+ Q3DSWidget w;
+ ...
+ return app.exec();
+ }
+ \endcode
+
+ To enable using Qt 3D Studio headers and libraries in the application, add
+ the \c 3dstudioruntime2 module in the application's \c{.pro} file:
+
+ \badcode
+ QT += 3dstudioruntime2
+ \endcode
+
+ \section2 QML/Qt Quick
+
+ When no C++ classes are used, the \c 3dstudioruntime2 module can be omitted
+ in the \c{.pro}. To use the \l Studio3D element in QML code, it is enough to add the
+ corresponding import statement:
+
+ \badcode
+ import QtStudio3D 2.0
+ \endcode
+
+ It is nonetheless strongly recommended to set the the default surface format
+ as shown above. Make sure the
+ \c{QSurfaceFormat::setDefaultFormat(Q3DS::surfaceFormat())} call is made
+ after constructing QGuiApplication but before the first QQuickWindow or
+ QQuickView. When this is not possible, for example because the QML contents
+ is hosted in an application that has no knowledge of the Qt Quick scene's 3D
+ needs, Studio3D may still be usable but this may be dependent on the OpenGL
+ implementation and the context versions it offers, and is therefore more fragile.
+*/
diff --git a/src/doc/src/gettingstarted.qdoc b/src/runtime/doc/src/toc.qdoc
index 2f5ae37..9e28102 100644
--- a/src/doc/src/gettingstarted.qdoc
+++ b/src/runtime/doc/src/toc.qdoc
@@ -26,8 +26,15 @@
****************************************************************************/
/*!
- \page qt3d-runtime-gettingstarted.html
- \title Getting Started
+\contentspage {Qt 3D Studio Runtime}
+\page qt3d-runtime-toc.html
+\title Qt 3D Studio Runtime TOC
- Basic blah blah
+\omit
+This file is used for generating a TOC in a .qch file.
+\endomit
+
+\list
+ \li \l {index.html}{Overview}
+\endlist
*/
diff --git a/src/runtime/doc/style/qt5-sidebar.html b/src/runtime/doc/style/qt5-sidebar.html
new file mode 100644
index 0000000..53a2bbe
--- /dev/null
+++ b/src/runtime/doc/style/qt5-sidebar.html
@@ -0,0 +1,28 @@
+<div class="sectionlist normallist">
+ <div>
+ <a name="reference"></a>
+ <h2 id="reference">Qt 3D Studio Runtime</h2>
+ </div>
+ <div class="indexboxcont indexboxbar">
+ <ul>
+ <li><a href="qt3d-runtime-index.html">Home</a></li>
+ <li><a href="qt3d-runtime-gettingstarted.html">Getting Started</a></li>
+ <li><a href="qt3d-runtime-qml.html">QML API Reference</a></li>
+ <li><a href="qt3d-runtime-cpp.html">C++ API Reference</a></li>
+ <li><a href="qt3d-runtime-attribute-names.html">Scene Object Attributes</a></li>
+ <li><a href="qt3d-runtime-examples-examples.html">Examples</a></li>
+ <li><a href="copyright-notices.html">Copyright Notices</a></li>
+ </ul>
+ </div>
+</div>
+<div class="sectionlist normallist">
+ <div>
+ <a name="reference"></a>
+ <h2 id="reference">Qt 3D Studio</h2>
+ </div>
+ <div class="indexboxcont indexboxbar">
+ <ul>
+ <li><a href="../index.html">Home</a></li>
+ </ul>
+ </div>
+</div>
diff --git a/src/runtime/q3dsanimationmanager.cpp b/src/runtime/q3dsanimationmanager.cpp
index 474a54d..9c8eadb 100644
--- a/src/runtime/q3dsanimationmanager.cpp
+++ b/src/runtime/q3dsanimationmanager.cpp
@@ -509,23 +509,28 @@ void Q3DSAnimationManager::updateAnimationHelper(const AnimationTrackListMap<T *
class DummyCallback : public Qt3DAnimation::QAnimationCallback
{
public:
- DummyCallback(Q3DSSlide *slide, Q3DSSlidePlayer* slidePlayer)
- : m_slide(slide), m_slidePlayer(slidePlayer) {}
+ DummyCallback(Q3DSSlide *slide)
+ : m_slide(slide) {}
void valueChanged(const QVariant &value) override {
Q_ASSERT(m_slide);
- Q_ASSERT(m_slidePlayer);
+ const float newValue = value.toFloat();
+ if (qFuzzyCompare(m_previousValue, newValue))
+ return;
+
+ Q3DSSlidePlayer *slidePlayer = m_slide->attached<Q3DSSlideAttached>()->slidePlayer;
// TODO: See QT3DS-1302
- if (m_slidePlayer != m_slide->attached<Q3DSSlideAttached>()->slidePlayer)
+ if (!slidePlayer)
return;
- m_slidePlayer->setSlideTime(m_slide, value.toFloat() * 1000.0f);
+ slidePlayer->setSlideTime(m_slide, newValue * 1000.0f);
+ m_previousValue = newValue;
}
private:
Q3DSSlide *m_slide;
- Q3DSSlidePlayer *m_slidePlayer;
+ float m_previousValue = -1.0f;
};
void Q3DSAnimationManager::clearAnimations(Q3DSSlide *slide)
@@ -613,7 +618,7 @@ void Q3DSAnimationManager::buildClipAnimator(Q3DSSlide *slide)
QChannelMapper *mapper = new QChannelMapper;
QCallbackMapping *mapping = new QCallbackMapping;
mapping->setChannelName(channelName);
- mapping->setCallback(QMetaType::Float, new DummyCallback(slide, m_slidePlayer));
+ mapping->setCallback(QMetaType::Float, new DummyCallback(slide));
mapper->addMapping(mapping);
animator->setChannelMapper(mapper);
// TODO: We could just use this to get the time values directly...
diff --git a/src/runtime/q3dsanimationmanager_p.h b/src/runtime/q3dsanimationmanager_p.h
index 47ec31e..88f1e05 100644
--- a/src/runtime/q3dsanimationmanager_p.h
+++ b/src/runtime/q3dsanimationmanager_p.h
@@ -50,8 +50,6 @@ QT_BEGIN_NAMESPACE
class Q3DSAnimationManager
{
public:
- Q3DSAnimationManager(Q3DSSlidePlayer *slidePlayer) : m_slidePlayer(slidePlayer) {}
-
void updateAnimations(Q3DSSlide *slide, bool editorMode = false);
void clearAnimations(Q3DSSlide *slide);
void applyChanges();
@@ -106,7 +104,6 @@ private:
QMultiHash<Q3DSGraphObject *, AnimationValueChange> m_changes;
- Q3DSSlidePlayer *m_slidePlayer;
QSet<Q3DSGraphObject *> m_activeTargets;
friend class Q3DSAnimationCallback;
diff --git a/src/runtime/q3dsengine.cpp b/src/runtime/q3dsengine.cpp
index 30c7a44..5faae2c 100644
--- a/src/runtime/q3dsengine.cpp
+++ b/src/runtime/q3dsengine.cpp
@@ -90,6 +90,8 @@ static const int MAX_LOG_MESSAGE_LENGTH = 1000;
static const int MAX_LOG_LENGTH = 10000;
static Q3DSGraphicsLimits gfxLimits;
+static bool surfaceFormatAdopted = false;
+static QSurfaceFormat adoptedSurfaceFormat;
static QMutex q3ds_msg_mutex;
static QStringList q3ds_msg_buf;
@@ -190,6 +192,25 @@ static void initGraphicsLimits(QOpenGLContext *ctx)
gfxLimits.multisampleTextureSupported = QOpenGLTexture::hasFeature(QOpenGLTexture::TextureMultisample);
qDebug(" multisample textures: %s", gfxLimits.multisampleTextureSupported ? "true" : "false");
+ auto extensions = ctx->extensions();
+ if (!extensions.isEmpty()) {
+ gfxLimits.extensions = extensions;
+
+ if (ctx->isOpenGLES() && ctx->format().majorVersion() == 2) {
+ gfxLimits.shaderTextureLodSupported = false;
+ gfxLimits.shaderUniformBufferSupported = false;
+ gfxLimits.packedDepthStencilBufferSupported = false;
+ }
+ if (extensions.contains("GL_EXT_shader_texture_lod"))
+ gfxLimits.shaderTextureLodSupported = true;
+ qDebug(" texture lod: %s", gfxLimits.shaderTextureLodSupported ? "true" : "false");
+
+ if (extensions.contains("GL_EXT_packed_depth_stencil"))
+ gfxLimits.packedDepthStencilBufferSupported = true;
+ qDebug(" packed depth-stencil: %s", gfxLimits.packedDepthStencilBufferSupported ? "true" : "false");
+ }
+ qDebug() << " extensions: " << extensions;
+
// version string bonanza for the profiler
const char *rendererStr = reinterpret_cast<const char *>(f->glGetString(GL_RENDERER));
if (rendererStr) {
@@ -207,22 +228,6 @@ static void initGraphicsLimits(QOpenGLContext *ctx)
qDebug(" version: %s", versionStr);
}
- auto extensions = ctx->extensions();
- if (!extensions.isEmpty()) {
- gfxLimits.extensions = extensions;
- qDebug() << " extensions: " << extensions;
-
- if (ctx->isOpenGLES() && ctx->format().majorVersion() == 2) {
- gfxLimits.shaderTextureLodSupported = false;
- gfxLimits.shaderUniformBufferSupported = false;
- gfxLimits.packedDepthStencilBufferSupported = false;
- }
- if (extensions.contains("GL_EXT_shader_texture_lod"))
- gfxLimits.shaderTextureLodSupported = true;
- if (extensions.contains("GL_EXT_packed_depth_stencil"))
- gfxLimits.packedDepthStencilBufferSupported = true;
- }
-
gfxLimits.format = ctx->format();
ctx->doneCurrent();
@@ -300,7 +305,7 @@ static QSurfaceFormat findIdealGLESVersion()
return fmt;
}
-QSurfaceFormat Q3DSEngine::surfaceFormat()
+static QSurfaceFormat idealSurfaceFormat()
{
static const QSurfaceFormat f = [] {
QSurfaceFormat fmt;
@@ -318,14 +323,33 @@ QSurfaceFormat Q3DSEngine::surfaceFormat()
}
namespace Q3DS {
+void adoptSurfaceFormat(const QSurfaceFormat &format)
+{
+ QSurfaceFormat adjustedFormat = format;
+ adjustedFormat.setDepthBufferSize(24);
+ adjustedFormat.setStencilBufferSize(8);
+ QOpenGLContext ctx;
+ ctx.setFormat(adjustedFormat);
+ if (ctx.create()) {
+ initGraphicsLimits(&ctx);
+ adoptedSurfaceFormat = adjustedFormat;
+ surfaceFormatAdopted = true;
+ } else {
+ qWarning() << "Failed to create OpenGL context with adopted surface format" << adjustedFormat;
+ }
+}
+
QSurfaceFormat surfaceFormat()
{
- return Q3DSEngine::surfaceFormat();
+ return surfaceFormatAdopted ? adoptedSurfaceFormat : idealSurfaceFormat();
}
Q3DSGraphicsLimits graphicsLimits()
{
- Q3DSEngine::surfaceFormat();
+ if (!surfaceFormatAdopted) {
+ // make sure gfxLimits is filled in
+ idealSurfaceFormat();
+ }
return gfxLimits;
}
}
@@ -790,19 +814,41 @@ bool Q3DSEngine::buildSubUipPresentationScene(UipPresentation *pres)
pres->subPres.colorTex->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
pres->subPres.colorTex->setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear);
color->setTexture(pres->subPres.colorTex);
-
- Qt3DRender::QRenderTargetOutput *ds = new Qt3DRender::QRenderTargetOutput;
- ds->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::DepthStencil);
- pres->subPres.dsTex = new Qt3DRender::QTexture2D(entityParent);
- pres->subPres.dsTex->setFormat(Qt3DRender::QAbstractTexture::D24S8);
- pres->subPres.dsTex->setWidth(pres3DS->presentationWidth());
- pres->subPres.dsTex->setHeight(pres3DS->presentationHeight());
- pres->subPres.dsTex->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
- pres->subPres.dsTex->setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear);
- ds->setTexture(pres->subPres.dsTex);
-
rt->addOutput(color);
- rt->addOutput(ds);
+
+ if (gfxLimits.packedDepthStencilBufferSupported) {
+ Qt3DRender::QRenderTargetOutput *ds = new Qt3DRender::QRenderTargetOutput;
+ ds->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::DepthStencil);
+ pres->subPres.depthOrDepthStencilTex = new Qt3DRender::QTexture2D(entityParent);
+ pres->subPres.depthOrDepthStencilTex->setFormat(Qt3DRender::QAbstractTexture::D24S8);
+ pres->subPres.depthOrDepthStencilTex->setWidth(pres3DS->presentationWidth());
+ pres->subPres.depthOrDepthStencilTex->setHeight(pres3DS->presentationHeight());
+ pres->subPres.depthOrDepthStencilTex->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
+ pres->subPres.depthOrDepthStencilTex->setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear);
+ ds->setTexture(pres->subPres.depthOrDepthStencilTex);
+ rt->addOutput(ds);
+ } else {
+ Qt3DRender::QRenderTargetOutput *depth = new Qt3DRender::QRenderTargetOutput;
+ depth->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::Depth);
+ pres->subPres.depthOrDepthStencilTex = new Qt3DRender::QTexture2D(entityParent);
+ pres->subPres.depthOrDepthStencilTex->setFormat(Qt3DRender::QAbstractTexture::D16);
+ pres->subPres.depthOrDepthStencilTex->setWidth(pres3DS->presentationWidth());
+ pres->subPres.depthOrDepthStencilTex->setHeight(pres3DS->presentationHeight());
+ pres->subPres.depthOrDepthStencilTex->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
+ pres->subPres.depthOrDepthStencilTex->setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear);
+ depth->setTexture(pres->subPres.depthOrDepthStencilTex);
+ rt->addOutput(depth);
+ Qt3DRender::QRenderTargetOutput *stencil = new Qt3DRender::QRenderTargetOutput;
+ stencil->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::Stencil);
+ pres->subPres.stencilTex = new Qt3DRender::QTexture2D(entityParent);
+ pres->subPres.stencilTex->setFormat(Qt3DRender::QAbstractTexture::TextureFormat(0x1901)); // GL_STENCIL_INDEX
+ pres->subPres.stencilTex->setWidth(pres3DS->presentationWidth());
+ pres->subPres.stencilTex->setHeight(pres3DS->presentationHeight());
+ pres->subPres.stencilTex->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
+ pres->subPres.stencilTex->setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear);
+ stencil->setTexture(pres->subPres.stencilTex);
+ rt->addOutput(stencil);
+ }
rtSel->setTarget(rt);
params.frameGraphRoot = rtSel;
diff --git a/src/runtime/q3dsengine_p.h b/src/runtime/q3dsengine_p.h
index 946f7a1..841e5e1 100644
--- a/src/runtime/q3dsengine_p.h
+++ b/src/runtime/q3dsengine_p.h
@@ -96,7 +96,6 @@ public:
};
Q_DECLARE_FLAGS(Flags, Flag)
- static QSurfaceFormat surfaceFormat();
static void clearLog();
Flags flags() const { return m_flags; }
diff --git a/src/runtime/q3dsgraphexplorer.cpp b/src/runtime/q3dsgraphexplorer.cpp
index 89d7063..be5973d 100644
--- a/src/runtime/q3dsgraphexplorer.cpp
+++ b/src/runtime/q3dsgraphexplorer.cpp
@@ -234,7 +234,7 @@ Q3DSGraphExplorer::Q3DSGraphExplorer(Q3DSGraphObject *root, QWidget *parent)
s += tr("\n%1 %2").arg((quintptr) slideObj, 0, 16).arg(QString::fromUtf8(slideObj->id()));
if (slide->parent()) {
s += tr("\n\nProperty changes:");
- const QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *> &a = slide->propertyChanges();
+ const auto &a = slide->propertyChanges();
for (auto it = a.cbegin(), ite = a.cend(); it != ite; ++it) {
s += tr("\nOn object %1 %2").arg((quintptr) it.key(), 0, 16).arg(QString::fromUtf8(it.key()->id()));
for (auto pit = it.value()->cbegin(), pite = it.value()->cend(); pit != pite; ++pit)
diff --git a/src/runtime/q3dsruntimeglobal_p.h b/src/runtime/q3dsruntimeglobal_p.h
index 9ed5bf0..4f19bd1 100644
--- a/src/runtime/q3dsruntimeglobal_p.h
+++ b/src/runtime/q3dsruntimeglobal_p.h
@@ -48,6 +48,10 @@
QT_BEGIN_NAMESPACE
+namespace Q3DS {
+Q3DSV_PRIVATE_EXPORT void adoptSurfaceFormat(const QSurfaceFormat &format);
+}
+
QT_END_NAMESPACE
#endif // Q3DSRUNTIMEGLOBAL_P_H
diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp
index 85356e7..877a733 100644
--- a/src/runtime/q3dsscenemanager.cpp
+++ b/src/runtime/q3dsscenemanager.cpp
@@ -514,7 +514,6 @@ void Q3DSSceneManager::setCurrentSlide(Q3DSSlide *newSlide, bool fromSlidePlayer
m_currentSlide = newSlide;
}
-// TODO: Only called from the slide test, but we keep it working for now...
void Q3DSSceneManager::setComponentCurrentSlide(Q3DSComponentNode *component, Q3DSSlide *newSlide)
{
Q3DSSlideAttached *data = component->masterSlide()->attached<Q3DSSlideAttached>();
@@ -537,11 +536,7 @@ void Q3DSSceneManager::setLayerCaching(bool enabled)
void Q3DSSceneManager::prepareAnimators()
{
- auto slideDeck = m_slidePlayer->slideDeck();
- if ((m_slidePlayer->mode() == Q3DSSlidePlayer::PlayerMode::Viewer)
- && (slideDeck->currentSlide()->initialPlayState() == Q3DSSlide::Play)) {
- m_slidePlayer->play();
- }
+ m_slidePlayer->sceneReady();
}
QDebug operator<<(QDebug dbg, const Q3DSSceneManager::SceneBuilderParams &p)
@@ -575,7 +570,7 @@ void Q3DSSceneManager::prepareEngineResetGlobal()
Q3DSShaderManager::instance().invalidate();
}
-/*!
+/*
Builds and "runs" a Qt 3D scene. To be called once per SceneManager instance.
Ownership of the generated Qt 3D objects is managed primarily via parenting
@@ -796,7 +791,7 @@ Q3DSSceneManager::Scene Q3DSSceneManager::buildScene(Q3DSUipPresentation *presen
return sc;
}
-/*!
+/*
To be called on the scenemanager corresponding to the main presentation
once after all subpresentation buildScene() calls have succeeded. This is
where the association of textures and subpresentation layers happens. That
@@ -1214,9 +1209,13 @@ void Q3DSSceneManager::buildSubPresentationLayer(Q3DSLayerNode *layer3DS, const
// Resize the offscreen subpresentation buffers
it->colorTex->setWidth(layerPixelSize.width());
it->colorTex->setHeight(layerPixelSize.height());
- if (it->dsTex) {
- it->dsTex->setWidth(layerPixelSize.width());
- it->dsTex->setHeight(layerPixelSize.height());
+ if (it->depthOrDepthStencilTex) {
+ it->depthOrDepthStencilTex->setWidth(layerPixelSize.width());
+ it->depthOrDepthStencilTex->setHeight(layerPixelSize.height());
+ }
+ if (it->stencilTex) {
+ it->stencilTex->setWidth(layerPixelSize.width());
+ it->stencilTex->setHeight(layerPixelSize.height());
}
// and communicate the new size to the subpresentation's renderer
// (viewport, camera, etc. need to adapt), just like a window would
@@ -6584,77 +6583,6 @@ bool Q3DSSceneManager::isComponentVisible(Q3DSComponentNode *component)
return visible;
}
-void Q3DSSceneManager::handleSlideChange(Q3DSSlide *prevSlide,
- Q3DSSlide *currentSlide)
-{
- Q_ASSERT(currentSlide->attached());
-
- if (prevSlide) {
- auto slideData = static_cast<Q3DSSlideAttached *>(prevSlide->attached());
- for (Q3DSNode *node : qAsConst(slideData->needsMasterRollback)) {
- const Q3DSPropertyChangeList *changeList = node->masterRollbackList();
- if (changeList) {
- qCDebug(lcScene, "Rolling back %d changes to master for %s", changeList->count(), node->id().constData());
- node->applyPropertyChanges(*changeList);
- node->notifyPropertyChanges(*changeList);
- updateSubTreeRecursive(node);
- }
- }
- slideData->needsMasterRollback.clear();
- }
-
- // Find properties on targets that has dynamic properties.
- // TODO: Find a better solution (e.g., there can be duplicate updates for e.g., xyz here).
- QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *> dynamicPropertyChanges;
- QVector<Q3DSPropertyChangeList *> ephemeralObjects;
- const auto &tracks = currentSlide->animations();
- std::find_if(tracks.cbegin(), tracks.cend(), [&dynamicPropertyChanges, &ephemeralObjects](const Q3DSAnimationTrack &track) {
- if (track.isDynamic()) {
- auto foundIt = dynamicPropertyChanges.find(track.target());
- const bool propertyFound = (foundIt != dynamicPropertyChanges.end());
- Q3DSPropertyChangeList *changesList = propertyFound
- ? *foundIt
- : new Q3DSPropertyChangeList;
- if (!propertyFound)
- ephemeralObjects.push_back(changesList);
-
- const QString property = track.property().split('.')[0];
- const auto value = track.target()->propertyValue(property);
- changesList->append(Q3DSPropertyChange::fromVariant(property, value));
-
- if (foundIt == dynamicPropertyChanges.end())
- dynamicPropertyChanges.insert(track.target(), changesList);
- }
- return false;
- });
-
- const auto &propertyChanges = currentSlide->propertyChanges();
-
- // Filter out properties that we needs to be marked dirty, i.e., eyeball changes.
- QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *> notifyPropertyChanges;
- for (auto it = propertyChanges.cbegin(); it != propertyChanges.cend(); ++it) {
- std::find_if((*it)->cbegin(), (*it)->cend(), [it, &notifyPropertyChanges, &ephemeralObjects](const Q3DSPropertyChange &propChange) {
- if (propChange.name() == QLatin1String("eyeball")) {
- Q3DSPropertyChangeList *propChangeList = new Q3DSPropertyChangeList;
- propChangeList->append(propChange);
- ephemeralObjects.push_back(propChangeList);
- notifyPropertyChanges[it.key()] = propChangeList;
- return true;
- }
- return false;
- });
- }
- // We avoid triggering notifications (i.e., setting dirty flags) just yet, as we
- // want to defer that until we're ready.
- m_presentation->applyPropertyChanges(propertyChanges);
- // notify about visibility changes.
- m_presentation->notifyPropertyChanges(notifyPropertyChanges);
- // Now re-apply the original values for those dynamic keyframes.
- m_presentation->applyPropertyChanges(dynamicPropertyChanges);
- // Now clean-up the objects we created.
- qDeleteAll(ephemeralObjects);
-}
-
void Q3DSSceneManager::prepareNextFrame()
{
m_wasDirty = false;
@@ -6883,6 +6811,7 @@ void Q3DSSceneManager::updateSubTreeRecursive(Q3DSGraphObject *obj)
Q3DSModelAttached *modelData = static_cast<Q3DSModelAttached *>(data->model3DS->attached());
data->opacity = modelData->globalOpacity * (mat3DS->opacity() / 100.0f);
updateDefaultMaterial(mat3DS);
+ retagSubMeshes(data->model3DS);
m_wasDirty = true;
markLayerForObjectDirty(mat3DS);
if (data->frameChangeFlags & Q3DSDefaultMaterial::BlendModeChanges)
@@ -6898,6 +6827,7 @@ void Q3DSSceneManager::updateSubTreeRecursive(Q3DSGraphObject *obj)
Q3DSModelAttached *modelData = static_cast<Q3DSModelAttached *>(data->model3DS->attached());
data->opacity = modelData->globalOpacity;
updateCustomMaterial(mat3DS);
+ retagSubMeshes(data->model3DS);
m_wasDirty = true;
markLayerForObjectDirty(mat3DS);
}
@@ -7192,10 +7122,14 @@ void Q3DSSceneManager::changeSlideByName(Q3DSGraphObject *sceneOrComponent, cons
});
if (targetSlide) {
- if (component)
- component->setCurrentSlide(targetSlide);
- else
+ if (component) {
+ if (m_currentSlide->objects().contains(component) || m_masterSlide->objects().contains(component))
+ setComponentCurrentSlide(component, targetSlide);
+ else
+ component->setCurrentSlide(targetSlide);
+ } else {
setCurrentSlide(targetSlide);
+ }
} else {
qWarning("changeSlideByName: Slide %s not found on %s", qPrintable(name), sceneOrComponent->id().constData());
}
@@ -7296,10 +7230,19 @@ void Q3DSSceneManager::setDataInputValue(const QString &dataInputName, const QVa
// timeline length and map the incoming value on it (just because 3DS1
// does it). If min-max is not specified, interpret value directly as
// timeline point in milliseconds
- const float seekTimeMs = meta.hasMinMax()
- ? ((value.toFloat() - meta.minValue) /
- (meta.maxValue - meta.minValue))* obj->endTime()
- : value.toFloat();
+ float seekTimeMs = 0.0f;
+ if (meta.hasMinMax()) {
+ Q_ASSERT(!qFuzzyIsNull(meta.maxValue));
+ const float normalized = qBound(0.0f, (value.toFloat() / (meta.maxValue - meta.minValue)), 1.0f);
+ Q3DSSlide *slide = (obj->type() == Q3DSGraphObject::Component) ? static_cast<Q3DSComponentNode *>(obj)->currentSlide()
+ : m_currentSlide;
+ qint32 startTime = 0;
+ qint32 endTime = 0;
+ Q3DSSlideUtils::getStartAndEndTime(slide, &startTime, &endTime);
+ seekTimeMs = normalized * (endTime - startTime);
+ } else {
+ seekTimeMs = value.toFloat();
+ }
goToTime(obj, seekTimeMs);
} else {
qWarning("Object %s with timeline data input is not Scene or Component", obj->id().constData());
diff --git a/src/runtime/q3dsscenemanager_p.h b/src/runtime/q3dsscenemanager_p.h
index fc494aa..d569284 100644
--- a/src/runtime/q3dsscenemanager_p.h
+++ b/src/runtime/q3dsscenemanager_p.h
@@ -592,7 +592,8 @@ struct Q3DSSubPresentation
QString id;
Q3DSSceneManager *sceneManager = nullptr;
Qt3DRender::QAbstractTexture *colorTex = nullptr;
- Qt3DRender::QAbstractTexture *dsTex = nullptr;
+ Qt3DRender::QAbstractTexture *depthOrDepthStencilTex = nullptr;
+ Qt3DRender::QAbstractTexture *stencilTex = nullptr;
};
struct Q3DSGuiData
@@ -819,8 +820,6 @@ private:
void prepareNextFrame();
bool isComponentVisible(Q3DSComponentNode *component);
- void handleSlideChange(Q3DSSlide *previousSlide,
- Q3DSSlide *currentSlide);
void setNodeVisibility(Q3DSNode *node, bool visible);
void handleSceneChange(Q3DSScene *scene, Q3DSGraphObject::DirtyFlag change, Q3DSGraphObject *obj);
diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp
index fee148c..f7c2ee2 100644
--- a/src/runtime/q3dsslideplayer.cpp
+++ b/src/runtime/q3dsslideplayer.cpp
@@ -44,45 +44,63 @@
QT_BEGIN_NAMESPACE
-// NOTE: We assume that the properties for the layer has been applied before this is called
-// if it hasn't it will either return the previous value or the odl value
void Q3DSSlideUtils::getStartAndEndTime(Q3DSSlide *slide, qint32 *startTime, qint32 *endTime)
{
Q_ASSERT(startTime != nullptr || endTime != nullptr);
- qint32 eTime = -1;
+ qint32 layerEndTime = -1;
+ qint32 nodesEndtime = -1;
- // First go through the slide's parent (master slide) and look for layers which have
- // endtime explicitly set by this slide's property changes
+ // Check if there are nodes from the parent slide that has property changes on this slide.
if (Q3DSSlide *p = static_cast<Q3DSSlide *>(slide->parent())) {
for (auto *obj : p->objects()) {
- if (obj->type() != Q3DSGraphObject::Layer)
+ if (!obj->isNode())
continue;
- const QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *> props =
- slide->propertyChanges();
- const QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *>::const_iterator it =
- props.find(obj);
- if (it == props.constEnd())
+ // Look for property updates on "this" slide.
+ const auto &props = slide->propertyChanges();
+ const auto foundIt = props.constFind(obj);
+ if (foundIt == props.constEnd())
continue;
- if ((*it)->keys().contains(QStringLiteral("endtime")) && obj->endTime() > eTime)
- eTime = obj->endTime();
+
+ // If there are property changes for the object, check if it has a new endtime.
+ std::find_if(foundIt.value()->cbegin(), foundIt.value()->cend(), [&layerEndTime, &nodesEndtime, obj](const Q3DSPropertyChange &propChange) {
+ if (propChange.name() == QLatin1String("endtime")) {
+ bool ok = false;
+ const qint32 value = propChange.value().toInt(&ok);
+ if (ok) {
+ if (obj->type() == Q3DSGraphObject::Layer && (value > layerEndTime))
+ layerEndTime = value;
+ else if (value > nodesEndtime)
+ nodesEndtime = value;
+ }
+ }
+ return false;
+ });
}
}
- // Now look for the endtime from the slides explicit layer objects
+ // Now look for the endtime on nodes on this slide.
for (const auto obj : slide->objects()) {
- if (obj->type() != Q3DSGraphObject::Layer)
+ // Skip non-node types.
+ if (!obj->isNode())
continue;
- if (obj->endTime() > eTime)
- eTime = obj->endTime();
+ // We collect both layer endtimes (if any) and object endtimes in one go.
+ if (obj->type() == Q3DSGraphObject::Layer && (obj->endTime() > layerEndTime))
+ layerEndTime = obj->endTime();
+ else if (obj->endTime() > nodesEndtime)
+ nodesEndtime = obj->endTime();
}
+ // Final fallback, if neither was found use the value set by the slide.
+ if (layerEndTime == -1 && nodesEndtime == -1)
+ nodesEndtime = slide->endTime();
+
if (startTime)
*startTime = slide->startTime();
if (endTime)
- *endTime = eTime != -1 ? eTime : slide->endTime();
+ *endTime = layerEndTime != -1 ? layerEndTime : nodesEndtime;
}
static QString getSlideName(Q3DSSlide *slide)
@@ -97,40 +115,28 @@ static Q3DSSlidePlayer::PlayerState getInitialSlideState(Q3DSSlide *slide)
}
-static void updatePosition(Q3DSSlide *slide, float pos, float duration)
+static void updatePosition(Q3DSSlide *slide, float newTimeMs, float durationMs)
{
- const auto updateAnimator = [pos](Qt3DAnimation::QClipAnimator *animator, float duration) {
+ const auto updateAnimator = [newTimeMs](Qt3DAnimation::QClipAnimator *animator, float durationMs) {
if (!animator)
return;
- const float nt = qBound(0.0f, pos / duration, 1.0f);
+ const float nt = qBound(0.0f, newTimeMs / durationMs, 1.0f);
// NOTE!!!: This is a bit funky, but it means we can avoid tracking the normalized values in the
// frontend node. This of course assumes that the limit in the fuzzy compare doesn't change!
animator->setNormalizedTime(qFuzzyCompare(nt, animator->normalizedTime()) ? qAbs(nt - (1.0f / 100000.0f)) : nt);
};
const auto updateAnimators = [&updateAnimator](const QVector<Qt3DAnimation::QClipAnimator *> &animators) {
for (auto animator : animators) {
- const float duration = animator->clip()->duration() * 1000.0f;
- updateAnimator(animator, duration);
- }
- };
-
- const auto updateAllComponentPlayers = [pos](Q3DSSlide *slide) {
- for (auto obj : slide->objects()) {
- if (obj->type() == Q3DSGraphObject::Component) {
- Q3DSComponentNode *comp = static_cast<Q3DSComponentNode *>(obj);
- const float slidePos = pos - obj->startTime();
- Q3DSSlidePlayer *player = comp->masterSlide()->attached<Q3DSSlideAttached>()->slidePlayer;
- player->seek(slidePos);
- }
+ const float durationMs = animator->clip()->duration() * 1000.0f;
+ updateAnimator(animator, durationMs);
}
};
Q3DSSlideAttached *data = slide->attached<Q3DSSlideAttached>();
Q_ASSERT(data);
- updateAllComponentPlayers(slide);
- updateAnimator(data->animator, duration);
+ updateAnimator(data->animator, durationMs);
updateAnimators(data->animators);
};
@@ -144,12 +150,11 @@ static void updateAnimators(Q3DSSlide *slide, bool running, bool restart, float
// NOTE!!!: This is a bit funky, but it means we can avoid tracking the normalized values in the
// frontend node. This of course assumes that the limit in the fuzzy compare doesn't change!
animator->setNormalizedTime(qFuzzyCompare(animator->normalizedTime(), 0.0f) ? (0.0f + (1.0f / 100000.0f)) : 0.0f);
- // NOTE: The running value might not have been updated in the frontend node yet,
- // so force update this one as well!
- if (animator->isRunning())
- animator->setRunning(false);
}
animator->clock()->setPlaybackRate(double(rate));
+ // NOTE: The running value might not have been updated in the frontend node yet,
+ // so force update if the values are the same...
+ animator->setRunning(!running);
animator->setRunning(running);
};
const auto updateAnimators = [&updateAnimator](const QVector<Qt3DAnimation::QClipAnimator *> &animators) {
@@ -157,24 +162,9 @@ static void updateAnimators(Q3DSSlide *slide, bool running, bool restart, float
updateAnimator(animator);
};
- const auto updateAllComponentPlayers = [running](Q3DSSlide *slide) {
- for (auto obj : slide->objects()) {
- if (obj->type() == Q3DSGraphObject::Component) {
- Q3DSComponentNode *comp = static_cast<Q3DSComponentNode *>(obj);
- Q3DSSlide *compSlide = comp->currentSlide();
- Q3DSSlidePlayer *player = comp->masterSlide()->attached<Q3DSSlideAttached>()->slidePlayer;
- if (running && compSlide->initialPlayState() == Q3DSSlide::Play)
- player->play();
- else
- player->stop();
- }
- }
- };
-
Q3DSSlideAttached *data = slide->attached<Q3DSSlideAttached>();
Q_ASSERT(data);
- updateAllComponentPlayers(slide);
updateAnimator(data->animator);
updateAnimators(data->animators);
}
@@ -192,20 +182,9 @@ static void updatePlaybackRate(Q3DSSlide *slide, float rate)
updateAnimator(animator);
};
- const auto updateAllComponentPlayers = [rate](Q3DSSlide *slide) {
- for (auto obj : slide->objects()) {
- if (obj->type() == Q3DSGraphObject::Component) {
- Q3DSComponentNode *comp = static_cast<Q3DSComponentNode *>(obj);
- Q3DSSlidePlayer *player = comp->masterSlide()->attached<Q3DSSlideAttached>()->slidePlayer;
- player->setPlaybackRate(rate);
- }
- }
- };
-
Q3DSSlideAttached *data = slide->attached<Q3DSSlideAttached>();
Q_ASSERT(data);
- updateAllComponentPlayers(slide);
updateAnimator(data->animator);
updateAnimators(data->animators);
}
@@ -214,7 +193,7 @@ Q3DSSlidePlayer::Q3DSSlidePlayer(Q3DSSceneManager *sceneManager,
QObject *parent)
: QObject(parent)
, m_sceneManager(sceneManager)
- , m_animationManager(new Q3DSAnimationManager(this))
+ , m_animationManager(new Q3DSAnimationManager)
{
}
@@ -236,6 +215,43 @@ void Q3DSSlidePlayer::advanceFrame()
m_animationManager->applyChanges();
}
+void Q3DSSlidePlayer::sceneReady()
+{
+ Q3DSSlideDeck *slideDeck = m_data.slideDeck;
+ if (!slideDeck)
+ return;
+
+ Q3DSSlide *currentSlide = slideDeck->currentSlide();
+ Q_ASSERT(currentSlide);
+
+ const bool viewerMode = (m_mode == PlayerMode::Viewer);
+ if (viewerMode && (currentSlide->initialPlayState() == Q3DSSlide::Play))
+ play();
+ else
+ pause();
+
+ // In viewer-mode we need to go through all components players as well
+ if (viewerMode) {
+ static const auto notifyComponentPlayers = [](Q3DSSlide *slide) {
+ if (!slide)
+ return;
+
+ const auto &objects = slide->objects();
+ std::find_if(objects.constBegin(), objects.constEnd(), [](Q3DSGraphObject *obj) {
+ if (obj->type() == Q3DSGraphObject::Component) {
+ Q3DSComponentNode *comp = static_cast<Q3DSComponentNode *>(obj);
+ Q3DSSlide *compSlide = comp->currentSlide();
+ Q3DSSlidePlayer *player = compSlide->attached<Q3DSSlideAttached>()->slidePlayer;
+ player->sceneReady();
+ }
+ return false;
+ });
+ };
+ notifyComponentPlayers(static_cast<Q3DSSlide *>(currentSlide->parent()));
+ notifyComponentPlayers(currentSlide);
+ }
+}
+
float Q3DSSlidePlayer::duration() const
{
if (m_data.state == PlayerState::Idle)
@@ -304,9 +320,14 @@ void Q3DSSlidePlayer::stop()
void Q3DSSlidePlayer::pause()
{
- if (m_data.state != PlayerState::Playing)
+ if (m_data.state == PlayerState::Paused)
return;
+ if (m_data.state == PlayerState::Idle) {
+ qCWarning(lcSlidePlayer) << "Pause called in Idle state (no content)";
+ return;
+ }
+
setInternalState(PlayerState::Paused);
}
@@ -378,8 +399,6 @@ void Q3DSSlidePlayer::setSlideDeck(Q3DSSlideDeck *slideDeck)
// Create a slide deck for this component
compMasterData->slidePlayer->setSlideDeck(new Q3DSSlideDeck(compMasterSlide, slide));
}
-
- Q_ASSERT(compMasterData->slidePlayer->state() == PlayerState::Ready);
};
const auto forAllComponentsOnSlide = [this, prepareComponentsOnSlide](Q3DSSlide *slide) {
@@ -546,10 +565,28 @@ void Q3DSSlidePlayer::handleCurrentSlideChanged(Q3DSSlide *slide,
qCDebug(lcSlidePlayer, "Handling current slide change: from slide \"%s\", to slide \"%s\"",
qPrintable(getSlideName(previousSlide)), qPrintable(getSlideName(slide)));
+ static const auto cleanUpComponentPlayers = [](Q3DSSlide *slide) {
+ if (!slide)
+ return;
+
+ const auto &objects = slide->objects();
+ std::find_if(objects.constBegin(), objects.constEnd(), [](Q3DSGraphObject *obj) {
+ if (obj->type() == Q3DSGraphObject::Component) {
+ Q3DSComponentNode *comp = static_cast<Q3DSComponentNode *>(obj);
+ Q3DSSlide *compSlide = comp->currentSlide();
+ Q3DSSlideAttached *data = compSlide->attached<Q3DSSlideAttached>();
+ data->slidePlayer->handleCurrentSlideChanged(nullptr, compSlide);
+ }
+ return false;
+ });
+ };
if (previousSlide && slideDidChange) {
- if (parentChanged)
+ if (parentChanged) {
+ cleanUpComponentPlayers(static_cast<Q3DSSlide *>(previousSlide->parent()));
setSlideTime(static_cast<Q3DSSlide *>(previousSlide->parent()), -1.0f);
+ }
setSlideTime(previousSlide, -1.0f);
+ cleanUpComponentPlayers(previousSlide);
Q3DSSlideAttached *data = previousSlide->attached<Q3DSSlideAttached>();
if (data && data->animator) {
// TODO: We probably want to be a bit less brute.
@@ -560,9 +597,8 @@ void Q3DSSlidePlayer::handleCurrentSlideChanged(Q3DSSlide *slide,
}
if (slide && slideDidChange && isSlideVisible(slide)) {
- m_sceneManager->handleSlideChange(previousSlide, slide);
+ processPropertyChanges(slide, previousSlide);
m_animationManager->updateAnimations(slide, (m_mode == PlayerMode::Editor));
-
if (parentChanged)
setSlideTime(static_cast<Q3DSSlide *>(slide->parent()), 0.0f);
setSlideTime(slide, 0.0f);
@@ -603,6 +639,26 @@ void Q3DSSlidePlayer::handleCurrentSlideChanged(Q3DSSlide *slide,
qint32 endTime = 0;
Q3DSSlideUtils::getStartAndEndTime(slide, &startTime, &endTime);
onDurationChanged(endTime - startTime);
+
+ static const auto updateComponentSlides = [](Q3DSSlide *slide) {
+ if (!slide)
+ return;
+ const auto &objects = slide->objects();
+ std::find_if(objects.constBegin(), objects.constEnd(), [](Q3DSGraphObject *obj) {
+ if (obj->type() == Q3DSGraphObject::Component) {
+ Q3DSComponentNode *comp = static_cast<Q3DSComponentNode *>(obj);
+ Q3DSSlide *compSlide = comp->currentSlide();
+ Q3DSSlideAttached *data = compSlide->attached<Q3DSSlideAttached>();
+ data->slidePlayer->handleCurrentSlideChanged(compSlide, nullptr);
+ if (data->slidePlayer->m_mode == PlayerMode::Viewer)
+ data->slidePlayer->setInternalState(getInitialSlideState(compSlide));
+ }
+ return false;
+ });
+ };
+ if (parentChanged)
+ updateComponentSlides(static_cast<Q3DSSlide *>(slide->parent()));
+ updateComponentSlides(slide);
}
if (previousSlide != slide)
@@ -646,27 +702,6 @@ void Q3DSSlidePlayer::setSlideTime(Q3DSSlide *slide, float time, bool parentVisi
&& node->flags().testFlag(Q3DSNode::Active)
&& static_cast<Q3DSNodeAttached *>(node->attached())->globalVisibility;
- if (obj->type() == Q3DSGraphObject::Component) {
- Q3DSComponentNode *comp = static_cast<Q3DSComponentNode *>(obj);
- Q3DSSlide *compMasterSlide = comp->masterSlide();
- Q_ASSERT(compMasterSlide);
- Q3DSSlidePlayer *compPlayer = compMasterSlide->attached<Q3DSSlideAttached>()->slidePlayer;
- Q_ASSERT(compPlayer);
-
- const float slideTime = time - obj->startTime();
- compPlayer->setSlideTime(compMasterSlide, slideTime, shouldBeVisible);
-
- if (!shouldBeVisible) {
- Q3DSGraphObject *n = compMasterSlide->firstChild();
- while (n) {
- compPlayer->setSlideTime(static_cast<Q3DSSlide *>(n), slideTime, shouldBeVisible);
- n = n->nextSibling();
- }
- } else {
- compPlayer->setSlideTime(comp->currentSlide(), slideTime);
- }
- }
-
if (forceUpdate || shouldBeVisible != nodeHasVisibilityTag(node))
updateNodeVisibility(node, shouldBeVisible);
}
@@ -686,7 +721,7 @@ void Q3DSSlidePlayer::sendPositionChanged(Q3DSSlide *slide, float pos)
if (!qFuzzyCompare(oldPosition, pos))
Q_EMIT positionChanged(pos);
- const bool onEOS = (m_data.state == PlayerState::Playing)
+ const bool onEOS = (m_data.state == PlayerState::Playing && m_data.pendingState == PlayerState::Playing)
&& ((m_data.position == 0.0f && m_data.playbackRate < 0.0f)
|| (m_data.position == duration() && m_data.playbackRate > 0.0f));
@@ -713,7 +748,9 @@ bool Q3DSSlidePlayer::isSlideVisible(Q3DSSlide *slide)
if (slide) {
Q3DSSlidePlayer *player = slide->attached<Q3DSSlideAttached>()->slidePlayer;
Q3DSSlideDeck *slideDeck = player->slideDeck();
- if (slideDeck->currentSlide() == slide) {
+ const bool isMasterSlide = (slideDeck->masterSlide() == slide);
+ const bool isCurrentSlide = (slideDeck->currentSlide() == slide);
+ if (isCurrentSlide || isMasterSlide) {
Q3DSSlide *parentSlide = slideDeck->parentSlide();
if (parentSlide) {
// We're a component and current, continue up the ladder...
@@ -731,6 +768,60 @@ bool Q3DSSlidePlayer::isSlideVisible(Q3DSSlide *slide)
return visible;
}
+void Q3DSSlidePlayer::processPropertyChanges(Q3DSSlide *currentSlide,
+ Q3DSSlide *previousSlide)
+{
+ Q_ASSERT(currentSlide->attached());
+
+ if (previousSlide) {
+ auto slideData = static_cast<Q3DSSlideAttached *>(previousSlide->attached());
+ for (Q3DSNode *node : qAsConst(slideData->needsMasterRollback)) {
+ const Q3DSPropertyChangeList *changeList = node->masterRollbackList();
+ if (changeList) {
+ qCDebug(lcScene, "Rolling back %d changes to master for %s", changeList->count(), node->id().constData());
+ node->applyPropertyChanges(*changeList);
+ node->notifyPropertyChanges(*changeList);
+ m_sceneManager->updateSubTreeRecursive(node);
+ }
+ }
+ slideData->needsMasterRollback.clear();
+ }
+
+ // Find properties on targets that has dynamic properties.
+ // TODO: Find a better solution (e.g., there can be duplicate updates for e.g., xyz here).
+ QHash<Q3DSGraphObject *, Q3DSPropertyChangeList> dynamicPropertyChanges;
+ const auto &tracks = currentSlide->animations();
+ std::find_if(tracks.cbegin(), tracks.cend(), [&dynamicPropertyChanges](const Q3DSAnimationTrack &track) {
+ if (track.isDynamic()) {
+ auto foundIt = dynamicPropertyChanges.constFind(track.target());
+ Q3DSPropertyChangeList changeList;
+ if (foundIt != dynamicPropertyChanges.constEnd())
+ changeList = *foundIt;
+ const QString property = track.property().split('.')[0];
+ const auto value = track.target()->propertyValue(property);
+ changeList.append(Q3DSPropertyChange::fromVariant(property, value));
+ dynamicPropertyChanges[track.target()] = changeList;
+ }
+ return false;
+ });
+
+ // Filter out properties that we needs to be marked dirty, i.e., eyeball changes.
+ const auto &propertyChanges = currentSlide->propertyChanges();
+ for (auto it = propertyChanges.cbegin(); it != propertyChanges.cend(); ++it) {
+ std::find_if((*it)->cbegin(), (*it)->cend(), [it](const Q3DSPropertyChange &propChange) {
+ if (propChange.name() == QLatin1String("eyeball"))
+ it.key()->notifyPropertyChanges(*it.value());
+
+ it.key()->applyPropertyChanges(*it.value());
+ return false;
+ });
+ }
+
+ // Now update the propeties from dynamic property values
+ for (auto it = dynamicPropertyChanges.cbegin(), ite = dynamicPropertyChanges.cend(); it != ite; ++it)
+ it.key()->applyPropertyChanges(it.value());
+}
+
void Q3DSSlidePlayer::onDurationChanged(float duration)
{
if (qFuzzyCompare(duration, m_data.duration))
diff --git a/src/runtime/q3dsslideplayer_p.h b/src/runtime/q3dsslideplayer_p.h
index 11dd8c2..01020e2 100644
--- a/src/runtime/q3dsslideplayer_p.h
+++ b/src/runtime/q3dsslideplayer_p.h
@@ -95,6 +95,7 @@ public:
Q3DSSlideDeck *slideDeck() const;
void advanceFrame();
+ void sceneReady();
float duration() const;
float position() const;
@@ -145,6 +146,8 @@ private:
void sendPositionChanged(Q3DSSlide *slide, float pos);
void updateNodeVisibility(Q3DSNode *node, bool visible);
bool isSlideVisible(Q3DSSlide *slide);
+ void processPropertyChanges(Q3DSSlide *currentSlide,
+ Q3DSSlide *previousSlide);
struct Data {
Q3DSSlideDeck *slideDeck = nullptr;
diff --git a/src/runtime/q3dsuippresentation.cpp b/src/runtime/q3dsuippresentation.cpp
index 5119b49..3633a2a 100644
--- a/src/runtime/q3dsuippresentation.cpp
+++ b/src/runtime/q3dsuippresentation.cpp
@@ -3878,8 +3878,8 @@ QHash<QString, bool> &Q3DSUipPresentation::imageTransparencyHash()
return m_imageTransparencyHash;
}
-/*!
- Maps a raw XML filename ref like ".\Headphones\meshes\Headphones.mesh#1"
+/*
+ Maps a raw XML filename ref like "./Headphones/meshes/Headphones.mesh#1"
onto a fully qualified filename that can be opened as-is (even if the uip
is in qrc etc.), and also decodes the optional part index.
*/
@@ -4093,13 +4093,13 @@ void Q3DSUipPresentation::removeDataInputTarget(Q3DSGraphObject *obj)
}
}
-void Q3DSUipPresentation::notifyPropertyChanges(const QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *> &changeList) const
+void Q3DSUipPresentation::notifyPropertyChanges(const Q3DSSlide::PropertyChanges &changeList) const
{
for (auto it = changeList.cbegin(), ite = changeList.cend(); it != ite; ++it)
it.key()->notifyPropertyChanges(*it.value());
}
-void Q3DSUipPresentation::applyPropertyChanges(const QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *> &changeList) const
+void Q3DSUipPresentation::applyPropertyChanges(const Q3DSSlide::PropertyChanges &changeList) const
{
for (auto it = changeList.cbegin(), ite = changeList.cend(); it != ite; ++it) {
for (auto change = it.value()->begin(); change != it.value()->end(); change++)
diff --git a/src/runtime/q3dsuippresentation_p.h b/src/runtime/q3dsuippresentation_p.h
index 1f73a98..bc4bec3 100644
--- a/src/runtime/q3dsuippresentation_p.h
+++ b/src/runtime/q3dsuippresentation_p.h
@@ -596,6 +596,8 @@ public:
Value
};
+ using PropertyChanges = QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *>;
+
Q3DSSlide();
~Q3DSSlide();
@@ -607,7 +609,7 @@ public:
void addObject(Q3DSGraphObject *obj);
void removeObject(Q3DSGraphObject *obj);
- const QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *> &propertyChanges() const { return m_propChanges; }
+ const PropertyChanges &propertyChanges() const { return m_propChanges; }
void addPropertyChanges(Q3DSGraphObject *target, Q3DSPropertyChangeList *changeList); // changeList ownership transferred
void removePropertyChanges(Q3DSGraphObject *target);
Q3DSPropertyChangeList *takePropertyChanges(Q3DSGraphObject *target);
@@ -679,7 +681,7 @@ private:
PlayThrough m_playThrough = Next;
QVariant m_playThroughValue;
QSet<Q3DSGraphObject *> m_objects;
- QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *> m_propChanges;
+ PropertyChanges m_propChanges;
QVector<Q3DSAnimationTrack> m_anims;
QVector<Q3DSAction> m_actions;
QVector<SlideGraphChangeCallback> m_slideGraphChangeCallbacks; // master only
@@ -1994,8 +1996,8 @@ public:
static void forAllModels(Q3DSGraphObject *obj, std::function<void(Q3DSModelNode *)> f, bool includeHidden = false);
void forAllImages(std::function<void(Q3DSImage *)> f);
- void notifyPropertyChanges(const QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *> &changeList) const;
- void applyPropertyChanges(const QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *> &changeList) const;
+ void notifyPropertyChanges(const Q3DSSlide::PropertyChanges &changeList) const;
+ void applyPropertyChanges(const Q3DSSlide::PropertyChanges &changeList) const;
void applySlidePropertyChanges(Q3DSSlide *slide) const;
qint64 loadTimeMsecs() const;
diff --git a/src/runtime/runtime.pro b/src/runtime/runtime.pro
index 483ce2b..8a0c957 100644
--- a/src/runtime/runtime.pro
+++ b/src/runtime/runtime.pro
@@ -96,4 +96,6 @@ include(shadergenerator/shadergenerator.pri)
qtConfig(q3ds-profileui): include(profileui/profileui.pri)
+include(doc/doc.pri)
+
load(qt_module)
diff --git a/src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp b/src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp
index 5eb616d..6d646da 100644
--- a/src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp
+++ b/src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp
@@ -213,6 +213,43 @@ struct ShaderGenerator : public Q3DSCustomMaterialShaderGenerator
vertexGenerator().beginVertexGeneration(nullptr);
}
+ void addProperties(Q3DSAbstractShaderStageGenerator &fragmentShader)
+ {
+ // Add Uniforms from material properties
+ for (auto property : m_currentMaterial->properties()) {
+ switch (property.type) {
+ case Q3DS::Boolean:
+ fragmentShader.addUniform(property.name.toLocal8Bit(), "bool");
+ break;
+ case Q3DS::Long:
+ fragmentShader.addUniform(property.name.toLocal8Bit(), "int");
+ break;
+ case Q3DS::FloatRange:
+ case Q3DS::Float:
+ case Q3DS::FontSize:
+ fragmentShader.addUniform(property.name.toLocal8Bit(), "float");
+ break;
+ case Q3DS::Float2:
+ fragmentShader.addUniform(property.name.toLocal8Bit(), "vec2");
+ break;
+ case Q3DS::Vector:
+ case Q3DS::Scale:
+ case Q3DS::Rotation:
+ case Q3DS::Color:
+ fragmentShader.addUniform(property.name.toLocal8Bit(), "vec3");
+ break;
+ case Q3DS::Texture:
+ fragmentShader.addUniform(property.name.toLocal8Bit(), "sampler2D");
+ break;
+ case Q3DS::StringList:
+ fragmentShader.addUniform(property.name.toLocal8Bit(), "int");
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
void generateFragmentShader(const QString &shaderName)
{
// Get the shader source from the Q3DSCustomMaterial based
@@ -290,6 +327,7 @@ struct ShaderGenerator : public Q3DSCustomMaterialShaderGenerator
vertexShader.generateWorldPosition();
vertexShader.generateViewVector();
+ addProperties(fragmentShader);
return;
}
@@ -331,40 +369,7 @@ struct ShaderGenerator : public Q3DSCustomMaterialShaderGenerator
fragmentShader << "}\n\n";
}
- // Add Uniforms from material properties
- for (auto property : m_currentMaterial->properties()) {
- switch (property.type) {
- case Q3DS::Boolean:
- fragmentShader.addUniform(property.name.toLocal8Bit(), "bool");
- break;
- case Q3DS::Long:
- fragmentShader.addUniform(property.name.toLocal8Bit(), "int");
- break;
- case Q3DS::FloatRange:
- case Q3DS::Float:
- case Q3DS::FontSize:
- fragmentShader.addUniform(property.name.toLocal8Bit(), "float");
- break;
- case Q3DS::Float2:
- fragmentShader.addUniform(property.name.toLocal8Bit(), "vec2");
- break;
- case Q3DS::Vector:
- case Q3DS::Scale:
- case Q3DS::Rotation:
- case Q3DS::Color:
- fragmentShader.addUniform(property.name.toLocal8Bit(), "vec3");
- break;
- case Q3DS::Texture:
- fragmentShader.addUniform(property.name.toLocal8Bit(), "sampler2D");
- break;
- case Q3DS::StringList:
- fragmentShader.addUniform(property.name.toLocal8Bit(), "int");
- break;
- default:
- break;
- }
- }
-
+ addProperties(fragmentShader);
// setup main
vertexGenerator().beginFragmentGeneration();
diff --git a/src/src.pro b/src/src.pro
index d1f86eb..1b02d69 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -1,8 +1,7 @@
TEMPLATE = subdirs
SUBDIRS += \
- runtime \
- doc
+ runtime
qtHaveModule(quick) {
SUBDIRS += imports
diff --git a/tests/auto/behaviors/tst_q3dsbehaviors.cpp b/tests/auto/behaviors/tst_q3dsbehaviors.cpp
index fdc8da5..9954c77 100644
--- a/tests/auto/behaviors/tst_q3dsbehaviors.cpp
+++ b/tests/auto/behaviors/tst_q3dsbehaviors.cpp
@@ -69,7 +69,7 @@ void tst_Q3DSBehaviors::initTestCase()
if (!isOpenGLGoodEnough())
QSKIP("This platform does not support OpenGL proper");
- QSurfaceFormat::setDefaultFormat(Q3DSEngine::surfaceFormat());
+ QSurfaceFormat::setDefaultFormat(Q3DS::surfaceFormat());
m_engine = new Q3DSEngine;
m_view = new Q3DSWindow;
m_view->setEngine(m_engine);
diff --git a/tests/auto/documents/tst_q3dsdocuments.cpp b/tests/auto/documents/tst_q3dsdocuments.cpp
index 61af29e..aee400d 100644
--- a/tests/auto/documents/tst_q3dsdocuments.cpp
+++ b/tests/auto/documents/tst_q3dsdocuments.cpp
@@ -113,7 +113,7 @@ void tst_Q3DSDocuments::initTestCase()
if (!isOpenGLGoodEnough())
QSKIP("This platform does not support OpenGL proper");
- QSurfaceFormat::setDefaultFormat(Q3DSEngine::surfaceFormat());
+ QSurfaceFormat::setDefaultFormat(Q3DS::surfaceFormat());
Q3DSUtils::setDialogsEnabled(false);
}
diff --git a/tests/auto/q3dslancelot/scenegrabber/main.cpp b/tests/auto/q3dslancelot/scenegrabber/main.cpp
index 357b257..6246746 100644
--- a/tests/auto/q3dslancelot/scenegrabber/main.cpp
+++ b/tests/auto/q3dslancelot/scenegrabber/main.cpp
@@ -150,7 +150,7 @@ int main(int argc, char *argv[])
qSetGlobalQHashSeed(0);
QGuiApplication a(argc, argv);
- QSurfaceFormat::setDefaultFormat(Q3DSEngine::surfaceFormat());
+ QSurfaceFormat::setDefaultFormat(Q3DS::surfaceFormat());
Q3DSUtils::setDialogsEnabled(false);
diff --git a/tests/auto/slideplayer/tst_q3dsslideplayer.cpp b/tests/auto/slideplayer/tst_q3dsslideplayer.cpp
index 3593646..96fa78b 100644
--- a/tests/auto/slideplayer/tst_q3dsslideplayer.cpp
+++ b/tests/auto/slideplayer/tst_q3dsslideplayer.cpp
@@ -101,7 +101,7 @@ void tst_Q3DSSlidePlayer::initTestCase()
if (!isOpenGLGoodEnough())
QSKIP("This platform does not support OpenGL proper");
- QSurfaceFormat::setDefaultFormat(Q3DSEngine::surfaceFormat());
+ QSurfaceFormat::setDefaultFormat(Q3DS::surfaceFormat());
m_engine = new Q3DSEngine;
m_view = new Q3DSWindow;
m_view->setEngine(m_engine);
diff --git a/tests/auto/slides/tst_q3dsslides.cpp b/tests/auto/slides/tst_q3dsslides.cpp
index cc6a62b..f68835a 100644
--- a/tests/auto/slides/tst_q3dsslides.cpp
+++ b/tests/auto/slides/tst_q3dsslides.cpp
@@ -133,7 +133,7 @@ void tst_Q3DSSlides::initTestCase()
if (!isOpenGLGoodEnough())
QSKIP("This platform does not support OpenGL proper");
- QSurfaceFormat::setDefaultFormat(Q3DSEngine::surfaceFormat());
+ QSurfaceFormat::setDefaultFormat(Q3DS::surfaceFormat());
m_engine = new Q3DSEngine;
m_view = new Q3DSWindow;
m_view->setEngine(m_engine);
diff --git a/tests/manual/qt3dsexplorer/main.cpp b/tests/manual/qt3dsexplorer/main.cpp
index e90ecda..0e2b793 100644
--- a/tests/manual/qt3dsexplorer/main.cpp
+++ b/tests/manual/qt3dsexplorer/main.cpp
@@ -38,7 +38,7 @@
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- QSurfaceFormat::setDefaultFormat(Q3DSEngine::surfaceFormat());
+ QSurfaceFormat::setDefaultFormat(Q3DS::surfaceFormat());
QCommandLineParser cmdLineParser;
cmdLineParser.addHelpOption();
diff --git a/tools/q3dsviewer/main.cpp b/tools/q3dsviewer/main.cpp
index 1c1c15f..306dceb 100644
--- a/tools/q3dsviewer/main.cpp
+++ b/tools/q3dsviewer/main.cpp
@@ -60,7 +60,7 @@ int main(int argc, char *argv[])
#else
QGuiApplication app(argc, argv);
#endif
- QSurfaceFormat::setDefaultFormat(Q3DSEngine::surfaceFormat());
+ QSurfaceFormat::setDefaultFormat(Q3DS::surfaceFormat());
QCommandLineParser cmdLineParser;
cmdLineParser.addHelpOption();
@@ -73,12 +73,10 @@ int main(int argc, char *argv[])
cmdLineParser.addOption(msaaOption);
QCommandLineOption noProfOption({ "p", "no-profile" }, QObject::tr("Opens presentation without profiling enabled"));
cmdLineParser.addOption(noProfOption);
- cmdLineParser.addOption({"connect", QObject::tr("main",
- "If this parameter is specified, the viewer\n"
- "is started in connection mode.\n"
- "The default value is 36000."),
- QObject::tr("main", "port"), QString::number(36000)});
-
+ QCommandLineOption remoteOption("port",
+ QObject::tr("Sets the <port> to listen on in remote connection mode. The default <port> is 36000."),
+ QObject::tr("port"), QLatin1String("36000"));
+ cmdLineParser.addOption(remoteOption);
cmdLineParser.process(app);
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
@@ -112,8 +110,8 @@ int main(int argc, char *argv[])
// Setup Remote Viewer
QScopedPointer<Q3DSRemoteDeploymentManager> remote(new Q3DSRemoteDeploymentManager(engine.data()));
int port = 36000;
- if (cmdLineParser.isSet(QStringLiteral("connect")))
- port = cmdLineParser.value(QStringLiteral("connect")).toInt();
+ if (cmdLineParser.isSet(remoteOption))
+ port = cmdLineParser.value(remoteOption).toInt();
remote->setConnectionPort(port);
if (fn.isEmpty()) {
remote->startServer();
@@ -133,6 +131,9 @@ int main(int argc, char *argv[])
else
view->show();
engine->setOnDemandRendering(true);
+ // in QWindow mode let F10 and double double clicks activate the
+ // profileui via the engine
+ engine->setAutoToggleProfileUi(true);
} else {
#ifdef Q3DSVIEWER_WIDGETS
mw = new Q3DStudioMainWindow(view.take(), remote.data());
@@ -140,6 +141,9 @@ int main(int argc, char *argv[])
mw->showFullScreen();
else
mw->show();
+ // with widgets the engine's built-in profileui activation is not
+ // desirable since we have menu items with the same shortcuts (F10)
+ engine->setAutoToggleProfileUi(false);
#endif
}
diff --git a/tools/q3dsviewer/q3dsmainwindow.cpp b/tools/q3dsviewer/q3dsmainwindow.cpp
index ff8ec7a..e89c7b8 100644
--- a/tools/q3dsviewer/q3dsmainwindow.cpp
+++ b/tools/q3dsviewer/q3dsmainwindow.cpp
@@ -73,7 +73,7 @@ Q3DStudioMainWindow::Q3DStudioMainWindow(Q3DSWindow *view, Q3DSRemoteDeploymentM
view->engine()->setFlag(Q3DSEngine::EnableProfiling, true);
open();
} , QKeySequence::Open);
- fileMenu->addAction(tr("Open without &profiling..."), this, [=] {
+ fileMenu->addAction(tr("Open Without &Profiling..."), this, [=] {
view->engine()->setFlag(Q3DSEngine::EnableProfiling, false);
open();
});
@@ -89,7 +89,7 @@ Q3DStudioMainWindow::Q3DStudioMainWindow(Q3DSWindow *view, Q3DSRemoteDeploymentM
return;
view->engine()->setSource(view->engine()->source());
}, QKeySequence::Refresh);
- fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
+ fileMenu->addAction(tr("E&xit"), this, &QWidget::close, QKeySequence::Quit);
QMenu *viewMenu = menuBar()->addMenu(tr("&View"));
if (enableDebugMenu) {
@@ -107,13 +107,13 @@ Q3DStudioMainWindow::Q3DStudioMainWindow(Q3DSWindow *view, Q3DSRemoteDeploymentM
});
}
- viewMenu->addAction(tr("Toggle fullscree&n"), this, [this] {
+ viewMenu->addAction(tr("Toggle Full Scree&n"), this, [this] {
Qt::WindowStates s = windowState();
s.setFlag(Qt::WindowFullScreen, !s.testFlag(Qt::WindowFullScreen));
setWindowState(s);
}, QKeySequence::FullScreen);
- QMenu *profileSubMenu = new QMenu(tr("&Profile and debug"));
+ QMenu *profileSubMenu = new QMenu(tr("&Profile and Debug"));
profileSubMenu->addAction(tr("Toggle in-scene &debug view"), this, [view] {
Q3DSEngine *engine = view->engine();
engine->setProfileUiVisible(!engine->isProfileUiVisible());