diff options
Diffstat (limited to 'src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.cpp')
m--------- | src/Runtime/ogl-runtime | 0 | ||||
-rw-r--r-- | src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.cpp | 2100 |
2 files changed, 0 insertions, 2100 deletions
diff --git a/src/Runtime/ogl-runtime b/src/Runtime/ogl-runtime new file mode 160000 +Subproject 2025912174c4cf99270b7439ec3b021e1d089ae diff --git a/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.cpp b/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.cpp deleted file mode 100644 index c07922cb..00000000 --- a/src/Runtime/ogl-runtime/src/api/studio3d/q3dspresentation.cpp +++ /dev/null @@ -1,2100 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt 3D Studio. -** -** $QT_BEGIN_LICENSE:GPL$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 or (at your option) any later version -** approved by the KDE Free Qt Foundation. The licenses are as published by -** the Free Software Foundation and appearing in the file LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "q3dspresentation_p.h" -#include "q3dssceneelement_p.h" -#include "q3dscommandqueue_p.h" -#include "viewerqmlstreamproxy_p.h" -#include "q3dsdatainput_p.h" -#include "q3dsdataoutput_p.h" -#include "q3dsgeometry_p.h" - -#include <QtCore/qdebug.h> -#include <QtCore/qsettings.h> -#include <QtCore/qcoreapplication.h> -#include <QtGui/qevent.h> - -QT_BEGIN_NAMESPACE - -/*! - \class Q3DSPresentation - \inmodule OpenGLRuntime - \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 - subpresentations. The subpresentations 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} - presentation file. When present, the \c{.uia} project file ties - these together by specifying a name for each of the - (sub-)presentations and specifies which one is the main one. - - The \c{.uia} project also defines \l{DataInput}s and - \l{DataOutput}s that are exported by the presentations. - \l{DataInput}s provide a way to provide input to the presentation - to e.g. control a timeline of a subpresentation from code. - \c{DataOutput}s provide a way to get notified when an attribute - is changed in the presentation by animation timeline, - by behavior scripts or by a \l{DataInput}. - - 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(). - */ - -/*! - Constructs a new Q3DSPresentation with the given \a parent. - */ -Q3DSPresentation::Q3DSPresentation(QObject *parent) - : QObject(parent) - , d_ptr(new Q3DSPresentationPrivate(this)) -{ -} - -/*! - Destructor. - */ -Q3DSPresentation::~Q3DSPresentation() -{ -} - -/*! - \qmlproperty string Presentation::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. - - Currently set \c{variantList} property will modify which variant groups - and tags are loaded from the presentations. See - Q3DSPresentation::variantList property. -*/ - -/*! - \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. - - Currently set variantList will modify which variant groups - and tags are loaded from the presentations. See - Q3DSPresentation::variantList property. -*/ -QUrl Q3DSPresentation::source() const -{ - return d_ptr->m_source; -} - -void Q3DSPresentation::setSource(const QUrl &source) -{ - if (d_ptr->m_source != source) { - d_ptr->setSource(source); - Q_EMIT sourceChanged(source); - } -} - -/*! - \qmlproperty list<string> Presentation::variantList - - Holds a list of (variant group):(variant) tags that are loaded when the - \c{source} property is set. If this list is left empty (default), no variant - filtering is applied and all items are loaded regardless of variant tags in - the presentation. Variant mechanism allows one presentation project to - contain multiple variants of the presentation and the decision which variant - set is loaded is determined during runtime based on the \c{variantList}. - - Variants are divided to variant groups, e.g. one variant group could be - \c{region} and the variants within that group could be e.g. \c{US, EU, CH}. - Another variant group could be e.g. \c{power} and variants within that could - be e.g. \c{gas, electric, diesel}. To filter in this example an electric - variant for the EU region, the variantList needs to contain two strings - "region:EU" and "power:electric". Also of course the presentation project - needs to contain these variant groups and tags applied appropriately to the - presentation content. - - When variant filters are used, the decision what gets loaded and what is not - loaded is based on checking every item in the presentation: - \list - \li If the item has no variant tags, it will be loaded. - \li If the item has no tags defined for the checked variant group(s), - it will be loaded. - \li If the item has tag(s) for the variant group, any of those tags must - match any of the variants defined in the filter for that group. - \endlist - - If the item doesn't fulfill the above rules it will not be loaded. -*/ - -/*! - \property Q3DSPresentation::variantList - - Holds a list of (variant group):(variant) tags that are loaded when the - \c{source} property is set. If this list is left empty (default), no variant - filtering is applied and all items are loaded regardless of variant tags in - the presentation. Variant mechanism allows one presentation project to - contain multiple variants of the presentation and the decision which variant - set is loaded is determined during runtime based on the \c{variantList}. - - Variants are divided to variant groups, e.g. one variant group could be - \c{region} and the variants within that group could be e.g. \c{US, EU, CH}. - Another variant group could be e.g. \c{power} and variants within that could - be e.g. \c{gas, electric, diesel}. To filter in this example an electric - variant for the EU region, the variantList needs to contain two strings - "region:EU" and "power:electric". Also of course the presentation project - needs to contain these variant groups and tags applied appropriately to the - presentation content. - - When variant filters are used, the decision what gets loaded and what is not - loaded is based on checking every item in the presentation: - \list - \li If the item has no variant tags, it will be loaded. - \li If the item has no tags defined for the checked variant group(s), - it will be loaded. - \li If the item has tag(s) for the variant group, any of those tags must - match any of the variants defined in the filter for that group. - \endlist - - If the item doesn't fulfill the above rules it will not be loaded. -*/ -QStringList Q3DSPresentation::variantList() const -{ - return d_ptr->m_variantList; -} - -void Q3DSPresentation::setVariantList(const QStringList &variantList) -{ - if (d_ptr->m_variantList != variantList) { - d_ptr->setVariantList(variantList); - Q_EMIT variantListChanged(variantList); - } -} - -/*! - \internal - */ -void Q3DSPresentation::registerElement(Q3DSElement *element) -{ - d_ptr->registerElement(element); -} - -/*! - \internal - */ -void Q3DSPresentation::unregisterElement(Q3DSElement *element) -{ - d_ptr->unregisterElement(element); -} - -/*! - \internal - */ -Q3DSElement *Q3DSPresentation::registeredElement(const QString &elementPath) const -{ - return d_ptr->m_elements.value(elementPath, nullptr); -} - -/*! - \internal - */ -void Q3DSPresentation::registerDataInput(Q3DSDataInput *dataInput) -{ - d_ptr->registerDataInput(dataInput); -} - -/*! - \internal - */ -void Q3DSPresentation::unregisterDataInput(Q3DSDataInput *dataInput) -{ - d_ptr->unregisterDataInput(dataInput); -} - -/*! - \internal - */ -Q3DSDataInput *Q3DSPresentation::registeredDataInput(const QString &name) const -{ - return d_ptr->m_dataInputs.value(name, nullptr); -} - -/*! - \internal - */ -void Q3DSPresentation::registerDataOutput(Q3DSDataOutput *dataOutput) -{ - d_ptr->registerDataOutput(dataOutput); -} - -/*! - \internal - */ -void Q3DSPresentation::unregisterDataOutput(Q3DSDataOutput *dataOutput) -{ - d_ptr->unregisterDataOutput(dataOutput); -} - -/*! - \internal - */ -Q3DSDataOutput *Q3DSPresentation::registeredDataOutput(const QString &name) const -{ - return d_ptr->m_dataOutputs.value(name, nullptr); -} - -/*! - Returns a list of datainputs defined for this presentation. Use setDataInputValue() - interface to set a datainput value using datainput name, or call Q3DSDataInput::setValue - directly for a specific datainput. - - \sa setDataInputValue - \sa Q3DSDataInput - */ -QVector<Q3DSDataInput *> Q3DSPresentation::dataInputs() const -{ - QVector<Q3DSDataInput *> ret; - // Just return local datainput list - const auto datainputs = d_ptr->m_dataInputs; - for (const auto &it : datainputs) - ret.append(it); - - return ret; -} - -/*! - \qmlmethod var Presentation::getDataInputs - Returns a list of datainputs defined for this presentation. Use setDataInputValue() - interface to set a datainput value using datainput name, or call Q3DSDataInput::setValue - directly for a specific datainput. - - \sa DataInput - */ - -/*! - Returns a list of datainputs defined for this presentation. Use setDataInputValue() - interface to set a datainput value using datainput name, or call Q3DSDataInput::setValue - directly for a specific datainput. - - \sa setDataInputValue - \sa Q3DSDataInput - */ -QVariantList Q3DSPresentation::getDataInputs() const -{ - QVariantList ret; - const auto datainputs = dataInputs(); - - for (const auto &it : datainputs) - ret.append(QVariant::fromValue(it)); - - return ret; -} - -/*! - Returns a list of datainputs defined for this presentation that have the specified - \a metadataKey. - - \sa setDataInputValue - \sa Q3DSDataInput - */ - -/*! - \qmlmethod var Presentation::getDataInputs - Returns a list of datainputs defined for this presentation that have the specified - \a metadataKey. - - \sa DataInput - */ -QVariantList Q3DSPresentation::getDataInputs(const QString &metadataKey) const -{ - QVariantList ret; - const auto datainputs = dataInputs(metadataKey); - - for (const auto &it : datainputs) - ret.append(QVariant::fromValue(it)); - - return ret; -} - -/*! - Returns a list of datainputs defined for this presentation that have the specified - \a metadataKey. - - \sa setDataInputValue - \sa Q3DSDataInput - */ -QVector<Q3DSDataInput *> Q3DSPresentation::dataInputs(const QString &metadataKey) const -{ - // Defer to presentation item as we want to read metadata from viewer app whenever - // possible. - return d_ptr->dataInputs(metadataKey); -} - -/*! - Returns a list of dataoutputs defined for this presentation. Use Qt's connect() method - to connect slots to the valueChanged() signal in the required \l{DataOutput}s to get notified - when the value tracked by the DataOutput is changed. - - \sa Q3DSDataOutput - */ -QVector<Q3DSDataOutput *> Q3DSPresentation::dataOutputs() const -{ - QVector<Q3DSDataOutput *> ret; - const auto datainputs = d_ptr->m_dataOutputs; - for (const auto &it : datainputs) - ret.append(it); - - return ret; -} - -/*! - \qmlmethod var Presentation::getDataOutputs - - Returns a list of dataoutputs defined for this presentation. Connect slots to the - \c{valueChanged()} signal in the required \l{DataOutput}s to get notified - when the value tracked by the DataOutput is changed. - - \sa SDataOutput - */ -/*! - * \brief Q3DSPresentation::getDataOutputs Returns \l{DataOutput}s. - Returns a list of dataoutputs defined for this presentation. Use Qt's connect() method - to connect slots to the valueChanged() signal in the required \l{DataOutput}s to get notified - when the value tracked by the DataOutput is changed. - - \sa Q3DSDataOutput - */ -QVariantList Q3DSPresentation::getDataOutputs() const -{ - QVariantList ret; - const auto dataoutputs = dataOutputs(); - - for (const auto &it : dataoutputs) - ret.append(QVariant::fromValue(it)); - - return ret; -} - -/*! - \qmlproperty bool Presentation::delayedLoading - - This property controls whether the presentation resources are loaded while loading - the presentation(false) or afterwards when they are actually used in the presentation(true). - The resources are loaded per slide basis so that all resources required by a slide will be - loaded at once. - - The resources can be images, subpresentations, materials, effects and meshes. - - Default is \c{false}. - */ - -/*! - \property Q3DSPresentation::delayedLoading - - This property controls whether the presentation resources are loaded while loading - the presentation(false) or afterwards when they are actually used in the presentation(true). - The resources are loaded per slide basis so that all resources required by a slide will be - loaded at once. - - The resources can be images, subpresentations, materials, effects and meshes. - - Default is \c{false}. - */ -bool Q3DSPresentation::delayedLoading() const -{ - return d_ptr->m_delayedLoading; -} - -void Q3DSPresentation::setDelayedLoading(bool enable) -{ - if (d_ptr->m_delayedLoading != enable) { - d_ptr->setDelayedLoading(enable); - Q_EMIT delayedLoadingChanged(enable); - } -} - -/*! - \qmlmethod Presentation::preloadSlide - Preloads slide resources to memory. All resources required by the given slide will be - loaded in the background. This function has effect only when delayed loading is enabled. - \param elementPath - */ -/*! - \brief Q3DSPresentation::preloadSlide - Preloads slide resources to memory. All resources required by the given slide will be - loaded in the background. This function has effect only when delayed loading is enabled. - \param elementPath - */ -void Q3DSPresentation::preloadSlide(const QString &elementPath) -{ - if (d_ptr->m_viewerApp) - d_ptr->m_viewerApp->preloadSlide(elementPath); - else if (d_ptr->m_commandQueue) - d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_PreloadSlide); -} - -/*! - \qmlmethod Presentation::unloadSlide - Unloads slide resources from memory. If the slide is current, then the resources are unloaded - when the slide is changed. This function has effect only when delayed loading is enabled. - \param elementPath - */ - -/*! - \brief Q3DSPresentation::unloadSlide - Unloads slide resources from memory. If the slide is current, then the resources are unloaded - when the slide is changed. This function has effect only when delayed loading is enabled. - \param elementPath - */ -void Q3DSPresentation::unloadSlide(const QString &elementPath) -{ - if (d_ptr->m_viewerApp) - d_ptr->m_viewerApp->unloadSlide(elementPath); - else if (d_ptr->m_commandQueue) - d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_UnloadSlide); -} - -/*! - This API is for backwards compatibility. We recommend using \l{DataInput}s to control - slide changes. \l{DataInput} provides stronger contract between the design and - code as it avoids use of elementPath (a reference to design's internal structure). - - 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, unsigned int index) -{ - if (d_ptr->m_viewerApp) { - const QByteArray path(elementPath.toUtf8()); - d_ptr->m_viewerApp->GoToSlideByIndex(path, index); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_GoToSlide, int(index)); - } -} - -/*! - This API is for backwards compatibility. We recommend using \l{DataInput}s to control - slide changes. \l{DataInput} provides stronger contract between the design and - code as it avoids use of elementPath (a reference to design's internal structure). - - 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) -{ - if (d_ptr->m_viewerApp) { - const QByteArray path(elementPath.toUtf8()); - const QByteArray byteName(name.toUtf8()); - d_ptr->m_viewerApp->GoToSlideByName(path, byteName); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_GoToSlideByName, name); - } -} - -/*! - This API is for backwards compatibility. We recommend using \l{DataInput}s to control - slide changes. \l{DataInput} provides stronger contract between the design and - code as it avoids use of elementPath (a reference to design's internal structure). - - 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) -{ - if (d_ptr->m_viewerApp) { - const QByteArray path(elementPath.toUtf8()); - d_ptr->m_viewerApp->GoToSlideRelative(path, next, wrap); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_GoToSlideRelative, - int(next), int(wrap)); - } -} - -/*! - This API is for backwards compatibility. We recommend using \l{DataInput}s to control - slide changes. \l{DataInput} provides stronger contract between the design and - code as it avoids use of elementPath (a reference to design's internal structure). - - 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 time) -{ - if (d_ptr->m_viewerApp) { - const QByteArray path(elementPath.toUtf8()); - d_ptr->m_viewerApp->GoToTime(path, time); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_GoToTime, time); - } -} - -/*! - This API is for backwards compatibility. We recommend using \l{DataInput}s to control - attributes in the presentation. \l{DataInput} provides stronger contract between the - design and code as it avoids use of elementPath (a reference to design's - internal structure). - - 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 by name, 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}). - - To reference an object stored in a property of another object, the dot - syntax can be used. The most typical example of this is changing the source - of a texture map by changing the \c sourcepath property on the object - selected by \c{SomeMaterial.diffusemap}. - - 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}. - */ -void Q3DSPresentation::setAttribute(const QString &elementPath, const QString &attributeName, - const QVariant &value) -{ - if (d_ptr->m_viewerApp) { - const QByteArray path(elementPath.toUtf8()); - const QByteArray name(attributeName.toUtf8()); - - QByteArray valueStr; - float valueFloat; - - const void *theValue = nullptr; - switch (static_cast<QMetaType::Type>(value.type())) { - case QMetaType::Bool: - case QMetaType::Int: - case QMetaType::Double: - case QMetaType::Float: - valueFloat = value.toFloat(); - theValue = &valueFloat; - break; - case QMetaType::QString: - default: // Try string for other types - valueStr = value.toString().toUtf8(); - theValue = valueStr.constData(); - break; - } - d_ptr->m_viewerApp->SetAttribute(path, name, (char *)theValue); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_SetAttribute, - attributeName, value); - } -} - -/*! - Activate or deactivate the presentation identified by \a id depending - on the value of \a active. - */ -void Q3DSPresentation::setPresentationActive(const QString &id, bool active) -{ - if (d_ptr->m_viewerApp) { - const QByteArray presId(id.toUtf8()); - d_ptr->m_viewerApp->SetPresentationActive(presId, active); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(id, CommandType_SetPresentationActive, active); - } -} - -/*! - Dispatches a Qt 3D Studio presentation event with \a eventName on - scene object specified by \a elementPath. These events provide a - way to communicate with the \c .qml based \c{behavior scripts} - attached to scene objects since they can register to be notified - via Behavior::registerForEvent(). - - See setAttribute() for a description of \a elementPath. - */ -void Q3DSPresentation::fireEvent(const QString &elementPath, const QString &eventName) -{ - if (d_ptr->m_viewerApp) { - const QByteArray path(elementPath.toUtf8()); - const QByteArray name(eventName.toUtf8()); - d_ptr->m_viewerApp->FireEvent(path, name); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_FireEvent, eventName); - } -} - -/*! - Set global animation time to manual value specified by \a milliseconds - (if non-zero) or resume normal timer (if zero). - */ -void Q3DSPresentation::setGlobalAnimationTime(qint64 milliseconds) -{ - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->SetGlobalAnimationTime(milliseconds); - } else { - d_ptr->m_commandQueue->m_globalAnimationTimeChanged = true; - d_ptr->m_commandQueue->m_globalAnimationTime = milliseconds; - } -} - -/*! - 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 internal 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. - - \sa DataInput - */ -void Q3DSPresentation::setDataInputValue(const QString &name, const QVariant &value, - Q3DSDataInput::ValueRole valueRole) -{ - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->SetDataInputValue(name, value, - (qt3ds::runtime::DataInputValueRole)valueRole); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(QString(), CommandType_SetDataInputValue, - name, value, static_cast<int>(valueRole)); - } -} - -/*! - Adds a new child element for the element specified by \a parentElementPath to the slide - specified with \a slideName. Only model and group element creation is currently supported. - The \a properties hash table specifies the name-value pairs of the properties of the new - element. The property names are the same the setAttribute() recognizes. - - A referenced material element is also created for the new model element. The source material - name can be specified with custom "material" attribute in the \a properties hash. - The source material must exist in the same presentation where the element is created. - - The mesh for a model is specified with the \c sourcepath property. This can be a local file - path to \c .mesh file, a studio mesh primitive (e.g. \c{#Cube}), or the name of a mesh created - dynamically with createMesh(). - - A property/properties of the element can be bound to be controlled by an existing datainput. - Control bindings can be indicated with custom "controlledproperty" attribute in the - \a properties hash. The format for attribute value is "$<datainputname> <attributename>", i.e. - "$Datainput_1 rotation $Datainput_2 diffusecolor". If datainput name does not match with - any of the datainputs defined in UIA file, binding has no impact. - - The element is ready for use once elementsCreated() signal is received for it. - - \sa createElements - \sa createMaterial - \sa createMesh - \sa elementsCreated - \sa setAttribute - \sa dataInputs - */ -void Q3DSPresentation::createElement(const QString &parentElementPath, const QString &slideName, - const QHash<QString, QVariant> &properties) -{ - QVector<QHash<QString, QVariant>> theProperties; - theProperties << properties; - createElements(parentElementPath, slideName, theProperties); -} - -/*! - Adds multiple new child elements for the element specified by \a parentElementPath to the slide - specified with \a slideName. Element properties are specified in \a properties. - For more details, see createElement(). - - \sa createElement - \sa elementsCreated - */ -void Q3DSPresentation::createElements(const QString &parentElementPath, const QString &slideName, - const QVector<QHash<QString, QVariant>> &properties) -{ - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->createElements(parentElementPath, slideName, properties); - } else if (d_ptr->m_commandQueue) { - // We need to copy the properties map as queue takes ownership of it - QVector<QHash<QString, QVariant>> *theProperties - = new QVector<QHash<QString, QVariant>>(properties); - d_ptr->m_commandQueue->queueCommand(parentElementPath, CommandType_CreateElements, - slideName, theProperties); - } -} - -/*! - Deletes the element specified by \a elementPath and all its child elements. - Deleting elements is supported only for elements that have been dynamically created with - createElement() or createElements(). - - \sa deleteElements - \sa createElement - */ -void Q3DSPresentation::deleteElement(const QString &elementPath) -{ - QStringList elementPaths; - elementPaths << elementPath; - deleteElements(elementPaths); -} - -/*! - Deletes multiple elements specified by \a elementPaths and all their child elements. - Deleting elements is supported only for elements that have been dynamically created with - createElement() or createElements(). - - \sa deleteElement - */ -void Q3DSPresentation::deleteElements(const QStringList &elementPaths) -{ - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->deleteElements(elementPaths); - } else if (d_ptr->m_commandQueue) { - // We need to copy the list as queue takes ownership of it - QStringList *theElementPaths = new QStringList(elementPaths); - d_ptr->m_commandQueue->queueCommand(CommandType_DeleteElements, theElementPaths); - } - for (const auto &elementPath : elementPaths) - d_ptr->m_createdElements.removeAll(elementPath); -} - -/*! - \qmlproperty list<string> Presentation::createdElements - - This property contains a list of all dynamically created elements on this presentation. - - This property is read-only. - - \note Elements can only be dynamically created via C++ API. - - \sa createElement - \sa createElements -*/ - -/*! - \property Q3DSPresentation::createdElements - - This property contains a list of all dynamically created elements on this presentation. - - This property is read-only. - - \sa createElement - \sa createElements -*/ -QStringList Q3DSPresentation::createdElements() const -{ - return d_ptr->m_createdElements; -} - -/*! - Creates a material specified by the \a materialDefinition parameter into the subpresentation - specified by the \a subPresId parameter. If \a subPresId is empty, the material - is created into the main presentation. - - The \a materialDefinition parameter can contain either the file path to a Qt 3D Studio - material definition file or the actual material definition in the - Qt 3D Studio material definition format. The material definition is a XML file that specifies - the material properties. They are not meant to be hand crafted - to create one, simply create - a new basic material in the Qt 3D Studio editor and edit the material properties in the - inspector. The properties are stored into \c{materialName.materialdef} file in \c materials - folder of the project, which you can include into the resources of you application and - use with this method. - - After creation, the material can be used for new elements created via createElement() by - setting \c material property of the new element to the name of the created material. - The material name is specified by the \c name property of the material definition. - - The material is ready for use once materialsCreated() signal is received for it. - - \note Creating materials that utilise custom shaders with mipmapped textures can in some cases - corrupt the textures on other elements if the same textures are already used by existing basic - materials in the scene, as basic materials do not create mipmaps for their textures. - Typical symptom of this is black texture on another element after creating a new element using - the custom material. - - \sa createMaterials - \sa createElement - \sa materialsCreated - */ -void Q3DSPresentation::createMaterial(const QString &materialDefinition, - const QString &subPresId) -{ - QStringList materialDefinitions; - materialDefinitions << materialDefinition; - createMaterials(materialDefinitions, subPresId); -} - -/*! - Creates multiple materials specified by the \a materialDefinitions parameter into the - subpresentation specified by the \a subPresId parameter. If \a subPresId is empty, - the materials are created into the main presentation. - - For more details, see createMaterial(). - - \sa createMaterial - \sa materialsCreated - */ -void Q3DSPresentation::createMaterials(const QStringList &materialDefinitions, - const QString &subPresId) -{ - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->createMaterials(subPresId, materialDefinitions); - } else if (d_ptr->m_commandQueue) { - // We need to copy the list as queue takes ownership of it - QStringList *theMaterialDefinitions = new QStringList(materialDefinitions); - d_ptr->m_commandQueue->queueCommand(subPresId, CommandType_CreateMaterials, - theMaterialDefinitions); - } -} - -/*! - Deletes the material specified by \a materialName from the presentation. - To delete material from a subpresentation, prefix \a materialName with the subpresentation ID - similarly to the element paths. For example: \c{"SubPresentationOne:MyMaterial"}. - - Deleting materials is supported only for materials that have been dynamically created with - createMaterial() or createMaterials(). - - \sa deleteMaterials - \sa createMaterial - */ -void Q3DSPresentation::deleteMaterial(const QString &materialName) -{ - QStringList materialNames; - materialNames << materialName; - deleteMaterials(materialNames); -} - -/*! - Deletes materials specified by \a materialNames from the presentation. - To delete material from a subpresentation, prefix the material name with the subpresentation ID - similarly to the element paths. For example: \c{"SubPresentationOne:MyMaterial"}. - - Deleting materials is supported only for materials that have been dynamically created with - createMaterial() or createMaterials(). - - \sa deleteMaterial - */ -void Q3DSPresentation::deleteMaterials(const QStringList &materialNames) -{ - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->deleteMaterials(materialNames); - } else if (d_ptr->m_commandQueue) { - // We need to copy the list as queue takes ownership of it - QStringList *theMaterialNames = new QStringList(materialNames); - d_ptr->m_commandQueue->queueCommand(CommandType_DeleteMaterials, theMaterialNames); - } - for (const auto &name : materialNames) - d_ptr->m_createdMaterials.removeAll(name); -} - -/*! - \qmlproperty list<string> Presentation::createdMaterials - - This property contains a list of all dynamically created materials on this presentation. - - This property is read-only. - - \note Materials can only be dynamically created via C++ API. - - \sa createMaterial - \sa createMaterials -*/ - -/*! - \property Q3DSPresentation::createdMaterials - - This property contains a list of all dynamically created materials on this presentation. - - This property is read-only. - - \sa createMaterial - \sa createMaterials -*/ -QStringList Q3DSPresentation::createdMaterials() const -{ - return d_ptr->m_createdMaterials; -} - -/*! - Creates a mesh specified by given \a geometry. The given \a meshName can be used as - \c sourcepath property value for model elements created with future createElement() calls. - - The mesh is ready for use once meshesCreated() signal is received for it. - - \sa createElement - \sa createMeshes - \sa meshesCreated -*/ -void Q3DSPresentation::createMesh(const QString &meshName, const Q3DSGeometry &geometry) -{ - QHash<QString, const Q3DSGeometry *> meshData; - meshData.insert(meshName, &geometry); - createMeshes(meshData); -} - -/*! - Creates multiple meshes specified by given \a meshData. The data is mesh name and geometry - pairs. For more details, see createMesh(). - - The ownership of supplied geometries stays with the caller. - - \sa createMesh - \sa meshesCreated -*/ -void Q3DSPresentation::createMeshes(const QHash<QString, const Q3DSGeometry *> &meshData) -{ - // We can't refer to API class Q3DSGeometry on the runtime side, so let's grab the meshdata - // from Q3DSGeometryPrivate that is in runtime approved format and pass that on instead - auto theMeshData = new QHash<QString, Q3DSViewer::MeshData>; - QHashIterator<QString, const Q3DSGeometry *> it(meshData); - while (it.hasNext()) { - it.next(); - theMeshData->insert(it.key(), it.value()->d_ptr->meshData()); - } - - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->createMeshes(*theMeshData); - delete theMeshData; - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(CommandType_CreateMeshes, theMeshData); - } -} - -/*! - Deletes the mesh specified by \a meshName. - Deleting meshes is supported only for meshes that have been dynamically created with - createMesh() or createMeshes(). - - \sa deleteMeshes - \sa createMesh - */ -void Q3DSPresentation::deleteMesh(const QString &meshName) -{ - QStringList meshNames; - meshNames << meshName; - deleteMeshes(meshNames); -} - -/*! - Deletes meshes specified by \a meshNames. - Deleting meshes is supported only for meshes that have been dynamically created with - createMesh() or createMeshes(). - - \sa deleteMesh - */ -void Q3DSPresentation::deleteMeshes(const QStringList &meshNames) -{ - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->deleteMeshes(meshNames); - } else if (d_ptr->m_commandQueue) { - // We need to copy the list as queue takes ownership of it - QStringList *theMeshNames = new QStringList(meshNames); - d_ptr->m_commandQueue->queueCommand(CommandType_DeleteMeshes, theMeshNames); - } - for (const auto &name : meshNames) - d_ptr->m_createdMeshes.removeAll(name); -} - -/*! - \qmlproperty list<string> Presentation::createdMeshes - - This property contains a list of all dynamically created meshes on this presentation. - - This property is read-only. - - \note Meshes can only be dynamically created via C++ API. - - \sa createMesh - \sa createMeshes -*/ - -/*! - \property Q3DSPresentation::createdMeshes - - This property contains a list of all dynamically created meshes on this presentation. - - This property is read-only. - - \sa createMesh - \sa createMeshes -*/ -QStringList Q3DSPresentation::createdMeshes() const -{ - return d_ptr->m_createdMeshes; -} - -/*! - * \internal - */ -void Q3DSPresentation::mousePressEvent(QMouseEvent *e) -{ - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->HandleMousePress(e->x(), e->y(), e->button(), true); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(QString(), CommandType_MousePress, - e->x(), e->y(), int(e->button())); - } -} - -/*! - * \internal - */ -void Q3DSPresentation::mouseReleaseEvent(QMouseEvent *e) -{ - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->HandleMousePress(e->x(), e->y(), e->button(), false); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(QString(), CommandType_MouseRelease, - e->x(), e->y(), int(e->button())); - } -} - -/*! - * \internal - */ -void Q3DSPresentation::mouseMoveEvent(QMouseEvent *e) -{ - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->HandleMouseMove(e->x(), e->y(), true); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(QString(), CommandType_MouseMove, - e->x(), e->y()); - } -} - -/*! - * \internal - */ -void Q3DSPresentation::wheelEvent(QWheelEvent *e) -{ - QPoint pixelData = e->pixelDelta(); - int numSteps = 0; - if (pixelData.isNull()) { - if (e->orientation() == Qt::Vertical) - numSteps = e->angleDelta().y() / 8; - else - numSteps = e->angleDelta().x() / 8; - } else { - // trackpad, pixel = one step in scroll wheel. - if (e->orientation() == Qt::Vertical) - numSteps = pixelData.y(); - else - numSteps = pixelData.x(); - } - if (numSteps != 0) { - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->HandleMouseWheel(e->x(), e->y(), - e->orientation() == Qt::Vertical ? 0 : 1, - numSteps); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(QString(), CommandType_MouseWheel, - e->x(), e->y(), - int(e->orientation() == Qt::Vertical), numSteps); - } - } -} - -/*! - * \internal - */ -void Q3DSPresentation::keyPressEvent(QKeyEvent *e) -{ - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->HandleKeyInput(d_ptr->getScanCode(e), true); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(QString(), CommandType_KeyPress, - d_ptr->getScanCode(e)); - } -} - -/*! - * \internal - */ -void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e) -{ - if (d_ptr->m_viewerApp) { - d_ptr->m_viewerApp->HandleKeyInput(d_ptr->getScanCode(e), false); - } else if (d_ptr->m_commandQueue) { - d_ptr->m_commandQueue->queueCommand(QString(), CommandType_KeyRelease, - d_ptr->getScanCode(e)); - } -} - -// #TODO: QT3DS-3562 Most Presentation signals missing documentation -/*! - * \qmlsignal Presentation::slideEntered - * Emitted when - * \param elementPath - * \param index - * \param name - */ - -/*! - * \fn Q3DSPresentation::slideEntered - * Emitted when - * \param elementPath - * \param index - * \param name - */ - -/*! - * \qmlsignal Presentation::slideExited - * Emitted when - * \param elementPath - * \param index - * \param name - */ - -/*! - * \fn Q3DSPresentation::slideExited - * Emitted when - * \param elementPath - * \param index - * \param name - */ - -/*! - * \fn Q3DSPresentation::dataInputsReady - * Emitted when \l{DataInput}s in the Studio project have been parsed and data inputs are available - * through dataInputs() and getDataInputs() methods. - */ - -/*! - * \fn Q3DSPresentation::dataOutputsReady - * Emitted when \l{DataOutput}s in the Studio project have been parsed and data outputs are available - * through dataOutputs() and getDataOutputs() methods. - */ - -/*! - * \qmlsignal Presentation::customSignalEmitted - * Emitted when - * \param elementPath - * \param name - */ - -/*! - * \fn Q3DSPresentation::customSignalEmitted - * Emitted when - * \param elementPath - * \param name - */ - -/*! - \qmlsignal Presentation::elementsCreated - Emitted when one or more elements have been created in response to createElement() - or createElements() calls. The \a elementPaths list contains the element paths of the created - elements. If creation failed, \a error string indicates the reason. - - \sa createElement - \sa createElements - */ - -/*! - \fn Q3DSPresentation::elementsCreated - Emitted when one or more elements have been created in response to createElement() - or createElements() calls. The \a elementPaths list contains the element paths of the created - elements. If creation failed, \a error string indicates the reason. - - \sa createElement - \sa createElements - */ - -/*! - \qmlsignal Presentation::materialsCreated - Emitted when one or more materials have been created in response to createMaterial() - or createMaterials() calls. The \a materialNames list contains the names of the created - materials. If the material is created into a subpresentation, the name is prefixed with - subpresentation ID followed by a colon. - If creation failed, \a error string indicates the reason. - - \sa createMaterial - \sa createMaterials - */ - -/*! - \fn Q3DSPresentation::materialsCreated - Emitted when one or more materials have been created in response to createMaterial() - or createMaterials() calls. The \a materialNames list contains the names of the created - materials. If creation failed, \a error string indicates the reason. - - \sa createMaterial - \sa createMaterials - */ - -/*! - \qmlsignal Presentation::meshesCreated - Emitted when one or more meshes have been created in response to createMesh() - or createMeshes() calls. The \a meshNames list contains the names of the created - meshes. If creation failed, \a error string indicates the reason. - - \sa createMesh - \sa createMeshes - */ - -/*! - \fn Q3DSPresentation::meshesCreated - Emitted when one or more meshes have been created in response to createMesh() - or createMeshes() calls. The \a meshNames list contains the names of the created - meshes. If creation failed, \a error string indicates the reason. - - \sa createMesh - \sa createMeshes - */ - -/*! - * \internal - */ -Q3DSPresentationPrivate::Q3DSPresentationPrivate(Q3DSPresentation *q) - : QObject(q) - , q_ptr(q) - , m_viewerApp(nullptr) - , m_commandQueue(nullptr) - , m_streamProxy(nullptr) - , m_delayedLoading(false) -{ -} - -Q3DSPresentationPrivate::~Q3DSPresentationPrivate() -{ - unregisterAllElements(); - unregisterAllDataInputs(); - unregisterAllDataOutputs(); - delete m_streamProxy; -} - -void Q3DSPresentationPrivate::setSource(const QUrl &source) -{ - m_source = source; - if (m_commandQueue) { - m_commandQueue->m_sourceChanged = true; - m_commandQueue->m_source = source; - } -} - -void Q3DSPresentationPrivate::setVariantList(const QStringList &variantList) -{ - m_variantList = variantList; - if (m_commandQueue) { - m_commandQueue->m_variantListChanged = true; - m_commandQueue->m_variantList = variantList; - } -} - -void Q3DSPresentationPrivate::setViewerApp(Q3DSViewer::Q3DSViewerApp *app, bool connectApp) -{ - Q3DSViewer::Q3DSViewerApp *oldApp = m_viewerApp; - m_viewerApp = app; - - const auto elements = m_elements.values(); - for (Q3DSElement *element : elements) - element->d_ptr->setViewerApp(app); - - if (m_viewerApp) { - const auto dataInputs = m_viewerApp->dataInputs(); - for (const auto &name : dataInputs) { - if (!m_dataInputs.contains(name)) { - // Name is sufficient for C++ side APIs, as other parameters - // (max/min) are queried synchronously. - auto *di = new Q3DSDataInput(name, nullptr); - registerDataInput(di); - } - } - Q_EMIT q_ptr->dataInputsReady(); - } - - if (connectApp) { - if (app) { - connect(app, &Q3DSViewer::Q3DSViewerApp::SigSlideEntered, - this, &Q3DSPresentationPrivate::handleSlideEntered); - connect(app, &Q3DSViewer::Q3DSViewerApp::SigSlideExited, - q_ptr, &Q3DSPresentation::slideExited); - connect(app, &Q3DSViewer::Q3DSViewerApp::SigCustomSignal, - q_ptr, &Q3DSPresentation::customSignalEmitted); - connect(app, &Q3DSViewer::Q3DSViewerApp::SigDataOutputValueUpdated, - this, &Q3DSPresentationPrivate::handleDataOutputValueUpdate); - connect(app, &Q3DSViewer::Q3DSViewerApp::SigElementsCreated, - this, &Q3DSPresentationPrivate::handleElementsCreated); - connect(app, &Q3DSViewer::Q3DSViewerApp::SigMaterialsCreated, - this, &Q3DSPresentationPrivate::handleMaterialsCreated); - connect(app, &Q3DSViewer::Q3DSViewerApp::SigMeshesCreated, - this, &Q3DSPresentationPrivate::handleMeshesCreated); - } - if (oldApp) { - disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigSlideEntered, - this, &Q3DSPresentationPrivate::handleSlideEntered); - disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigSlideExited, - q_ptr, &Q3DSPresentation::slideExited); - disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigCustomSignal, - q_ptr, &Q3DSPresentation::customSignalEmitted); - disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigDataOutputValueUpdated, - this, &Q3DSPresentationPrivate::handleDataOutputValueUpdate); - disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigElementsCreated, - this, &Q3DSPresentationPrivate::handleElementsCreated); - disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigMaterialsCreated, - this, &Q3DSPresentationPrivate::handleMaterialsCreated); - disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigMeshesCreated, - this, &Q3DSPresentationPrivate::handleMeshesCreated); - } - } -} - -void Q3DSPresentationPrivate::setCommandQueue(CommandQueue *queue) -{ - m_commandQueue = queue; - - const auto elements = m_elements.values(); - const auto dataInputs = m_dataInputs.values(); - for (Q3DSElement *element : elements) - element->d_ptr->setCommandQueue(queue); - for (Q3DSDataInput *di : dataInputs) - di->d_ptr->setCommandQueue(queue); - - if (m_commandQueue) { - setDelayedLoading(m_delayedLoading); - setVariantList(m_variantList); - // Queue a request ASAP for datainputs and outputs defined in UIA file so that - // getDataInputs has up-to-date info at the earliest and that data outputs - // connect from source to destination - m_commandQueue->queueCommand({}, CommandType_RequestDataInputs); - m_commandQueue->queueCommand({}, CommandType_RequestDataOutputs); - setSource(m_source); - } -} - -void Q3DSPresentationPrivate::setDelayedLoading(bool enable) -{ - m_delayedLoading = enable; - if (m_commandQueue) { - m_commandQueue->m_delayedLoading = enable; - m_commandQueue->m_delayedLoadingChanged = true; - } -} - -void Q3DSPresentationPrivate::requestResponseHandler(CommandType commandType, void *requestData) -{ - switch (commandType) { - case CommandType_RequestDataInputs: { - QVariantList *response = reinterpret_cast<QVariantList *>(requestData); - - for (int i = 0; i < response->size(); ++i) { - // Check and append to QML-side list if the (UIA) presentation has additional datainputs - // that are not explicitly defined in QML code. - auto receivedDI = response->at(i).value<Q3DSDataInput *>(); - // For QML behind async command queue, we cache min/max and metadata values in addition - // to name, in order to be able to return values initially set in UIA file (in QML - // getters). - if (!m_dataInputs.contains(receivedDI->name())) { - auto newDI = new Q3DSDataInput(receivedDI->name(), nullptr); - newDI->d_ptr->m_min = receivedDI->d_ptr->m_min; - newDI->d_ptr->m_max = receivedDI->d_ptr->m_max; - newDI->d_ptr->m_metadata = receivedDI->d_ptr->m_metadata; - registerDataInput(newDI); - } else { - m_dataInputs[receivedDI->name()]->d_ptr->m_min = receivedDI->d_ptr->m_min; - m_dataInputs[receivedDI->name()]->d_ptr->m_max = receivedDI->d_ptr->m_max; - m_dataInputs[receivedDI->name()]->d_ptr->m_metadata = receivedDI->d_ptr->m_metadata; - } - } - delete response; - Q_EMIT q_ptr->dataInputsReady(); - break; - } - case CommandType_RequestDataOutputs: { - QVariantList *response = reinterpret_cast<QVariantList *>(requestData); - - for (int i = 0; i < response->size(); ++i) { - // Check and append to QML-side list if the (UIA) presentation has additional - // dataoutputs that are not explicitly defined in QML code. - if (!m_dataOutputs.contains(response->at(i).value<QString>())) - registerDataOutput(new Q3DSDataOutput(response->at(i).value<QString>(), nullptr)); - } - delete response; - Q_EMIT q_ptr->dataOutputsReady(); - break; - } - default: - Q_ASSERT(false); - break; - } -} - -// Doc note: The ownership of the registered scenes remains with the caller, who needs to -// ensure that registered scenes are alive as long as the presentation is alive. -void Q3DSPresentationPrivate::registerElement(Q3DSElement *element) -{ - Q_ASSERT(!element->elementPath().isEmpty()); - - // Allow only single registration for each element path and scene object - QMutableHashIterator<QString, Q3DSElement *> i(m_elements); - while (i.hasNext()) { - i.next(); - if (i.value() == element) { - // If the same scene object is already registered with different path, - // remove it from the map to avoid duplication. - if (i.key() != element->elementPath()) - i.remove(); - } else if (i.key() == element->elementPath()) { - // If the same element path is registered by another scene object, the old - // scene object is unregistered. - i.value()->d_ptr->setViewerApp(nullptr); - i.value()->d_ptr->setPresentation(nullptr); - i.remove(); - } - } - - element->d_ptr->setViewerApp(m_viewerApp); - element->d_ptr->setCommandQueue(m_commandQueue); - element->d_ptr->setPresentation(this); - - m_elements.insert(element->elementPath(), element); -} - -void Q3DSPresentationPrivate::unregisterElement(Q3DSElement *element) -{ - Q3DSElement *oldScene = m_elements.value(element->elementPath()); - if (oldScene == element) { - element->d_ptr->setViewerApp(nullptr); - element->d_ptr->setCommandQueue(nullptr); - element->d_ptr->setPresentation(nullptr); - m_elements.remove(element->elementPath()); - } -} - -void Q3DSPresentationPrivate::unregisterAllElements() -{ - for (Q3DSElement *element : m_elements.values()) { - element->d_ptr->setViewerApp(nullptr); - element->d_ptr->setCommandQueue(nullptr); - element->d_ptr->setPresentation(nullptr); - } - m_elements.clear(); -} - -void Q3DSPresentationPrivate::registerDataInput(Q3DSDataInput *dataInput) -{ - Q_ASSERT(!dataInput->name().isEmpty()); - - // Allow only single registration for each DataInput - QMutableHashIterator<QString, Q3DSDataInput *> i(m_dataInputs); - while (i.hasNext()) { - i.next(); - if (i.value() == dataInput) { - // If the same DataInput object is already registered with different name, - // remove it from the map to avoid duplication. - if (i.key() != dataInput->name()) - i.remove(); - } else if (i.key() == dataInput->name()) { - // If the same name is registered by another DataInput object, the old - // DataInput object is unregistered. - i.value()->d_ptr->setViewerApp(nullptr); - i.value()->d_ptr->setPresentation(nullptr); - i.remove(); - } - } - - dataInput->d_ptr->setPresentation(q_ptr); - dataInput->d_ptr->setViewerApp(m_viewerApp); - dataInput->d_ptr->setCommandQueue(m_commandQueue); - - m_dataInputs.insert(dataInput->name(), dataInput); -} - -void Q3DSPresentationPrivate::unregisterDataInput(Q3DSDataInput *dataInput) -{ - Q3DSDataInput *oldDi = m_dataInputs.value(dataInput->name()); - if (oldDi == dataInput) { - dataInput->d_ptr->setCommandQueue(nullptr); - dataInput->d_ptr->setViewerApp(nullptr); - dataInput->d_ptr->setPresentation(nullptr); - m_dataInputs.remove(dataInput->name()); - } -} - -void Q3DSPresentationPrivate::unregisterAllDataInputs() -{ - for (Q3DSDataInput *di : m_dataInputs.values()) { - di->d_ptr->setViewerApp(nullptr); - di->d_ptr->setCommandQueue(nullptr); - di->d_ptr->setPresentation(nullptr); - } - m_dataInputs.clear(); -} -bool Q3DSPresentationPrivate::isValidDataInput(const Q3DSDataInput *dataInput) const -{ - // For QML instance separated from runtime engine by command queue, - // check locally cached list for this datainput (initialised at presentation load). - if (!m_viewerApp) { - if (m_dataInputs.contains(dataInput->name())) - return true; - else - return false; - } - - return m_viewerApp->dataInputs().contains(dataInput->name()); -} - -float Q3DSPresentationPrivate::dataInputMin(const QString &name) const -{ - // For QML instance separated from runtime engine by command queue, - // return locally cached value (initialised at presentation load). - if (!m_viewerApp) { - if (m_dataInputs.contains(name)) - return m_dataInputs[name]->d_ptr->m_min; - else - return 0.0f; - } - return m_viewerApp->dataInputMin(name); -} - -float Q3DSPresentationPrivate::dataInputMax(const QString &name) const -{ - // For QML instance separated from runtime engine by command queue, - // return locally cached value (initialised at presentation load). - if (!m_viewerApp) { - if (m_dataInputs.contains(name)) - return m_dataInputs[name]->d_ptr->m_max; - else - return 0.0f; - } - return m_viewerApp->dataInputMax(name); -} - -QHash<QString, QString> Q3DSPresentationPrivate::dataInputMetadata(const QString &name) const -{ - // For QML instance separated from runtime engine by command queue, - // return locally cached value (initialised at presentation load). - if (!m_viewerApp) { - if (m_dataInputs.contains(name)) - return m_dataInputs[name]->d_ptr->m_metadata; - else - return {}; - } - return m_viewerApp->dataInputMetadata(name); -} - -QVector<Q3DSDataInput *> Q3DSPresentationPrivate::dataInputs(const QString &key) const -{ - QVector<Q3DSDataInput *> ret; - // For QML instance separated from runtime engine by command queue, - // return locally cached value (initialised at presentation load). - if (!m_viewerApp) { - for (const auto &it : m_dataInputs) { - if (it->metadataKeys().contains(key)) - ret.append(it); - } - } else { - // Otherwise, defer to viewer app. - const auto &diList = m_viewerApp->dataInputs(); - // We fetch the metadata(s) from the source (viewer app) but - // return the corresponding datainput object(s) held by presentation item. - for (const auto &it : diList) { - if (m_viewerApp->dataInputMetadata(it).contains(key)) - ret.append(m_dataInputs[it]); - } - } - - return ret; -} - -void Q3DSPresentationPrivate::registerDataOutput(Q3DSDataOutput *dataOutput) -{ - Q_ASSERT(!dataOutput->name().isEmpty()); - - // Allow only single registration for each DataOutput - QMutableHashIterator<QString, Q3DSDataOutput *> i(m_dataOutputs); - while (i.hasNext()) { - i.next(); - if (i.value() == dataOutput) { - // If the same DataOutput object is already registered with different name, - // remove it from the map to avoid duplication. - if (i.key() != dataOutput->name()) - i.remove(); - } else if (i.key() == dataOutput->name()) { - // If the same name is registered by another DataOutput object, the old - // DataOutput object is unregistered. - i.value()->d_ptr->setViewerApp(nullptr); - i.value()->d_ptr->setPresentation(nullptr); - i.value()->d_ptr->setCommandQueue(nullptr); - i.remove(); - } - } - - dataOutput->d_ptr->setPresentation(q_ptr); - dataOutput->d_ptr->setViewerApp(m_viewerApp); - dataOutput->d_ptr->setCommandQueue(m_commandQueue); - - m_dataOutputs.insert(dataOutput->name(), dataOutput); -} - -void Q3DSPresentationPrivate::unregisterDataOutput(Q3DSDataOutput *dataOutput) -{ - Q3DSDataOutput *oldDout = m_dataOutputs.value(dataOutput->name()); - if (oldDout == dataOutput) { - dataOutput->d_ptr->setCommandQueue(nullptr); - dataOutput->d_ptr->setViewerApp(nullptr); - dataOutput->d_ptr->setPresentation(nullptr); - m_dataOutputs.remove(dataOutput->name()); - } -} - -void Q3DSPresentationPrivate::unregisterAllDataOutputs() -{ - const auto values = m_dataOutputs.values(); - for (Q3DSDataOutput *dout : values) { - dout->d_ptr->setViewerApp(nullptr); - dout->d_ptr->setCommandQueue(nullptr); - dout->d_ptr->setPresentation(nullptr); - } - m_dataOutputs.clear(); -} - -bool Q3DSPresentationPrivate::isValidDataOutput(const Q3DSDataOutput *dataOutput) const -{ - if (!m_viewerApp) - return false; - - return m_viewerApp->dataOutputs().contains(dataOutput->name()); -} - -Q3DStudio::EKeyCode Q3DSPresentationPrivate::getScanCode(QKeyEvent *e) -{ - enum { - RIGHT_SHIFT = 0x036, - RIGHT_CTRL = 0x11d, - RIGHT_ALT = 0x138, - }; - - Qt::Key keyScanCode = static_cast<Qt::Key>(e->key()); - - Q3DStudio::EKeyCode newScanCode = Q3DStudio::KEY_NOKEY; - switch (keyScanCode) { - case Qt::Key_Down: - newScanCode = Q3DStudio::KEY_DOWN; - break; - case Qt::Key_Up: - newScanCode = Q3DStudio::KEY_UP; - break; - case Qt::Key_Left: - newScanCode = Q3DStudio::KEY_LEFT; - break; - case Qt::Key_Right: - newScanCode = Q3DStudio::KEY_RIGHT; - break; - case Qt::Key_Return: - case Qt::Key_Enter: - newScanCode = e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPADENTER - : Q3DStudio::KEY_RETURN; - break; - case Qt::Key_Backspace: - newScanCode = Q3DStudio::KEY_BACK; - break; - case Qt::Key_Tab: - newScanCode = Q3DStudio::KEY_TAB; - break; - case Qt::Key_Escape: - newScanCode = Q3DStudio::KEY_ESCAPE; - break; - case Qt::Key_A: - newScanCode = Q3DStudio::KEY_A; - break; - case Qt::Key_B: - newScanCode = Q3DStudio::KEY_B; - break; - case Qt::Key_C: - newScanCode = Q3DStudio::KEY_C; - break; - case Qt::Key_D: - newScanCode = Q3DStudio::KEY_D; - break; - case Qt::Key_E: - newScanCode = Q3DStudio::KEY_E; - break; - case Qt::Key_F: - newScanCode = Q3DStudio::KEY_F; - break; - case Qt::Key_G: - newScanCode = Q3DStudio::KEY_G; - break; - case Qt::Key_H: - newScanCode = Q3DStudio::KEY_H; - break; - case Qt::Key_I: - newScanCode = Q3DStudio::KEY_I; - break; - case Qt::Key_J: - newScanCode = Q3DStudio::KEY_J; - break; - case Qt::Key_K: - newScanCode = Q3DStudio::KEY_K; - break; - case Qt::Key_L: - newScanCode = Q3DStudio::KEY_L; - break; - case Qt::Key_M: - newScanCode = Q3DStudio::KEY_M; - break; - case Qt::Key_N: - newScanCode = Q3DStudio::KEY_N; - break; - case Qt::Key_O: - newScanCode = Q3DStudio::KEY_O; - break; - case Qt::Key_P: - newScanCode = Q3DStudio::KEY_P; - break; - case Qt::Key_Q: - newScanCode = Q3DStudio::KEY_Q; - break; - case Qt::Key_R: - newScanCode = Q3DStudio::KEY_R; - break; - case Qt::Key_S: - newScanCode = Q3DStudio::KEY_S; - break; - case Qt::Key_T: - newScanCode = Q3DStudio::KEY_T; - break; - case Qt::Key_U: - newScanCode = Q3DStudio::KEY_U; - break; - case Qt::Key_V: - newScanCode = Q3DStudio::KEY_V; - break; - case Qt::Key_W: - newScanCode = Q3DStudio::KEY_W; - break; - case Qt::Key_X: - newScanCode = Q3DStudio::KEY_X; - break; - case Qt::Key_Y: - newScanCode = Q3DStudio::KEY_Y; - break; - case Qt::Key_Z: - newScanCode = Q3DStudio::KEY_Z; - break; - case Qt::Key_0: - newScanCode = - e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD0 : Q3DStudio::KEY_0; - break; - case Qt::Key_1: - newScanCode = - e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD1 : Q3DStudio::KEY_1; - break; - case Qt::Key_2: - newScanCode = - e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD2 : Q3DStudio::KEY_2; - break; - case Qt::Key_3: - newScanCode = - e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD3 : Q3DStudio::KEY_3; - break; - case Qt::Key_4: - newScanCode = - e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD4 : Q3DStudio::KEY_4; - break; - case Qt::Key_5: - newScanCode = - e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD5 : Q3DStudio::KEY_5; - break; - case Qt::Key_6: - newScanCode = - e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD6 : Q3DStudio::KEY_6; - break; - case Qt::Key_7: - newScanCode = - e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD7 : Q3DStudio::KEY_7; - break; - case Qt::Key_8: - newScanCode = - e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD8 : Q3DStudio::KEY_8; - break; - case Qt::Key_9: - newScanCode = - e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD9 : Q3DStudio::KEY_9; - break; - case Qt::Key_Minus: - newScanCode = e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPADSUBTRACT - : Q3DStudio::KEY_SUBTRACT; - break; - case Qt::Key_Plus: - newScanCode = e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPADADD - : Q3DStudio::KEY_EQUALS; - break; - case Qt::Key_NumLock: - newScanCode = Q3DStudio::KEY_NUMLOCK; - break; - case Qt::Key_ScrollLock: - newScanCode = Q3DStudio::KEY_SCROLL; - break; - case Qt::Key_CapsLock: - newScanCode = Q3DStudio::KEY_CAPITAL; - break; - case Qt::Key_Pause: - newScanCode = Q3DStudio::KEY_PAUSE; - break; - case Qt::Key_Print: - newScanCode = Q3DStudio::KEY_PRINTSCREEN; - break; - case Qt::Key_Insert: - newScanCode = Q3DStudio::KEY_INSERT; - break; - case Qt::Key_Delete: - newScanCode = Q3DStudio::KEY_DELETE; - break; - case Qt::Key_Home: - newScanCode = Q3DStudio::KEY_HOME; - break; - case Qt::Key_End: - newScanCode = Q3DStudio::KEY_END; - break; - case Qt::Key_PageUp: - newScanCode = Q3DStudio::KEY_PGUP; - break; - case Qt::Key_PageDown: - newScanCode = Q3DStudio::KEY_PGDN; - break; - case Qt::Key_F1: - newScanCode = Q3DStudio::KEY_F1; - break; - case Qt::Key_F2: - newScanCode = Q3DStudio::KEY_F2; - break; - case Qt::Key_F3: - newScanCode = Q3DStudio::KEY_F3; - break; - case Qt::Key_F4: - newScanCode = Q3DStudio::KEY_F4; - break; - case Qt::Key_F5: - newScanCode = Q3DStudio::KEY_F5; - break; - case Qt::Key_F6: - newScanCode = Q3DStudio::KEY_F6; - break; - case Qt::Key_F7: - newScanCode = Q3DStudio::KEY_F7; - break; - case Qt::Key_F8: - newScanCode = Q3DStudio::KEY_F8; - break; - case Qt::Key_F9: - newScanCode = Q3DStudio::KEY_F9; - break; - case Qt::Key_F10: - newScanCode = Q3DStudio::KEY_F10; - break; - case Qt::Key_F11: - newScanCode = Q3DStudio::KEY_F11; - break; - case Qt::Key_F12: - newScanCode = Q3DStudio::KEY_F12; - break; - case Qt::Key_F13: - newScanCode = Q3DStudio::KEY_F13; - break; - case Qt::Key_F14: - newScanCode = Q3DStudio::KEY_F14; - break; - case Qt::Key_QuoteLeft: - newScanCode = Q3DStudio::KEY_GRAVE; - break; - case Qt::Key_Asterisk: - newScanCode = Q3DStudio::KEY_MULTIPLY; - break; - case Qt::Key_BracketRight: - newScanCode = Q3DStudio::KEY_RBRACKET; - break; - case Qt::Key_BracketLeft: - newScanCode = Q3DStudio::KEY_LBRACKET; - break; - case Qt::Key_Semicolon: - newScanCode = Q3DStudio::KEY_SEMICOLON; - break; - case Qt::Key_Comma: - newScanCode = Q3DStudio::KEY_COMMA; - break; - case Qt::Key_Period: - newScanCode = e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPADDECIMAL - : Q3DStudio::KEY_PERIOD; - break; - case Qt::Key_Apostrophe: - newScanCode = Q3DStudio::KEY_APOSTROPHE; - break; - case Qt::Key_Slash: - newScanCode = Q3DStudio::KEY_SLASH; - break; - case Qt::Key_Backslash: - newScanCode = Q3DStudio::KEY_BACKSLASH; - break; - case Qt::Key_Equal: - newScanCode = Q3DStudio::KEY_EQUALS; - break; - case Qt::Key_Space: - newScanCode = Q3DStudio::KEY_SPACE; - break; - case Qt::Key_Shift: - newScanCode = - e->nativeScanCode() == RIGHT_SHIFT ? Q3DStudio::KEY_RSHIFT : Q3DStudio::KEY_LSHIFT; - break; - case Qt::Key_Control: - newScanCode = e->nativeScanCode() == RIGHT_CTRL ? Q3DStudio::KEY_RCONTROL - : Q3DStudio::KEY_LCONTROL; - break; - case Qt::Key_Alt: - newScanCode = - e->nativeScanCode() == RIGHT_ALT ? Q3DStudio::KEY_RALT : Q3DStudio::KEY_LALT; - break; - default: - break; - } - - return newScanCode; -} - -ViewerQmlStreamProxy *Q3DSPresentationPrivate::streamProxy() -{ - if (!m_streamProxy) - m_streamProxy = new ViewerQmlStreamProxy(); - return m_streamProxy; -} - -void Q3DSPresentationPrivate::handleSlideEntered(const QString &elementPath, unsigned int index, - const QString &name) -{ - Q3DSSceneElement *scene = qobject_cast<Q3DSSceneElement *>(m_elements.value(elementPath)); - if (scene) - scene->d_func()->handleSlideEntered(index, name); - Q_EMIT q_ptr->slideEntered(elementPath, index, name); -} - -void Q3DSPresentationPrivate::handleDataOutputValueUpdate(const QString &name, - const QVariant &newValue) -{ - if (!m_dataOutputs.contains(name)) - return; - - Q3DSDataOutput *node = m_dataOutputs[name]; - node->setValue(newValue); -} - -void Q3DSPresentationPrivate::handleElementsCreated(const QStringList &elementPaths, - const QString &error) -{ - if (error.isEmpty()) - m_createdElements << elementPaths; - - Q_EMIT q_ptr->elementsCreated(elementPaths, error); -} - -void Q3DSPresentationPrivate::handleMaterialsCreated(const QStringList &materialNames, - const QString &error) -{ - if (error.isEmpty()) - m_createdMaterials << materialNames; - - Q_EMIT q_ptr->materialsCreated(materialNames, error); -} - -void Q3DSPresentationPrivate::handleMeshesCreated(const QStringList &meshNames, - const QString &error) -{ - if (error.isEmpty()) - m_createdMeshes << meshNames; - - Q_EMIT q_ptr->meshesCreated(meshNames, error); -} - -QT_END_NAMESPACE |