summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp174
-rw-r--r--tests/auto/viewer/tst_qt3dsviewer.cpp42
-rw-r--r--tests/scenes/simple_cube_animation/presentations/simple_cube_animation.uip7
3 files changed, 141 insertions, 82 deletions
diff --git a/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp b/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp
index 448fc2be..02e5053e 100644
--- a/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp
+++ b/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp
@@ -925,6 +925,8 @@ void CQmlEngineImpl::createElements(const QString &parentElementPath, const QStr
const QVector<QHash<QString, QVariant>> &properties,
qt3ds::render::IQt3DSRenderer *renderer)
{
+ using namespace qt3ds::render;
+
int elementIndex = -1;
QString error;
CPresentation *presentation = nullptr;
@@ -955,10 +957,10 @@ void CQmlEngineImpl::createElements(const QString &parentElementPath, const QStr
return;
}
- auto parentTranslator = static_cast<qt3ds::render::Qt3DSTranslator *>(
+ auto parentTranslator = static_cast<Qt3DSTranslator *>(
parentElement->GetAssociation());
- if (!parentTranslator || !qt3ds::render::GraphObjectTypes::IsNodeType(
+ if (!parentTranslator || !GraphObjectTypes::IsNodeType(
parentTranslator->GetUIPType())) {
error = QObject::tr("Parent element is not a valid node: '%1'").arg(parentElementPath);
handleError();
@@ -966,7 +968,7 @@ void CQmlEngineImpl::createElements(const QString &parentElementPath, const QStr
}
TElement &component = parentElement->GetComponentParent();
- auto &parentObject = static_cast<qt3ds::render::SNode &>(parentTranslator->RenderObject());
+ auto &parentObject = static_cast<SNode &>(parentTranslator->RenderObject());
presentation = static_cast<CPresentation *>(parentElement->GetBelongedPresentation());
// Resolve slide
@@ -986,6 +988,7 @@ void CQmlEngineImpl::createElements(const QString &parentElementPath, const QStr
const QString startTimePropName = QStringLiteral("starttime");
const QString endTimePropName = QStringLiteral("endtime");
const QString eyeBallPropName = QStringLiteral("eyeball");
+ const QString typePropName = QStringLiteral("type");
Q3DStudio::UVariant attValue;
parentElement->GetAttribute(Q3DStudio::ATTRIBUTE_STARTTIME, attValue);
@@ -1020,15 +1023,25 @@ void CQmlEngineImpl::createElements(const QString &parentElementPath, const QStr
}
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;
+ CRegisteredString metaType;
+ const CRegisteredString elementSubType;
+ GraphObjectTypes::Enum objectType = GraphObjectTypes::Unknown;
+
+ QString typeStr = theProperties.take(typePropName).toString();
+ if (typeStr.isEmpty() || typeStr.compare(QLatin1String("model"),
+ Qt::CaseInsensitive) == 0) {
+ metaType = strTable.RegisterStr("Model");
+ objectType = GraphObjectTypes::Model;
+ } else if (typeStr.compare(QLatin1String("group"), Qt::CaseInsensitive) == 0) {
+ metaType = strTable.RegisterStr("Group");
+ objectType = GraphObjectTypes::Node;
+ }
// Set default values for missing mandatory properties
bool eyeBall = true;
theProperties.value(eyeBallPropName, true).toBool();
- if (!theProperties.contains(sourcePathPropName)) {
+ if (objectType == GraphObjectTypes::Model && !theProperties.contains(sourcePathPropName)) {
addStringAttribute(strTable, elementProperties, sourcePathPropName,
QStringLiteral("#Cube"));
}
@@ -1082,7 +1095,7 @@ void CQmlEngineImpl::createElements(const QString &parentElementPath, const QStr
// Create new element
TElement &newElem = m_Application->GetElementAllocator().CreateElement(
- regName, elementType, elementSubType,
+ regName, metaType, elementSubType,
toConstDataRef(elementProperties.data(), QT3DSU32(elementProperties.size())),
presentation, parentElement, false);
newElem.m_Path = strTable.RegisterStr(elementPaths[elementIndex]);
@@ -1096,89 +1109,92 @@ void CQmlEngineImpl::createElements(const QString &parentElementPath, const QStr
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);
-
- QString matElemPath = elementPaths[elementIndex] + 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 = 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;
+ if (objectType == GraphObjectTypes::Model) {
+ // 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 = elementPaths[elementIndex] + 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 = 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 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;
+ 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<Qt3DSTranslator *>(
+ nextChild->GetAssociation());
+ referencedMaterial = static_cast<SGraphObject *>(
+ &tr->RenderObject());
+ break;
+ }
+ nextChild = nextChild->GetSibling();
}
- 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 *>(
- 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 = QObject::tr("Unable to resolve a fallback material");
- handleError();
- return;
+ // 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<Qt3DSTranslator *>(
+ firstChild->GetAssociation());
+ referencedMaterial = static_cast<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 = QObject::tr("Unable to resolve a fallback material");
+ handleError();
+ 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_")
+ SModel *newObject = QT3DS_NEW(allocator, SModel)();
+ newObject->m_Id = strTable.RegisterStr((QByteArrayLiteral("__newObj_")
+ QByteArray::number(_idCounter)).constData());
parentObject.AddChild(*newObject);
- qt3ds::render::Qt3DSTranslator::CreateTranslatorForElement(newElem, *newObject, allocator);
+ 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);
+ if (referencedMaterial) {
+ // Create material SGraphObject
+ SReferencedMaterial *newMaterial = QT3DS_NEW(allocator, SReferencedMaterial)();
+ newMaterial->m_Id = strTable.RegisterStr(
+ (QByteArrayLiteral("__newMat_")
+ + 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;
@@ -1518,7 +1534,7 @@ void CQmlEngineImpl::createMaterials(const QString &elementPath,
// Create render object for the material
qt3ds::render::SGraphObject *newMaterial = nullptr;
CRegisteredString newMatId = strTable.RegisterStr(
- (QByteArrayLiteral("_newMaterial_") + QByteArray::number(++_idCounter))
+ (QByteArrayLiteral("__newMat_") + QByteArray::number(++_idCounter))
.constData());
if (isCustomMaterial) {
newMaterial = customMaterialSystem->CreateCustomMaterial(matClass, allocator);
@@ -1596,7 +1612,7 @@ void CQmlEngineImpl::createMaterials(const QString &elementPath,
qt3ds::render::SImage *newImageObj
= QT3DS_NEW(allocator, qt3ds::render::SImage)();
newImageObj->m_Id = strTable.RegisterStr(
- (QByteArrayLiteral("_newImage_")
+ (QByteArrayLiteral("__newImage_")
+ QByteArray::number(++_idCounter)).constData());
qt3ds::render::Qt3DSTranslator::CreateTranslatorForElement(
*imageElem, *newImageObj, allocator);
diff --git a/tests/auto/viewer/tst_qt3dsviewer.cpp b/tests/auto/viewer/tst_qt3dsviewer.cpp
index d261c2a9..e0653d7c 100644
--- a/tests/auto/viewer/tst_qt3dsviewer.cpp
+++ b/tests/auto/viewer/tst_qt3dsviewer.cpp
@@ -215,6 +215,7 @@ void tst_qt3dsviewer::testCreateElement()
Q3DSElement newCylinder(m_presentation, QStringLiteral("Scene.Layer.New Cylinder"));
Q3DSElement newCylinder2(m_presentation,
QStringLiteral("Scene.Layer.New Cylinder.New Cylinder 2"));
+ Q3DSElement newGroup(m_presentation, QStringLiteral("Scene.Layer.New Group"));
Q3DSElement newSphere(m_presentation, QStringLiteral("Scene.Layer.Cube2.New Sphere"));
QTimer animationTimer;
@@ -227,6 +228,7 @@ void tst_qt3dsviewer::testCreateElement()
newCylinder.setAttribute(QStringLiteral("rotation.x"), animValue * 4);
newCylinder2.setAttribute(QStringLiteral("position.y"), animValue * 3);
newSphere.setAttribute(QStringLiteral("position.x"), 50 + animValue * 2);
+ newGroup.setAttribute(QStringLiteral("opacity"), qAbs(animValue));
});
// Create objects to slides 1 & 2 while slide 1 is executing
@@ -265,6 +267,44 @@ void tst_qt3dsviewer::testCreateElement()
createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide2"), data);
+ data.clear();
+ data.insert(QStringLiteral("name"), QStringLiteral("New Group"));
+ data.insert(QStringLiteral("type"), QStringLiteral("group"));
+ data.insert(QStringLiteral("starttime"), 0);
+ data.insert(QStringLiteral("endtime"), 10000);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(50, -100, 0)));
+
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+
+ QVector<QHash<QString, QVariant>> groupElemProps;
+ data.clear();
+ data.insert(QStringLiteral("name"), QStringLiteral("Child 1 of Group"));
+ data.insert(QStringLiteral("type"), QStringLiteral("model"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cylinder"));
+ data.insert(QStringLiteral("material"), QStringLiteral("Basic Green"));
+ data.insert(QStringLiteral("starttime"), 1000);
+ data.insert(QStringLiteral("endtime"), 4000);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(0, 0, 0)));
+ groupElemProps << data;
+ data.clear();
+ data.insert(QStringLiteral("name"), QStringLiteral("Child 2 of Group"));
+ data.insert(QStringLiteral("type"), QStringLiteral("model"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cylinder"));
+ data.insert(QStringLiteral("material"), QStringLiteral("Basic Green"));
+ data.insert(QStringLiteral("starttime"), 2000);
+ data.insert(QStringLiteral("endtime"), 4000);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(100, 0, 0)));
+ groupElemProps << data;
+
+ m_createdElements << QStringLiteral("Scene.Layer.New Group.Child 1 of Group")
+ << QStringLiteral("Scene.Layer.New Group.Child 2 of Group");
+
+ m_presentation->createElements(QStringLiteral("Scene.Layer.New Group"),
+ QStringLiteral("Slide1"), groupElemProps);
+
animationTimer.start();
});
@@ -330,7 +370,7 @@ void tst_qt3dsviewer::testCreateElement()
QVERIFY(spyExited.wait(20000));
QTest::qWait(500);
- QCOMPARE(spyElemCreated.count(), 7);
+ QCOMPARE(spyElemCreated.count(), 9);
deleteCreatedElements();
// Switch to slide 1
diff --git a/tests/scenes/simple_cube_animation/presentations/simple_cube_animation.uip b/tests/scenes/simple_cube_animation/presentations/simple_cube_animation.uip
index bfedf1e1..e0de7206 100644
--- a/tests/scenes/simple_cube_animation/presentations/simple_cube_animation.uip
+++ b/tests/scenes/simple_cube_animation/presentations/simple_cube_animation.uip
@@ -49,8 +49,11 @@
<Add ref="#Basic Green" name="Basic Green" endtime="5000" referencedmaterial="#materials/Basic Green" sourcepath="../materials/Basic Green.materialdef" />
</State>
<State id="Scene-Slide2" name="Slide2" playmode="Play Through To..." playthroughto="Previous" >
- <Add ref="#Cube2" name="Cube2" position="-401.836 -18.4752 600" scale="3 3 3" sourcepath="#Cube" />
- <Add ref="#Basic Red" name="Basic Red" referencedmaterial="#materials/Basic Red" sourcepath="../materials/Basic Red.materialdef" />
+ <Set ref="#Layer" endtime="5000" />
+ <Set ref="#Camera" endtime="5000" />
+ <Set ref="#Light" endtime="5000" />
+ <Add ref="#Cube2" name="Cube2" endtime="5000" position="-401.836 -18.4752 600" scale="3 3 3" sourcepath="#Cube" />
+ <Add ref="#Basic Red" name="Basic Red" endtime="5000" referencedmaterial="#materials/Basic Red" sourcepath="../materials/Basic Red.materialdef" />
</State>
</State>
</Logic>