summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2019-05-15 13:55:24 +0300
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2019-05-17 08:58:22 +0000
commitdc093d844948715ab2d77eb5eb38dd81b2655521 (patch)
tree3f3184a3fe0631f8562df630e96618b824f4f0db
parent09b3156579460b5d1b30ab6b17bd26b8a2f04c08 (diff)
Add methods to create/delete multiple elements/materials at once
Also modified the notification signals to notify multiple creations with a single signal. Task-number: QT3DS-3376 Change-Id: I75bc867601d3f7943733b451ddfad18fab9383ea Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r--src/Runtime/Source/engine/Qt3DSRuntimeView.cpp38
-rw-r--r--src/Runtime/Source/engine/Qt3DSRuntimeView.h15
-rw-r--r--src/Runtime/Source/runtime/Qt3DSIScriptBridge.h18
-rw-r--r--src/Runtime/Source/runtime/Qt3DSPresentation.h4
-rw-r--r--src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp1209
-rw-r--r--src/Runtime/Source/viewer/Qt3DSViewerApp.cpp24
-rw-r--r--src/Runtime/Source/viewer/Qt3DSViewerApp.h18
-rw-r--r--src/Runtime/api/studio3d/q3dscommandqueue.cpp52
-rw-r--r--src/Runtime/api/studio3d/q3dscommandqueue_p.h9
-rw-r--r--src/Runtime/api/studio3d/q3dspresentation.cpp65
-rw-r--r--src/Runtime/api/studio3d/q3dspresentation.h12
-rw-r--r--src/Runtime/api/studio3dqml/q3dsrenderer.cpp33
-rw-r--r--src/Runtime/api/studio3dqml/q3dsrenderer.h4
-rw-r--r--src/Runtime/api/studio3dqml/q3dsstudio3d.cpp8
-rw-r--r--src/Runtime/api/studio3dqml/q3dsstudio3d.h2
-rw-r--r--tests/auto/viewer/tst_qt3dsviewer.cpp191
-rw-r--r--tests/auto/viewer/tst_qt3dsviewer.h2
17 files changed, 929 insertions, 775 deletions
diff --git a/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp b/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp
index 3e95f46d..eb17a9b2 100644
--- a/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp
+++ b/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp
@@ -211,10 +211,11 @@ public:
float dataInputMax(const QString &name) const override;
float dataInputMin(const QString &name) const override;
- void createElement(const QString &parentElementPath, const QString &slideName,
- const QHash<QString, QVariant> &properties) override;
- void deleteElement(const QString &elementPath) override;
- void createMaterial(const QString &elementPath, const QString &materialDefinition) override;
+ void createElements(const QString &parentElementPath, const QString &slideName,
+ const QVector<QHash<QString, QVariant>> &properties) override;
+ void deleteElements(const QStringList &elementPaths) override;
+ void createMaterials(const QString &elementPath,
+ const QStringList &materialDefinitions) override;
void SetAttribute(const char *elementPath, const char *attributeName,
const char *value) override;
bool GetAttribute(const char *elementPath, const char *attributeName, void *value) override;
@@ -309,10 +310,10 @@ bool CRuntimeView::InitializeGraphics(const QSurfaceFormat &format, bool delayed
QObject::connect(m_Presentation->signalProxy(),
&QPresentationSignalProxy::SigPresentationReady,
signalProxy(), &QRuntimeViewSignalProxy::SigPresentationReady);
- QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigElementCreated,
- signalProxy(), &QRuntimeViewSignalProxy::SigElementCreated);
- QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigMaterialCreated,
- signalProxy(), &QRuntimeViewSignalProxy::SigMaterialCreated);
+ QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigElementsCreated,
+ signalProxy(), &QRuntimeViewSignalProxy::SigElementsCreated);
+ QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigMaterialsCreated,
+ signalProxy(), &QRuntimeViewSignalProxy::SigMaterialsCreated);
m_TimeProvider.Reset();
return true;
@@ -619,34 +620,35 @@ float CRuntimeView::dataInputMin(const QString &name) const
return 0;
}
-void CRuntimeView::createElement(const QString &parentElementPath, const QString &slideName,
- const QHash<QString, QVariant> &properties)
+void CRuntimeView::createElements(const QString &parentElementPath, const QString &slideName,
+ const QVector<QHash<QString, QVariant>> &properties)
{
if (m_Application) {
Q3DStudio::CQmlEngine &theBridgeEngine
= static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
- theBridgeEngine.createElement(parentElementPath, slideName, properties,
- &m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer());
+ theBridgeEngine.createElements(parentElementPath, slideName, properties,
+ &m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer());
}
}
-void CRuntimeView::deleteElement(const QString &elementPath)
+void CRuntimeView::deleteElements(const QStringList &elementPaths)
{
if (m_Application) {
Q3DStudio::CQmlEngine &theBridgeEngine
= static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
- theBridgeEngine.deleteElement(elementPath,
- &m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer());
+ theBridgeEngine.deleteElements(elementPaths,
+ &m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer());
}
}
-void CRuntimeView::createMaterial(const QString &elementPath, const QString &materialDefinition)
+void CRuntimeView::createMaterials(const QString &elementPath,
+ const QStringList &materialDefinitions)
{
if (m_Application) {
Q3DStudio::CQmlEngine &theBridgeEngine
= static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
- theBridgeEngine.createMaterial(
- elementPath, materialDefinition,
+ theBridgeEngine.createMaterials(
+ elementPath, materialDefinitions,
&m_RuntimeFactory->GetQt3DSRenderContext().GetCustomMaterialSystem(),
&m_RuntimeFactory->GetQt3DSRenderContext().GetDynamicObjectSystem(),
&m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer());
diff --git a/src/Runtime/Source/engine/Qt3DSRuntimeView.h b/src/Runtime/Source/engine/Qt3DSRuntimeView.h
index f728f220..38d30fa7 100644
--- a/src/Runtime/Source/engine/Qt3DSRuntimeView.h
+++ b/src/Runtime/Source/engine/Qt3DSRuntimeView.h
@@ -44,6 +44,8 @@
#include "Qt3DSPresentation.h"
#include "Qt3DSRenderRuntimeBinding.h"
#include <QtCore/qobject.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qstringlist.h>
#include <QtGui/qsurfaceformat.h>
typedef void (*qml_Function)(void *inUserData);
@@ -56,8 +58,8 @@ Q_SIGNALS:
void SigSlideExited(const QString &elementPath, unsigned int index, const QString &name);
void SigCustomSignal(const QString &elementPath, const QString &name);
void SigPresentationReady();
- void SigElementCreated(const QString &elementName, const QString &error);
- void SigMaterialCreated(const QString &name, const QString &error);
+ void SigElementsCreated(const QStringList &elementPaths, const QString &error);
+ void SigMaterialsCreated(const QStringList &materialNames, const QString &error);
};
namespace qt3ds {
@@ -192,10 +194,11 @@ public:
virtual QList<QString> dataInputs() const = 0;
virtual float dataInputMax(const QString &name) const = 0;
virtual float dataInputMin(const QString &name) const = 0;
- virtual void createElement(const QString &parentElementPath, const QString &slideName,
- const QHash<QString, QVariant> &properties) = 0;
- virtual void deleteElement(const QString &elementPath) = 0;
- virtual void createMaterial(const QString &elementPath, const QString &materialDefinition) = 0;
+ virtual void createElements(const QString &parentElementPath, const QString &slideName,
+ const QVector<QHash<QString, QVariant>> &properties) = 0;
+ virtual void deleteElements(const QStringList &elementPaths) = 0;
+ virtual void createMaterials(const QString &elementPath,
+ const QStringList &materialDefinitions) = 0;
virtual void SetAttribute(const char *elementPath, const char *attributeName,
const char *value) = 0;
virtual bool GetAttribute(const char *elementPath, const char *attributeName, void *value) = 0;
diff --git a/src/Runtime/Source/runtime/Qt3DSIScriptBridge.h b/src/Runtime/Source/runtime/Qt3DSIScriptBridge.h
index 8edced36..69a4be66 100644
--- a/src/Runtime/Source/runtime/Qt3DSIScriptBridge.h
+++ b/src/Runtime/Source/runtime/Qt3DSIScriptBridge.h
@@ -36,6 +36,8 @@
#include "Qt3DSApplication.h"
#include <QtCore/qvariant.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qstringlist.h>
namespace qt3ds {
namespace runtime {
@@ -161,15 +163,15 @@ public: // Elements
const QString &name, const QVariant &value,
qt3ds::runtime::DataInputValueRole property
= qt3ds::runtime::DataInputValueRole::Value) = 0;
- virtual void createElement(const QString &parentElementPath, const QString &slideName,
- const QHash<QString, QVariant> &properties,
- qt3ds::render::IQt3DSRenderer *renderer) = 0;
- virtual void deleteElement(const QString &elementPath,
- qt3ds::render::IQt3DSRenderer *renderer) = 0;
- virtual void createMaterial(const QString &elementPath, const QString &materialDefinition,
- qt3ds::render::ICustomMaterialSystem *customMaterialSystem,
- qt3ds::render::IDynamicObjectSystem *dynamicObjectSystem,
+ virtual void createElements(const QString &parentElementPath, const QString &slideName,
+ const QVector<QHash<QString, QVariant>> &properties,
qt3ds::render::IQt3DSRenderer *renderer) = 0;
+ virtual void deleteElements(const QStringList &elementPath,
+ qt3ds::render::IQt3DSRenderer *renderer) = 0;
+ virtual void createMaterials(const QString &elementPath, const QStringList &materialDefinitions,
+ qt3ds::render::ICustomMaterialSystem *customMaterialSystem,
+ qt3ds::render::IDynamicObjectSystem *dynamicObjectSystem,
+ qt3ds::render::IQt3DSRenderer *renderer) = 0;
public: // Components
virtual void GotoSlide(const char *component, const char *slideName,
diff --git a/src/Runtime/Source/runtime/Qt3DSPresentation.h b/src/Runtime/Source/runtime/Qt3DSPresentation.h
index ff5656e3..b2edd416 100644
--- a/src/Runtime/Source/runtime/Qt3DSPresentation.h
+++ b/src/Runtime/Source/runtime/Qt3DSPresentation.h
@@ -51,8 +51,8 @@ Q_SIGNALS:
void SigSlideExited(const QString &elementPath, unsigned int index, const QString &name);
void SigCustomSignal(const QString &elementPath, const QString &name);
void SigPresentationReady();
- void SigElementCreated(const QString &elementName, const QString &error);
- void SigMaterialCreated(const QString &name, const QString &error);
+ void SigElementsCreated(const QStringList &elementPaths, const QString &error);
+ void SigMaterialsCreated(const QStringList &materialNames, const QString &error);
};
namespace qt3ds {
diff --git a/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp b/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp
index c837aad1..448fc2be 100644
--- a/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp
+++ b/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp
@@ -427,16 +427,15 @@ public:
void FireEvent(const char *element, const char *evtName) override;
void SetDataInputValue(const QString &name, const QVariant &value,
qt3ds::runtime::DataInputValueRole valueRole) override;
- void createElement(const QString &parentElementPath, const QString &slideName,
- const QHash<QString, QVariant> &properties,
- qt3ds::render::IQt3DSRenderer *renderer) override;
- void deleteElement(const QString &elementPath,
- qt3ds::render::IQt3DSRenderer *renderer) override;
- void createMaterial(const QString &elementPath, const QString &materialDefinition,
- qt3ds::render::ICustomMaterialSystem *customMaterialSystem,
- IDynamicObjectSystem *dynamicObjectSystem,
+ void createElements(const QString &parentElementPath, const QString &slideName,
+ const QVector<QHash<QString, QVariant>> &properties,
qt3ds::render::IQt3DSRenderer *renderer) override;
- //void createMesh() override; // TODO (QT3DS-3378)
+ void deleteElements(const QStringList &elementPaths,
+ qt3ds::render::IQt3DSRenderer *renderer) override;
+ void createMaterials(const QString &elementPath, const QStringList &materialDefinitions,
+ qt3ds::render::ICustomMaterialSystem *customMaterialSystem,
+ IDynamicObjectSystem *dynamicObjectSystem,
+ qt3ds::render::IQt3DSRenderer *renderer) override;
void GotoSlide(const char *component, const char *slideName,
const SScriptEngineGotoSlideArgs &inArgs) override;
@@ -519,9 +518,12 @@ private:
QVector3D parseFloat3Property(const QString &propValue);
QVector4D parseFloat4Property(const QString &propValue);
- void notifyElementCreation(CPresentation *pres, const QString &elementName,
+ void notifyElementCreation(CPresentation *pres, const QStringList &elementNames,
const QString &error);
- void notifyMaterialCreation(CPresentation *pres, const QString &name, const QString &error);
+ void notifyMaterialCreation(CPresentation *pres, const QStringList &materialNames,
+ const QString &error);
+ void deleteElements(const QVector<TElement *> &elements,
+ qt3ds::render::IQt3DSRenderer *renderer);
};
CQmlEngineImpl::CQmlEngineImpl(NVFoundationBase &fnd, ITimeProvider &)
@@ -919,24 +921,37 @@ void CQmlEngineImpl::SetDataInputValue(
static int _idCounter = 0;
-void CQmlEngineImpl::createElement(const QString &parentElementPath, const QString &slideName,
- const QHash<QString, QVariant> &properties,
- qt3ds::render::IQt3DSRenderer *renderer)
+void CQmlEngineImpl::createElements(const QString &parentElementPath, const QString &slideName,
+ const QVector<QHash<QString, QVariant>> &properties,
+ qt3ds::render::IQt3DSRenderer *renderer)
{
+ int elementIndex = -1;
QString error;
CPresentation *presentation = nullptr;
- QString elementPath = parentElementPath + QLatin1Char('.')
- + properties.value(QStringLiteral("name")).toString();
+ QStringList elementPaths;
+ elementPaths.reserve(properties.size());
+ for (auto &props : properties) {
+ elementPaths << parentElementPath + QLatin1Char('.')
+ + props.value(QStringLiteral("name")).toString();
+ }
+ QVector<TElement *> createdElements;
+ TElement *parentElement = nullptr;
+
+ auto handleError = [&]() {
+ if (!error.isEmpty())
+ deleteElements(createdElements, renderer);
+ notifyElementCreation(presentation, elementPaths, error);
+ };
// Resolve parent element
QByteArray theParentPath = parentElementPath.toUtf8();
- TElement *parentElement = getTarget(theParentPath.constData());
+ parentElement = getTarget(theParentPath.constData());
if (!parentElement) {
- error = QStringLiteral("Invalid parent element");
+ error = QObject::tr("Invalid parent element: '%1'").arg(parentElementPath);
TElement *sceneElement = getTarget("Scene");
presentation = static_cast<CPresentation *>(sceneElement->GetBelongedPresentation());
- notifyElementCreation(presentation, elementPath, error);
+ handleError();
return;
}
@@ -945,8 +960,8 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri
if (!parentTranslator || !qt3ds::render::GraphObjectTypes::IsNodeType(
parentTranslator->GetUIPType())) {
- error = QStringLiteral("Parent element is not a valid node");
- notifyElementCreation(presentation, elementPath, error);
+ error = QObject::tr("Parent element is not a valid node: '%1'").arg(parentElementPath);
+ handleError();
return;
}
@@ -954,304 +969,271 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri
auto &parentObject = static_cast<qt3ds::render::SNode &>(parentTranslator->RenderObject());
presentation = static_cast<CPresentation *>(parentElement->GetBelongedPresentation());
- ++_idCounter;
-
// Resolve slide
QByteArray theSlideName = slideName.toUtf8();
ISlideSystem &slideSystem = presentation->GetSlideSystem();
int slideIndex = slideSystem.FindSlide(component, theSlideName.constData());
int currentSlide = static_cast<TComponent &>(component).GetCurrentSlide();
if (slideIndex == 0xff) {
- error = QStringLiteral("Invalid slide name for time context: '%1'").arg(slideName);
- notifyElementCreation(presentation, elementPath, error);
- return;
- }
-
- // Remove properties requiring custom handling
- QHash<QString, QVariant> theProperties = properties;
- QString newElementName = theProperties.take(QStringLiteral("name")).toString();
- QString refMatName = theProperties.take(QStringLiteral("material")).toString();
- if (refMatName.startsWith(QLatin1Char('#'))) // Absolute reference
- refMatName = refMatName.mid(1);
- else if (!refMatName.isEmpty() && !refMatName.contains(QLatin1Char('/')))
- refMatName = QStringLiteral("/") + refMatName;
-
- if (newElementName.isEmpty())
- newElementName = QStringLiteral("NewElement_%1").arg(_idCounter);
- QByteArray newElementNameBa = newElementName.toUtf8();
-
- // Make sure the name is not duplicate
- TElement *existingChild
- = parentElement->FindChild(CHash::HashString(newElementNameBa.constData()));
- if (existingChild) {
- qWarning() << __FUNCTION__
- << "The specified parent" << parentElementPath
- << "already has a child with the same name:" << newElementName;
- error = QStringLiteral("Element already exists");
- notifyElementCreation(presentation, elementPath, error);
+ error = QObject::tr("Invalid slide name for time context: '%1'").arg(slideName);
+ handleError();
return;
}
auto &strTable = presentation->GetStringTable();
- const CRegisteredString regName = strTable.RegisterStr(newElementNameBa);
- // TODO: Support also some non-model element types, like group and text elements (QT3DS-3381)
- const CRegisteredString elementType = strTable.RegisterStr("Model");
- const CRegisteredString elementSubType;
- TPropertyDescAndValueList elementProperties;
- // Set default values for missing mandatory properties
const QString sourcePathPropName = QStringLiteral("sourcepath");
const QString startTimePropName = QStringLiteral("starttime");
const QString endTimePropName = QStringLiteral("endtime");
const QString eyeBallPropName = QStringLiteral("eyeball");
+
Q3DStudio::UVariant attValue;
- bool eyeBall = true;
- theProperties.value(QStringLiteral("eyeball"), true).toBool();
- if (!theProperties.contains(sourcePathPropName)) {
- addStringAttribute(strTable, elementProperties, sourcePathPropName,
- QStringLiteral("#Cube"));
- }
- if (!theProperties.contains(startTimePropName)) {
- parentElement->GetAttribute(Q3DStudio::ATTRIBUTE_STARTTIME, attValue);
- addIntAttribute(strTable, elementProperties, startTimePropName, int(attValue.m_INT32));
- }
- if (!theProperties.contains(endTimePropName)) {
- parentElement->GetAttribute(Q3DStudio::ATTRIBUTE_ENDTIME, attValue);
- addIntAttribute(strTable, elementProperties, endTimePropName, int(attValue.m_INT32));
- }
- if (!theProperties.contains(eyeBallPropName))
- addBoolAttribute(strTable, elementProperties, eyeBallPropName, true);
- else
- eyeBall = theProperties.value(QStringLiteral("eyeball")).toBool();
-
- QHashIterator<QString, QVariant> it(theProperties);
- while (it.hasNext()) {
- it.next();
- switch (it.value().type()) {
- case QVariant::Double:
- addFloatAttribute(strTable, elementProperties, it.key(), it.value().toFloat());
- break;
- case QVariant::Bool:
- addBoolAttribute(strTable, elementProperties, it.key(), it.value().toBool());
- break;
- case QVariant::Int:
- addIntAttribute(strTable, elementProperties, it.key(), it.value().toInt());
- break;
- case QVariant::String:
- addStringAttribute(strTable, elementProperties, it.key(), it.value().toString());
- break;
- case QVariant::Vector3D: {
- QVector3D vec = it.value().value<QVector3D>();
- if (it.key() == QLatin1String("rotation")) {
- vec.setX(qDegreesToRadians(vec.x()));
- vec.setY(qDegreesToRadians(vec.y()));
- vec.setZ(qDegreesToRadians(vec.z()));
+ parentElement->GetAttribute(Q3DStudio::ATTRIBUTE_STARTTIME, attValue);
+ const int parentStartTime = int(attValue.m_INT32);
+ parentElement->GetAttribute(Q3DStudio::ATTRIBUTE_ENDTIME, attValue);
+ const int parentEndTime = int(attValue.m_INT32);
+
+ for (const auto &currentProperties : properties) {
+ ++_idCounter;
+ ++elementIndex;
+
+ // Remove properties requiring custom handling
+ QHash<QString, QVariant> theProperties = currentProperties;
+ QString newElementName = theProperties.take(QStringLiteral("name")).toString();
+ QString refMatName = theProperties.take(QStringLiteral("material")).toString();
+ if (refMatName.startsWith(QLatin1Char('#'))) // Absolute reference
+ refMatName = refMatName.mid(1);
+ else if (!refMatName.isEmpty() && !refMatName.contains(QLatin1Char('/')))
+ refMatName = QStringLiteral("/") + refMatName;
+
+ if (newElementName.isEmpty())
+ newElementName = QStringLiteral("NewElement_%1").arg(_idCounter);
+ QByteArray newElementNameBa = newElementName.toUtf8();
+
+ // Make sure the name is not duplicate
+ TElement *existingChild
+ = parentElement->FindChild(CHash::HashString(newElementNameBa.constData()));
+ if (existingChild) {
+ error = QObject::tr("Element already exists: '%1'").arg(elementPaths[elementIndex]);
+ handleError();
+ return;
+ }
+
+ const CRegisteredString regName = strTable.RegisterStr(newElementNameBa);
+ // TODO: Support also some non-model elements, like group and text elements (QT3DS-3381)
+ const CRegisteredString elementType = strTable.RegisterStr("Model");
+ const CRegisteredString elementSubType;
+ TPropertyDescAndValueList elementProperties;
+
+ // Set default values for missing mandatory properties
+ bool eyeBall = true;
+ theProperties.value(eyeBallPropName, true).toBool();
+ if (!theProperties.contains(sourcePathPropName)) {
+ addStringAttribute(strTable, elementProperties, sourcePathPropName,
+ QStringLiteral("#Cube"));
+ }
+ if (!theProperties.contains(startTimePropName))
+ addIntAttribute(strTable, elementProperties, startTimePropName, parentStartTime);
+ if (!theProperties.contains(endTimePropName))
+ addIntAttribute(strTable, elementProperties, endTimePropName, parentEndTime);
+ if (!theProperties.contains(eyeBallPropName))
+ addBoolAttribute(strTable, elementProperties, eyeBallPropName, true);
+ else
+ eyeBall = theProperties.value(eyeBallPropName).toBool();
+
+ QHashIterator<QString, QVariant> it(theProperties);
+ while (it.hasNext()) {
+ it.next();
+ switch (it.value().type()) {
+ case QVariant::Double:
+ addFloatAttribute(strTable, elementProperties, it.key(), it.value().toFloat());
+ break;
+ case QVariant::Bool:
+ addBoolAttribute(strTable, elementProperties, it.key(), it.value().toBool());
+ break;
+ case QVariant::Int:
+ addIntAttribute(strTable, elementProperties, it.key(), it.value().toInt());
+ break;
+ case QVariant::String:
+ addStringAttribute(strTable, elementProperties, it.key(), it.value().toString());
+ break;
+ case QVariant::Vector3D: {
+ QVector3D vec = it.value().value<QVector3D>();
+ if (it.key() == QLatin1String("rotation")) {
+ vec.setX(qDegreesToRadians(vec.x()));
+ vec.setY(qDegreesToRadians(vec.y()));
+ vec.setZ(qDegreesToRadians(vec.z()));
+ }
+ // TODO: Need to support also colors if non-model elements what need colors are
+ // TODO: supported (QT3DS-3381)
+ QStringList atts;
+ atts << (it.key() + QLatin1String(".x"))
+ << (it.key() + QLatin1String(".y"))
+ << (it.key() + QLatin1String(".z"));
+ addFloat3Attribute(strTable, elementProperties, atts, vec);
+ break;
+ }
+ default:
+ error = QObject::tr("Unsupported property type for: '%1'").arg(it.key());
+ handleError();
+ return;
}
- // TODO: Need to support also colors if non-model elements what need colors are
- // TODO: supported (QT3DS-3381)
- QStringList atts;
- atts << (it.key() + QLatin1String(".x"))
- << (it.key() + QLatin1String(".y"))
- << (it.key() + QLatin1String(".z"));
- addFloat3Attribute(strTable, elementProperties, atts, vec);
- break;
}
- default:
- error = QStringLiteral("Unsupported property type for: '%1'").arg(it.key());
- notifyElementCreation(presentation, elementPath, error);
+
+ // Create new element
+ TElement &newElem = m_Application->GetElementAllocator().CreateElement(
+ regName, elementType, elementSubType,
+ toConstDataRef(elementProperties.data(), QT3DSU32(elementProperties.size())),
+ presentation, parentElement, false);
+ newElem.m_Path = strTable.RegisterStr(elementPaths[elementIndex]);
+
+ // Insert the new element into the correct slide
+ if (!slideSystem.addSlideElement(component, slideIndex, newElem, eyeBall)) {
+ // Delete created element if adding to slide failed
+ m_Application->GetElementAllocator().ReleaseElement(newElem, true);
+ error = QObject::tr("Failed to add the new element to a slide");
+ handleError();
return;
}
- }
- // Create new element
- TElement &newElem = m_Application->GetElementAllocator().CreateElement(
- regName, elementType, elementSubType,
- toConstDataRef(elementProperties.data(), QT3DSU32(elementProperties.size())),
- presentation, parentElement, false);
- newElem.m_Path = strTable.RegisterStr(elementPath);
-
- // Insert the new element into the correct slide
- if (!slideSystem.addSlideElement(component, slideIndex, newElem, eyeBall)) {
- // Delete created element if adding to slide failed
- m_Application->GetElementAllocator().ReleaseElement(newElem, true);
- error = QStringLiteral("Failed to add the new element to a slide");
- notifyElementCreation(presentation, elementPath, error);
- return;
- }
+ // Create material element
+ const CRegisteredString matName = strTable.RegisterStr("refmat");
+ const CRegisteredString matType = strTable.RegisterStr("ReferencedMaterial");
+ TPropertyDescAndValueList matProperties;
+ TElement &newMatElem = m_Application->GetElementAllocator().CreateElement(
+ matName, matType, elementSubType,
+ toConstDataRef(matProperties.data(), QT3DSU32(matProperties.size())),
+ presentation, &newElem, false);
- // Create material element
- const CRegisteredString matName = strTable.RegisterStr("refmat");
- const CRegisteredString matType = strTable.RegisterStr("ReferencedMaterial");
- TPropertyDescAndValueList matProperties;
- TElement &newMatElem = m_Application->GetElementAllocator().CreateElement(
- matName, matType, elementSubType,
- toConstDataRef(matProperties.data(), QT3DSU32(matProperties.size())),
- presentation, &newElem, false);
-
- QString matElemPath = elementPath + QLatin1String(".refmat");
- newMatElem.m_Path = strTable.RegisterStr(matElemPath);
-
- if (!slideSystem.addSlideElement(component, slideIndex, newMatElem, eyeBall)) {
- // Delete created element and material element if adding to slide failed
- m_Application->GetElementAllocator().ReleaseElement(newElem, true);
- error = QStringLiteral("Failed to add the new material element to a slide");
- notifyElementCreation(presentation, elementPath, error);
- return;
- }
+ QString matElemPath = elementPaths[elementIndex] + QLatin1String(".refmat");
+ newMatElem.m_Path = strTable.RegisterStr(matElemPath);
- // First check if we can resolve the referenced material before creating any graph objects
- // Find a match in material container
- // If the specified material is not available in original presentation, or was not specified,
- // use the first material found as placeholder
- TElement *rootElement = presentation->GetRoot();
- TElement *container = rootElement->FindChild(CHash::HashString("__Container"));
- TElement *firstChild = nullptr;
- SGraphObject *referencedMaterial = nullptr;
- if (container) {
- TElement *nextChild = container->GetChild();
- firstChild = nextChild;
- while (nextChild) {
- QString childName = QString::fromUtf8(nextChild->m_Name);
- if (childName.endsWith(refMatName)) {
+ if (!slideSystem.addSlideElement(component, slideIndex, newMatElem, eyeBall)) {
+ // Delete created element and material element if adding to slide failed
+ m_Application->GetElementAllocator().ReleaseElement(newElem, true);
+ error = QObject::tr("Failed to add the new material element to a slide");
+ handleError();
+ return;
+ }
+
+ // First check if we can resolve the referenced material before creating any graph objects
+ // Find a match in material container
+ // If the specified material is not available in original presentation, or was not
+ // specified, use the first material found as placeholder
+ TElement *rootElement = presentation->GetRoot();
+ TElement *container = rootElement->FindChild(CHash::HashString("__Container"));
+ TElement *firstChild = nullptr;
+ SGraphObject *referencedMaterial = nullptr;
+ if (container) {
+ TElement *nextChild = container->GetChild();
+ firstChild = nextChild;
+ while (nextChild) {
+ QString childName = QString::fromUtf8(nextChild->m_Name);
+ if (childName.endsWith(refMatName)) {
+ auto tr = static_cast<qt3ds::render::Qt3DSTranslator *>(
+ nextChild->GetAssociation());
+ referencedMaterial = static_cast<qt3ds::render::SGraphObject *>(
+ &tr->RenderObject());
+ break;
+ }
+ nextChild = nextChild->GetSibling();
+ }
+ }
+
+ if (!referencedMaterial) {
+ // Empty material is assumed to be deliberate, so don't warn in that case
+ if (!refMatName.isEmpty()) {
+ qWarning() << __FUNCTION__ << "Requested material" << refMatName
+ << "was not found. Trying to find a fallback material.";
+ }
+ if (firstChild) {
auto tr = static_cast<qt3ds::render::Qt3DSTranslator *>(
- nextChild->GetAssociation());
+ firstChild->GetAssociation());
referencedMaterial = static_cast<qt3ds::render::SGraphObject *>(
&tr->RenderObject());
- break;
}
- nextChild = nextChild->GetSibling();
+ if (!referencedMaterial) {
+ // We could create default material into the container in case there is no materials
+ // in there, but it is unlikely that such a presentation would be used in practice.
+ m_Application->GetElementAllocator().ReleaseElement(newElem, true);
+ error = QObject::tr("Unable to resolve a fallback material");
+ handleError();
+ return;
+ }
}
- }
- if (!referencedMaterial) {
- // Empty material is assumed to be deliberate, so don't warn in that case
- if (!refMatName.isEmpty()) {
- qWarning() << __FUNCTION__ << "Requested material" << refMatName
- << "was not found. Trying to find a fallback material.";
- }
- if (firstChild) {
- auto tr = static_cast<qt3ds::render::Qt3DSTranslator *>(firstChild->GetAssociation());
- referencedMaterial = static_cast<qt3ds::render::SGraphObject *>(&tr->RenderObject());
- }
- if (!referencedMaterial) {
- // We could create default material into the container in case there is no materials
- // in there, but it is unlikely that such a presentation would be used in practice.
- m_Application->GetElementAllocator().ReleaseElement(newElem, true);
- error = QStringLiteral("Unable to resolve a fallback material");
- notifyElementCreation(presentation, elementPath, error);
- return;
- }
- }
+ // Create model SGraphObject
+ NVAllocatorCallback &allocator = presentation->GetScene()->allocator();
+ qt3ds::render::SModel *newObject = QT3DS_NEW(allocator, qt3ds::render::SModel)();
+ newObject->m_Id = strTable.RegisterStr((QByteArrayLiteral("_newObject_")
+ + QByteArray::number(_idCounter)).constData());
+ parentObject.AddChild(*newObject);
- // Create model SGraphObject
- NVAllocatorCallback &allocator = presentation->GetScene()->allocator();
- qt3ds::render::SModel *newObject = QT3DS_NEW(allocator, qt3ds::render::SModel)();
- newObject->m_Id = strTable.RegisterStr((QByteArrayLiteral("_newObject_")
- + QByteArray::number(_idCounter)).constData());
- parentObject.AddChild(*newObject);
-
- qt3ds::render::Qt3DSTranslator::CreateTranslatorForElement(newElem, *newObject, allocator);
-
- // Create material SGraphObject
- qt3ds::render::SReferencedMaterial *newMaterial
- = QT3DS_NEW(allocator, qt3ds::render::SReferencedMaterial)();
- newMaterial->m_Id = strTable.RegisterStr((QByteArrayLiteral("_newMaterial_")
- + QByteArray::number(_idCounter)).constData());
- newMaterial->m_ReferencedMaterial = referencedMaterial;
-
- newObject->AddMaterial(*newMaterial);
-
- // Determine if element should be active based on start/end times
- TTimeUnit startTime = 0;
- TTimeUnit stopTime = 0;
- if (newElem.GetAttribute(Q3DStudio::ATTRIBUTE_STARTTIME, attValue))
- startTime = TTimeUnit(attValue.m_INT32);
- if (newElem.GetAttribute(Q3DStudio::ATTRIBUTE_ENDTIME, attValue))
- stopTime = TTimeUnit(attValue.m_INT32);
- TTimeUnit localTime = newElem.GetActivityZone().GetItemLocalTime(newElem);
-
- bool isActiveRightNow = eyeBall && localTime >= startTime && localTime <= stopTime
- && currentSlide == slideIndex;
-
- newElem.SetActive(isActiveRightNow);
- newObject->m_Flags.SetActive(isActiveRightNow);
- if (eyeBall)
- newElem.GetActivityZone().UpdateItemInfo(newElem);
+ qt3ds::render::Qt3DSTranslator::CreateTranslatorForElement(newElem, *newObject, allocator);
- renderer->ChildrenUpdated(parentObject);
+ // Create material SGraphObject
+ qt3ds::render::SReferencedMaterial *newMaterial
+ = QT3DS_NEW(allocator, qt3ds::render::SReferencedMaterial)();
+ newMaterial->m_Id = strTable.RegisterStr((QByteArrayLiteral("_newMaterial_")
+ + QByteArray::number(_idCounter)).constData());
+ newMaterial->m_ReferencedMaterial = referencedMaterial;
- notifyElementCreation(presentation, elementPath, {});
-}
+ newObject->AddMaterial(*newMaterial);
-// Only supports deleting element types that can be added via createElement.
-void CQmlEngineImpl::deleteElement(const QString &elementPath,
- qt3ds::render::IQt3DSRenderer *renderer)
-{
- // Resolve element
- QByteArray thePath = elementPath.toUtf8();
- TElement *element = getTarget(thePath.constData());
+ // Determine if element should be active based on start/end times
+ TTimeUnit startTime = 0;
+ TTimeUnit stopTime = 0;
+ if (newElem.GetAttribute(Q3DStudio::ATTRIBUTE_STARTTIME, attValue))
+ startTime = TTimeUnit(attValue.m_INT32);
+ if (newElem.GetAttribute(Q3DStudio::ATTRIBUTE_ENDTIME, attValue))
+ stopTime = TTimeUnit(attValue.m_INT32);
+ TTimeUnit localTime = newElem.GetActivityZone().GetItemLocalTime(newElem);
- if (!element) {
- qWarning() << __FUNCTION__ << "Invalid element:" << elementPath;
- return;
- }
+ bool isActiveRightNow = eyeBall && localTime >= startTime && localTime <= stopTime
+ && currentSlide == slideIndex;
- // Remove element recursively from slide system
- IPresentation *presentation = element->GetBelongedPresentation();
- TElement &component = element->GetComponentParent();
- ISlideSystem &slideSystem = presentation->GetSlideSystem();
- slideSystem.removeElement(component, *element);
+ newElem.SetActive(isActiveRightNow);
+ newObject->m_Flags.SetActive(isActiveRightNow);
+ if (eyeBall)
+ newElem.GetActivityZone().UpdateItemInfo(newElem);
- TElement *parentElement = element->GetParent();
- Q_ASSERT(parentElement);
+ createdElements << &newElem;
+ }
- NVAllocatorCallback &allocator = presentation->GetScene()->allocator();
+ renderer->ChildrenUpdated(parentObject);
- // Recursive deleter for translators and graph objects
- std::function<void(TElement *)> deleteRenderObjects;
- deleteRenderObjects = [&](TElement *elem) {
- TElement *child = elem->m_Child;
- while (child) {
- TElement *sibling = child->m_Sibling;
- deleteRenderObjects(child);
- child = sibling;
- }
+ handleError();
+}
- auto translator = static_cast<qt3ds::render::Qt3DSTranslator *>(elem->GetAssociation());
- if (translator) {
- if (translator->GetUIPType() == qt3ds::render::GraphObjectTypes::Model) {
- auto model = static_cast<qt3ds::render::SModel *>(&translator->RenderObject());
- // Delete material
- if (model->m_FirstMaterial) {
- auto material = static_cast<qt3ds::render::SReferencedMaterial *>(
- model->m_FirstMaterial);
- QT3DS_FREE(allocator, material);
- }
- QT3DS_FREE(allocator, model);
+// Only supports deleting element types that can be added via createElement.
+void CQmlEngineImpl::deleteElements(const QStringList &elementPaths,
+ qt3ds::render::IQt3DSRenderer *renderer)
+{
+ QVector<TElement *> elements;
+ // Convert the path list to set for quicker lookups
+ QSet<QString> pathSet = elementPaths.toSet();
+
+ for (auto &elementPath : elementPaths) {
+ // Check that parent is not already included in the deleted elements
+ int idx = elementPath.lastIndexOf(QLatin1Char('.'));
+ bool parentFound = false;
+ while (idx != -1) {
+ QString parentPath = elementPath.left(idx);
+ if (pathSet.contains(parentPath)) {
+ parentFound = true;
+ break;
}
- QT3DS_FREE(allocator, translator);
+ idx = parentPath.lastIndexOf(QLatin1Char('.'));
}
- };
-
- qt3ds::render::SNode *node = nullptr;
- qt3ds::render::SNode *parentNode = nullptr;
- auto translator = static_cast<qt3ds::render::Qt3DSTranslator *>(element->GetAssociation());
-
- if (translator) {
- node = &static_cast<qt3ds::render::SNode &>(translator->RenderObject());
- auto parentTranslator = static_cast<qt3ds::render::Qt3DSTranslator *>(
- parentElement->GetAssociation());
- if (parentTranslator) {
- parentNode = &static_cast<qt3ds::render::SNode &>(parentTranslator->RenderObject());
- parentNode->RemoveChild(*node);
- renderer->ChildrenUpdated(*parentNode);
+ if (!parentFound) {
+ // Resolve element
+ QByteArray thePath = elementPath.toUtf8();
+ TElement *element = getTarget(thePath.constData());
+ if (element)
+ elements << element;
}
- // Release child element graph objects/translators
- deleteRenderObjects(element);
}
-
- // Remove element recursively
- m_Application->GetElementAllocator().ReleaseElement(*element, true);
+ deleteElements(elements, renderer);
}
/**
@@ -1259,52 +1241,64 @@ void CQmlEngineImpl::deleteElement(const QString &elementPath,
The materialDefinition parameter can contain a .materialdef file path or
the entire material definition in the .materialdef format.
*/
-void CQmlEngineImpl::createMaterial(const QString &elementPath,
- const QString &materialDefinition,
- ICustomMaterialSystem *customMaterialSystem,
- IDynamicObjectSystem *dynamicObjectSystem,
- qt3ds::render::IQt3DSRenderer *renderer)
+void CQmlEngineImpl::createMaterials(const QString &elementPath,
+ const QStringList &materialDefinitions,
+ ICustomMaterialSystem *customMaterialSystem,
+ IDynamicObjectSystem *dynamicObjectSystem,
+ qt3ds::render::IQt3DSRenderer *renderer)
{
- QString materialName;
- QMap<QString, QString> materialProps;
- QMap<QString, QMap<QString, QString>> textureProps;
CPresentation *presentation = nullptr;
QString error;
+ QString presPath;
+ QString projPath;
+ struct MaterialInfo {
+ QString materialDefinition;
+ QString materialName;
+ QMap<QString, QString> materialProps;
+ QMap<QString, QMap<QString, QString>> textureProps;
+ };
+ QVector<MaterialInfo *> materialInfos;
+ QVector<TElement *> createdElements;
+
+ auto handleError = [&]() {
+ if (!error.isEmpty())
+ deleteElements(createdElements, renderer);
+ QStringList materialNames;
+ for (auto &materialInfo : materialInfos)
+ materialNames << materialInfo->materialName;
+ qDeleteAll(materialInfos);
+ notifyMaterialCreation(presentation, materialNames, error);
+ };
- auto getMaterialInfo = [&]() {
- QString presPath = QFileInfo(presentation->GetFilePath()).absolutePath();
- QString projPath = presentation->getProjectPath();
-
- Q3DSMaterialDefinitionParser::getMaterialInfo(materialDefinition,
- projPath, presPath,
- materialName, materialProps, textureProps);
+ auto getMaterialInfos = [&]() {
+ for (auto &materialDefinition : materialDefinitions) {
+ MaterialInfo *info = new MaterialInfo;
+ info->materialDefinition = materialDefinition;
+ Q3DSMaterialDefinitionParser::getMaterialInfo(materialDefinition, projPath, presPath,
+ info->materialName, info->materialProps,
+ info->textureProps);
+ materialInfos << info;
+ }
};
QByteArray thePath = elementPath.toUtf8();
TElement *element = getTarget(thePath.constData());
if (!element) {
- error = QStringLiteral("Invalid element: '%1'").arg(elementPath);
+ error = QObject::tr("Invalid element: '%1'").arg(elementPath);
TElement *sceneElement = getTarget("Scene");
presentation = static_cast<CPresentation *>(sceneElement->GetBelongedPresentation());
- getMaterialInfo();
- notifyMaterialCreation(presentation, materialName, error);
+ presPath = QFileInfo(presentation->GetFilePath()).absolutePath();
+ projPath = presentation->getProjectPath();
+ getMaterialInfos();
+ handleError();
return;
}
presentation = static_cast<CPresentation *>(element->GetBelongedPresentation());
- getMaterialInfo();
-
- if (materialName.isEmpty() || materialProps.isEmpty()) {
- error = QStringLiteral("Invalid material definition: '%1'").arg(materialDefinition);
- notifyMaterialCreation(presentation, materialName, error);
- return;
- }
-
- // We don't care about the path parameter
- const QString pathStr = QStringLiteral("path");
- if (materialProps.contains(pathStr))
- materialProps.remove(pathStr);
+ presPath = QFileInfo(presentation->GetFilePath()).absolutePath();
+ projPath = presentation->getProjectPath();
+ getMaterialInfos();
// Find material container
auto &strTable = presentation->GetStringTable();
@@ -1312,289 +1306,310 @@ void CQmlEngineImpl::createMaterial(const QString &elementPath,
TElement *rootElement = presentation->GetRoot();
const auto containerName = strTable.RegisterStr("__Container");
TElement *container = rootElement->FindChild(CHash::HashString(containerName.c_str()));
- if (container) {
+ if (!container) {
+ // TODO: Create a material container if it doesn't exist (QT3DS-3412)
+ error = QObject::tr("Presentation has no material container");
+ handleError();
+ return;
+ }
+
+ for (auto &materialInfo : materialInfos) {
+ if (materialInfo->materialName.isEmpty() || materialInfo->materialProps.isEmpty()) {
+ error = QObject::tr("Invalid material definition: '%1'")
+ .arg(materialInfo->materialDefinition);
+ handleError();
+ return;
+ }
+
+ // We don't care about the path parameter
+ const QString pathStr = QStringLiteral("path");
+ if (materialInfo->materialProps.contains(pathStr))
+ materialInfo->materialProps.remove(pathStr);
+
// Check that the material doesn't already exist in container
TElement *firstChild = nullptr;
TElement *nextChild = container->GetChild();
firstChild = nextChild;
while (nextChild) {
QString childName = QString::fromUtf8(nextChild->m_Name);
- if (childName == materialName) {
- error = QStringLiteral("Material already exists in material container");
- notifyMaterialCreation(presentation, materialName, error);
+ if (childName == materialInfo->materialName) {
+ error = QObject::tr("Material already exists in material container");
+ handleError();
return;
}
nextChild = nextChild->GetSibling();
}
- } else {
- // TODO: Create a material container if it doesn't exist (QT3DS-3412)
- error = QStringLiteral("Presentation has no material container");
- notifyMaterialCreation(presentation, materialName, error);
- return;
- }
- // Create material element in the container based on the material definition
- auto &metaData = m_Application->GetMetaData();
- const auto matName = strTable.RegisterStr(materialName);
- const bool isCustomMaterial
- = materialProps.value(QStringLiteral("type")) == QLatin1String("CustomMaterial");
- CRegisteredString matType;
- CRegisteredString matClass;
- QHash<QString, qt3ds::render::dynamic::SPropertyDefinition> dynPropDefs;
-
- if (isCustomMaterial) {
- CRegisteredString sourcePath
- = strTable.RegisterStr(materialProps.value(QStringLiteral("sourcepath")).toUtf8());
- matType = strTable.RegisterStr("CustomMaterial");
- matClass = sourcePath; // Create just one class per shader
- if (sourcePath.IsValid()) {
- Option<qt3dsdm::SMetaDataCustomMaterial> matMetaData =
- metaData.GetMaterialMetaDataBySourcePath(sourcePath.c_str());
- if (!matMetaData.hasValue()) {
- metaData.LoadMaterialXMLFile(matType.c_str(), matClass.c_str(), matName.c_str(),
- sourcePath.c_str());
- matMetaData = metaData.GetMaterialMetaDataBySourcePath(sourcePath.c_str());
- }
- if (matMetaData.hasValue()) {
- qt3ds::render::IUIPLoader::CreateMaterialClassFromMetaMaterial(
- matClass, m_Foundation, *customMaterialSystem, matMetaData,
- strTable);
- NVConstDataRef<qt3ds::render::dynamic::SPropertyDefinition> customProperties;
- customProperties = dynamicObjectSystem->GetProperties(matClass);
- for (QT3DSU32 i = 0, end = customProperties.size(); i < end; ++i) {
- QString propName = QString::fromUtf8(customProperties[i].m_Name.c_str());
- if (materialProps.contains(propName))
- dynPropDefs.insert(propName, customProperties[i]);
+ // Create material element in the container based on the material definition
+ auto &metaData = m_Application->GetMetaData();
+ const auto matName = strTable.RegisterStr(materialInfo->materialName);
+ const bool isCustomMaterial = (materialInfo->materialProps.value(QStringLiteral("type"))
+ == QLatin1String("CustomMaterial"));
+ CRegisteredString matType;
+ CRegisteredString matClass;
+ QHash<QString, qt3ds::render::dynamic::SPropertyDefinition> dynPropDefs;
+
+ if (isCustomMaterial) {
+ CRegisteredString sourcePath
+ = strTable.RegisterStr(materialInfo->materialProps.value(
+ QStringLiteral("sourcepath")).toUtf8());
+ matType = strTable.RegisterStr("CustomMaterial");
+ matClass = sourcePath; // Create just one class per shader
+ if (sourcePath.IsValid()) {
+ Option<qt3dsdm::SMetaDataCustomMaterial> matMetaData =
+ metaData.GetMaterialMetaDataBySourcePath(sourcePath.c_str());
+ if (!matMetaData.hasValue()) {
+ metaData.LoadMaterialXMLFile(matType.c_str(), matClass.c_str(), matName.c_str(),
+ sourcePath.c_str());
+ matMetaData = metaData.GetMaterialMetaDataBySourcePath(sourcePath.c_str());
+ }
+ if (matMetaData.hasValue()) {
+ qt3ds::render::IUIPLoader::CreateMaterialClassFromMetaMaterial(
+ matClass, m_Foundation, *customMaterialSystem, matMetaData,
+ strTable);
+ NVConstDataRef<qt3ds::render::dynamic::SPropertyDefinition> customProperties;
+ customProperties = dynamicObjectSystem->GetProperties(matClass);
+ for (QT3DSU32 i = 0, end = customProperties.size(); i < end; ++i) {
+ QString propName = QString::fromUtf8(customProperties[i].m_Name.c_str());
+ if (materialInfo->materialProps.contains(propName))
+ dynPropDefs.insert(propName, customProperties[i]);
+ }
+ } else {
+ error = QObject::tr("Could not resolve properties for CustomMaterial");
+ handleError();
+ return;
}
} else {
- error = QStringLiteral("Could not resolve material properties for CustomMaterial");
- notifyMaterialCreation(presentation, materialName, error);
+ error = QObject::tr("Missing sourcepath in definition of CustomMaterial");
+ handleError();
return;
}
} else {
- error = QStringLiteral("Missing sourcepath in material definition of a CustomMaterial");
- notifyMaterialCreation(presentation, materialName, error);
- return;
+ matType = strTable.RegisterStr("Material");
}
- } else {
- matType = strTable.RegisterStr("Material");
- }
- auto createElementPropsFromDefProps = [&](const QMap<QString, QString> &defProps,
- TPropertyDescAndValueList &elementProps,
- const CRegisteredString &elementType) {
- QMapIterator<QString, QString> propIter(defProps);
- while (propIter.hasNext()) {
- propIter.next();
- if (dynPropDefs.contains(propIter.key()))
- continue; // Dynamic properties are added directly to graph objects later
-
- auto propName = strTable.RegisterStr(propIter.key());
- ERuntimeDataModelDataType dataType;
- ERuntimeAdditionalMetaDataType additionalType;
- dataType = metaData.GetPropertyType(elementType, propName);
- additionalType = metaData.GetAdditionalType(elementType, propName);
-
- switch (dataType) {
- case ERuntimeDataModelDataTypeLong: {
- addIntAttribute(strTable, elementProps, propIter.key(),
- propIter.value().toInt());
- break;
- }
- case ERuntimeDataModelDataTypeFloat: {
- addFloatAttribute(strTable, elementProps, propIter.key(),
- propIter.value().toFloat());
- break;
- }
- case ERuntimeDataModelDataTypeFloat2: {
- QVector2D vec = parseFloat2Property(propIter.value());
- QStringList atts;
- atts << (propIter.key() + QLatin1String(".x"))
- << (propIter.key() + QLatin1String(".y"));
- addFloat2Attribute(strTable, elementProps, atts, vec);
- break;
- }
- case ERuntimeDataModelDataTypeFloat3: {
- QVector3D vec = parseFloat3Property(propIter.value());
- if (additionalType == ERuntimeAdditionalMetaDataTypeRotation) {
- vec.setX(qDegreesToRadians(vec.x()));
- vec.setY(qDegreesToRadians(vec.y()));
- vec.setZ(qDegreesToRadians(vec.z()));
+ auto createElementPropsFromDefProps = [&](const QMap<QString, QString> &defProps,
+ TPropertyDescAndValueList &elementProps,
+ const CRegisteredString &elementType) {
+ QMapIterator<QString, QString> propIter(defProps);
+ while (propIter.hasNext()) {
+ propIter.next();
+ if (dynPropDefs.contains(propIter.key()))
+ continue; // Dynamic properties are added directly to graph objects later
+
+ auto propName = strTable.RegisterStr(propIter.key());
+ ERuntimeDataModelDataType dataType;
+ ERuntimeAdditionalMetaDataType additionalType;
+ dataType = metaData.GetPropertyType(elementType, propName);
+ additionalType = metaData.GetAdditionalType(elementType, propName);
+
+ switch (dataType) {
+ case ERuntimeDataModelDataTypeLong: {
+ addIntAttribute(strTable, elementProps, propIter.key(),
+ propIter.value().toInt());
+ break;
}
- QStringList atts;
- atts << (propIter.key() + QLatin1String(".x"))
- << (propIter.key() + QLatin1String(".y"))
- << (propIter.key() + QLatin1String(".z"));
- addFloat3Attribute(strTable, elementProps, atts, vec);
- break;
- }
- case ERuntimeDataModelDataTypeFloat4: {
- QVector4D vec = parseFloat4Property(propIter.value());
- QStringList atts;
- if (additionalType == ERuntimeAdditionalMetaDataTypeColor) {
- atts << (propIter.key() + QLatin1String(".r"))
- << (propIter.key() + QLatin1String(".g"))
- << (propIter.key() + QLatin1String(".b"))
- << (propIter.key() + QLatin1String(".a"));
- } else {
+ case ERuntimeDataModelDataTypeFloat: {
+ addFloatAttribute(strTable, elementProps, propIter.key(),
+ propIter.value().toFloat());
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat2: {
+ QVector2D vec = parseFloat2Property(propIter.value());
+ QStringList atts;
+ atts << (propIter.key() + QLatin1String(".x"))
+ << (propIter.key() + QLatin1String(".y"));
+ addFloat2Attribute(strTable, elementProps, atts, vec);
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat3: {
+ QVector3D vec = parseFloat3Property(propIter.value());
+ if (additionalType == ERuntimeAdditionalMetaDataTypeRotation) {
+ vec.setX(qDegreesToRadians(vec.x()));
+ vec.setY(qDegreesToRadians(vec.y()));
+ vec.setZ(qDegreesToRadians(vec.z()));
+ }
+ QStringList atts;
atts << (propIter.key() + QLatin1String(".x"))
<< (propIter.key() + QLatin1String(".y"))
- << (propIter.key() + QLatin1String(".z"))
- << (propIter.key() + QLatin1String(".w"));
+ << (propIter.key() + QLatin1String(".z"));
+ addFloat3Attribute(strTable, elementProps, atts, vec);
+ break;
}
- addFloat4Attribute(strTable, elementProps, atts, vec);
- break;
- }
- case ERuntimeDataModelDataTypeBool: {
- bool boolValue = propIter.value().compare(QLatin1String("true"),
- Qt::CaseInsensitive) == 0;
- addBoolAttribute(strTable, elementProps, propIter.key(), boolValue);
- break;
- }
- case ERuntimeDataModelDataTypeStringRef:
- case ERuntimeDataModelDataTypeString: {
- addStringAttribute(strTable, elementProps, propIter.key(), propIter.value());
- break;
- }
- case ERuntimeDataModelDataTypeLong4: {
- if (additionalType == ERuntimeAdditionalMetaDataTypeImage) {
- // Insert placeholder for now, will be patched later
- addElementRefAttribute(strTable, elementProps, propIter.key(), nullptr);
+ case ERuntimeDataModelDataTypeFloat4: {
+ QVector4D vec = parseFloat4Property(propIter.value());
+ QStringList atts;
+ if (additionalType == ERuntimeAdditionalMetaDataTypeColor) {
+ atts << (propIter.key() + QLatin1String(".r"))
+ << (propIter.key() + QLatin1String(".g"))
+ << (propIter.key() + QLatin1String(".b"))
+ << (propIter.key() + QLatin1String(".a"));
+ } else {
+ atts << (propIter.key() + QLatin1String(".x"))
+ << (propIter.key() + QLatin1String(".y"))
+ << (propIter.key() + QLatin1String(".z"))
+ << (propIter.key() + QLatin1String(".w"));
+ }
+ addFloat4Attribute(strTable, elementProps, atts, vec);
+ break;
+ }
+ case ERuntimeDataModelDataTypeBool: {
+ bool boolValue = propIter.value().compare(QLatin1String("true"),
+ Qt::CaseInsensitive) == 0;
+ addBoolAttribute(strTable, elementProps, propIter.key(), boolValue);
+ break;
+ }
+ case ERuntimeDataModelDataTypeStringRef:
+ case ERuntimeDataModelDataTypeString: {
+ addStringAttribute(strTable, elementProps, propIter.key(), propIter.value());
+ break;
+ }
+ case ERuntimeDataModelDataTypeLong4: {
+ if (additionalType == ERuntimeAdditionalMetaDataTypeImage) {
+ // Insert placeholder for now, will be patched later
+ addElementRefAttribute(strTable, elementProps, propIter.key(), nullptr);
+ }
+ break;
+ }
+ default:
+ error = QObject::tr("Unsupported material property type for property: '%1'")
+ .arg(propIter.key());
+ return;
}
- break;
- }
- default:
- error = QStringLiteral("Unsupported material property type for property: '%1'")
- .arg(propIter.key());
- break;
}
- }
- };
+ };
- TPropertyDescAndValueList elementProps;
- createElementPropsFromDefProps(materialProps, elementProps, matType);
- if (!error.isEmpty()) {
- notifyMaterialCreation(presentation, materialName, error);
- return;
- }
-
- TElement &newMatElem = m_Application->GetElementAllocator().CreateElement(
- matName, matType, matClass,
- toConstDataRef(elementProps.data(), QT3DSU32(elementProps.size())),
- presentation, container, false);
- newMatElem.SetActive(true);
-
- // Create image elements
- CRegisteredString imageType = strTable.RegisterStr("Image");
- QMapIterator<QString, QMap<QString, QString>> texIter(textureProps);
- QHash<QString, TElement *> imageElementMap;
- while (texIter.hasNext()) {
- texIter.next();
- elementProps.clear();
- createElementPropsFromDefProps(texIter.value(), elementProps, imageType);
+ TPropertyDescAndValueList elementProps;
+ createElementPropsFromDefProps(materialInfo->materialProps, elementProps, matType);
if (!error.isEmpty()) {
- m_Application->GetElementAllocator().ReleaseElement(newMatElem, true);
- notifyMaterialCreation(presentation, materialName, error);
+ handleError();
return;
}
- CRegisteredString imageName = strTable.RegisterStr(texIter.key());
- TElement &newImageElem = m_Application->GetElementAllocator().CreateElement(
- imageName, imageType, CRegisteredString(),
+ TElement &newMatElem = m_Application->GetElementAllocator().CreateElement(
+ matName, matType, matClass,
toConstDataRef(elementProps.data(), QT3DSU32(elementProps.size())),
- presentation, &newMatElem, false);
- imageElementMap.insert(texIter.key(), &newImageElem);
- newImageElem.SetActive(true);
- }
-
- // Create render object for the material
- qt3ds::render::SGraphObject *newMaterial = nullptr;
- CRegisteredString newMatId = strTable.RegisterStr(
- (QByteArrayLiteral("_newMaterial_") + QByteArray::number(++_idCounter))
- .constData());
- if (isCustomMaterial) {
- newMaterial = customMaterialSystem->CreateCustomMaterial(matClass, allocator);
- newMaterial->m_Id = newMatId;
- auto dynObj = static_cast<qt3ds::render::SDynamicObject *>(newMaterial);
-
- QHashIterator<QString, qt3ds::render::dynamic::SPropertyDefinition>
- dynPropIter(dynPropDefs);
- while (dynPropIter.hasNext()) {
- dynPropIter.next();
- QByteArray propValStr = materialProps.value(dynPropIter.key()).toUtf8();
- const auto propDesc = dynPropIter.value();
- switch (propDesc.m_DataType) {
- case qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool: {
- bool boolValue = propValStr.compare(QByteArrayLiteral("true"),
- Qt::CaseInsensitive) == 0;
- setDynamicObjectProperty(*dynObj, propDesc, boolValue);
- break;
+ presentation, container, false);
+ newMatElem.SetActive(true);
+
+ // Create image elements
+ CRegisteredString imageType = strTable.RegisterStr("Image");
+ QMapIterator<QString, QMap<QString, QString>> texIter(materialInfo->textureProps);
+ QHash<QString, TElement *> imageElementMap;
+ while (texIter.hasNext()) {
+ texIter.next();
+ elementProps.clear();
+ createElementPropsFromDefProps(texIter.value(), elementProps, imageType);
+ if (!error.isEmpty()) {
+ m_Application->GetElementAllocator().ReleaseElement(newMatElem, true);
+ handleError();
+ return;
}
- case qt3ds::render::NVRenderShaderDataTypes::QT3DSF32:
- setDynamicObjectProperty(*dynObj, propDesc, propValStr.toFloat());
- break;
- case qt3ds::render::NVRenderShaderDataTypes::QT3DSI32:
- if (!propDesc.m_IsEnumProperty) {
- setDynamicObjectProperty(*dynObj, propDesc, propValStr.toInt());
- } else {
- const NVConstDataRef<CRegisteredString> &enumNames = propDesc.m_EnumValueNames;
- for (QT3DSU32 i = 0, end = enumNames.size(); i < end; ++i) {
- if (propValStr.compare(enumNames[i].c_str()) == 0) {
- setDynamicObjectProperty(*dynObj, propDesc, i);
- break;
+ CRegisteredString imageName = strTable.RegisterStr(texIter.key());
+
+ TElement &newImageElem = m_Application->GetElementAllocator().CreateElement(
+ imageName, imageType, CRegisteredString(),
+ toConstDataRef(elementProps.data(), QT3DSU32(elementProps.size())),
+ presentation, &newMatElem, false);
+ imageElementMap.insert(texIter.key(), &newImageElem);
+ newImageElem.SetActive(true);
+ }
+
+ // Create render object for the material
+ qt3ds::render::SGraphObject *newMaterial = nullptr;
+ CRegisteredString newMatId = strTable.RegisterStr(
+ (QByteArrayLiteral("_newMaterial_") + QByteArray::number(++_idCounter))
+ .constData());
+ if (isCustomMaterial) {
+ newMaterial = customMaterialSystem->CreateCustomMaterial(matClass, allocator);
+ newMaterial->m_Id = newMatId;
+ auto dynObj = static_cast<qt3ds::render::SDynamicObject *>(newMaterial);
+
+ QHashIterator<QString, qt3ds::render::dynamic::SPropertyDefinition>
+ dynPropIter(dynPropDefs);
+ while (dynPropIter.hasNext()) {
+ dynPropIter.next();
+ QByteArray propValStr = materialInfo->materialProps.value(
+ dynPropIter.key()).toUtf8();
+ const auto propDesc = dynPropIter.value();
+ switch (propDesc.m_DataType) {
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool: {
+ bool boolValue = propValStr.compare(QByteArrayLiteral("true"),
+ Qt::CaseInsensitive) == 0;
+ setDynamicObjectProperty(*dynObj, propDesc, boolValue);
+ break;
+ }
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSF32:
+ setDynamicObjectProperty(*dynObj, propDesc, propValStr.toFloat());
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSI32:
+ if (!propDesc.m_IsEnumProperty) {
+ setDynamicObjectProperty(*dynObj, propDesc, propValStr.toInt());
+ } else {
+ const NVConstDataRef<CRegisteredString> &enumNames
+ = propDesc.m_EnumValueNames;
+ for (QT3DSU32 i = 0, end = enumNames.size(); i < end; ++i) {
+ if (propValStr.compare(enumNames[i].c_str()) == 0) {
+ setDynamicObjectProperty(*dynObj, propDesc, i);
+ break;
+ }
}
}
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec2:
+ setDynamicObjectProperty(*dynObj, propDesc, parseFloat2Property(propValStr));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec3:
+ setDynamicObjectProperty(*dynObj, propDesc, parseFloat3Property(propValStr));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4:
+ setDynamicObjectProperty(*dynObj, propDesc, parseFloat4Property(propValStr));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr:
+ case qt3ds::render::NVRenderShaderDataTypes::NVRenderImage2DPtr: {
+ CRegisteredString regStr;
+ regStr = strTable.RegisterStr(propValStr);
+ setDynamicObjectProperty(*dynObj, propDesc, regStr);
+ break;
+ }
+ default:
+ error = QObject::tr("Unsupported custom material property type for '%1'")
+ .arg(dynPropIter.key());
+ m_Application->GetElementAllocator().ReleaseElement(newMatElem, true);
+ handleError();
+ return;
}
- break;
- case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec2:
- setDynamicObjectProperty(*dynObj, propDesc, parseFloat2Property(propValStr));
- break;
- case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec3:
- setDynamicObjectProperty(*dynObj, propDesc, parseFloat3Property(propValStr));
- break;
- case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4:
- setDynamicObjectProperty(*dynObj, propDesc, parseFloat4Property(propValStr));
- break;
- case qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr:
- case qt3ds::render::NVRenderShaderDataTypes::NVRenderImage2DPtr: {
- CRegisteredString regStr;
- regStr = strTable.RegisterStr(propValStr);
- setDynamicObjectProperty(*dynObj, propDesc, regStr);
- break;
- }
- default:
- error = QStringLiteral("Unsupported custom material property type for '%1'")
- .arg(dynPropIter.key());
- notifyMaterialCreation(presentation, materialName, error);
- return;
}
- }
- } else {
- newMaterial = QT3DS_NEW(allocator, qt3ds::render::SDefaultMaterial)();
- newMaterial->m_Id = newMatId;
-
- // Update element refs for image elements and create graph objects & translators
- QHashIterator<QString, TElement *> imageIter(imageElementMap);
- while (imageIter.hasNext()) {
- imageIter.next();
- TElement *imageElem = imageIter.value();
- UVariant *propValue = newMatElem.FindPropertyValue(imageElem->m_Name);
- if (propValue) {
- propValue->m_ElementHandle = imageIter.value()->GetHandle();
-
- qt3ds::render::SImage *newImageObj = QT3DS_NEW(allocator, qt3ds::render::SImage)();
- newImageObj->m_Id
- = strTable.RegisterStr((QByteArrayLiteral("_newImage_")
- + QByteArray::number(++_idCounter)).constData());
- qt3ds::render::Qt3DSTranslator::CreateTranslatorForElement(*imageElem,
- *newImageObj, allocator);
+ } else {
+ newMaterial = QT3DS_NEW(allocator, qt3ds::render::SDefaultMaterial)();
+ newMaterial->m_Id = newMatId;
+
+ // Update element refs for image elements and create graph objects & translators
+ QHashIterator<QString, TElement *> imageIter(imageElementMap);
+ while (imageIter.hasNext()) {
+ imageIter.next();
+ TElement *imageElem = imageIter.value();
+ UVariant *propValue = newMatElem.FindPropertyValue(imageElem->m_Name);
+ if (propValue) {
+ propValue->m_ElementHandle = imageIter.value()->GetHandle();
+
+ qt3ds::render::SImage *newImageObj
+ = QT3DS_NEW(allocator, qt3ds::render::SImage)();
+ newImageObj->m_Id = strTable.RegisterStr(
+ (QByteArrayLiteral("_newImage_")
+ + QByteArray::number(++_idCounter)).constData());
+ qt3ds::render::Qt3DSTranslator::CreateTranslatorForElement(
+ *imageElem, *newImageObj, allocator);
+ }
}
+ createdElements << &newMatElem;
}
- }
- qt3ds::render::Qt3DSTranslator::CreateTranslatorForElement(newMatElem, *newMaterial, allocator);
+ qt3ds::render::Qt3DSTranslator::CreateTranslatorForElement(newMatElem, *newMaterial,
+ allocator);
+ }
- notifyMaterialCreation(presentation, materialName, {});
+ handleError();
}
void CQmlEngineImpl::GotoSlide(const char *component, const char *slideName,
@@ -2258,32 +2273,110 @@ QVector4D CQmlEngineImpl::parseFloat4Property(const QString &propValue)
return retVal;
}
-void CQmlEngineImpl::notifyElementCreation(CPresentation *pres, const QString &elementName,
+void CQmlEngineImpl::notifyElementCreation(CPresentation *pres, const QStringList &elementNames,
const QString &error)
{
// Notify presentation asynchronously to give renderer time to initialize the elements properly
if (!error.isEmpty()) {
- qWarning() << "Warning: Element creation failed:" << elementName << error;
+ qWarning() << "Warning: Element creation failed:" << error;
QT3DS_ASSERT(false);
}
- QTimer::singleShot(0, [pres, elementName, error]() {
- pres->signalProxy()->SigElementCreated(elementName, error);
+ QTimer::singleShot(0, [pres, elementNames, error]() {
+ pres->signalProxy()->SigElementsCreated(elementNames, error);
});
}
-void CQmlEngineImpl::notifyMaterialCreation(CPresentation *pres, const QString &name,
+void CQmlEngineImpl::notifyMaterialCreation(CPresentation *pres,
+ const QStringList &materialNames,
const QString &error)
{
// Notify presentation asynchronously to give renderer time to initialize the materials properly
if (!error.isEmpty()) {
- qWarning() << "Warning: Material creation failed:" << name << error;
+ qWarning() << "Warning: Material creation failed:" << materialNames << error;
QT3DS_ASSERT(false);
}
- QTimer::singleShot(0, [pres, name, error]() {
- pres->signalProxy()->SigMaterialCreated(name, error);
+ QTimer::singleShot(0, [pres, materialNames, error]() {
+ pres->signalProxy()->SigMaterialsCreated(materialNames, error);
});
}
+void CQmlEngineImpl::deleteElements(const QVector<TElement *> &elements,
+ IQt3DSRenderer *renderer)
+{
+ TElement *lastParent = nullptr;
+ IPresentation *presentation = nullptr;
+ TElement *component = nullptr;
+ ISlideSystem *slideSystem = nullptr;
+ QSet<qt3ds::render::SNode *> parentNodes;
+ for (auto element : elements) {
+ TElement *parentElement = element->GetParent();
+ if (parentElement != lastParent) {
+ lastParent = parentElement;
+ presentation = element->GetBelongedPresentation();
+ component = &element->GetComponentParent();
+ slideSystem = &presentation->GetSlideSystem();
+ }
+ // Remove element recursively from slide system
+ slideSystem->removeElement(*component, *element);
+
+ Q_ASSERT(parentElement);
+
+ NVAllocatorCallback &allocator = presentation->GetScene()->allocator();
+
+ // Recursive deleter for translators and graph objects
+ std::function<void(TElement *)> deleteRenderObjects;
+ deleteRenderObjects = [&](TElement *elem) {
+ TElement *child = elem->m_Child;
+ while (child) {
+ TElement *sibling = child->m_Sibling;
+ deleteRenderObjects(child);
+ child = sibling;
+ }
+
+ auto translator = static_cast<qt3ds::render::Qt3DSTranslator *>(elem->GetAssociation());
+ if (translator) {
+ qt3ds::render::GraphObjectTypes::Enum type = translator->GetUIPType();
+ if (type == qt3ds::render::GraphObjectTypes::Model) {
+ auto model = static_cast<qt3ds::render::SModel *>(&translator->RenderObject());
+ // Delete material
+ if (model->m_FirstMaterial) {
+ auto material = static_cast<qt3ds::render::SReferencedMaterial *>(
+ model->m_FirstMaterial);
+ QT3DS_FREE(allocator, material);
+ }
+ }
+ QT3DS_FREE(allocator, &translator->RenderObject());
+ QT3DS_FREE(allocator, translator);
+ }
+ };
+
+ qt3ds::render::SNode *node = nullptr;
+ qt3ds::render::SNode *parentNode = nullptr;
+ auto translator = static_cast<qt3ds::render::Qt3DSTranslator *>(element->GetAssociation());
+
+ if (translator) {
+ if (qt3ds::render::GraphObjectTypes::IsNodeType(translator->GetUIPType())) {
+ node = &static_cast<qt3ds::render::SNode &>(translator->RenderObject());
+ auto parentTranslator = static_cast<qt3ds::render::Qt3DSTranslator *>(
+ parentElement->GetAssociation());
+ if (parentTranslator) {
+ parentNode = &static_cast<qt3ds::render::SNode &>(
+ parentTranslator->RenderObject());
+ parentNode->RemoveChild(*node);
+ parentNodes.insert(parentNode);
+ }
+ }
+ // Release child element graph objects/translators
+ deleteRenderObjects(element);
+ }
+
+ // Remove element recursively
+ m_Application->GetElementAllocator().ReleaseElement(*element, true);
+ }
+ for (auto parentNode : qAsConst(parentNodes))
+ renderer->ChildrenUpdated(*parentNode);
+}
+
template<typename TDataType>
void CQmlEngineImpl::setDynamicObjectProperty(qt3ds::render::SDynamicObject &material,
const dynamic::SPropertyDefinition &propDesc,
diff --git a/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp b/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp
index a74fb57e..c5ac0d6b 100644
--- a/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp
+++ b/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp
@@ -357,10 +357,6 @@ bool Q3DSViewerApp::InitializeApp(int winWidth, int winHeight, const QSurfaceFor
&QRuntimeViewSignalProxy::SigSlideExited, this, &Q3DSViewerApp::SigSlideExited);
connect(m_Impl.m_view->signalProxy(),
&QRuntimeViewSignalProxy::SigCustomSignal, this, &Q3DSViewerApp::SigCustomSignal);
- connect(m_Impl.m_view->signalProxy(), &QRuntimeViewSignalProxy::SigElementCreated, this,
- &Q3DSViewerApp::SigElementCreated);
- connect(m_Impl.m_view->signalProxy(), &QRuntimeViewSignalProxy::SigMaterialCreated, this,
- &Q3DSViewerApp::SigMaterialCreated);
QMetaObject::Connection *presReadyconn = new QMetaObject::Connection();
*presReadyconn = connect(m_Impl.m_view->signalProxy(),
&QRuntimeViewSignalProxy::SigPresentationReady, [&, presReadyconn]{
@@ -370,6 +366,11 @@ bool Q3DSViewerApp::InitializeApp(int winWidth, int winHeight, const QSurfaceFor
disconnect(*presReadyconn);
delete presReadyconn;
});
+ connect(m_Impl.m_view->signalProxy(), &QRuntimeViewSignalProxy::SigElementsCreated, this,
+ &Q3DSViewerApp::SigElementsCreated);
+ connect(m_Impl.m_view->signalProxy(), &QRuntimeViewSignalProxy::SigMaterialsCreated, this,
+ &Q3DSViewerApp::SigMaterialsCreated);
+
Resize(winWidth, winHeight);
Q_EMIT SigPresentationLoaded();
@@ -806,29 +807,30 @@ float Q3DSViewerApp::dataInputMin(const QString &name) const
return m_Impl.m_view->dataInputMin(name);
}
-void Q3DSViewerApp::createElement(const QString &parentElementPath, const QString &slideName,
- const QHash<QString, QVariant> &properties)
+void Q3DSViewerApp::createElements(const QString &parentElementPath, const QString &slideName,
+ const QVector<QHash<QString, QVariant>> &properties)
{
if (!m_Impl.m_view)
return;
- m_Impl.m_view->createElement(parentElementPath, slideName, properties);
+ m_Impl.m_view->createElements(parentElementPath, slideName, properties);
}
-void Q3DSViewerApp::deleteElement(const QString &elementPath)
+void Q3DSViewerApp::deleteElements(const QStringList &elementPaths)
{
if (!m_Impl.m_view)
return;
- m_Impl.m_view->deleteElement(elementPath);
+ m_Impl.m_view->deleteElements(elementPaths);
}
-void Q3DSViewerApp::createMaterial(const QString &elementPath, const QString &materialDefinition)
+void Q3DSViewerApp::createMaterials(const QString &elementPath,
+ const QStringList &materialDefinitions)
{
if (!m_Impl.m_view)
return;
- m_Impl.m_view->createMaterial(elementPath, materialDefinition);
+ m_Impl.m_view->createMaterials(elementPath, materialDefinitions);
}
Q3DSViewerApp &Q3DSViewerApp::Create(void *glContext, Q3DStudio::IAudioPlayer *inAudioPlayer,
diff --git a/src/Runtime/Source/viewer/Qt3DSViewerApp.h b/src/Runtime/Source/viewer/Qt3DSViewerApp.h
index 971bf473..8c873098 100644
--- a/src/Runtime/Source/viewer/Qt3DSViewerApp.h
+++ b/src/Runtime/Source/viewer/Qt3DSViewerApp.h
@@ -32,13 +32,15 @@
#define QT3DS_VIEWER_H
#include "qt3dsruntimeglobal.h"
+#include "Qt3DSApplication.h"
+#include "Qt3DSInputDefs.h"
#include <string>
#include <vector>
#include <QObject>
#include <QtCore/qelapsedtimer.h>
-#include "Qt3DSApplication.h"
-#include "Qt3DSInputDefs.h"
+#include <QtCore/qvector.h>
+#include <QtCore/qstringlist.h>
#include <QtGui/qsurfaceformat.h>
namespace Q3DStudio {
@@ -359,10 +361,10 @@ public:
float dataInputMax(const QString &name) const;
float dataInputMin(const QString &name) const;
- void createElement(const QString &parentElementPath, const QString &slideName,
- const QHash<QString, QVariant> &properties);
- void deleteElement(const QString &elementPath);
- void createMaterial(const QString &elementPath, const QString &materialDefinition);
+ void createElements(const QString &parentElementPath, const QString &slideName,
+ const QVector<QHash<QString, QVariant>> &properties);
+ void deleteElements(const QStringList &elementPaths);
+ void createMaterials(const QString &elementPath, const QStringList &materialDefinitions);
QString error();
@@ -405,8 +407,8 @@ Q_SIGNALS:
void SigSlideEntered(const QString &elementPath, unsigned int index, const QString &name);
void SigSlideExited(const QString &elementPath, unsigned int index, const QString &name);
void SigCustomSignal(const QString &elementPath, const QString &name);
- void SigElementCreated(const QString &elementName, const QString &error);
- void SigMaterialCreated(const QString &name, const QString &error);
+ void SigElementsCreated(const QStringList &elementPaths, const QString &error);
+ void SigMaterialsCreated(const QStringList &materialNames, const QString &error);
void SigPresentationReady();
void SigPresentationLoaded();
};
diff --git a/src/Runtime/api/studio3d/q3dscommandqueue.cpp b/src/Runtime/api/studio3d/q3dscommandqueue.cpp
index ed0ad8b5..02ae9395 100644
--- a/src/Runtime/api/studio3d/q3dscommandqueue.cpp
+++ b/src/Runtime/api/studio3d/q3dscommandqueue.cpp
@@ -30,6 +30,8 @@
#include "q3dscommandqueue_p.h"
#include "q3dspresentation.h"
+#include <QtCore/qstringlist.h>
+
ElementCommand::ElementCommand()
: m_commandType(CommandType_Invalid)
{
@@ -160,6 +162,16 @@ ElementCommand &CommandQueue::queueCommand(const QString &elementPath, CommandTy
return cmd;
}
+ElementCommand &CommandQueue::queueCommand(CommandType commandType, void *commandData)
+{
+ ElementCommand &cmd = nextFreeCommand();
+
+ cmd.m_commandType = commandType;
+ cmd.m_data = commandData;
+
+ return cmd;
+}
+
ElementCommand &CommandQueue::queueCommand(const QString &elementPath, CommandType commandType)
{
ElementCommand &cmd = nextFreeCommand();
@@ -170,6 +182,18 @@ ElementCommand &CommandQueue::queueCommand(const QString &elementPath, CommandTy
return cmd;
}
+ElementCommand &CommandQueue::queueCommand(const QString &elementPath, CommandType commandType,
+ void *commandData)
+{
+ ElementCommand &cmd = nextFreeCommand();
+
+ cmd.m_commandType = commandType;
+ cmd.m_elementPath = elementPath;
+ cmd.m_data = commandData;
+
+ return cmd;
+}
+
void CommandQueue::copyCommands(CommandQueue &fromQueue)
{
m_visibleChanged = m_visibleChanged || fromQueue.m_visibleChanged;
@@ -217,16 +241,13 @@ void CommandQueue::copyCommands(CommandQueue &fromQueue)
break;
case CommandType_GoToSlideByName:
case CommandType_FireEvent:
- case CommandType_CreateMaterial:
queueCommand(source.m_elementPath, source.m_commandType, source.m_stringValue);
break;
case CommandType_SetPresentationActive:
- queueCommand(source.m_elementPath, source.m_commandType,
- source.m_boolValue);
+ queueCommand(source.m_elementPath, source.m_commandType, source.m_boolValue);
break;
case CommandType_GoToTime:
- queueCommand(source.m_elementPath, source.m_commandType,
- source.m_floatValue);
+ queueCommand(source.m_elementPath, source.m_commandType, source.m_floatValue);
break;
case CommandType_GoToSlide:
case CommandType_GoToSlideRelative:
@@ -240,12 +261,19 @@ void CommandQueue::copyCommands(CommandQueue &fromQueue)
source.m_intValues[0], source.m_intValues[1],
source.m_intValues[2], source.m_intValues[3]);
break;
- case CommandType_CreateElement:
+ case CommandType_CreateElements:
queueCommand(source.m_elementPath, source.m_commandType, source.m_stringValue,
source.m_data);
fromQueue.commandAt(i).m_data = nullptr; // This queue takes ownership of data
break;
- case CommandType_DeleteElement:
+ case CommandType_DeleteElements:
+ queueCommand(source.m_commandType, source.m_data);
+ fromQueue.commandAt(i).m_data = nullptr; // This queue takes ownership of data
+ break;
+ case CommandType_CreateMaterials:
+ queueCommand(source.m_elementPath, source.m_commandType, source.m_data);
+ fromQueue.commandAt(i).m_data = nullptr; // This queue takes ownership of data
+ break;
case CommandType_RequestSlideInfo:
case CommandType_UnloadSlide:
case CommandType_PreloadSlide:
@@ -277,8 +305,14 @@ void CommandQueue::clear(bool deleteCommandData)
ElementCommand &cmd = m_elementCommands[i];
if (cmd.m_data) {
switch (cmd.m_commandType) {
- case CommandType_CreateElement:
- delete static_cast<QHash<QString, QVariant> *>(cmd.m_data);
+ case CommandType_CreateElements:
+ delete static_cast<QVector<QHash<QString, QVariant>> *>(cmd.m_data);
+ break;
+ case CommandType_DeleteElements:
+ delete static_cast<QStringList *>(cmd.m_data);
+ break;
+ case CommandType_CreateMaterials:
+ delete static_cast<QStringList *>(cmd.m_data);
break;
default:
Q_ASSERT(false); // Should never come here
diff --git a/src/Runtime/api/studio3d/q3dscommandqueue_p.h b/src/Runtime/api/studio3d/q3dscommandqueue_p.h
index ff30829f..c396ec8e 100644
--- a/src/Runtime/api/studio3d/q3dscommandqueue_p.h
+++ b/src/Runtime/api/studio3d/q3dscommandqueue_p.h
@@ -68,9 +68,9 @@ enum CommandType {
CommandType_KeyRelease,
CommandType_SetGlobalAnimationTime,
CommandType_SetDataInputValue,
- CommandType_CreateElement,
- CommandType_DeleteElement,
- CommandType_CreateMaterial,
+ CommandType_CreateElements,
+ CommandType_DeleteElements,
+ CommandType_CreateMaterials,
// Requests
CommandType_RequestSlideInfo,
@@ -122,7 +122,10 @@ public:
int value2 = 0, int value3 = 0);
ElementCommand &queueCommand(const QString &elementPath, CommandType commandType,
const QString &stringValue, void *commandData);
+ ElementCommand &queueCommand(CommandType commandType, void *commandData);
ElementCommand &queueCommand(const QString &elementPath, CommandType commandType);
+ ElementCommand &queueCommand(const QString &elementPath, CommandType commandType,
+ void *commandData);
void copyCommands(CommandQueue &fromQueue);
diff --git a/src/Runtime/api/studio3d/q3dspresentation.cpp b/src/Runtime/api/studio3d/q3dspresentation.cpp
index 0887d702..880780ff 100644
--- a/src/Runtime/api/studio3d/q3dspresentation.cpp
+++ b/src/Runtime/api/studio3d/q3dspresentation.cpp
@@ -283,12 +283,21 @@ void Q3DSPresentation::setDataInputValue(const QString &name, const QVariant &va
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);
+}
+
+void Q3DSPresentation::createElements(const QString &parentElementPath, const QString &slideName,
+ const QVector<QHash<QString, QVariant>> &properties)
+{
if (d_ptr->m_viewerApp) {
- d_ptr->m_viewerApp->createElement(parentElementPath, slideName, properties);
+ 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
- QHash<QString, QVariant> *theProperties = new QHash<QString, QVariant>(properties);
- d_ptr->m_commandQueue->queueCommand(parentElementPath, CommandType_CreateElement,
+ QVector<QHash<QString, QVariant>> *theProperties
+ = new QVector<QHash<QString, QVariant>>(properties);
+ d_ptr->m_commandQueue->queueCommand(parentElementPath, CommandType_CreateElements,
slideName, theProperties);
}
}
@@ -298,10 +307,20 @@ void Q3DSPresentation::createElement(const QString &parentElementPath, const QSt
*/
void Q3DSPresentation::deleteElement(const QString &elementPath)
{
- if (d_ptr->m_viewerApp)
- d_ptr->m_viewerApp->deleteElement(elementPath);
- else if (d_ptr->m_commandQueue)
- d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_DeleteElement);
+ QStringList elementPaths;
+ elementPaths << elementPath;
+ deleteElements(elementPaths);
+}
+
+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);
+ }
}
/**
@@ -314,11 +333,21 @@ void Q3DSPresentation::deleteElement(const QString &elementPath)
void Q3DSPresentation::createMaterial(const QString &elementPath,
const QString &materialDefinition)
{
+ QStringList materialDefinitions;
+ materialDefinitions << materialDefinition;
+ createMaterials(elementPath, materialDefinitions);
+}
+
+void Q3DSPresentation::createMaterials(const QString &elementPath,
+ const QStringList &materialDefinitions)
+{
if (d_ptr->m_viewerApp) {
- d_ptr->m_viewerApp->createMaterial(elementPath, materialDefinition);
+ d_ptr->m_viewerApp->createMaterials(elementPath, materialDefinitions);
} else if (d_ptr->m_commandQueue) {
- d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_CreateMaterial,
- materialDefinition);
+ // We need to copy the list as queue takes ownership of it
+ QStringList *theMaterialDefinitions = new QStringList(materialDefinitions);
+ d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_CreateMaterials,
+ theMaterialDefinitions);
}
}
@@ -464,10 +493,10 @@ void Q3DSPresentationPrivate::setViewerApp(Q3DSViewer::Q3DSViewerApp *app, bool
q_ptr, &Q3DSPresentation::slideExited);
connect(app, &Q3DSViewer::Q3DSViewerApp::SigCustomSignal,
q_ptr, &Q3DSPresentation::customSignalEmitted);
- connect(app, &Q3DSViewer::Q3DSViewerApp::SigElementCreated,
- q_ptr, &Q3DSPresentation::elementCreated);
- connect(app, &Q3DSViewer::Q3DSViewerApp::SigMaterialCreated,
- q_ptr, &Q3DSPresentation::materialCreated);
+ connect(app, &Q3DSViewer::Q3DSViewerApp::SigElementsCreated,
+ q_ptr, &Q3DSPresentation::elementsCreated);
+ connect(app, &Q3DSViewer::Q3DSViewerApp::SigMaterialsCreated,
+ q_ptr, &Q3DSPresentation::materialsCreated);
}
if (oldApp) {
disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigSlideEntered,
@@ -476,10 +505,10 @@ void Q3DSPresentationPrivate::setViewerApp(Q3DSViewer::Q3DSViewerApp *app, bool
q_ptr, &Q3DSPresentation::slideExited);
disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigCustomSignal,
q_ptr, &Q3DSPresentation::customSignalEmitted);
- disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigElementCreated,
- q_ptr, &Q3DSPresentation::elementCreated);
- disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigMaterialCreated,
- q_ptr, &Q3DSPresentation::materialCreated);
+ disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigElementsCreated,
+ q_ptr, &Q3DSPresentation::elementsCreated);
+ disconnect(oldApp, &Q3DSViewer::Q3DSViewerApp::SigMaterialsCreated,
+ q_ptr, &Q3DSPresentation::materialsCreated);
}
}
}
diff --git a/src/Runtime/api/studio3d/q3dspresentation.h b/src/Runtime/api/studio3d/q3dspresentation.h
index d7f02e49..89daa262 100644
--- a/src/Runtime/api/studio3d/q3dspresentation.h
+++ b/src/Runtime/api/studio3d/q3dspresentation.h
@@ -31,9 +31,11 @@
#define Q3DSPRESENTATION_H
#include <QtStudio3D/qstudio3dglobal.h>
+#include <QtStudio3D/q3dsdatainput.h>
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
-#include <QtStudio3D/q3dsdatainput.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qstringlist.h>
QT_BEGIN_NAMESPACE
@@ -85,8 +87,12 @@ public:
void createElement(const QString &parentElementPath, const QString &slideName,
const QHash<QString, QVariant> &properties);
+ void createElements(const QString &parentElementPath, const QString &slideName,
+ const QVector<QHash<QString, QVariant>> &properties);
void deleteElement(const QString &elementPath);
+ void deleteElements(const QStringList &elementPaths);
void createMaterial(const QString &elementPath, const QString &materialDefinition);
+ void createMaterials(const QString &elementPath, const QStringList &materialDefinitions);
public Q_SLOTS:
void setSource(const QUrl &source);
@@ -113,8 +119,8 @@ Q_SIGNALS:
void dataInputsReady();
void customSignalEmitted(const QString &elementPath, const QString &name);
void delayedLoadingChanged(bool enable);
- void elementCreated(const QString &elementPath, const QString &error);
- void materialCreated(const QString &name, const QString &error);
+ void elementsCreated(const QStringList &elementPaths, const QString &error);
+ void materialsCreated(const QStringList &materialNames, const QString &error);
private:
Q_DISABLE_COPY(Q3DSPresentation)
diff --git a/src/Runtime/api/studio3dqml/q3dsrenderer.cpp b/src/Runtime/api/studio3dqml/q3dsrenderer.cpp
index 7e063ab4..591cc37a 100644
--- a/src/Runtime/api/studio3dqml/q3dsrenderer.cpp
+++ b/src/Runtime/api/studio3dqml/q3dsrenderer.cpp
@@ -211,10 +211,10 @@ bool Q3DSRenderer::initializeRuntime(QOpenGLFramebufferObject *inFbo)
this, &Q3DSRenderer::exitSlide);
connect(m_runtime, &Q3DSViewer::Q3DSViewerApp::SigCustomSignal,
this, &Q3DSRenderer::customSignalEmitted);
- connect(m_runtime, &Q3DSViewer::Q3DSViewerApp::SigElementCreated,
- this, &Q3DSRenderer::elementCreated);
- connect(m_runtime, &Q3DSViewer::Q3DSViewerApp::SigMaterialCreated,
- this, &Q3DSRenderer::materialCreated);
+ connect(m_runtime, &Q3DSViewer::Q3DSViewerApp::SigElementsCreated,
+ this, &Q3DSRenderer::elementsCreated);
+ connect(m_runtime, &Q3DSViewer::Q3DSViewerApp::SigMaterialsCreated,
+ this, &Q3DSRenderer::materialsCreated);
return true;
}
@@ -337,21 +337,30 @@ void Q3DSRenderer::processCommands()
cmd.m_stringValue, cmd.m_variantValue,
static_cast<qt3ds::runtime::DataInputValueRole>(cmd.m_intValues[0]));
break;
- case CommandType_CreateElement: {
- m_runtime->createElement(cmd.m_elementPath, cmd.m_stringValue,
- *static_cast<QHash<QString, QVariant> *>(cmd.m_data));
+ case CommandType_CreateElements: {
+ m_runtime->createElements(
+ cmd.m_elementPath, cmd.m_stringValue,
+ *static_cast<QVector<QHash<QString, QVariant>> *>(cmd.m_data));
// Runtime makes copy of the data in its own format, so we can delete it now
auto &command = m_commands.commandAt(i);
- delete reinterpret_cast<QHash<QString, QVariant> *>(command.m_data);
+ delete reinterpret_cast<QVector<QHash<QString, QVariant>> *>(command.m_data);
command.m_data = nullptr;
break;
}
- case CommandType_DeleteElement: {
- m_runtime->deleteElement(cmd.m_elementPath);
+ case CommandType_DeleteElements: {
+ m_runtime->deleteElements(*static_cast<QStringList *>(cmd.m_data));
+ // Runtime makes copy of the data in its own format, so we can delete it now
+ auto &command = m_commands.commandAt(i);
+ delete reinterpret_cast<QStringList *>(command.m_data);
+ command.m_data = nullptr;
break;
}
- case CommandType_CreateMaterial: {
- m_runtime->createMaterial(cmd.m_elementPath, cmd.m_stringValue);
+ case CommandType_CreateMaterials: {
+ m_runtime->createMaterials(cmd.m_elementPath, *static_cast<QStringList *>(cmd.m_data));
+ // Runtime makes copy of the data in its own format, so we can delete it now
+ auto &command = m_commands.commandAt(i);
+ delete reinterpret_cast<QStringList *>(command.m_data);
+ command.m_data = nullptr;
break;
}
case CommandType_RequestSlideInfo: {
diff --git a/src/Runtime/api/studio3dqml/q3dsrenderer.h b/src/Runtime/api/studio3dqml/q3dsrenderer.h
index 12f98aef..757ec4af 100644
--- a/src/Runtime/api/studio3dqml/q3dsrenderer.h
+++ b/src/Runtime/api/studio3dqml/q3dsrenderer.h
@@ -63,8 +63,8 @@ Q_SIGNALS:
void presentationReady();
void presentationLoaded();
void customSignalEmitted(const QString &elNmentPath, const QString &name);
- void elementCreated(const QString &elementName, const QString &error);
- void materialCreated(const QString &name, const QString &error);
+ void elementsCreated(const QStringList &elementPaths, const QString &error);
+ void materialsCreated(const QStringList &materialNames, const QString &error);
protected:
static void onInitHandler(void *userData);
diff --git a/src/Runtime/api/studio3dqml/q3dsstudio3d.cpp b/src/Runtime/api/studio3dqml/q3dsstudio3d.cpp
index 2a6c7be2..75633a09 100644
--- a/src/Runtime/api/studio3dqml/q3dsstudio3d.cpp
+++ b/src/Runtime/api/studio3dqml/q3dsstudio3d.cpp
@@ -207,10 +207,10 @@ QQuickFramebufferObject::Renderer *Q3DSStudio3D::createRenderer() const
m_presentation, &Q3DSPresentation::slideExited);
connect(renderer, &Q3DSRenderer::customSignalEmitted,
m_presentation, &Q3DSPresentation::customSignalEmitted);
- connect(renderer, &Q3DSRenderer::elementCreated,
- m_presentation, &Q3DSPresentation::elementCreated);
- connect(renderer, &Q3DSRenderer::materialCreated,
- m_presentation, &Q3DSPresentation::materialCreated);
+ connect(renderer, &Q3DSRenderer::elementsCreated,
+ m_presentation, &Q3DSPresentation::elementsCreated);
+ connect(renderer, &Q3DSRenderer::materialsCreated,
+ m_presentation, &Q3DSPresentation::materialsCreated);
connect(renderer, &Q3DSRenderer::requestResponse,
this, &Q3DSStudio3D::requestResponseHandler);
connect(renderer, &Q3DSRenderer::presentationLoaded,
diff --git a/src/Runtime/api/studio3dqml/q3dsstudio3d.h b/src/Runtime/api/studio3dqml/q3dsstudio3d.h
index 484e9f65..f27dbf17 100644
--- a/src/Runtime/api/studio3dqml/q3dsstudio3d.h
+++ b/src/Runtime/api/studio3dqml/q3dsstudio3d.h
@@ -51,7 +51,7 @@ class Q3DSStudio3D : public QQuickFramebufferObject
public:
Q3DSStudio3D();
- virtual ~Q3DSStudio3D();
+ ~Q3DSStudio3D() override;
QQuickFramebufferObject::Renderer *createRenderer() const override;
diff --git a/tests/auto/viewer/tst_qt3dsviewer.cpp b/tests/auto/viewer/tst_qt3dsviewer.cpp
index 333ac950..d261c2a9 100644
--- a/tests/auto/viewer/tst_qt3dsviewer.cpp
+++ b/tests/auto/viewer/tst_qt3dsviewer.cpp
@@ -102,7 +102,7 @@ void tst_qt3dsviewer::init()
void tst_qt3dsviewer::cleanup()
{
- deleteCreatedElements(0);
+ deleteCreatedElements();
if (!m_ignoreError)
QCOMPARE(m_studio3DItem->property("error").toString(), {});
m_studio3DItem = nullptr;
@@ -185,14 +185,16 @@ void tst_qt3dsviewer::testCreateElement()
QSignalSpy spyExited(m_presentation,
SIGNAL(slideExited(const QString &, unsigned int, const QString &)));
- QSignalSpy spyElemCreated(m_presentation, SIGNAL(elementCreated(const QString &,
- const QString &)));
-
- QObject::connect(m_presentation, &Q3DSPresentation::elementCreated,
- [this](const QString &elementName, const QString &error) {
- QVERIFY(error.isEmpty());
- if (!m_createdElements.contains(elementName))
- QVERIFY(false);
+ QSignalSpy spyElemCreated(m_presentation, SIGNAL(elementsCreated(const QStringList &,
+ const QString &)));
+
+ QObject::connect(m_presentation, &Q3DSPresentation::elementsCreated,
+ [this](const QStringList &elementNames, const QString &error) {
+ QCOMPARE(error, QString());
+ for (auto &elementName : elementNames) {
+ if (!m_createdElements.contains(elementName))
+ QVERIFY(false);
+ }
});
int animValue = 0;
@@ -304,45 +306,32 @@ void tst_qt3dsviewer::testCreateElement()
// Switch to slide 1
QVERIFY(spyExited.wait(20000));
- QTimer createTimer;
- createTimer.setInterval(0);
- static int elemCounter = 0;
QRandomGenerator rnd;
-
- auto createElementsConnection = QObject::connect(&createTimer, &QTimer::timeout, [&]() {
- // Create a bunch of elements to slide 2 in small batches to avoid slowdown
- for (int i = 0; i < 5; ++i) {
- ++elemCounter;
- data.clear();
- QString elementName = QStringLiteral("MassElement_%1").arg(elemCounter);
- data.insert(QStringLiteral("name"), elementName);
- data.insert(QStringLiteral("sourcepath"),
- elemCounter % 2 ? QStringLiteral("#Cube") : QStringLiteral("#Cone"));
- data.insert(QStringLiteral("material"),
- elemCounter % 2 ? QStringLiteral("Basic Green")
- : QStringLiteral("Basic Red"));
- data.insert(QStringLiteral("position"),
- QVariant::fromValue<QVector3D>(QVector3D(rnd.bounded(-600, 600),
- rnd.bounded(-600, 600),
- rnd.bounded(800, 1200))));
-
- createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide2"), data);
- }
- if (elemCounter >= 1000) {
- qDebug() << "Extra elements created:" << elemCounter;
- createTimer.stop();
- }
- });
- qDebug() << "Start creating extra elements";
- createTimer.start();
+ QVector<QHash<QString, QVariant>> massProps;
+ for (int i = 0; i < 1000; ++i) {
+ data.clear();
+ QString elementName = QStringLiteral("MassElement_%1").arg(i);
+ data.insert(QStringLiteral("name"), elementName);
+ data.insert(QStringLiteral("sourcepath"),
+ i % 2 ? QStringLiteral("#Cube") : QStringLiteral("#Cone"));
+ data.insert(QStringLiteral("material"),
+ i % 2 ? QStringLiteral("Basic Green") : QStringLiteral("Basic Red"));
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(rnd.bounded(-600, 600),
+ rnd.bounded(-600, 600),
+ rnd.bounded(800, 1200))));
+ massProps << data;
+ m_createdElements << QStringLiteral("Scene.Layer.") + elementName;
+ }
+ m_presentation->createElements(QStringLiteral("Scene.Layer"), QStringLiteral("Slide2"),
+ massProps);
// Switch to slide 2
QVERIFY(spyExited.wait(20000));
- QObject::disconnect(createElementsConnection);
QTest::qWait(500);
- QCOMPARE(spyElemCreated.count(), m_createdElements.count());
- deleteCreatedElements(1);
+ QCOMPARE(spyElemCreated.count(), 7);
+ deleteCreatedElements();
// Switch to slide 1
QVERIFY(spyExited.wait(20000));
@@ -358,19 +347,16 @@ void tst_qt3dsviewer::testCreateMaterial()
QSignalSpy spyExited(m_presentation,
SIGNAL(slideExited(const QString &, unsigned int, const QString &)));
- QSignalSpy spyMatCreated(m_presentation, SIGNAL(materialCreated(const QString &,
- const QString &)));
- QSignalSpy spyElemCreated(m_presentation, SIGNAL(elementCreated(const QString &,
- const QString &)));
+ QSignalSpy spyMatCreated(m_presentation, SIGNAL(materialsCreated(const QStringList &,
+ const QString &)));
+ QSignalSpy spyElemCreated(m_presentation, SIGNAL(elementsCreated(const QStringList &,
+ const QString &)));
+
+ QStringList materialDefinitions;
// Create material via .materialdef file in resources
- m_presentation->createMaterial(
- QStringLiteral("Scene"),
- QStringLiteral(
- ":/scenes/simple_cube_animation/materials/Basic Blue.materialdef"));
- m_presentation->createMaterial(
- QStringLiteral("Scene"),
- QStringLiteral(
- ":/scenes/simple_cube_animation/materials/Basic Texture.materialdef"));
+ materialDefinitions
+ << QStringLiteral(":/scenes/simple_cube_animation/materials/Basic Blue.materialdef")
+ << QStringLiteral(":/scenes/simple_cube_animation/materials/Basic Texture.materialdef");
// Create material directly from materialdef content
auto loadMatDefFile = [&](const QString &fileName) -> QString {
@@ -384,46 +370,47 @@ void tst_qt3dsviewer::testCreateMaterial()
QString matDef = loadMatDefFile(
QStringLiteral(":/scenes/simple_cube_animation/materials/Copper.materialdef"));
QVERIFY(!matDef.isEmpty());
+ materialDefinitions << matDef;
- m_presentation->createMaterial(QStringLiteral("Scene"), matDef);
-
- QObject::connect(m_presentation, &Q3DSPresentation::materialCreated,
- [this](const QString &name, const QString &error) {
- QHash<QString, QVariant> data;
+ m_presentation->createMaterials(QStringLiteral("Scene"), materialDefinitions);
+ QObject::connect(m_presentation, &Q3DSPresentation::materialsCreated,
+ [this](const QStringList &materialNames, const QString &error) {
QVERIFY(error.isEmpty());
-
- if (name == QLatin1String("materials/Basic Blue")) {
- data.insert(QStringLiteral("name"), QStringLiteral("Blue Cylinder"));
- data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cylinder"));
- data.insert(QStringLiteral("material"), name);
- data.insert(QStringLiteral("position"),
- QVariant::fromValue<QVector3D>(QVector3D(200, 300, 200)));
- createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
- } else if (name == QLatin1String("materials/Basic Texture")) {
- data.insert(QStringLiteral("name"), QStringLiteral("Textured Cone"));
- data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cone"));
- data.insert(QStringLiteral("material"), name);
- data.insert(QStringLiteral("position"),
- QVariant::fromValue<QVector3D>(QVector3D(-200, -300, 200)));
- createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
- } else if (name == QLatin1String("materials/Copper")) {
- data.insert(QStringLiteral("name"), QStringLiteral("Copper Sphere"));
- data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Sphere"));
- data.insert(QStringLiteral("material"), name);
- data.insert(QStringLiteral("position"),
- QVariant::fromValue<QVector3D>(QVector3D(-200, 300, 200)));
- createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
- } else if (name == QLatin1String("materials/Just Yellow")) {
+ for (auto &name : materialNames) {
QHash<QString, QVariant> data;
- data.insert(QStringLiteral("name"), QStringLiteral("Yellow Cube"));
- data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cube"));
- data.insert(QStringLiteral("material"), name);
- data.insert(QStringLiteral("position"),
- QVariant::fromValue<QVector3D>(QVector3D(200, -300, 200)));
- createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
- } else {
- QVERIFY(false);
+ if (name == QLatin1String("materials/Basic Blue")) {
+ data.insert(QStringLiteral("name"), QStringLiteral("Blue Cylinder"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cylinder"));
+ data.insert(QStringLiteral("material"), name);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(200, 300, 200)));
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+ } else if (name == QLatin1String("materials/Basic Texture")) {
+ data.insert(QStringLiteral("name"), QStringLiteral("Textured Cone"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cone"));
+ data.insert(QStringLiteral("material"), name);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(-200, -300, 200)));
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+ } else if (name == QLatin1String("materials/Copper")) {
+ data.insert(QStringLiteral("name"), QStringLiteral("Copper Sphere"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Sphere"));
+ data.insert(QStringLiteral("material"), name);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(-200, 300, 200)));
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+ } else if (name == QLatin1String("materials/Just Yellow")) {
+ QHash<QString, QVariant> data;
+ data.insert(QStringLiteral("name"), QStringLiteral("Yellow Cube"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cube"));
+ data.insert(QStringLiteral("material"), name);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(200, -300, 200)));
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+ } else {
+ QVERIFY(false);
+ }
}
});
@@ -439,32 +426,14 @@ void tst_qt3dsviewer::testCreateMaterial()
});
QVERIFY(spyExited.wait(20000));
- QCOMPARE(spyMatCreated.count(), 4);
+ QCOMPARE(spyMatCreated.count(), 2);
QCOMPARE(spyElemCreated.count(), 4);
QTest::qWait(200); // Extra wait to verify slide change visually
}
-void tst_qt3dsviewer::deleteCreatedElements(int interval)
+void tst_qt3dsviewer::deleteCreatedElements()
{
- QTimer deleteTimer;
- deleteTimer.setInterval(interval);
- int elemCounter = m_createdElements.size() - 1;
- QObject::connect(&deleteTimer, &QTimer::timeout, [&]() {
- // Delete all elements we created previously
- if (elemCounter >= 0) {
- m_presentation->deleteElement(m_createdElements[elemCounter]);
- --elemCounter;
- } else {
- qDebug() << "Extra elements deleted";
- deleteTimer.stop();
- }
- });
- qDebug() << "Start deleting extra elements";
- deleteTimer.start();
-
- while (deleteTimer.isActive())
- QTest::qWait(20);
-
+ m_presentation->deleteElements(m_createdElements);
m_createdElements.clear();
}
diff --git a/tests/auto/viewer/tst_qt3dsviewer.h b/tests/auto/viewer/tst_qt3dsviewer.h
index 41c7ed31..f6281881 100644
--- a/tests/auto/viewer/tst_qt3dsviewer.h
+++ b/tests/auto/viewer/tst_qt3dsviewer.h
@@ -59,7 +59,7 @@ private Q_SLOTS:
void testCreateMaterial();
private:
- void deleteCreatedElements(int interval);
+ void deleteCreatedElements();
void createElement(const QString &parentElementPath, const QString &slideName,
const QHash<QString, QVariant> &properties);