From 00b40db9326f0b951b423a97b7302d87280f029b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pasi=20Kera=CC=88nen?= Date: Thu, 21 Mar 2019 14:49:23 +0200 Subject: Add variant support to OpenGL runtime Task-number: QT3DS-3193 Change-Id: I5606d452104659e60ecbc2e8e08ec3e6f5b15cbc Reviewed-by: Mahmoud Badri Reviewed-by: Miikka Heikkinen --- .../Qt3DSRuntimeStatic/Qt3DSRuntimeStatic.pro | 2 + .../Source/Engine/Include/Qt3DSTegraApplication.h | 4 +- .../Engine/Source/Qt3DSRenderRuntimeBinding.cpp | 6 +- .../Source/Engine/Source/Qt3DSTegraApplication.cpp | 10 +- .../Include/Qt3DSRenderUIPLoader.h | 7 + .../Source/Qt3DSRenderUIPLoader.cpp | 495 +++++++++++---------- .../Source/Runtime/Include/Qt3DSApplication.h | 3 +- .../Source/Runtime/Include/Qt3DSSceneManager.h | 6 +- .../Source/Runtime/Include/q3dsvariantconfig_p.h | 79 ++++ .../Source/Runtime/Source/Qt3DSApplication.cpp | 25 +- .../Source/Runtime/Source/q3dsvariantconfig.cpp | 122 +++++ src/Runtime/Source/Viewer/Qt3DSViewerApp.cpp | 3 +- src/Runtime/Source/Viewer/Qt3DSViewerApp.h | 1 + src/Runtime/qt3d-runtime | 2 +- src/Viewer/Qt3DViewer/main.cpp | 17 + src/Viewer/Qt3DViewer/viewer.cpp | 17 +- src/Viewer/Qt3DViewer/viewer.h | 5 + src/Viewer/qmlviewer/Qt3DSRenderer.cpp | 13 +- src/Viewer/qmlviewer/Qt3DSView.cpp | 2 + src/Viewer/studio3d/q3dscommandqueue.cpp | 5 + src/Viewer/studio3d/q3dscommandqueue_p.h | 2 + src/Viewer/studio3d/q3dspresentation.cpp | 26 +- src/Viewer/studio3d/q3dspresentation.h | 4 + src/Viewer/studio3d/q3dspresentation_p.h | 2 + src/Viewer/studio3d/q3dssurfaceviewer.cpp | 1 + src/Viewer/studio3d/q3dswidget.cpp | 2 + 26 files changed, 600 insertions(+), 261 deletions(-) create mode 100644 src/Runtime/Source/Runtime/Include/q3dsvariantconfig_p.h create mode 100644 src/Runtime/Source/Runtime/Source/q3dsvariantconfig.cpp diff --git a/src/Runtime/Qt3DSRuntimeStatic/Qt3DSRuntimeStatic.pro b/src/Runtime/Qt3DSRuntimeStatic/Qt3DSRuntimeStatic.pro index e004a44d..c1986ce0 100644 --- a/src/Runtime/Qt3DSRuntimeStatic/Qt3DSRuntimeStatic.pro +++ b/src/Runtime/Qt3DSRuntimeStatic/Qt3DSRuntimeStatic.pro @@ -56,6 +56,7 @@ SOURCES += \ ../Source/Runtime/Source/Qt3DSQmlEngine.cpp \ ../Source/Runtime/Source/Qt3DSSlideSystem.cpp \ ../Source/Runtime/Source/Qt3DSTimePolicy.cpp \ + ../Source/Runtime/Source/q3dsvariantconfig.cpp \ ../Source/Qt3DSRuntimeRender/GraphObjects/Qt3DSRenderCamera.cpp \ ../Source/Qt3DSRuntimeRender/GraphObjects/Qt3DSRenderDefaultMaterial.cpp \ ../Source/Qt3DSRuntimeRender/GraphObjects/Qt3DSRenderDynamicObject.cpp \ @@ -263,6 +264,7 @@ HEADERS += \ ../Source/Runtime/Include/Qt3DSIStateful.h \ ../Source/Runtime/Include/Qt3DSIText.h \ ../Source/Runtime/Include/Qt3DSKernelTypes.h \ + ../Source/Runtime/Include/q3dsvariantconfig_p.h \ ../Source/Qt3DSRuntimeRender/GraphObjects/Qt3DSRenderCamera.h \ ../Source/Qt3DSRuntimeRender/GraphObjects/Qt3DSRenderCustomMaterial.h \ ../Source/Qt3DSRuntimeRender/GraphObjects/Qt3DSRenderDefaultMaterial.h \ diff --git a/src/Runtime/Source/Engine/Include/Qt3DSTegraApplication.h b/src/Runtime/Source/Engine/Include/Qt3DSTegraApplication.h index 0d4c8d0a..91233355 100644 --- a/src/Runtime/Source/Engine/Include/Qt3DSTegraApplication.h +++ b/src/Runtime/Source/Engine/Include/Qt3DSTegraApplication.h @@ -153,7 +153,7 @@ public: virtual ~INDDView(){} public: // loading - virtual bool BeginLoad(const QString &sourcePath) = 0; + virtual bool BeginLoad(const QString &sourcePath, const QStringList &variantList) = 0; virtual bool HasOfflineLoadingCompleted() = 0; virtual bool InitializeGraphics(const QSurfaceFormat &format) = 0; @@ -222,7 +222,7 @@ public: IAudioPlayer *inAudioPlayer = 0); virtual ~CTegraApplication(); // loading - bool BeginLoad(const QString &sourcePath); + bool BeginLoad(const QString &sourcePath, const QStringList &variantList); // asynchronous BeginLoad completed? That only valid for binary presentation, for text // presentation, always true bool HasOfflineLoadingCompleted() { return m_NDDView->HasOfflineLoadingCompleted(); } diff --git a/src/Runtime/Source/Engine/Source/Qt3DSRenderRuntimeBinding.cpp b/src/Runtime/Source/Engine/Source/Qt3DSRenderRuntimeBinding.cpp index b70bd48e..8fa75792 100644 --- a/src/Runtime/Source/Engine/Source/Qt3DSRenderRuntimeBinding.cpp +++ b/src/Runtime/Source/Engine/Source/Qt3DSRenderRuntimeBinding.cpp @@ -958,7 +958,8 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager, Q3DStudio::IScene *LoadScene(Q3DStudio::IPresentation *inPresentation, Q3DStudio::IUIPParser *inParser, - Q3DStudio::IScriptBridge &inBridge) override + Q3DStudio::IScriptBridge &inBridge, + const qt3ds::Q3DSVariantConfig &variantConfig) override { // We have to initialize the tags late so that we can load flow data before adding anything // to the string table. @@ -985,7 +986,8 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager, m_Context->m_Context->GetRenderPluginManager(), m_Context->m_Context->GetCustomMaterialSystem(), m_Context->m_Context->GetDynamicObjectSystem(), - m_Context->m_Context->GetPathManager(), &theResolver, false); + m_Context->m_Context->GetPathManager(), &theResolver, + variantConfig, false); if (!theScene->m_Presentation) { QT3DS_ASSERT(false); return NULL; diff --git a/src/Runtime/Source/Engine/Source/Qt3DSTegraApplication.cpp b/src/Runtime/Source/Engine/Source/Qt3DSTegraApplication.cpp index a2dcca91..92c7f6cc 100644 --- a/src/Runtime/Source/Engine/Source/Qt3DSTegraApplication.cpp +++ b/src/Runtime/Source/Engine/Source/Qt3DSTegraApplication.cpp @@ -170,7 +170,7 @@ public: QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(qt3ds::render::g_BaseAllocator); - bool BeginLoad(const QString &sourcePath) override; + bool BeginLoad(const QString &sourcePath, const QStringList &variantList) override; bool HasOfflineLoadingCompleted() override; bool InitializeGraphics(const QSurfaceFormat &format) override; @@ -233,7 +233,7 @@ CNDDView::~CNDDView() { } -bool CNDDView::BeginLoad(const QString &sourcePath) +bool CNDDView::BeginLoad(const QString &sourcePath, const QStringList &variantList) { bool theResult = false; @@ -241,7 +241,7 @@ bool CNDDView::BeginLoad(const QString &sourcePath) BootupPreGraphicsInitObjects(); // If there was a presentation file then we have to load it or something failed. - if (m_ApplicationCore->BeginLoad(sourcePath.toUtf8())) + if (m_ApplicationCore->BeginLoad(sourcePath.toUtf8(), variantList)) theResult = true; else theResult = false; @@ -692,7 +692,7 @@ CTegraApplication::~CTegraApplication() { } -bool CTegraApplication::BeginLoad(const QString &sourcePath) +bool CTegraApplication::BeginLoad(const QString &sourcePath, const QStringList &variantList) { #ifndef QT3DS_NO_SEARCH_PATH // We need these later on in case we try to load any files @@ -708,7 +708,7 @@ bool CTegraApplication::BeginLoad(const QString &sourcePath) if (!sourcePath.isEmpty()) { // If there was a presentation file then we have to load it or something failed. - if (m_NDDView->BeginLoad(sourcePath)) { + if (m_NDDView->BeginLoad(sourcePath, variantList)) { qCInfo(TRACE_INFO) << "CTegraApplication::BeginLoad: Successfully begin loading presentation: " << sourcePath; diff --git a/src/Runtime/Source/Qt3DSRuntimeRender/Include/Qt3DSRenderUIPLoader.h b/src/Runtime/Source/Qt3DSRuntimeRender/Include/Qt3DSRenderUIPLoader.h index 22f6ea2c..2b70c687 100644 --- a/src/Runtime/Source/Qt3DSRuntimeRender/Include/Qt3DSRenderUIPLoader.h +++ b/src/Runtime/Source/Qt3DSRuntimeRender/Include/Qt3DSRenderUIPLoader.h @@ -38,6 +38,7 @@ #include #include "foundation/Qt3DSContainers.h" #include "Qt3DSRenderGraphObject.h" +#include namespace Q3DStudio { class IRuntimeMetaData; @@ -50,6 +51,8 @@ struct SMetaDataCustomMaterial; } namespace qt3ds { +class Q3DSVariantConfig; + namespace render { class IBufferManager; @@ -102,6 +105,10 @@ namespace render { // its normal mode of operation so we try to reuse that code. , IUIPReferenceResolver *inResolver + // Variant config defines variant groups and tags to be used to filter out + // unneeded parts of the presentation + , + const Q3DSVariantConfig &variantConfig // Set some initial values by going to the master slide then slide 1 // Useful for quick testing, sort of equivalent to showing the first frame // of a given presentation diff --git a/src/Runtime/Source/Qt3DSRuntimeRender/Source/Qt3DSRenderUIPLoader.cpp b/src/Runtime/Source/Qt3DSRuntimeRender/Source/Qt3DSRenderUIPLoader.cpp index 63341c9e..f64efbcc 100644 --- a/src/Runtime/Source/Qt3DSRuntimeRender/Source/Qt3DSRenderUIPLoader.cpp +++ b/src/Runtime/Source/Qt3DSRuntimeRender/Source/Qt3DSRenderUIPLoader.cpp @@ -76,6 +76,7 @@ #include "Qt3DSRenderPath.h" #include "Qt3DSRenderPathSubPath.h" #include "Qt3DSRenderPathManager.h" +#include "q3dsvariantconfig_p.h" using qt3ds::foundation::Option; using qt3ds::foundation::Empty; @@ -471,6 +472,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver MemoryBuffer m_TempBuffer; MemoryBuffer m_ValueBuffer; TIdPathAnchorIndexMap m_AnchorIdToPathAndAnchorIndexMap; + const Q3DSVariantConfig &m_variantConfig; SRenderUIPLoader(qt3dsdm::IDOMReader &inReader, const char8_t *inFullPathToPresentationFile, Q3DStudio::IRuntimeMetaData &inMetaData, IStringTable &inStrTable @@ -487,7 +489,8 @@ struct SRenderUIPLoader : public IDOMReferenceResolver qt3ds::render::IRenderPluginManager &inRPM, qt3ds::render::ICustomMaterialSystem &inCMS, qt3ds::render::IDynamicObjectSystem &inDynamicSystem, - qt3ds::render::IPathManager &inPathManager, IUIPReferenceResolver *inResolver) + qt3ds::render::IPathManager &inPathManager, IUIPReferenceResolver *inResolver, + const Q3DSVariantConfig &variantConfig) : m_Reader(inReader) , m_MetaData(inMetaData) , m_StrTable(inStrTable) @@ -504,6 +507,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver , m_DynamicObjectSystem(inDynamicSystem) , m_PathManager(inPathManager) , m_ReferenceResolver(inResolver) + , m_variantConfig(variantConfig) { std::string presentationFile = inFullPathToPresentationFile; std::string::size_type pos = presentationFile.find_last_of("\\/"); @@ -668,6 +672,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver #define Node_LocalOpacity "opacity" #define Node_RotationOrder "rotationorder" #define Node_LeftHanded "orientation" +#define Layer_Variants "variants" #define Layer_TemporalAAEnabled "temporalaa" #define Layer_LayerEnableDepthTest "disabledepthtest" #define Layer_LayerEnableDepthPrePass "disabledepthprepass" @@ -1175,103 +1180,111 @@ struct SRenderUIPLoader : public IDOMReferenceResolver qt3dsdm::ComposerObjectTypes::Convert(m_Reader.GetElementName()); SGraphObject *theNewObject(NULL); const char8_t *theId; + const char8_t *theVariants; m_Reader.Att("id", theId); - - switch (theObjType) { - case qt3dsdm::ComposerObjectTypes::Scene: { - SScene *theScene = QT3DS_NEW(m_PresentationAllocator, SScene)(); - theNewObject = theScene; - m_Presentation->m_Scene = theScene; - theScene->m_Presentation = m_Presentation; - } break; - case qt3dsdm::ComposerObjectTypes::Layer: - theNewObject = QT3DS_NEW(m_PresentationAllocator, SLayer)(); - break; - case qt3dsdm::ComposerObjectTypes::Group: - theNewObject = QT3DS_NEW(m_PresentationAllocator, SNode)(); - break; - case qt3dsdm::ComposerObjectTypes::Component: - theNewObject = QT3DS_NEW(m_PresentationAllocator, SNode)(); - break; - case qt3dsdm::ComposerObjectTypes::Camera: - theNewObject = QT3DS_NEW(m_PresentationAllocator, SCamera)(); - break; - case qt3dsdm::ComposerObjectTypes::Light: - theNewObject = QT3DS_NEW(m_PresentationAllocator, SLight)(); - break; - case qt3dsdm::ComposerObjectTypes::Model: - theNewObject = QT3DS_NEW(m_PresentationAllocator, SModel)(); - break; - case qt3dsdm::ComposerObjectTypes::Material: - theNewObject = QT3DS_NEW(m_PresentationAllocator, SDefaultMaterial)(); - break; - case qt3dsdm::ComposerObjectTypes::ReferencedMaterial: - theNewObject = QT3DS_NEW(m_PresentationAllocator, SReferencedMaterial)(); - break; - case qt3dsdm::ComposerObjectTypes::Image: - theNewObject = QT3DS_NEW(m_PresentationAllocator, SImage)(); - break; - case qt3dsdm::ComposerObjectTypes::Text: - theNewObject = QT3DS_NEW(m_PresentationAllocator, SText)(); - break; - case qt3dsdm::ComposerObjectTypes::Path: - theNewObject = QT3DS_NEW(m_PresentationAllocator, SPath)(); - break; - case qt3dsdm::ComposerObjectTypes::SubPath: { - SPathSubPath *thePath = QT3DS_NEW(m_PresentationAllocator, SPathSubPath)(); - theNewObject = thePath; - QT3DSU32 anchorCount = 0; - TScope _childScope(m_Reader); - for (bool success = m_Reader.MoveToFirstChild("PathAnchorPoint"); success; - success = m_Reader.MoveToNextSibling("PathAnchorPoint")) { - const char8_t *theId; - m_Reader.Att("id", theId); - CRegisteredString theIdStr = m_StrTable.RegisterStr(theId); - m_AnchorIdToPathAndAnchorIndexMap.insert( - eastl::make_pair(theIdStr, SPathAndAnchorIndex(thePath, anchorCount))); - ++anchorCount; - } - m_PathManager.ResizePathSubPathBuffer(*thePath, anchorCount); - } break; - case qt3dsdm::ComposerObjectTypes::Effect: { - const char8_t *effectClassId; - m_Reader.Att("class", effectClassId); - CRegisteredString theStr = m_StrTable.RegisterStr(effectClassId + 1); - if (m_EffectSystem.IsEffectRegistered(theStr)) - theNewObject = m_EffectSystem.CreateEffectInstance(theStr, m_PresentationAllocator); - } break; - case qt3dsdm::ComposerObjectTypes::RenderPlugin: { - const char8_t *classId; - m_Reader.Att("class", classId); - if (!qt3ds::foundation::isTrivial(classId)) { - ++classId; - TIdStringMap::iterator iter = - m_RenderPluginSourcePaths.find(m_StrTable.RegisterStr(classId)); - if (iter != m_RenderPluginSourcePaths.end()) { - CRegisteredString thePluginPath = m_StrTable.RegisterStr(iter->second.c_str()); - qt3ds::render::IRenderPluginClass *theClass = - m_RenderPluginManager.GetRenderPlugin(thePluginPath); - if (theClass) { - qt3ds::render::SRenderPlugin *thePlugin = - QT3DS_NEW(m_PresentationAllocator, qt3ds::render::SRenderPlugin)(); - thePlugin->m_PluginPath = thePluginPath; - thePlugin->m_Flags.SetActive(true); - theNewObject = thePlugin; + m_Reader.Att("variants", theVariants); + + QString theString(theVariants); + QStringRef theStringRef(&theString); + bool isPartOfConfig = m_variantConfig.isPartOfConfig(theStringRef); + if (isPartOfConfig) { + switch (theObjType) { + case qt3dsdm::ComposerObjectTypes::Scene: { + SScene *theScene = QT3DS_NEW(m_PresentationAllocator, SScene)(); + theNewObject = theScene; + m_Presentation->m_Scene = theScene; + theScene->m_Presentation = m_Presentation; + } break; + case qt3dsdm::ComposerObjectTypes::Layer: + theNewObject = QT3DS_NEW(m_PresentationAllocator, SLayer)(); + break; + case qt3dsdm::ComposerObjectTypes::Group: + theNewObject = QT3DS_NEW(m_PresentationAllocator, SNode)(); + break; + case qt3dsdm::ComposerObjectTypes::Component: + theNewObject = QT3DS_NEW(m_PresentationAllocator, SNode)(); + break; + case qt3dsdm::ComposerObjectTypes::Camera: + theNewObject = QT3DS_NEW(m_PresentationAllocator, SCamera)(); + break; + case qt3dsdm::ComposerObjectTypes::Light: + theNewObject = QT3DS_NEW(m_PresentationAllocator, SLight)(); + break; + case qt3dsdm::ComposerObjectTypes::Model: + theNewObject = QT3DS_NEW(m_PresentationAllocator, SModel)(); + break; + case qt3dsdm::ComposerObjectTypes::Material: + theNewObject = QT3DS_NEW(m_PresentationAllocator, SDefaultMaterial)(); + break; + case qt3dsdm::ComposerObjectTypes::ReferencedMaterial: + theNewObject = QT3DS_NEW(m_PresentationAllocator, SReferencedMaterial)(); + break; + case qt3dsdm::ComposerObjectTypes::Image: + theNewObject = QT3DS_NEW(m_PresentationAllocator, SImage)(); + break; + case qt3dsdm::ComposerObjectTypes::Text: + theNewObject = QT3DS_NEW(m_PresentationAllocator, SText)(); + break; + case qt3dsdm::ComposerObjectTypes::Path: + theNewObject = QT3DS_NEW(m_PresentationAllocator, SPath)(); + break; + case qt3dsdm::ComposerObjectTypes::SubPath: { + SPathSubPath *thePath = QT3DS_NEW(m_PresentationAllocator, SPathSubPath)(); + theNewObject = thePath; + QT3DSU32 anchorCount = 0; + TScope _childScope(m_Reader); + for (bool success = m_Reader.MoveToFirstChild("PathAnchorPoint"); success; + success = m_Reader.MoveToNextSibling("PathAnchorPoint")) { + const char8_t *theId; + m_Reader.Att("id", theId); + CRegisteredString theIdStr = m_StrTable.RegisterStr(theId); + m_AnchorIdToPathAndAnchorIndexMap.insert( + eastl::make_pair(theIdStr, SPathAndAnchorIndex(thePath, anchorCount))); + ++anchorCount; + } + m_PathManager.ResizePathSubPathBuffer(*thePath, anchorCount); + } break; + case qt3dsdm::ComposerObjectTypes::Effect: { + const char8_t *effectClassId; + m_Reader.Att("class", effectClassId); + CRegisteredString theStr = m_StrTable.RegisterStr(effectClassId + 1); + if (m_EffectSystem.IsEffectRegistered(theStr)) + theNewObject = m_EffectSystem.CreateEffectInstance(theStr, m_PresentationAllocator); + } break; + case qt3dsdm::ComposerObjectTypes::RenderPlugin: { + const char8_t *classId; + m_Reader.Att("class", classId); + if (!qt3ds::foundation::isTrivial(classId)) { + ++classId; + TIdStringMap::iterator iter = + m_RenderPluginSourcePaths.find(m_StrTable.RegisterStr(classId)); + if (iter != m_RenderPluginSourcePaths.end()) { + CRegisteredString thePluginPath = m_StrTable.RegisterStr(iter->second.c_str()); + qt3ds::render::IRenderPluginClass *theClass = + m_RenderPluginManager.GetRenderPlugin(thePluginPath); + if (theClass) { + qt3ds::render::SRenderPlugin *thePlugin = + QT3DS_NEW(m_PresentationAllocator, qt3ds::render::SRenderPlugin)(); + thePlugin->m_PluginPath = thePluginPath; + thePlugin->m_Flags.SetActive(true); + theNewObject = thePlugin; + } } } + } break; + case qt3dsdm::ComposerObjectTypes::CustomMaterial: { + const char8_t *materialClassId; + m_Reader.Att("class", materialClassId); + CRegisteredString theStr = m_StrTable.RegisterStr(materialClassId + 1); + if (m_CustomMaterialSystem.IsMaterialRegistered(theStr)) { + theNewObject = + m_CustomMaterialSystem.CreateCustomMaterial(theStr, m_PresentationAllocator); + } + } break; + default: + // Ignoring unknown objects entirely at this point + break; } - } break; - case qt3dsdm::ComposerObjectTypes::CustomMaterial: { - const char8_t *materialClassId; - m_Reader.Att("class", materialClassId); - CRegisteredString theStr = m_StrTable.RegisterStr(materialClassId + 1); - if (m_CustomMaterialSystem.IsMaterialRegistered(theStr)) - theNewObject = - m_CustomMaterialSystem.CreateCustomMaterial(theStr, m_PresentationAllocator); - } break; - default: - // Ignoring unknown objects entirely at this point - break; } if (theNewObject) { CRegisteredString theObjectId(m_StrTable.RegisterStr(theId)); @@ -1385,9 +1398,15 @@ struct SRenderUIPLoader : public IDOMReferenceResolver valid = m_Reader.MoveToNextSibling()) ParseGraphPass1(theNewObject); } else { - for (bool valid = m_Reader.MoveToFirstChild(); valid; - valid = m_Reader.MoveToNextSibling()) - ParseGraphPass1(NULL); + if (isPartOfConfig) { + // Object was of unknown type -> parse children with NULL parent + for (bool valid = m_Reader.MoveToFirstChild(); valid; + valid = m_Reader.MoveToNextSibling()) { + ParseGraphPass1(NULL); + } + } + // If object wasn't part of variant config -> skip children. + // Continue parsing from next sibling with same parent. } } @@ -1411,64 +1430,76 @@ struct SRenderUIPLoader : public IDOMReferenceResolver const char8_t *theId; m_Reader.Att("id", theId); const char8_t *theClass = ""; + const char8_t *theVariants = ""; m_Reader.Att("class", theClass); - TIdObjectMap::iterator theObject = m_ObjectMap.find(m_StrTable.RegisterStr(theId)); - if (theObject != m_ObjectMap.end()) { - switch (theObject->second->m_Type) { - case GraphObjectTypes::Scene: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - case GraphObjectTypes::Node: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - case GraphObjectTypes::Layer: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - case GraphObjectTypes::Camera: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - case GraphObjectTypes::Light: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - case GraphObjectTypes::Model: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - case GraphObjectTypes::DefaultMaterial: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - case GraphObjectTypes::ReferencedMaterial: - ParsePass2Properties(*static_cast(theObject->second), - theClass); - break; - case GraphObjectTypes::Image: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - case GraphObjectTypes::Text: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - case GraphObjectTypes::Effect: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - case GraphObjectTypes::RenderPlugin: - ParsePass2Properties(*static_cast(theObject->second), - theClass); - break; - case GraphObjectTypes::CustomMaterial: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - case GraphObjectTypes::Path: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - case GraphObjectTypes::PathSubPath: - ParsePass2Properties(*static_cast(theObject->second), theClass); - break; - default: - QT3DS_ASSERT(false); - break; + m_Reader.Att("variants", theVariants); + + QString theString(theVariants); + QStringRef theStringRef(&theString); + bool isPartOfConfig = m_variantConfig.isPartOfConfig(theStringRef); + if (isPartOfConfig) { + TIdObjectMap::iterator theObject = m_ObjectMap.find(m_StrTable.RegisterStr(theId)); + if (theObject != m_ObjectMap.end()) { + switch (theObject->second->m_Type) { + case GraphObjectTypes::Scene: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + case GraphObjectTypes::Node: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + case GraphObjectTypes::Layer: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + case GraphObjectTypes::Camera: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + case GraphObjectTypes::Light: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + case GraphObjectTypes::Model: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + case GraphObjectTypes::DefaultMaterial: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + case GraphObjectTypes::ReferencedMaterial: + ParsePass2Properties(*static_cast(theObject->second), + theClass); + break; + case GraphObjectTypes::Image: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + case GraphObjectTypes::Text: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + case GraphObjectTypes::Effect: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + case GraphObjectTypes::RenderPlugin: + ParsePass2Properties(*static_cast(theObject->second), + theClass); + break; + case GraphObjectTypes::CustomMaterial: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + case GraphObjectTypes::Path: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + case GraphObjectTypes::PathSubPath: + ParsePass2Properties(*static_cast(theObject->second), theClass); + break; + default: + QT3DS_ASSERT(false); + break; + } } } - for (bool valid = m_Reader.MoveToFirstChild(); valid; valid = m_Reader.MoveToNextSibling()) - ParseGraphPass2(); + + // If not part of variant config -> ignore children + if (isPartOfConfig) { + for (bool valid = m_Reader.MoveToFirstChild(); valid; valid = m_Reader.MoveToNextSibling()) + ParseGraphPass2(); + } } static bool ParseVec2(SDomReaderPropertyParser &inParser, const char *inName, QT3DSVec2 &outValue) @@ -1499,83 +1530,85 @@ struct SRenderUIPLoader : public IDOMReferenceResolver const char8_t *theId; m_Reader.Att("ref", theId); CRegisteredString theIdStr(m_StrTable.RegisterStr(theId + 1)); - TIdObjectMap::iterator theObject = m_ObjectMap.find(theIdStr); - if (theObject != m_ObjectMap.end()) { - SDomReaderPropertyParser parser(m_Reader, m_TempBuf, *this, *theObject->second); - switch (theObject->second->m_Type) { - case GraphObjectTypes::Scene: - ParseProperties(*reinterpret_cast(theObject->second), parser); - break; - case GraphObjectTypes::Node: - ParseProperties(*reinterpret_cast(theObject->second), parser); - break; - case GraphObjectTypes::Layer: - ParseProperties(*reinterpret_cast(theObject->second), parser); - break; - case GraphObjectTypes::Camera: - ParseProperties(*reinterpret_cast(theObject->second), parser); - break; - case GraphObjectTypes::Light: - ParseProperties(*reinterpret_cast(theObject->second), parser); - break; - case GraphObjectTypes::Model: - ParseProperties(*reinterpret_cast(theObject->second), parser); - break; - case GraphObjectTypes::DefaultMaterial: - ParseProperties(*reinterpret_cast(theObject->second), - parser); - break; - case GraphObjectTypes::ReferencedMaterial: - ParseProperties(*static_cast(theObject->second), - parser); - break; - case GraphObjectTypes::Image: - ParseProperties(*reinterpret_cast(theObject->second), parser); - break; - case GraphObjectTypes::Text: - ParseProperties(*static_cast(theObject->second), parser); - break; - case GraphObjectTypes::Effect: - ParseProperties(*static_cast(theObject->second), parser); - break; - case GraphObjectTypes::RenderPlugin: - ParseProperties( - *static_cast(theObject->second), parser); - break; - case GraphObjectTypes::CustomMaterial: - ParseProperties( - *static_cast(theObject->second), - parser); - break; - case GraphObjectTypes::Path: - ParseProperties(*static_cast(theObject->second), - parser); - break; - case GraphObjectTypes::PathSubPath: - ParseProperties( - *static_cast(theObject->second), parser); - break; - default: - QT3DS_ASSERT(false); - break; - } - } else { - TIdPathAnchorIndexMap::iterator iter = - m_AnchorIdToPathAndAnchorIndexMap.find(theIdStr); - if (iter != m_AnchorIdToPathAndAnchorIndexMap.end()) { - SDomReaderPropertyParser parser(m_Reader, m_TempBuf, *this, - *iter->second.m_Segment); - NVDataRef thePathBuffer = - m_PathManager.GetPathSubPathBuffer(*iter->second.m_Segment); - QT3DSU32 anchorIndex = iter->second.m_AnchorIndex; - QT3DSU32 numAnchors = thePathBuffer.size(); - if (anchorIndex < numAnchors) { - qt3ds::render::SPathAnchorPoint &thePoint(thePathBuffer[anchorIndex]); - ParseVec2(parser, "position", thePoint.m_Position); - ParseFloat(parser, "incomingangle", thePoint.m_IncomingAngle); - thePoint.m_OutgoingAngle = thePoint.m_IncomingAngle + 180.0f; - ParseFloat(parser, "incomingdistance", thePoint.m_IncomingDistance); - ParseFloat(parser, "outgoingdistance", thePoint.m_OutgoingDistance); + if (m_ObjectMap.contains(theIdStr)) { + TIdObjectMap::iterator theObject = m_ObjectMap.find(theIdStr); + if (theObject != m_ObjectMap.end()) { + SDomReaderPropertyParser parser(m_Reader, m_TempBuf, *this, *theObject->second); + switch (theObject->second->m_Type) { + case GraphObjectTypes::Scene: + ParseProperties(*reinterpret_cast(theObject->second), parser); + break; + case GraphObjectTypes::Node: + ParseProperties(*reinterpret_cast(theObject->second), parser); + break; + case GraphObjectTypes::Layer: + ParseProperties(*reinterpret_cast(theObject->second), parser); + break; + case GraphObjectTypes::Camera: + ParseProperties(*reinterpret_cast(theObject->second), parser); + break; + case GraphObjectTypes::Light: + ParseProperties(*reinterpret_cast(theObject->second), parser); + break; + case GraphObjectTypes::Model: + ParseProperties(*reinterpret_cast(theObject->second), parser); + break; + case GraphObjectTypes::DefaultMaterial: + ParseProperties(*reinterpret_cast(theObject->second), + parser); + break; + case GraphObjectTypes::ReferencedMaterial: + ParseProperties(*static_cast(theObject->second), + parser); + break; + case GraphObjectTypes::Image: + ParseProperties(*reinterpret_cast(theObject->second), parser); + break; + case GraphObjectTypes::Text: + ParseProperties(*static_cast(theObject->second), parser); + break; + case GraphObjectTypes::Effect: + ParseProperties(*static_cast(theObject->second), parser); + break; + case GraphObjectTypes::RenderPlugin: + ParseProperties( + *static_cast(theObject->second), parser); + break; + case GraphObjectTypes::CustomMaterial: + ParseProperties( + *static_cast(theObject->second), + parser); + break; + case GraphObjectTypes::Path: + ParseProperties(*static_cast(theObject->second), + parser); + break; + case GraphObjectTypes::PathSubPath: + ParseProperties( + *static_cast(theObject->second), parser); + break; + default: + QT3DS_ASSERT(false); + break; + } + } else { + TIdPathAnchorIndexMap::iterator iter = + m_AnchorIdToPathAndAnchorIndexMap.find(theIdStr); + if (iter != m_AnchorIdToPathAndAnchorIndexMap.end()) { + SDomReaderPropertyParser parser(m_Reader, m_TempBuf, *this, + *iter->second.m_Segment); + NVDataRef thePathBuffer = + m_PathManager.GetPathSubPathBuffer(*iter->second.m_Segment); + QT3DSU32 anchorIndex = iter->second.m_AnchorIndex; + QT3DSU32 numAnchors = thePathBuffer.size(); + if (anchorIndex < numAnchors) { + qt3ds::render::SPathAnchorPoint &thePoint(thePathBuffer[anchorIndex]); + ParseVec2(parser, "position", thePoint.m_Position); + ParseFloat(parser, "incomingangle", thePoint.m_IncomingAngle); + thePoint.m_OutgoingAngle = thePoint.m_IncomingAngle + 180.0f; + ParseFloat(parser, "incomingdistance", thePoint.m_IncomingDistance); + ParseFloat(parser, "outgoingdistance", thePoint.m_OutgoingDistance); + } } } } @@ -1811,12 +1844,12 @@ SPresentation *qt3ds::render::IUIPLoader::LoadUIPFile( const char8_t *inPresentationDir, IRenderPluginManager &inPluginManager, ICustomMaterialSystem &inCMS, IDynamicObjectSystem &inDynamicSystem, qt3ds::render::IPathManager &inPathManager, IUIPReferenceResolver *inResolver, - bool inSetValuesFromSlides) + const Q3DSVariantConfig &variantConfig, bool inSetValuesFromSlides) { SRenderUIPLoader theLoader(inReader, inFullPathToPresentationFile, inMetaData, inStrTable, inFoundation, inPresentationAllocator, ioObjectMap, inBufferManager, inEffectSystem, inPresentationDir, inPluginManager, inCMS, - inDynamicSystem, inPathManager, inResolver); + inDynamicSystem, inPathManager, inResolver, variantConfig); return theLoader.Load(inSetValuesFromSlides); } using namespace qt3dsdm; diff --git a/src/Runtime/Source/Runtime/Include/Qt3DSApplication.h b/src/Runtime/Source/Runtime/Include/Qt3DSApplication.h index e078f4f3..d825fe0f 100644 --- a/src/Runtime/Source/Runtime/Include/Qt3DSApplication.h +++ b/src/Runtime/Source/Runtime/Include/Qt3DSApplication.h @@ -134,7 +134,8 @@ public: virtual void DisableStateMachine() = 0; // nonblocking call to begin loading, loads uia file alone and returns. - virtual bool BeginLoad(const char8_t *inFilePath) = 0; + virtual bool BeginLoad(const QString &sourcePath, const QStringList &variantList) = 0; + // blocking call to end all loading threads and such/wait till finished virtual void EndLoad() = 0; // Will EndLoad cause nontrivial blocking. diff --git a/src/Runtime/Source/Runtime/Include/Qt3DSSceneManager.h b/src/Runtime/Source/Runtime/Include/Qt3DSSceneManager.h index 079e67ed..7b8a4aab 100644 --- a/src/Runtime/Source/Runtime/Include/Qt3DSSceneManager.h +++ b/src/Runtime/Source/Runtime/Include/Qt3DSSceneManager.h @@ -48,6 +48,7 @@ namespace foundation { } namespace qt3ds { +class Q3DSVariantConfig; namespace render { class IQt3DSRenderContextCore; class ILoadedBuffer; @@ -109,7 +110,7 @@ struct FacePositionPlanes class ISceneManager : public qt3ds::foundation::NVRefCounted { protected: - virtual ~ISceneManager(){}; + virtual ~ISceneManager(){} public: // Presentations //============================================================================== @@ -121,7 +122,8 @@ public: // Presentations * @param inPresentation the current presentation loaded */ virtual IScene *LoadScene(IPresentation *inPresentation, IUIPParser *inParser, - IScriptBridge &inBridge) = 0; + IScriptBridge &inBridge, + const qt3ds::Q3DSVariantConfig &variantConfig) = 0; virtual void LoadRenderPlugin(const CHAR *inAssetIDString, const CHAR *inPath, const CHAR *inArgs) = 0; diff --git a/src/Runtime/Source/Runtime/Include/q3dsvariantconfig_p.h b/src/Runtime/Source/Runtime/Include/q3dsvariantconfig_p.h new file mode 100644 index 00000000..1905f44a --- /dev/null +++ b/src/Runtime/Source/Runtime/Include/q3dsvariantconfig_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef Q3DSVARIANTCONFIG_P_H +#define Q3DSVARIANTCONFIG_P_H + +#include +#include +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +namespace qt3ds { + +class Q3DSVariantConfig +{ +public: + Q3DSVariantConfig(); + ~Q3DSVariantConfig(); + + inline bool operator==(const Q3DSVariantConfig &other) const + { + return (this->m_variantList == other.m_variantList); + } + + inline bool operator!=(const Q3DSVariantConfig &other) const + { + return (this->m_variantList != other.m_variantList); + } + + inline bool isEmpty() const { return m_variantList.isEmpty(); } + + void setVariantList(const QStringList &variantList); + + bool isPartOfConfig(const QStringRef &variantAttributes) const; + + inline const QStringList &variantList() const { return m_variantList; } + +private: + QStringList m_variantList; + QList m_internalVariantList; + QHash> m_variantFilter; +}; + +}; +#endif // Q3DSVARIANTCONFIG_P_H diff --git a/src/Runtime/Source/Runtime/Source/Qt3DSApplication.cpp b/src/Runtime/Source/Runtime/Source/Qt3DSApplication.cpp index 25b1f4b0..249070c2 100644 --- a/src/Runtime/Source/Runtime/Source/Qt3DSApplication.cpp +++ b/src/Runtime/Source/Runtime/Source/Qt3DSApplication.cpp @@ -82,6 +82,7 @@ #include #include #include +#include "q3dsvariantconfig_p.h" using namespace qt3ds; using namespace qt3ds::runtime; @@ -444,6 +445,7 @@ struct SApp : public IApplication Q3DStudio::INT32 m_FrameCount; // the name of the file without extension. eastl::string m_Filename; + Q3DSVariantConfig m_variantConfig; qt3ds::foundation::NVScopedReleasable m_MetaData; nvvector> m_Behaviors; @@ -1069,7 +1071,8 @@ struct SApp : public IApplication // Load the scene graph portion of the scene. newScene = m_RuntimeFactory->GetSceneManager().LoadScene( thePresentation, theUIPParser.mPtr, - m_CoreFactory->GetScriptEngineQml()); + m_CoreFactory->GetScriptEngineQml(), + m_variantConfig); } if (newScene == NULL) { @@ -1288,13 +1291,13 @@ struct SApp : public IApplication } } - bool BeginLoad(const char8_t *inFilePath) override + virtual bool BeginLoad(const QString &sourcePath, const QStringList &variantList) override { SStackPerfTimer __loadTimer(m_CoreFactory->GetPerfTimer(), "Application: Begin Load"); eastl::string directory; eastl::string filename; eastl::string extension; - CFileTools::Split(inFilePath, directory, filename, extension); + CFileTools::Split(sourcePath.toUtf8().constData(), directory, filename, extension); eastl::string projectDirectory(directory); m_ProjectDir.assign(projectDirectory.c_str()); @@ -1319,6 +1322,7 @@ struct SApp : public IApplication m_CoreFactory->GetRenderContextCore().GetPerfTimer()); } m_Filename = filename; + m_variantConfig.setVariantList(variantList); bool retval = false; if (extension.comparei("uip") == 0) { #if !defined(_LINUXPLATFORM) && !defined(_INTEGRITYPLATFORM) @@ -1339,27 +1343,28 @@ struct SApp : public IApplication #if !defined(_LINUXPLATFORM) && !defined(_INTEGRITYPLATFORM) ConnectDebugger(); #endif - CFileSeekableIOStream inputStream(inFilePath, FileReadFlags()); + CFileSeekableIOStream inputStream(sourcePath, FileReadFlags()); if (inputStream.IsOpen()) { NVScopedRefCounted strTable( IStringTable::CreateStringTable(fnd.getAllocator())); NVScopedRefCounted domFactory( IDOMFactory::CreateDOMFactory(fnd.getAllocator(), strTable)); - SAppXMLErrorHandler errorHandler(fnd, inFilePath); + SAppXMLErrorHandler errorHandler(fnd, sourcePath.toUtf8().constData()); eastl::pair readResult = CDOMSerializer::Read(*domFactory, inputStream, &errorHandler); if (!readResult.second) { qCCritical(INVALID_PARAMETER, "%s doesn't appear to be valid xml", - inFilePath); + sourcePath.toUtf8().constData()); } else { NVScopedRefCounted domReader = IDOMReader::CreateDOMReader( fnd.getAllocator(), *readResult.second, strTable, domFactory); if (m_visitor) - m_visitor->visit(inFilePath); + m_visitor->visit(sourcePath.toUtf8().constData()); retval = LoadUIA(*domReader, fnd); } } else { - qCCritical(INVALID_PARAMETER, "Unable to open input file %s", inFilePath); + qCCritical(INVALID_PARAMETER, "Unable to open input file %s", + sourcePath.toUtf8().constData()); } } else { QT3DS_ASSERT(false); @@ -1717,8 +1722,8 @@ struct SXMLLoader : public IAppLoadContext if (!m_App.LoadUIP(thePresentationAsset, toConstDataRef(theUIPReferences.data(), (QT3DSU32)theUIPReferences.size()))) { - qCWarning(INVALID_OPERATION, "Unable to load presentation %s", - thePathStr.c_str()); + qCCritical(INVALID_OPERATION, "Unable to load presentation %s", + thePathStr.c_str()); } } break; case AssetValueTypes::Behavior: { diff --git a/src/Runtime/Source/Runtime/Source/q3dsvariantconfig.cpp b/src/Runtime/Source/Runtime/Source/q3dsvariantconfig.cpp new file mode 100644 index 00000000..e1fa04c6 --- /dev/null +++ b/src/Runtime/Source/Runtime/Source/q3dsvariantconfig.cpp @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "q3dsvariantconfig_p.h" + +namespace qt3ds { + +Q3DSVariantConfig::Q3DSVariantConfig() +{ + +} + +Q3DSVariantConfig::~Q3DSVariantConfig() +{ + for (auto str : qAsConst(m_internalVariantList)) + delete str; + m_internalVariantList.clear(); +} + +void Q3DSVariantConfig::setVariantList(const QStringList &variantList) +{ + // Store the QStringList to be returned from the API + m_variantList = variantList; + + for (auto str : qAsConst(m_internalVariantList)) + delete str; + m_internalVariantList.clear(); + + // Build a fixed (in mem location) list of the variant strings + for (auto tag : variantList) + m_internalVariantList.append(new QString(tag)); + + // Parse the variantGroup:variant list to map using the fixed list + m_variantFilter.clear(); + for (auto tag : qAsConst(m_internalVariantList)) { + QStringRef refTag = QStringRef(tag); + int separatorIdx = refTag.indexOf(QLatin1Char(':')); + QStringRef group = refTag.left(separatorIdx); + QStringRef variant = refTag.mid(separatorIdx + 1); + m_variantFilter[group].append(variant); + } +} + +bool Q3DSVariantConfig::isPartOfConfig(const QStringRef &variantAttributes) const +{ + // Variant filter is ignored when it's not defined + // or if the object has no variant attributes + if (m_variantFilter.isEmpty() || variantAttributes.isEmpty()) + return true; + + // Collect all variant tags per group from the element + QHash> groupToVariants; + const QVector variantTags = variantAttributes.split( + QLatin1Char(','), + QString::SkipEmptyParts); + + for (auto tag : variantTags) { + // Break each variantGroup:value to group and value strings + int groupSeparatorIdx = tag.indexOf(QLatin1Char(':')); + QStringRef group = tag.left(groupSeparatorIdx); + + // Only collect variant tags that are relevant to variant filtering + if (m_variantFilter.contains(group)) { + QStringRef variant = tag.mid(groupSeparatorIdx + 1); + groupToVariants[group].append(variant); + } + } + + // If no relevant variant tags found in element, load the element + if (groupToVariants.isEmpty()) + return true; + + // Verify that the element matches the variant filtering per group. + // To match the element must either: + // - Have no variant tag defined for the group + // - Have a matching tag for the group + bool isLoaded = true; + const auto filteredGroups = m_variantFilter.keys(); + for (auto group : filteredGroups) { + const QVector variants = groupToVariants[group]; + const QVector filteredVariants = m_variantFilter[group]; + + if (variants.size() > 0) { + // Check if ANY of the variant values of the element matches ANY + // of the included variants in the filter for this variant group + bool matchesFilter = false; + for (auto variant : variants) + matchesFilter |= filteredVariants.contains(variant); + + isLoaded &= matchesFilter; + } + } + + return isLoaded; +} + +} diff --git a/src/Runtime/Source/Viewer/Qt3DSViewerApp.cpp b/src/Runtime/Source/Viewer/Qt3DSViewerApp.cpp index 1eac8e56..d393f2af 100644 --- a/src/Runtime/Source/Viewer/Qt3DSViewerApp.cpp +++ b/src/Runtime/Source/Viewer/Qt3DSViewerApp.cpp @@ -302,6 +302,7 @@ void Q3DSViewerApp::setOffscreenId(int offscreenID) bool Q3DSViewerApp::InitializeApp(int winWidth, int winHeight, const QSurfaceFormat &format, int offscreenID, const QString &source, + const QStringList &variantList, qt3ds::Qt3DSAssetVisitor *assetVisitor) { bool hasValidPresentationFile = !source.isEmpty(); @@ -332,7 +333,7 @@ bool Q3DSViewerApp::InitializeApp(int winWidth, int winHeight, const QSurfaceFor if (assetVisitor) m_Impl.m_tegraApp->getNDDView()->setAssetVisitor(assetVisitor); - m_Impl.m_appInitSuccessful = m_Impl.m_tegraApp->BeginLoad(source) ? true : false; + m_Impl.m_appInitSuccessful = m_Impl.m_tegraApp->BeginLoad(source, variantList); // Simulate killing the application during loading. Useful for finding serious issues with // loading. diff --git a/src/Runtime/Source/Viewer/Qt3DSViewerApp.h b/src/Runtime/Source/Viewer/Qt3DSViewerApp.h index 0b7f9351..0d56c3a1 100644 --- a/src/Runtime/Source/Viewer/Qt3DSViewerApp.h +++ b/src/Runtime/Source/Viewer/Qt3DSViewerApp.h @@ -115,6 +115,7 @@ public: */ bool InitializeApp(int winWidth, int winHeight, const QSurfaceFormat& format, int offscreenID, const QString &source, + const QStringList &variantList, qt3ds::Qt3DSAssetVisitor *assetVisitor = nullptr); bool IsInitialised(void); diff --git a/src/Runtime/qt3d-runtime b/src/Runtime/qt3d-runtime index 5e0bfe93..228b1c7c 160000 --- a/src/Runtime/qt3d-runtime +++ b/src/Runtime/qt3d-runtime @@ -1 +1 @@ -Subproject commit 5e0bfe934b9930b7e41d457b4f88fce91342a0ea +Subproject commit 228b1c7ce76a134e4d2e67809ef8b86f371a15ef diff --git a/src/Viewer/Qt3DViewer/main.cpp b/src/Viewer/Qt3DViewer/main.cpp index 6b020a4f..12abd3b2 100644 --- a/src/Viewer/Qt3DViewer/main.cpp +++ b/src/Viewer/Qt3DViewer/main.cpp @@ -208,6 +208,14 @@ int main(int argc, char *argv[]) "The default value is 'center'."), QCoreApplication::translate("main", "center|fit|fill"), QStringLiteral("center")}); + QCommandLineOption variantListOption({QStringLiteral("v"), + QStringLiteral("variants")}, + QObject::tr("Gives list of variant groups and variants\n" + "to be loaded from the presentation.\n" + "For example VarGroupA:var1,VarGroupB:var4"), + QStringLiteral("variants")); + parser.addOption(variantListOption); + parser.process(a); const QStringList files = parser.positionalArguments(); @@ -222,6 +230,13 @@ int main(int argc, char *argv[]) || parser.isSet("seq-height") || parser.isSet("seq-outpath") || parser.isSet("seq-outfile"); + QStringList variantList; + if (parser.isSet(variantListOption)) { + QString variantOption = parser.value(variantListOption); + variantList = variantOption.split(QLatin1Char(','), + QString::SkipEmptyParts); + } + #ifndef Q_OS_ANDROID Q3DSImageSequenceGenerator *generator = nullptr; #endif @@ -320,6 +335,8 @@ int main(int argc, char *argv[]) appWindow->setProperty("scaleMode", Q3DSViewerSettings::ScaleModeCenter); } + viewer.setVariantList(variantList); + #ifndef Q_OS_ANDROID if (generateSequence) { if (files.count() != 1) { diff --git a/src/Viewer/Qt3DViewer/viewer.cpp b/src/Viewer/Qt3DViewer/viewer.cpp index 4d6bcea3..2a32cb76 100644 --- a/src/Viewer/Qt3DViewer/viewer.cpp +++ b/src/Viewer/Qt3DViewer/viewer.cpp @@ -95,6 +95,19 @@ void Viewer::disconnectRemote() m_remoteDeploymentReceiver->disconnectRemote(); } +void Viewer::setVariantList(const QStringList &variantList) +{ + if (m_variantList != variantList) { + m_variantList = variantList; + Q_EMIT variantListChanged(); + } +} + +QStringList Viewer::variantList() const +{ + return m_variantList; +} + // Used to load files via command line and when using remote deployment void Viewer::loadFile(const QString &filename) { @@ -122,8 +135,10 @@ void Viewer::loadFile(const QString &filename) setContentView(StudioView); - if (qmlStudio()) + if (qmlStudio()) { + qmlStudio()->presentation()->setVariantList(m_variantList); qmlStudio()->presentation()->setSource(sourceUrl); + } } QString Viewer::convertUrlListToFilename(const QList &list) diff --git a/src/Viewer/Qt3DViewer/viewer.h b/src/Viewer/Qt3DViewer/viewer.h index 9931483e..989481b9 100644 --- a/src/Viewer/Qt3DViewer/viewer.h +++ b/src/Viewer/Qt3DViewer/viewer.h @@ -47,6 +47,7 @@ class Viewer : public QObject Q_PROPERTY(int connectPort READ connectPort WRITE setConnectPort NOTIFY connectPortChanged) Q_PROPERTY(QString connectText READ connectText NOTIFY connectTextChanged) Q_PROPERTY(bool connected READ isConnected NOTIFY connectedChanged) + Q_PROPERTY(QStringList variantList READ variantList WRITE setVariantList NOTIFY variantListChanged) public: enum ContentView { @@ -72,6 +73,8 @@ public: Q_INVOKABLE void handleMouseRelease(int x, int y, int button, int buttons, int modifiers); Q_INVOKABLE void handleMouseMove(int x, int y, int button, int buttons, int modifiers); + void setVariantList(const QStringList &variantList); + QStringList variantList() const; void setContentView(ContentView view); ContentView contentView() const; void setOpenFolder(const QUrl &folder); @@ -104,12 +107,14 @@ Q_SIGNALS: void connectPortChanged(); void connectTextChanged(); void connectedChanged(); + void variantListChanged(); void showInfoOverlay(const QString &infoStr); private: Q3DSView *qmlStudio(); QString m_openFileDir; + QStringList m_variantList; RemoteDeploymentReceiver *m_remoteDeploymentReceiver = nullptr; bool m_generatorMode = false; ContentView m_contentView = DefaultView; diff --git a/src/Viewer/qmlviewer/Qt3DSRenderer.cpp b/src/Viewer/qmlviewer/Qt3DSRenderer.cpp index 39d0c9d6..53f6d388 100644 --- a/src/Viewer/qmlviewer/Qt3DSRenderer.cpp +++ b/src/Viewer/qmlviewer/Qt3DSRenderer.cpp @@ -88,9 +88,11 @@ void Q3DSRenderer::synchronize(QQuickFramebufferObject *inView) if (m_initializationFailure) static_cast(inView)->setError(m_error); - if (m_commands.m_sourceChanged) { + if (m_commands.m_sourceChanged || m_commands.m_variantListChanged) { releaseRuntime(); - // Need to update source here rather than processCommands, as source is needed for init + // Need to update source and variant list here rather than + // processCommands, as both are needed for init + m_presentation->setVariantList(m_commands.m_variantList); m_presentation->setSource(m_commands.m_source); m_initialized = false; m_initializationFailure = false; @@ -176,8 +178,11 @@ bool Q3DSRenderer::initializeRuntime(QOpenGLFramebufferObject *inFbo) const QString localSource = Q3DSUtils::urlToLocalFileOrQrc(m_presentation->source()); - if (!m_runtime->InitializeApp(theWidth, theHeight, QOpenGLContext::currentContext()->format(), - inFbo->handle(), localSource, m_visitor)) { + if (!m_runtime->InitializeApp(theWidth, theHeight, + QOpenGLContext::currentContext()->format(), + inFbo->handle(), localSource, + m_presentation->variantList(), + m_visitor)) { m_error = m_runtime->error(); releaseRuntime(); return false; diff --git a/src/Viewer/qmlviewer/Qt3DSView.cpp b/src/Viewer/qmlviewer/Qt3DSView.cpp index 08103d5e..13a2845d 100644 --- a/src/Viewer/qmlviewer/Qt3DSView.cpp +++ b/src/Viewer/qmlviewer/Qt3DSView.cpp @@ -161,6 +161,8 @@ void Q3DSView::reset() // Fake a source change to trigger a reloading of the presentation m_pendingCommands.m_sourceChanged = true; m_pendingCommands.m_source = m_presentation->source(); + m_pendingCommands.m_variantListChanged = true; + m_pendingCommands.m_variantList = m_presentation->variantList(); } void Q3DSView::requestResponseHandler(const QString &elementPath, CommandType commandType, diff --git a/src/Viewer/studio3d/q3dscommandqueue.cpp b/src/Viewer/studio3d/q3dscommandqueue.cpp index aec8cc26..ba0816d4 100644 --- a/src/Viewer/studio3d/q3dscommandqueue.cpp +++ b/src/Viewer/studio3d/q3dscommandqueue.cpp @@ -48,6 +48,7 @@ CommandQueue::CommandQueue() , m_showRenderStatsChanged(false) , m_matteColorChanged(false) , m_sourceChanged(false) + , m_variantListChanged(false) , m_globalAnimationTimeChanged(false) , m_visible(false) , m_scaleMode(Q3DSViewerSettings::ScaleModeCenter) @@ -144,6 +145,7 @@ void CommandQueue::copyCommands(const CommandQueue &fromQueue) m_showRenderStatsChanged = m_showRenderStatsChanged || fromQueue.m_showRenderStatsChanged; m_matteColorChanged = m_matteColorChanged || fromQueue.m_matteColorChanged; m_sourceChanged = m_sourceChanged || fromQueue.m_sourceChanged; + m_variantListChanged = m_variantListChanged || fromQueue.m_variantListChanged; m_globalAnimationTimeChanged = m_globalAnimationTimeChanged || fromQueue.m_globalAnimationTimeChanged; @@ -159,6 +161,8 @@ void CommandQueue::copyCommands(const CommandQueue &fromQueue) m_matteColor = fromQueue.m_matteColor; if (fromQueue.m_sourceChanged) m_source = fromQueue.m_source; + if (fromQueue.m_variantListChanged) + m_variantList = fromQueue.m_variantList; if (fromQueue.m_globalAnimationTimeChanged) m_globalAnimationTime = fromQueue.m_globalAnimationTime; @@ -215,6 +219,7 @@ void CommandQueue::clear() m_showRenderStatsChanged = false; m_matteColorChanged = false; m_sourceChanged = false; + m_variantListChanged = false; m_globalAnimationTimeChanged = false; // We do not clear the actual queued commands, those will be reused the next frame diff --git a/src/Viewer/studio3d/q3dscommandqueue_p.h b/src/Viewer/studio3d/q3dscommandqueue_p.h index 42e3bc5c..567fae29 100644 --- a/src/Viewer/studio3d/q3dscommandqueue_p.h +++ b/src/Viewer/studio3d/q3dscommandqueue_p.h @@ -118,6 +118,7 @@ public: bool m_showRenderStatsChanged; bool m_matteColorChanged; bool m_sourceChanged; + bool m_variantListChanged; bool m_globalAnimationTimeChanged; bool m_visible; @@ -126,6 +127,7 @@ public: bool m_showRenderStats; QColor m_matteColor; QUrl m_source; + QStringList m_variantList; qint64 m_globalAnimationTime; void clear(); diff --git a/src/Viewer/studio3d/q3dspresentation.cpp b/src/Viewer/studio3d/q3dspresentation.cpp index 27c050b1..9e73c2c4 100644 --- a/src/Viewer/studio3d/q3dspresentation.cpp +++ b/src/Viewer/studio3d/q3dspresentation.cpp @@ -57,6 +57,11 @@ QUrl Q3DSPresentation::source() const return d_ptr->m_source; } +QStringList Q3DSPresentation::variantList() const +{ + return d_ptr->m_variantList; +} + void Q3DSPresentation::registerElement(Q3DSElement *element) { d_ptr->registerElement(element); @@ -95,6 +100,14 @@ void Q3DSPresentation::setSource(const QUrl &source) } } +void Q3DSPresentation::setVariantList(const QStringList &variantList) +{ + if (d_ptr->m_variantList != variantList) { + d_ptr->setVariantList(variantList); + Q_EMIT variantListChanged(variantList); + } +} + void Q3DSPresentation::goToSlide(const QString &elementPath, unsigned int index) { if (d_ptr->m_viewerApp) { @@ -314,6 +327,15 @@ void Q3DSPresentationPrivate::setSource(const QUrl &source) } } +void Q3DSPresentationPrivate::setVariantList(const QStringList &variantList) +{ + m_variantList = variantList; + if (m_commandQueue) { + m_commandQueue->m_variantListChanged = true; + m_commandQueue->m_variantList = variantList; + } +} + void Q3DSPresentationPrivate::setViewerApp(Q3DSViewer::Q3DSViewerApp *app, bool connectApp) { Q3DSViewer::Q3DSViewerApp *oldApp = m_viewerApp; @@ -353,8 +375,10 @@ void Q3DSPresentationPrivate::setCommandQueue(CommandQueue *queue) for (Q3DSDataInput *di : dataInputs) di->d_ptr->setCommandQueue(queue); - if (m_commandQueue) + if (m_commandQueue) { setSource(m_source); + setVariantList(m_variantList); + } } // Doc note: The ownership of the registered scenes remains with the caller, who needs to diff --git a/src/Viewer/studio3d/q3dspresentation.h b/src/Viewer/studio3d/q3dspresentation.h index cbae780a..d904641d 100644 --- a/src/Viewer/studio3d/q3dspresentation.h +++ b/src/Viewer/studio3d/q3dspresentation.h @@ -48,12 +48,14 @@ class Q_STUDIO3D_EXPORT Q3DSPresentation : public QObject Q_OBJECT Q_DECLARE_PRIVATE(Q3DSPresentation) Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(QStringList variantList READ variantList WRITE setVariantList NOTIFY variantListChanged) public: explicit Q3DSPresentation(QObject *parent = nullptr); ~Q3DSPresentation(); QUrl source() const; + QStringList variantList() const; void registerElement(Q3DSElement *scene); void unregisterElement(Q3DSElement *scene); @@ -73,6 +75,7 @@ public: public Q_SLOTS: void setSource(const QUrl &source); + void setVariantList(const QStringList &variantList); void goToSlide(const QString &elementPath, unsigned int index); void goToSlide(const QString &elementPath, const QString &name); void goToSlide(const QString &elementPath, bool next, bool wrap); @@ -85,6 +88,7 @@ public Q_SLOTS: void setDataInputValue(const QString &name, const QVariant &value); Q_SIGNALS: + void variantListChanged(const QStringList &variantList); void sourceChanged(const QUrl &source); void slideEntered(const QString &elementPath, unsigned int index, const QString &name); void slideExited(const QString &elementPath, unsigned int index, const QString &name); diff --git a/src/Viewer/studio3d/q3dspresentation_p.h b/src/Viewer/studio3d/q3dspresentation_p.h index 27e553ca..d3803719 100644 --- a/src/Viewer/studio3d/q3dspresentation_p.h +++ b/src/Viewer/studio3d/q3dspresentation_p.h @@ -65,6 +65,7 @@ public: ~Q3DSPresentationPrivate(); void setSource(const QUrl &source); + void setVariantList(const QStringList &variantList); void setViewerApp(Q3DSViewer::Q3DSViewerApp *app, bool connectApp = true); void setCommandQueue(CommandQueue *queue); @@ -91,6 +92,7 @@ private: ElementMap m_elements; DataInputMap m_dataInputs; QUrl m_source; + QStringList m_variantList; ViewerQmlStreamProxy *m_streamProxy; }; diff --git a/src/Viewer/studio3d/q3dssurfaceviewer.cpp b/src/Viewer/studio3d/q3dssurfaceviewer.cpp index fd20eb3d..f477723b 100644 --- a/src/Viewer/studio3d/q3dssurfaceviewer.cpp +++ b/src/Viewer/studio3d/q3dssurfaceviewer.cpp @@ -355,6 +355,7 @@ bool Q3DSSurfaceViewerPrivate::initializeRuntime() if (!m_viewerApp->InitializeApp(int(m_size.width() * m_pixelRatio), int(m_size.height() * m_pixelRatio), m_context->format(), m_fboId, localSource, + m_presentation->variantList(), m_presentation->d_ptr->streamProxy())) { releaseRuntime(); qWarning("Failed to initialize runtime"); diff --git a/src/Viewer/studio3d/q3dswidget.cpp b/src/Viewer/studio3d/q3dswidget.cpp index 4db1b7be..8a2f52b2 100644 --- a/src/Viewer/studio3d/q3dswidget.cpp +++ b/src/Viewer/studio3d/q3dswidget.cpp @@ -34,6 +34,7 @@ #include "q3dsviewersettings_p.h" #include "q3dspresentation_p.h" #include "studioutils_p.h" +#include "q3dsvariantconfig_p.h" #include #include @@ -282,6 +283,7 @@ bool Q3DSWidgetPrivate::initializeRuntime() int(q_ptr->height() * m_pixelRatio), q_ptr->context()->format(), q_ptr->defaultFramebufferObject(), localSource, + m_presentation->variantList(), m_presentation->d_ptr->streamProxy())) { releaseRuntime(); qWarning("Failed to initialize runtime"); -- cgit v1.2.3