diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2019-05-13 17:49:20 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2019-05-14 12:02:29 +0000 |
commit | c46b03d90eedc1f13c178dd69e019fd2b6de9994 (patch) | |
tree | 3e034c47f5e644f47e4b7207a5beef3a4a511ce0 | |
parent | 0a82b82de3ad7796cf91a355017a24ace2c830b4 (diff) |
Add elementCreated signal
Also unified elementCreated and materialCreated signals to include
error string to indicate failure.
Task-number: QT3DS-3418
Change-Id: I4b60b1e32594b2993a5a421ac1ce66d33b521a05
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r-- | src/Runtime/Source/engine/Qt3DSRuntimeView.cpp | 2 | ||||
-rw-r--r-- | src/Runtime/Source/engine/Qt3DSRuntimeView.h | 3 | ||||
-rw-r--r-- | src/Runtime/Source/runtime/Qt3DSPresentation.h | 3 | ||||
-rw-r--r-- | src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp | 164 | ||||
-rw-r--r-- | src/Runtime/Source/viewer/Qt3DSViewerApp.cpp | 2 | ||||
-rw-r--r-- | src/Runtime/Source/viewer/Qt3DSViewerApp.h | 3 | ||||
-rw-r--r-- | src/Viewer/qmlviewer/Qt3DSRenderer.cpp | 2 | ||||
-rw-r--r-- | src/Viewer/qmlviewer/Qt3DSRenderer.h | 5 | ||||
-rw-r--r-- | src/Viewer/qmlviewer/Qt3DSView.cpp | 2 | ||||
-rw-r--r-- | src/Viewer/studio3d/q3dspresentation.cpp | 4 | ||||
-rw-r--r-- | src/Viewer/studio3d/q3dspresentation.h | 3 | ||||
-rw-r--r-- | tests/auto/viewer/tst_qt3dsviewer.cpp | 75 | ||||
-rw-r--r-- | tests/auto/viewer/tst_qt3dsviewer.h | 3 |
13 files changed, 182 insertions, 89 deletions
diff --git a/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp b/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp index 5d6b0a6c..e5c0f298 100644 --- a/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp +++ b/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp @@ -310,6 +310,8 @@ bool CRuntimeView::InitializeGraphics(const QSurfaceFormat &format, bool delayed signalProxy(), &QRuntimeViewSignalProxy::SigSlideExited); QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigCustomSignal, signalProxy(), &QRuntimeViewSignalProxy::SigCustomSignal); + QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigElementCreated, + signalProxy(), &QRuntimeViewSignalProxy::SigElementCreated); QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigMaterialCreated, signalProxy(), &QRuntimeViewSignalProxy::SigMaterialCreated); diff --git a/src/Runtime/Source/engine/Qt3DSRuntimeView.h b/src/Runtime/Source/engine/Qt3DSRuntimeView.h index ec136525..6dc0487b 100644 --- a/src/Runtime/Source/engine/Qt3DSRuntimeView.h +++ b/src/Runtime/Source/engine/Qt3DSRuntimeView.h @@ -55,7 +55,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 SigMaterialCreated(const QString &name); + void SigElementCreated(const QString &elementName, const QString &error); + void SigMaterialCreated(const QString &name, const QString &error); }; namespace qt3ds { diff --git a/src/Runtime/Source/runtime/Qt3DSPresentation.h b/src/Runtime/Source/runtime/Qt3DSPresentation.h index 5e3145fd..d39c2bf7 100644 --- a/src/Runtime/Source/runtime/Qt3DSPresentation.h +++ b/src/Runtime/Source/runtime/Qt3DSPresentation.h @@ -50,7 +50,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 SigMaterialCreated(const QString &name); + void SigElementCreated(const QString &elementName, const QString &error); + void SigMaterialCreated(const QString &name, const QString &error); }; namespace qt3ds { diff --git a/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp b/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp index 4825c7ef..c837aad1 100644 --- a/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp +++ b/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp @@ -518,6 +518,10 @@ private: QVector2D parseFloat2Property(const QString &propValue); QVector3D parseFloat3Property(const QString &propValue); QVector4D parseFloat4Property(const QString &propValue); + + void notifyElementCreation(CPresentation *pres, const QString &elementName, + const QString &error); + void notifyMaterialCreation(CPresentation *pres, const QString &name, const QString &error); }; CQmlEngineImpl::CQmlEngineImpl(NVFoundationBase &fnd, ITimeProvider &) @@ -919,12 +923,20 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri const QHash<QString, QVariant> &properties, qt3ds::render::IQt3DSRenderer *renderer) { + QString error; + CPresentation *presentation = nullptr; + QString elementPath = parentElementPath + QLatin1Char('.') + + properties.value(QStringLiteral("name")).toString(); + // Resolve parent element QByteArray theParentPath = parentElementPath.toUtf8(); TElement *parentElement = getTarget(theParentPath.constData()); if (!parentElement) { - qWarning() << __FUNCTION__ << "Invalid parent element:" << parentElementPath; + error = QStringLiteral("Invalid parent element"); + TElement *sceneElement = getTarget("Scene"); + presentation = static_cast<CPresentation *>(sceneElement->GetBelongedPresentation()); + notifyElementCreation(presentation, elementPath, error); return; } @@ -933,14 +945,14 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri if (!parentTranslator || !qt3ds::render::GraphObjectTypes::IsNodeType( parentTranslator->GetUIPType())) { - qWarning() << __FUNCTION__ << "Parent element is not a valid node"; + error = QStringLiteral("Parent element is not a valid node"); + notifyElementCreation(presentation, elementPath, error); return; } TElement &component = parentElement->GetComponentParent(); auto &parentObject = static_cast<qt3ds::render::SNode &>(parentTranslator->RenderObject()); - - IPresentation *presentation = parentElement->GetBelongedPresentation(); + presentation = static_cast<CPresentation *>(parentElement->GetBelongedPresentation()); ++_idCounter; @@ -950,7 +962,8 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri int slideIndex = slideSystem.FindSlide(component, theSlideName.constData()); int currentSlide = static_cast<TComponent &>(component).GetCurrentSlide(); if (slideIndex == 0xff) { - qWarning() << __FUNCTION__ << "Invalid slide name for time context:" << slideName; + error = QStringLiteral("Invalid slide name for time context: '%1'").arg(slideName); + notifyElementCreation(presentation, elementPath, error); return; } @@ -974,6 +987,8 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri qWarning() << __FUNCTION__ << "The specified parent" << parentElementPath << "already has a child with the same name:" << newElementName; + error = QStringLiteral("Element already exists"); + notifyElementCreation(presentation, elementPath, error); return; } @@ -1042,8 +1057,9 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri break; } default: - qWarning() << __FUNCTION__ << "Unsupported property type for" << it.key(); - break; + error = QStringLiteral("Unsupported property type for: '%1'").arg(it.key()); + notifyElementCreation(presentation, elementPath, error); + return; } } @@ -1052,15 +1068,14 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri regName, elementType, elementSubType, toConstDataRef(elementProperties.data(), QT3DSU32(elementProperties.size())), presentation, parentElement, false); - - QString elementPath = parentElementPath + QLatin1Char('.') + newElementName; newElem.m_Path = strTable.RegisterStr(elementPath); // Insert the new element into the correct slide if (!slideSystem.addSlideElement(component, slideIndex, newElem, eyeBall)) { - qWarning() << __FUNCTION__ << "Failed to add the new element to a slide"; // 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; } @@ -1077,9 +1092,10 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri newMatElem.m_Path = strTable.RegisterStr(matElemPath); if (!slideSystem.addSlideElement(component, slideIndex, newMatElem, eyeBall)) { - qWarning() << __FUNCTION__ << "Failed to add the new material element to a slide"; // 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; } @@ -1120,8 +1136,9 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri 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. - qWarning() << __FUNCTION__ << "Unable to resolve a fallback material"; m_Application->GetElementAllocator().ReleaseElement(newElem, true); + error = QStringLiteral("Unable to resolve a fallback material"); + notifyElementCreation(presentation, elementPath, error); return; } } @@ -1162,6 +1179,8 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri newElem.GetActivityZone().UpdateItemInfo(newElem); renderer->ChildrenUpdated(parentObject); + + notifyElementCreation(presentation, elementPath, {}); } // Only supports deleting element types that can be added via createElement. @@ -1246,25 +1265,41 @@ void CQmlEngineImpl::createMaterial(const QString &elementPath, IDynamicObjectSystem *dynamicObjectSystem, qt3ds::render::IQt3DSRenderer *renderer) { + QString materialName; + QMap<QString, QString> materialProps; + QMap<QString, QMap<QString, QString>> textureProps; + CPresentation *presentation = nullptr; + QString error; + + auto getMaterialInfo = [&]() { + QString presPath = QFileInfo(presentation->GetFilePath()).absolutePath(); + QString projPath = presentation->getProjectPath(); + + Q3DSMaterialDefinitionParser::getMaterialInfo(materialDefinition, + projPath, presPath, + materialName, materialProps, textureProps); + }; + QByteArray thePath = elementPath.toUtf8(); TElement *element = getTarget(thePath.constData()); if (!element) { - qWarning() << __FUNCTION__ << "Invalid element:" << elementPath; + error = QStringLiteral("Invalid element: '%1'").arg(elementPath); + TElement *sceneElement = getTarget("Scene"); + presentation = static_cast<CPresentation *>(sceneElement->GetBelongedPresentation()); + getMaterialInfo(); + notifyMaterialCreation(presentation, materialName, error); return; } - CPresentation *presentation = static_cast<CPresentation *>(element->GetBelongedPresentation()); - QString presPath = QFileInfo(presentation->GetFilePath()).absolutePath(); - QString projPath = presentation->getProjectPath(); + presentation = static_cast<CPresentation *>(element->GetBelongedPresentation()); + getMaterialInfo(); - QString materialName; - QMap<QString, QString> materialProps; - QMap<QString, QMap<QString, QString>> textureProps; - - Q3DSMaterialDefinitionParser::getMaterialInfo(materialDefinition, - projPath, presPath, - materialName, materialProps, textureProps); + 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"); @@ -1285,14 +1320,16 @@ void CQmlEngineImpl::createMaterial(const QString &elementPath, while (nextChild) { QString childName = QString::fromUtf8(nextChild->m_Name); if (childName == materialName) { - qWarning() << __FUNCTION__ << "Material already exists in material container"; + error = QStringLiteral("Material already exists in material container"); + notifyMaterialCreation(presentation, materialName, error); return; } nextChild = nextChild->GetSibling(); } } else { // TODO: Create a material container if it doesn't exist (QT3DS-3412) - qWarning() << __FUNCTION__ << "Presentation has no material container"; + error = QStringLiteral("Presentation has no material container"); + notifyMaterialCreation(presentation, materialName, error); return; } @@ -1330,14 +1367,14 @@ void CQmlEngineImpl::createMaterial(const QString &elementPath, dynPropDefs.insert(propName, customProperties[i]); } } else { - qWarning() << __FUNCTION__ - << "Could not resolve material properties for CustomMaterial:" - << materialName; + error = QStringLiteral("Could not resolve material properties for CustomMaterial"); + notifyMaterialCreation(presentation, materialName, error); + return; } } else { - qWarning() << __FUNCTION__ - << "Missing sourcepath from material definition of a CustomMaterial:" - << materialName; + error = QStringLiteral("Missing sourcepath in material definition of a CustomMaterial"); + notifyMaterialCreation(presentation, materialName, error); + return; } } else { matType = strTable.RegisterStr("Material"); @@ -1345,7 +1382,7 @@ void CQmlEngineImpl::createMaterial(const QString &elementPath, auto createElementPropsFromDefProps = [&](const QMap<QString, QString> &defProps, TPropertyDescAndValueList &elementProps, - const CRegisteredString &elementType) -> bool { + const CRegisteredString &elementType) { QMapIterator<QString, QString> propIter(defProps); while (propIter.hasNext()) { propIter.next(); @@ -1427,20 +1464,19 @@ void CQmlEngineImpl::createMaterial(const QString &elementPath, break; } default: - qWarning() << __FUNCTION__ - << "Unsupported material property type for property:" - << propIter.key(); - QT3DS_ASSERT(false); + error = QStringLiteral("Unsupported material property type for property: '%1'") + .arg(propIter.key()); break; } } - return true; }; TPropertyDescAndValueList elementProps; - bool success = createElementPropsFromDefProps(materialProps, elementProps, matType); - if (!success) - return; // createElementPropsFromDefProps already prints a warning + createElementPropsFromDefProps(materialProps, elementProps, matType); + if (!error.isEmpty()) { + notifyMaterialCreation(presentation, materialName, error); + return; + } TElement &newMatElem = m_Application->GetElementAllocator().CreateElement( matName, matType, matClass, @@ -1455,10 +1491,11 @@ void CQmlEngineImpl::createMaterial(const QString &elementPath, while (texIter.hasNext()) { texIter.next(); elementProps.clear(); - success = createElementPropsFromDefProps(texIter.value(), elementProps, imageType); - if (!success) { + createElementPropsFromDefProps(texIter.value(), elementProps, imageType); + if (!error.isEmpty()) { m_Application->GetElementAllocator().ReleaseElement(newMatElem, true); - return; // createElementPropsFromDefProps already prints a warning + notifyMaterialCreation(presentation, materialName, error); + return; } CRegisteredString imageName = strTable.RegisterStr(texIter.key()); @@ -1526,12 +1563,10 @@ void CQmlEngineImpl::createMaterial(const QString &elementPath, break; } default: - qWarning() << __FUNCTION__ - << "Unsupported custom material property type '" << propDesc.m_DataType - << "' for property:" - << dynPropIter.key(); - QT3DS_ASSERT(false); - break; + error = QStringLiteral("Unsupported custom material property type for '%1'") + .arg(dynPropIter.key()); + notifyMaterialCreation(presentation, materialName, error); + return; } } } else { @@ -1559,10 +1594,7 @@ void CQmlEngineImpl::createMaterial(const QString &elementPath, qt3ds::render::Qt3DSTranslator::CreateTranslatorForElement(newMatElem, *newMaterial, allocator); - // Notify presentation asynchronously to give renderer time to initialize the materials properly - QTimer::singleShot(0, [materialName, presentation]() { - presentation->signalProxy()->SigMaterialCreated(materialName); - }); + notifyMaterialCreation(presentation, materialName, {}); } void CQmlEngineImpl::GotoSlide(const char *component, const char *slideName, @@ -2226,6 +2258,32 @@ QVector4D CQmlEngineImpl::parseFloat4Property(const QString &propValue) return retVal; } +void CQmlEngineImpl::notifyElementCreation(CPresentation *pres, const QString &elementName, + 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; + QT3DS_ASSERT(false); + } + QTimer::singleShot(0, [pres, elementName, error]() { + pres->signalProxy()->SigElementCreated(elementName, error); + }); +} + +void CQmlEngineImpl::notifyMaterialCreation(CPresentation *pres, const QString &name, + 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; + QT3DS_ASSERT(false); + } + QTimer::singleShot(0, [pres, name, error]() { + pres->signalProxy()->SigMaterialCreated(name, error); + }); +} + 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 fadd680c..11199efc 100644 --- a/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp +++ b/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp @@ -357,6 +357,8 @@ 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); diff --git a/src/Runtime/Source/viewer/Qt3DSViewerApp.h b/src/Runtime/Source/viewer/Qt3DSViewerApp.h index 5cd52bca..b0fe9d9d 100644 --- a/src/Runtime/Source/viewer/Qt3DSViewerApp.h +++ b/src/Runtime/Source/viewer/Qt3DSViewerApp.h @@ -404,7 +404,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 SigMaterialCreated(const QString &name); + void SigElementCreated(const QString &elementName, const QString &error); + void SigMaterialCreated(const QString &name, const QString &error); void SigPresentationReady(); }; diff --git a/src/Viewer/qmlviewer/Qt3DSRenderer.cpp b/src/Viewer/qmlviewer/Qt3DSRenderer.cpp index 4122a645..bd48a1ed 100644 --- a/src/Viewer/qmlviewer/Qt3DSRenderer.cpp +++ b/src/Viewer/qmlviewer/Qt3DSRenderer.cpp @@ -209,6 +209,8 @@ 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); diff --git a/src/Viewer/qmlviewer/Qt3DSRenderer.h b/src/Viewer/qmlviewer/Qt3DSRenderer.h index 2d3b69db..6453f977 100644 --- a/src/Viewer/qmlviewer/Qt3DSRenderer.h +++ b/src/Viewer/qmlviewer/Qt3DSRenderer.h @@ -61,8 +61,9 @@ Q_SIGNALS: void exitSlide(const QString &elementPath, unsigned int slide, const QString &slideName); void requestResponse(const QString &elementPath, CommandType commandType, void *requestData); void presentationReady(); - void customSignalEmitted(const QString &elementPath, const QString &name); - void materialCreated(const QString &name); + void customSignalEmitted(const QString &elNmentPath, const QString &name); + void elementCreated(const QString &elementName, const QString &error); + void materialCreated(const QString &name, const QString &error); protected: static void onInitHandler(void *userData); diff --git a/src/Viewer/qmlviewer/Qt3DSView.cpp b/src/Viewer/qmlviewer/Qt3DSView.cpp index a68bd667..beece5ac 100644 --- a/src/Viewer/qmlviewer/Qt3DSView.cpp +++ b/src/Viewer/qmlviewer/Qt3DSView.cpp @@ -207,6 +207,8 @@ QQuickFramebufferObject::Renderer *Q3DSView::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::requestResponse, diff --git a/src/Viewer/studio3d/q3dspresentation.cpp b/src/Viewer/studio3d/q3dspresentation.cpp index 3739ae66..0887d702 100644 --- a/src/Viewer/studio3d/q3dspresentation.cpp +++ b/src/Viewer/studio3d/q3dspresentation.cpp @@ -464,6 +464,8 @@ 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); } @@ -474,6 +476,8 @@ 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); } diff --git a/src/Viewer/studio3d/q3dspresentation.h b/src/Viewer/studio3d/q3dspresentation.h index b444f008..c0295e15 100644 --- a/src/Viewer/studio3d/q3dspresentation.h +++ b/src/Viewer/studio3d/q3dspresentation.h @@ -113,7 +113,8 @@ Q_SIGNALS: void dataInputsReady(); void customSignalEmitted(const QString &elementPath, const QString &name); void delayedLoadingChanged(bool enable); - void materialCreated(const QString &name); + void elementCreated(const QString &elementPath, const QString &error); + void materialCreated(const QString &name, const QString &error); private: Q_DISABLE_COPY(Q3DSPresentation) diff --git a/tests/auto/viewer/tst_qt3dsviewer.cpp b/tests/auto/viewer/tst_qt3dsviewer.cpp index d3387678..333ac950 100644 --- a/tests/auto/viewer/tst_qt3dsviewer.cpp +++ b/tests/auto/viewer/tst_qt3dsviewer.cpp @@ -56,12 +56,10 @@ void messageOutput(QtMsgType type, const QMessageLogContext &context, void tst_qt3dsviewer::initTestCase() { qInstallMessageHandler(messageOutput); - m_viewer.setTitle(QStringLiteral("tst_qt3dsviewer")); } void tst_qt3dsviewer::cleanupTestCase() { - QCOMPARE(m_studio3DItem->property("error").toString(), QString()); } void tst_qt3dsviewer::init() @@ -80,10 +78,13 @@ void tst_qt3dsviewer::init() QSurfaceFormat::setDefaultFormat(format); #endif - m_viewer.setSource(QUrl("qrc:/tst_qt3dsviewer.qml")); - m_studio3DItem = m_viewer.rootObject(); + m_viewer = new QQuickView; + m_viewer->setTitle(QStringLiteral("tst_qt3dsviewer")); + m_viewer->setSource(QUrl("qrc:/tst_qt3dsviewer.qml")); + m_studio3DItem = m_viewer->rootObject(); m_presentation = nullptr; m_settings = nullptr; + m_ignoreError = false; QVERIFY(m_studio3DItem); @@ -102,21 +103,28 @@ void tst_qt3dsviewer::init() void tst_qt3dsviewer::cleanup() { deleteCreatedElements(0); - m_viewer.hide(); + if (!m_ignoreError) + QCOMPARE(m_studio3DItem->property("error").toString(), {}); + m_studio3DItem = nullptr; + m_viewer->hide(); + m_viewer->deleteLater(); + m_viewer = nullptr; } void tst_qt3dsviewer::testEmpty() { m_presentation->setProperty("source", QUrl()); - m_viewer.show(); + m_viewer->show(); QTest::qWait(1000); QCOMPARE(m_studio3DItem->property("running").toBool(), false); + QVERIFY(!m_studio3DItem->property("error").toString().isEmpty()); + m_ignoreError = true; // To avoid triggering cleanup() fail as we are expecting an error } void tst_qt3dsviewer::testLoading() { QCOMPARE(m_studio3DItem->property("running").toBool(), false); - m_viewer.show(); + m_viewer->show(); QTest::qWait(1000); QCOMPARE(m_studio3DItem->property("running").toBool(), true); } @@ -131,7 +139,7 @@ void tst_qt3dsviewer::testSlides() QCOMPARE(spyEntered.count(), 0); QCOMPARE(spyExited.count(), 0); - m_viewer.show(); + m_viewer->show(); QTest::qWait(1000); QCOMPARE(spyEntered.count(), 1); @@ -147,14 +155,15 @@ void tst_qt3dsviewer::testFrameUpdates() QSignalSpy spyFrames(m_studio3DItem, SIGNAL(frameUpdate())); QSignalSpy spyExited(m_presentation, SIGNAL(slideExited(const QString &, unsigned int, const QString &))); - m_viewer.show(); + m_viewer->show(); QVERIFY(spyExited.wait(12000)); - QVERIFY(spyFrames.count() > 590); // Should be 60 with fudge for startup + // Just ensure we get some frames, exact count will vary a lot due to external factors + QVERIFY(spyFrames.count() > 10); } void tst_qt3dsviewer::testSettings() { - m_viewer.show(); + m_viewer->show(); m_settings->setMatteColor(QColor("#0000ff")); QVERIFY(m_settings->matteColor() == QColor("#0000ff")); @@ -169,16 +178,22 @@ void tst_qt3dsviewer::testSettings() void tst_qt3dsviewer::testCreateElement() { - // Currently this method is very bare bones on actual testing due to lack of programmatic - // feedback on dynamic object creation. - // It can be used to visually check if items are getting created. - m_viewer.show(); + m_viewer->show(); m_settings->setShowRenderStats(true); m_settings->setScaleMode(Q3DSViewerSettings::ScaleModeFill); 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); + }); int animValue = 0; @@ -326,6 +341,7 @@ void tst_qt3dsviewer::testCreateElement() QObject::disconnect(createElementsConnection); QTest::qWait(500); + QCOMPARE(spyElemCreated.count(), m_createdElements.count()); deleteCreatedElements(1); // Switch to slide 1 @@ -335,15 +351,17 @@ void tst_qt3dsviewer::testCreateElement() void tst_qt3dsviewer::testCreateMaterial() { - m_viewer.show(); + m_viewer->show(); m_settings->setShowRenderStats(true); m_settings->setScaleMode(Q3DSViewerSettings::ScaleModeFill); QSignalSpy spyExited(m_presentation, SIGNAL(slideExited(const QString &, unsigned int, const QString &))); - QSignalSpy spyMatCreated(m_presentation, SIGNAL(materialCreated(const QString &))); - + QSignalSpy spyMatCreated(m_presentation, SIGNAL(materialCreated(const QString &, + const QString &))); + QSignalSpy spyElemCreated(m_presentation, SIGNAL(elementCreated(const QString &, + const QString &))); // Create material via .materialdef file in resources m_presentation->createMaterial( QStringLiteral("Scene"), @@ -370,37 +388,33 @@ void tst_qt3dsviewer::testCreateMaterial() m_presentation->createMaterial(QStringLiteral("Scene"), matDef); QObject::connect(m_presentation, &Q3DSPresentation::materialCreated, - [this](const QString &name) { + [this](const QString &name, const QString &error) { QHash<QString, QVariant> data; - if (name == QStringLiteral("materials/Basic Blue")) { + 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); - } - - if (name == QStringLiteral("materials/Basic Texture")) { + } 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); - } - - if (name == QStringLiteral("materials/Copper")) { + } 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); - } - - if (name == QStringLiteral("materials/Just Yellow")) { + } else if (name == QLatin1String("materials/Just Yellow")) { QHash<QString, QVariant> data; data.insert(QStringLiteral("name"), QStringLiteral("Yellow Cube")); data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cube")); @@ -408,6 +422,8 @@ void tst_qt3dsviewer::testCreateMaterial() data.insert(QStringLiteral("position"), QVariant::fromValue<QVector3D>(QVector3D(200, -300, 200))); createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data); + } else { + QVERIFY(false); } }); @@ -424,6 +440,7 @@ void tst_qt3dsviewer::testCreateMaterial() QVERIFY(spyExited.wait(20000)); QCOMPARE(spyMatCreated.count(), 4); + QCOMPARE(spyElemCreated.count(), 4); QTest::qWait(200); // Extra wait to verify slide change visually } diff --git a/tests/auto/viewer/tst_qt3dsviewer.h b/tests/auto/viewer/tst_qt3dsviewer.h index bd5d0cd9..41c7ed31 100644 --- a/tests/auto/viewer/tst_qt3dsviewer.h +++ b/tests/auto/viewer/tst_qt3dsviewer.h @@ -63,11 +63,12 @@ private: void createElement(const QString &parentElementPath, const QString &slideName, const QHash<QString, QVariant> &properties); - QQuickView m_viewer; + QQuickView *m_viewer = nullptr; QObject *m_studio3DItem = nullptr; Q3DSPresentation *m_presentation = nullptr; Q3DSViewerSettings *m_settings = nullptr; QStringList m_createdElements; + bool m_ignoreError = false; }; |