summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2019-05-13 17:49:20 +0300
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2019-05-14 12:02:29 +0000
commitc46b03d90eedc1f13c178dd69e019fd2b6de9994 (patch)
tree3e034c47f5e644f47e4b7207a5beef3a4a511ce0
parent0a82b82de3ad7796cf91a355017a24ace2c830b4 (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.cpp2
-rw-r--r--src/Runtime/Source/engine/Qt3DSRuntimeView.h3
-rw-r--r--src/Runtime/Source/runtime/Qt3DSPresentation.h3
-rw-r--r--src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp164
-rw-r--r--src/Runtime/Source/viewer/Qt3DSViewerApp.cpp2
-rw-r--r--src/Runtime/Source/viewer/Qt3DSViewerApp.h3
-rw-r--r--src/Viewer/qmlviewer/Qt3DSRenderer.cpp2
-rw-r--r--src/Viewer/qmlviewer/Qt3DSRenderer.h5
-rw-r--r--src/Viewer/qmlviewer/Qt3DSView.cpp2
-rw-r--r--src/Viewer/studio3d/q3dspresentation.cpp4
-rw-r--r--src/Viewer/studio3d/q3dspresentation.h3
-rw-r--r--tests/auto/viewer/tst_qt3dsviewer.cpp75
-rw-r--r--tests/auto/viewer/tst_qt3dsviewer.h3
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;
};