summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Määttä <antti.maatta@qt.io>2019-04-12 13:54:35 +0300
committerAntti Määttä <antti.maatta@qt.io>2019-05-03 09:34:00 +0000
commit73ebd0f9cf6376a762c96d37ab6046fefd8d4789 (patch)
treee415e2af7e30002563422ba9cbec02f3276b013e
parentccc70e48e576c0dffc289df4850a909fb6fef83d (diff)
Implement dynamic loading of slide resources
Implements loading of textures and images during runtime instead of load time. - Images which are not part of any slide are loaded at load time - Master slide images are always loaded at load time - Images used in a slide are loaded when the slide is entered - Images are unloaded when slide is exited and any other slide does not use them Task-number: QT3DS-3208 Change-Id: I7a827a5e828908efd2b104fe25374c66958319d2 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
-rw-r--r--src/Authoring/Studio/Render/StudioRenderer.cpp2
-rw-r--r--src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.cpp159
-rw-r--r--src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.h2
-rw-r--r--src/Runtime/Source/engine/Qt3DSRenderRuntimeBindingImpl.h9
-rw-r--r--src/Runtime/Source/engine/Qt3DSRuntimeView.cpp35
-rw-r--r--src/Runtime/Source/engine/Qt3DSRuntimeView.h6
-rw-r--r--src/Runtime/Source/runtime/Qt3DSApplication.cpp297
-rw-r--r--src/Runtime/Source/runtime/Qt3DSApplication.h120
-rw-r--r--src/Runtime/Source/runtime/Qt3DSComponentManager.cpp7
-rw-r--r--src/Runtime/Source/runtime/Qt3DSElementSystem.h10
-rw-r--r--src/Runtime/Source/runtime/Qt3DSIScene.h4
-rw-r--r--src/Runtime/Source/runtime/Qt3DSIScriptBridge.h3
-rw-r--r--src/Runtime/Source/runtime/Qt3DSLogicSystem.cpp2
-rw-r--r--src/Runtime/Source/runtime/Qt3DSPresentation.cpp4
-rw-r--r--src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp7
-rw-r--r--src/Runtime/Source/runtime/Qt3DSRuntimeFactory.h5
-rw-r--r--src/Runtime/Source/runtime/Qt3DSSlideSystem.cpp119
-rw-r--r--src/Runtime/Source/runtime/Qt3DSSlideSystem.h10
-rw-r--r--src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.cpp12
-rw-r--r--src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.h3
-rw-r--r--src/Runtime/Source/runtimerender/Qt3DSRenderImageTextureData.h42
-rw-r--r--src/Runtime/Source/runtimerender/Qt3DSRenderRenderList.cpp20
-rw-r--r--src/Runtime/Source/runtimerender/Qt3DSRenderRenderList.h4
-rw-r--r--src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.cpp32
-rw-r--r--src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.h1
-rw-r--r--src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp245
-rw-r--r--src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h10
-rw-r--r--src/Runtime/Source/uipparser/Qt3DSUIPParser.h2
-rw-r--r--src/Runtime/Source/uipparser/Qt3DSUIPParserImpl.cpp5
-rw-r--r--src/Runtime/Source/uipparser/Qt3DSUIPParserImpl.h6
-rw-r--r--src/Runtime/Source/viewer/Qt3DSViewerApp.cpp30
-rw-r--r--src/Runtime/Source/viewer/Qt3DSViewerApp.h4
m---------src/Runtime/qt3d-runtime0
-rw-r--r--src/Viewer/qmlviewer/Qt3DSRenderer.cpp10
-rw-r--r--src/Viewer/studio3d/q3dscommandqueue.cpp8
-rw-r--r--src/Viewer/studio3d/q3dscommandqueue_p.h6
-rw-r--r--src/Viewer/studio3d/q3dspresentation.cpp42
-rw-r--r--src/Viewer/studio3d/q3dspresentation.h8
-rw-r--r--src/Viewer/studio3d/q3dspresentation_p.h2
39 files changed, 1019 insertions, 274 deletions
diff --git a/src/Authoring/Studio/Render/StudioRenderer.cpp b/src/Authoring/Studio/Render/StudioRenderer.cpp
index d6b5b3b2..ee03a614 100644
--- a/src/Authoring/Studio/Render/StudioRenderer.cpp
+++ b/src/Authoring/Studio/Render/StudioRenderer.cpp
@@ -328,7 +328,7 @@ struct SRendererImpl : public IStudioRenderer,
m_Context = theCore->CreateRenderContext(
m_RenderContext->GetRenderContext(),
m_RenderContext->GetRenderContext().GetStringTable().RegisterStr(
- theResourcePath.c_str()));
+ theResourcePath.c_str()), false);
// Allow the artist to interact with the top level objects alone.
m_Context->GetRenderer().PickRenderPlugins(false);
diff --git a/src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.cpp b/src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.cpp
index 10496753..8ba76fd1 100644
--- a/src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.cpp
+++ b/src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.cpp
@@ -133,9 +133,9 @@ struct SSceneLoadData
SSceneLoadData(NVAllocatorCallback &alloc)
: m_Allocator(alloc)
- , m_Presentation(NULL)
+ , m_Presentation(nullptr)
, m_AutoAllocator(alloc)
- , m_RuntimePresentation(NULL)
+ , m_RuntimePresentation(nullptr)
, mRefCount(0)
{
}
@@ -170,9 +170,9 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
, m_LoadData(inLoadData)
, m_Presentation(inLoadData.m_Presentation)
, m_RuntimePresentation(inLoadData.m_RuntimePresentation)
- , m_UserData(NULL)
+ , m_UserData(nullptr)
, m_DirtySet(inContext.GetAllocator(), "Qt3DSRenderScene::m_DirtySet")
- , m_OffscreenRenderer(NULL)
+ , m_OffscreenRenderer(nullptr)
, m_SubPresentationType(
inContext.GetStringTable().RegisterStr(CSubPresentationRenderer::GetRendererName()))
, m_GraphObjectList(inContext.GetAllocator(), "Qt3DSDSRenderScene::m_GraphObjectList")
@@ -188,7 +188,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
{
if (m_OffscreenRenderer)
m_Context->GetOffscreenRenderManager().ReleaseOffscreenRenderer(m_OffscreenRendererId);
- m_OffscreenRenderer = NULL;
+ m_OffscreenRenderer = nullptr;
if (m_Presentation && m_Presentation->m_Scene) {
for (SLayer *theLayer = m_Presentation->m_Scene->m_FirstChild; theLayer;
theLayer = static_cast<SLayer *>(theLayer->m_NextSibling)) {
@@ -216,7 +216,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
// changes.
if (theTranslator
&& theTranslator->RenderObject().m_Type != GraphObjectTypes::PathSubPath)
- theTranslator = NULL;
+ theTranslator = nullptr;
}
}
if (theTranslator)
@@ -282,12 +282,12 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
,
mousePos, true, true);
- if (thePickResult.m_HitObject != NULL) {
+ if (thePickResult.m_HitObject != nullptr) {
SModel *theHitModel =
static_cast<SModel *>(const_cast<SGraphObject *>(thePickResult.m_HitObject));
return &Qt3DSTranslator::GetTranslatorFromGraphNode(*theHitModel)->Element();
}
- return NULL;
+ return nullptr;
}
virtual Option<QT3DSVec2> FacePosition(Q3DStudio::TElement &inElement, float mouseX, float mouseY,
@@ -300,7 +300,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
}
Qt3DSTranslator *theTranslator =
reinterpret_cast<Qt3DSTranslator *>(inElement.GetAssociation());
- if (theTranslator == NULL)
+ if (theTranslator == nullptr)
return Empty();
bool isValidPickObject =
GraphObjectTypes::IsNodeType(theTranslator->m_RenderObject->m_Type);
@@ -314,11 +314,11 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
for (QT3DSU32 idx = 0, end = inMapperElements.size(); idx < end; ++idx) {
Qt3DSTranslator *theMapperTranslator =
reinterpret_cast<Qt3DSTranslator *>(inMapperElements[idx]->GetAssociation());
- SGraphObject *theMapperObject = NULL;
+ SGraphObject *theMapperObject = nullptr;
if (theMapperTranslator) {
theMapperObject = theMapperTranslator->m_RenderObject;
}
- if (theMapperObject == NULL) {
+ if (theMapperObject == nullptr) {
QT3DS_ASSERT(false);
} else {
theMapperObjects[idx] = theMapperObject;
@@ -363,7 +363,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
m_Context->GetMousePickMouseCoords(
QT3DSVec2(ioPickFrame.m_InputFrame.m_PickX, ioPickFrame.m_InputFrame.m_PickY)),
true);
- if (thePickResult.m_HitObject != NULL) {
+ if (thePickResult.m_HitObject != nullptr) {
SModel *theHitModel = static_cast<SModel *>(
const_cast<SGraphObject *>(thePickResult.m_HitObject));
ioPickFrame.m_Model =
@@ -415,7 +415,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
void CalculateGlobalTransform(Q3DStudio::TElement *inElement,
Q3DStudio::RuntimeMatrix &outTransform) override
{
- if (inElement == NULL) {
+ if (inElement == nullptr) {
QT3DS_ASSERT(false);
return;
}
@@ -439,7 +439,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
void SetLocalTransformMatrix(Q3DStudio::TElement *inElement,
const Q3DStudio::RuntimeMatrix &inTransform) override
{
- if (inElement == NULL) {
+ if (inElement == nullptr) {
QT3DS_ASSERT(false);
return;
}
@@ -472,7 +472,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
NVBounds3 GetNodeLocalBoundingBox(Q3DStudio::TElement *inElement, bool inSelfOnly)
{
NVBounds3 retval(NVBounds3::empty());
- if (inElement == NULL) {
+ if (inElement == nullptr) {
QT3DS_ASSERT(false);
return retval;
}
@@ -534,7 +534,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
{
Q3DStudio::CBoundingBox retval;
retval.SetEmpty();
- if (inElement == NULL) {
+ if (inElement == nullptr) {
QT3DS_ASSERT(false);
return retval;
}
@@ -609,7 +609,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
NVRenderTextureFormats::Enum destFormat = qt3ds::render::NVRenderTextureFormats::RGBA16F;
Qt3DSRenderPrefilterTexture *theBSDFMipMap = theImage->m_TextureData.m_BSDFMipMap;
- if (theBSDFMipMap == NULL) {
+ if (theBSDFMipMap == nullptr) {
theBSDFMipMap = Qt3DSRenderPrefilterTexture::Create(
&theContext->GetRenderContext(), inWidth, inHeight,
*theImage->m_TextureData.m_Texture, destFormat, theContext->GetFoundation());
@@ -669,7 +669,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
unsigned int *indexData, unsigned int numIndices,
qt3ds::NVBounds3 &objBounds) override
{
- SRenderMesh *theMesh = NULL;
+ SRenderMesh *theMesh = nullptr;
if (inPathStr && vertData && indexData) {
theMesh = m_Context->GetBufferManager().CreateMesh(
@@ -679,7 +679,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
"CreateOrSetMeshData was not supplied necessary buffers or object path");
}
- return (theMesh != NULL);
+ return (theMesh != nullptr);
}
Q3DStudio::STextSizes MeasureText(Q3DStudio::TElement *inElement, const char *inTextStr) override
@@ -720,28 +720,6 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
return Q3DStudio::STextSizes();
}
- // This is the best place for now...
- void GetImageInfoFromRenderEngine(Q3DStudio::TElement *inElement,
- Q3DStudio::INT32 &ioWidth, Q3DStudio::INT32 &ioHeight) override
- {
- ioWidth = 0;
- ioHeight = 0;
- Qt3DSTranslator *theTranslator =
- reinterpret_cast<Qt3DSTranslator *>(inElement->GetAssociation());
- if (theTranslator->GetUIPType() == GraphObjectTypes::Image) {
- SImage *theImage = static_cast<SImage *>(&theTranslator->RenderObject());
- if (theImage) {
- SImageTextureData theTextureData(
- m_Context->GetBufferManager().LoadRenderImage(theImage->m_ImagePath));
- if (theTextureData.m_Texture) {
- STextureDetails theDetails = theTextureData.m_Texture->GetTextureDetails();
- ioWidth = theDetails.m_Width;
- ioHeight = theDetails.m_Height;
- }
- }
- }
- }
-
virtual Q3DStudio::SMousePosition
WindowToPresentation(const Q3DStudio::SMousePosition &inWindowCoords) override
{
@@ -780,6 +758,30 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
*m_OffscreenRenderer);
}
+ template <typename T, typename C>
+ void forAllObjects(nvvector<SGraphObject *> &vec, GraphObjectTypes::Enum type, C callable)
+ {
+ nvvector<SGraphObject *>::iterator it = vec.begin();
+ nvvector<SGraphObject *>::iterator end = vec.end();
+ while (it != end) {
+ if ((*it)->m_Type == type)
+ callable(static_cast<T*>(*it));
+ ++it;
+ }
+ }
+
+ void PostLoadStep()
+ {
+ IBufferManager &mgr = m_Context->GetBufferManager();
+ forAllObjects<SImage>(m_GraphObjectList, GraphObjectTypes::Image, [&mgr](SImage *image){
+ if (image->m_ImagePath.IsValid()) {
+ image->m_LoadedTextureData = mgr.CreateReloadableImage(image->m_ImagePath,
+ false, false);
+ image->m_LoadedTextureData->m_callbacks.push_back(image);
+ }
+ });
+ }
+
void Release() override { NVDelete(m_Context->GetAllocator(), this); }
};
@@ -849,7 +851,7 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
, m_ViewWidth(0)
, m_ViewHeight(0)
, m_SourcePaths(ctx.GetAllocator(), "Qt3DSRenderSceneManager::m_SourcePaths")
- , m_LastRenderedScene(NULL)
+ , m_LastRenderedScene(nullptr)
, m_WindowSystem(inWindowSystem)
, m_LoadingScenesMutex(ctx.GetAllocator())
, m_ProjectInitialized(false)
@@ -879,7 +881,7 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
return false;
return stricmp(ending, "jpg") == 0 || stricmp(ending, "peg") == 0
|| stricmp(ending, "png") == 0 || stricmp(ending, "dds") == 0
- || stricmp(ending, "hdr") == 0;
+ || stricmp(ending, "hdr") == 0 || stricmp(ending, "ktx") == 0;
}
static bool IsMesh(const char *ending)
{
@@ -961,16 +963,16 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
};
Q3DStudio::IScene *LoadScene(Q3DStudio::IPresentation *inPresentation,
- Q3DStudio::IUIPParser *inParser,
- Q3DStudio::IScriptBridge &inBridge,
- const qt3ds::Q3DSVariantConfig &variantConfig) override
+ Q3DStudio::IUIPParser *inParser,
+ 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.
Qt3DSTranslator::InitializePointerTags(m_Context->m_RenderContext->GetStringTable());
NVScopedRefCounted<SSceneLoadData> theScene =
QT3DS_NEW(m_Context->GetAllocator(), SSceneLoadData)(m_Context->GetAllocator());
- Qt3DSRenderScene *theIScene = NULL;
+ Qt3DSRenderScene *theIScene = nullptr;
if (inParser) {
QString thePath(inPresentation->GetFilePath());
QFileInfo fileInfo(thePath);
@@ -994,10 +996,11 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
variantConfig, false);
if (!theScene->m_Presentation) {
QT3DS_ASSERT(false);
- return NULL;
+ return nullptr;
}
NVConstDataRef<eastl::string> theSourcePathData(inParser->GetSourcePaths());
+ const QVector<QString> slideSourcePaths = inParser->GetSlideSourcePaths();
IBufferManager &theManager(m_Context->m_Context->GetBufferManager());
// List of image paths to be loaded in parallel at the end.
eastl::vector<CRegisteredString> theSourcePathList;
@@ -1010,11 +1013,16 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
const char *ending = theValue.c_str() + theValueSize - 3;
CRegisteredString theObjectPath = theSourcePath;
if (IsImage(ending)) {
- theManager.SetImageTransparencyToFalseIfNotSet(theObjectPath);
- if (m_SourcePathSet.insert(theSourcePath).second)
- m_SourcePaths.push_back(eastl::make_pair(
- theSourcePath, theManager.GetImageHasTransparency(theObjectPath)));
- theSourcePathList.push_back(theObjectPath);
+ // load only images not on any slide
+ if (!theManager.isReloadableResourcesEnabled() ||
+ !slideSourcePaths.contains(QString::fromLatin1(theValue.c_str()))) {
+ theManager.SetImageTransparencyToFalseIfNotSet(theObjectPath);
+ if (m_SourcePathSet.insert(theSourcePath).second) {
+ m_SourcePaths.push_back(eastl::make_pair(theSourcePath,
+ theManager.GetImageHasTransparency(theObjectPath)));
+ }
+ theSourcePathList.push_back(theObjectPath);
+ }
} else if (theValue.find(".mesh") != eastl::string::npos) {
theManager.LoadMesh(theObjectPath);
}
@@ -1049,6 +1057,7 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
}
}
}
+ theIScene->PostLoadStep();
} else {
// Binary load path is quite different than normal load path and
// nothing else will load here.
@@ -1218,6 +1227,7 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
Qt3DSRenderScene *theIScene = QT3DS_NEW(m_Context->GetAllocator(), Qt3DSRenderScene)(
*m_Context, *m_Context->m_Context, theScene);
FinalizeScene(*theScene.m_RuntimePresentation, *theIScene);
+ theIScene->PostLoadStep();
} else {
qCWarning(WARNING, "Failed to finalize scene %d", (int)idx + 1);
}
@@ -1425,7 +1435,7 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
{
SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(),
"Load UIAB - String Table + Render Objects");
- QT3DS_ASSERT(m_Context->m_FlowData == NULL);
+ QT3DS_ASSERT(m_Context->m_FlowData == nullptr);
QT3DSU32 dataSize = 0;
inStream.Read(dataSize);
m_Context->m_FlowData = (QT3DSU8 *)m_Context->m_CoreContext->GetAllocator().allocate(
@@ -1544,8 +1554,8 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
Q3DStudio::BOOL RenderPresentation(Q3DStudio::IPresentation *inPresentation) override
{
- Qt3DSRenderScene *theFirstScene = NULL;
- for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end && theFirstScene == NULL; ++idx)
+ Qt3DSRenderScene *theFirstScene = nullptr;
+ for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end && theFirstScene == nullptr; ++idx)
if (m_Scenes[idx].second->m_RuntimePresentation == inPresentation)
theFirstScene = m_Scenes[idx].second;
@@ -1606,8 +1616,8 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
Q3DStudio::STextSizes GetDisplayDimensions(Q3DStudio::IPresentation *inPresentation) override
{
- Qt3DSRenderScene *theFirstScene = NULL;
- for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end && theFirstScene == NULL; ++idx)
+ Qt3DSRenderScene *theFirstScene = nullptr;
+ for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end && theFirstScene == nullptr; ++idx)
if (m_Scenes[idx].second->m_RuntimePresentation == inPresentation)
theFirstScene = m_Scenes[idx].second;
if (theFirstScene) {
@@ -1629,7 +1639,7 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
if (m_LastRenderedScene) {
return m_LastRenderedScene->UserPick(mouseX, mouseY);
}
- return NULL;
+ return nullptr;
}
Option<QT3DSVec2> FacePosition(Q3DStudio::TElement &inElement, float mouseX, float mouseY,
@@ -1648,7 +1658,7 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
{
// We now have a new input frame, and our results are invalid but ready to be filled
m_PickFrame.m_InputFrame = inInputFrame;
- m_PickFrame.m_Model = NULL;
+ m_PickFrame.m_Model = nullptr;
m_PickFrame.m_ResultValid = false;
if (m_LastRenderedScene) {
if (m_PickFrame.m_InputFrame.m_PickValid)
@@ -1687,16 +1697,14 @@ struct SRenderFactory : public IQt3DSRenderFactoryCore, public IQt3DSRenderFacto
NVScopedRefCounted<Q3DStudio::CQmlEngine> m_ScriptBridgeQml;
NVScopedRefCounted<Qt3DSRenderSceneManager> m_SceneManager;
NVScopedRefCounted<qt3ds::evt::IEventSystem> m_EventSystem;
- qt3ds::runtime::IApplicationCore *m_ApplicationCore;
qt3ds::runtime::IApplication *m_Application;
QT3DSI32 m_RefCount;
SRenderFactory(SBindingCore &inCore)
: m_Context(inCore)
- , m_ScriptBridgeQml(NULL)
- , m_SceneManager(NULL)
- , m_ApplicationCore(NULL)
- , m_Application(NULL)
+ , m_ScriptBridgeQml(nullptr)
+ , m_SceneManager(nullptr)
+ , m_Application(nullptr)
, m_RefCount(0)
{
}
@@ -1705,7 +1713,7 @@ struct SRenderFactory : public IQt3DSRenderFactoryCore, public IQt3DSRenderFacto
{
using namespace Q3DStudio;
// Release the event system, it must be released before script engine
- m_EventSystem = NULL;
+ m_EventSystem = nullptr;
m_ScriptBridgeQml->Shutdown(*m_Context->m_Foundation);
}
@@ -1725,15 +1733,15 @@ struct SRenderFactory : public IQt3DSRenderFactoryCore, public IQt3DSRenderFacto
return *m_Context->m_CoreContext;
}
- qt3ds::runtime::IApplicationCore *GetApplicationCore() override { return m_ApplicationCore; }
- void SetApplicationCore(qt3ds::runtime::IApplicationCore *app) override
+ qt3ds::runtime::IApplication *GetApplicationCore() override { return m_Application; }
+ void SetApplicationCore(qt3ds::runtime::IApplication *app) override
{
- m_ApplicationCore = app;
+ m_Application = app;
}
Q3DStudio::ISceneBinaryLoader &GetSceneLoader() override
{
- if (m_SceneManager == NULL)
+ if (m_SceneManager == nullptr)
m_SceneManager = QT3DS_NEW(m_Context->GetAllocator(),
Qt3DSRenderSceneManager)(*m_Context, m_Context->m_WindowSystem);
return *m_SceneManager;
@@ -1745,14 +1753,14 @@ struct SRenderFactory : public IQt3DSRenderFactoryCore, public IQt3DSRenderFacto
}
Q3DStudio::ISceneManager &GetSceneManager() override
{
- if (m_SceneManager == NULL)
+ if (m_SceneManager == nullptr)
m_SceneManager = QT3DS_NEW(m_Context->GetAllocator(),
Qt3DSRenderSceneManager)(*m_Context, m_Context->m_WindowSystem);
return *m_SceneManager;
}
Q3DStudio::IScriptBridge &GetScriptEngineQml() override
{
- if (m_ScriptBridgeQml == NULL) {
+ if (m_ScriptBridgeQml == nullptr) {
m_ScriptBridgeQml =
Q3DStudio::CQmlEngine::Create(*m_Context->m_Foundation, m_Context->m_TimeProvider);
}
@@ -1823,17 +1831,18 @@ struct SRenderFactory : public IQt3DSRenderFactoryCore, public IQt3DSRenderFacto
qt3ds::render::NVRenderContext &retval = NVRenderContext::CreateGL(foundat, strt, format);
return &retval;
#else
- qt3ds::render::NVRenderContext &retval = NVRenderContext::CreateNULL(foundat, strt);
+ qt3ds::render::NVRenderContext &retval = NVRenderContext::Createnullptr(foundat, strt);
return &retval;
#endif
}
};
- IQt3DSRenderFactory &CreateRenderFactory(const QSurfaceFormat& format) override
+ IQt3DSRenderFactory &CreateRenderFactory(const QSurfaceFormat& format,
+ bool delayedLoading) override
{
SContextTypeRenderFactory theContextFactory(format);
- m_Context->CreateRenderContext(theContextFactory);
+ m_Context->CreateRenderContext(theContextFactory, delayedLoading);
GetSceneLoader();
{
diff --git a/src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.h b/src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.h
index ea95b943..ad0c4e6b 100644
--- a/src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.h
+++ b/src/Runtime/Source/engine/Qt3DSRenderRuntimeBinding.h
@@ -63,7 +63,7 @@ namespace render {
{
public:
virtual IQt3DSRenderFactory &
- CreateRenderFactory(const QSurfaceFormat &format) = 0;
+ CreateRenderFactory(const QSurfaceFormat &format, bool delayedLoading) = 0;
static IQt3DSRenderFactoryCore &
CreateRenderFactoryCore(const char8_t *inApplicationDirectory,
diff --git a/src/Runtime/Source/engine/Qt3DSRenderRuntimeBindingImpl.h b/src/Runtime/Source/engine/Qt3DSRenderRuntimeBindingImpl.h
index 1d27f293..c174d4a7 100644
--- a/src/Runtime/Source/engine/Qt3DSRenderRuntimeBindingImpl.h
+++ b/src/Runtime/Source/engine/Qt3DSRenderRuntimeBindingImpl.h
@@ -136,12 +136,15 @@ namespace render {
m_FlowData = NULL;
}
- void CreateRenderContext(qt3ds::render::IRuntimeFactoryRenderFactory &inContextFactory)
+ void CreateRenderContext(qt3ds::render::IRuntimeFactoryRenderFactory &inContextFactory,
+ bool delayedLoading)
{
m_RenderContext = inContextFactory.CreateRenderContext(*m_Foundation, *m_StringTable);
- if (m_RenderContext)
+ if (m_RenderContext) {
m_Context =
- m_CoreContext->CreateRenderContext(*m_RenderContext, m_PrimitivePath.c_str());
+ m_CoreContext->CreateRenderContext(*m_RenderContext, m_PrimitivePath.c_str(),
+ delayedLoading);
+ }
}
QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(g_BaseAllocator)
diff --git a/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp b/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp
index f2ce9d67..e4e8453d 100644
--- a/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp
+++ b/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp
@@ -144,7 +144,7 @@ private:
// Pre graphics init objects
NVScopedRefCounted<qt3ds::render::IQt3DSRenderFactoryCore> m_RuntimeFactoryCore;
///< Base application before graphics
- NVScopedRefCounted<qt3ds::runtime::IApplicationCore> m_ApplicationCore;
+ NVScopedRefCounted<qt3ds::runtime::IApplication> m_ApplicationCore;
// Post graphics init objects
NVScopedRefCounted<qt3ds::render::IQt3DSRenderFactory> m_RuntimeFactory;
@@ -170,7 +170,7 @@ public:
bool BeginLoad(const QString &sourcePath, const QStringList &variantList) override;
bool HasOfflineLoadingCompleted() override;
- bool InitializeGraphics(const QSurfaceFormat &format) override;
+ bool InitializeGraphics(const QSurfaceFormat &format, bool delayedLoading) override;
void Cleanup() override;
@@ -219,6 +219,9 @@ public:
bool RegisterScriptCallback(int callbackType, qml_Function func, void *inUserData) override;
void FireEvent(const TEventCommandHash inEventType, eastl::string inArgument) override;
qt3ds::foundation::Option<SPresentationSize> GetPresentationSize() override;
+ void preloadSlide(const QString &slide) override;
+ void unloadSlide(const QString &slide) override;
+ void setDelayedLoading(bool enable) override;
void BootupPreGraphicsInitObjects();
};
@@ -275,12 +278,12 @@ bool CRuntimeView::HasOfflineLoadingCompleted()
return true;
}
-bool CRuntimeView::InitializeGraphics(const QSurfaceFormat &format)
+bool CRuntimeView::InitializeGraphics(const QSurfaceFormat &format, bool delayedLoading)
{
m_ApplicationCore->EndLoad();
// Next call will initialize the render portion of the scenes. This *must* have a loaded
// application to go further as it will bind scene graph data to application data.
- m_RuntimeFactory = m_RuntimeFactoryCore->CreateRenderFactory(format);
+ m_RuntimeFactory = m_RuntimeFactoryCore->CreateRenderFactory(format, delayedLoading);
m_Application
= m_ApplicationCore->CreateApplication(*m_InputEngine, m_AudioPlayer,
*m_RuntimeFactory);
@@ -655,6 +658,24 @@ void CRuntimeView::FireEvent(const TEventCommandHash inEventType, eastl::string
}
}
+void CRuntimeView::preloadSlide(const QString &slide)
+{
+ if (m_Application)
+ m_Application->preloadSlide(slide);
+}
+
+void CRuntimeView::unloadSlide(const QString &slide)
+{
+ if (m_Application)
+ m_Application->unloadSlide(slide);
+}
+
+void CRuntimeView::setDelayedLoading(bool enable)
+{
+ if (m_Application)
+ m_Application->setDelayedLoading(enable);
+}
+
qt3ds::foundation::Option<SPresentationSize> CRuntimeView::GetPresentationSize()
{
if (m_Application) {
@@ -678,7 +699,7 @@ void CRuntimeView::BootupPreGraphicsInitObjects()
m_RuntimeFactoryCore = qt3ds::render::IQt3DSRenderFactoryCore::CreateRenderFactoryCore(
theAppDir.c_str(), m_WindowSystem, m_TimeProvider);
m_ApplicationCore = qt3ds::runtime::IApplication::CreateApplicationCore(*m_RuntimeFactoryCore,
- theAppDir.c_str());
+ theAppDir.c_str());
if (m_ApplicationCore && m_visitor)
m_ApplicationCore->setAssetVisitor(m_visitor);
@@ -697,10 +718,10 @@ void CRuntimeView::setAssetVisitor(qt3ds::Qt3DSAssetVisitor *v)
}
IRuntimeView &IRuntimeView::Create(ITimeProvider &inProvider, IWindowSystem &inWindowSystem,
- IAudioPlayer *inAudioPlayer)
+ IAudioPlayer *inAudioPlayer)
{
return *QT3DS_NEW(qt3ds::render::g_BaseAllocator, CRuntimeView)(inProvider, inWindowSystem,
- inAudioPlayer);
+ inAudioPlayer);
}
QRuntimeViewSignalProxy *IRuntimeView::signalProxy()
diff --git a/src/Runtime/Source/engine/Qt3DSRuntimeView.h b/src/Runtime/Source/engine/Qt3DSRuntimeView.h
index 87418c8e..52aa969c 100644
--- a/src/Runtime/Source/engine/Qt3DSRuntimeView.h
+++ b/src/Runtime/Source/engine/Qt3DSRuntimeView.h
@@ -157,7 +157,7 @@ public:
public: // loading
virtual bool BeginLoad(const QString &sourcePath, const QStringList &variantList) = 0;
virtual bool HasOfflineLoadingCompleted() = 0;
- virtual bool InitializeGraphics(const QSurfaceFormat &format) = 0;
+ virtual bool InitializeGraphics(const QSurfaceFormat &format, bool delayedLoading) = 0;
virtual void Cleanup() = 0;
@@ -204,8 +204,10 @@ public:
virtual bool RegisterScriptCallback(int callbackType, qml_Function func, void *inUserData) = 0;
virtual void FireEvent(const TEventCommandHash inEventType, eastl::string inArgument) = 0;
virtual qt3ds::foundation::Option<SPresentationSize> GetPresentationSize() = 0;
-
virtual void setAssetVisitor(qt3ds::Qt3DSAssetVisitor *) = 0;
+ virtual void preloadSlide(const QString &slide) = 0;
+ virtual void unloadSlide(const QString &slide) = 0;
+ virtual void setDelayedLoading(bool enable) = 0;
public:
static IRuntimeView &Create(ITimeProvider &inProvider, IWindowSystem &inWindowSystem,
diff --git a/src/Runtime/Source/runtime/Qt3DSApplication.cpp b/src/Runtime/Source/runtime/Qt3DSApplication.cpp
index 5f335fec..a1d5812d 100644
--- a/src/Runtime/Source/runtime/Qt3DSApplication.cpp
+++ b/src/Runtime/Source/runtime/Qt3DSApplication.cpp
@@ -75,6 +75,10 @@
#include "Qt3DSRenderInputStreamFactory.h"
#include "Qt3DSAudioPlayer.h"
#include "Qt3DSElementSystem.h"
+#include "Qt3DSSlideSystem.h"
+#include "Qt3DSQmlElementHelper.h"
+#include "Qt3DSRenderBufferManager.h"
+#include "Qt3DSRenderRenderList.h"
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qpair.h>
#include <QtCore/qdir.h>
@@ -82,6 +86,7 @@
using namespace qt3ds;
using namespace qt3ds::runtime;
+using namespace qt3ds::render;
using namespace Q3DStudio;
namespace qt3ds {
@@ -201,6 +206,139 @@ struct SHandleElementPairComparator
}
};
+struct SSlideResourceCounter
+{
+ QHash<QString, int> counters;
+ QSet<QString> createSet;
+ QSet<QString> deleteSet;
+
+ QVector<QString> loadedSlides;
+
+ void increment(const QSet<QString> &set)
+ {
+ for (auto &r : set) {
+ if (counters.value(r, 0) == 0)
+ createSet.insert(r);
+ counters[r]++;
+ }
+ }
+ void decrement(const QSet<QString> &set)
+ {
+ for (auto &r : set) {
+ if (counters.contains(r)) {
+ int count = qMax(counters[r] - 1, 0);
+ if (count == 0)
+ deleteSet.insert(r);
+ counters[r] = count;
+ }
+ }
+ }
+ void begin()
+ {
+ createSet.clear();
+ deleteSet.clear();
+ }
+ void reset()
+ {
+ loadedSlides.clear();
+ counters.clear();
+ begin();
+ }
+ bool isImage(const QString &path)
+ {
+ int index = path.lastIndexOf(".");
+ if (index < 0)
+ return false;
+ const QString ext = path.right(path.length() - index - 1);
+ return (ext == QLatin1String("jpg") || ext == QLatin1String("jpeg")
+ || ext == QLatin1String("png") || ext == QLatin1String("hdr")
+ || ext == QLatin1String("dds") || ext == QLatin1String("ktx"));
+ }
+ QSet<QString> toImageSet(const QVector<QString> &vec)
+ {
+ QSet<QString> s;
+ for (const auto &x : vec) {
+ if (isImage(x))
+ s.insert(x);
+ }
+ return s;
+ }
+ void handleLoadSlide(const QString &slide, SSlideKey key, ISlideSystem &slideSystem)
+ {
+ if (loadedSlides.contains(slide))
+ return;
+ loadedSlides.push_back(slide);
+ begin();
+ increment(toImageSet(slideSystem.GetSourcePaths(key)));
+ print();
+ }
+ void handleUnloadSlide(const QString &slide, SSlideKey key, ISlideSystem &slideSystem)
+ {
+ if (!loadedSlides.contains(slide))
+ return;
+ loadedSlides.removeOne(slide);
+ begin();
+ decrement(toImageSet(slideSystem.GetSourcePaths(key)));
+ print();
+ }
+ void print()
+ {
+ static const bool debugging = qEnvironmentVariableIntValue("QT3DS_DEBUG") >= 1;
+ if (debugging) {
+ qDebug() << "SlideResourceCounter resources:";
+ const auto keys = counters.keys();
+ for (auto &x : keys)
+ qDebug() << x << ": " << counters[x];
+ if (createSet.size()) {
+ qDebug() << "New resources: ";
+ for (auto y : qAsConst(createSet))
+ qDebug() << y;
+ }
+ if (deleteSet.size()) {
+ qDebug() << "Deleted resources: ";
+ for (auto y : qAsConst(deleteSet))
+ qDebug() << y;
+ }
+ }
+ }
+};
+
+struct STextureUploadRenderTask : public IRenderTask
+{
+ IBufferManager &m_bufferManager;
+ QSet<QString> m_uploadSet;
+ QSet<QString> m_deleteSet;
+ QMutex m_updateMutex;
+
+ STextureUploadRenderTask(IBufferManager &mgr)
+ : m_bufferManager(mgr)
+ {
+
+ }
+ void Run() override
+ {
+ QMutexLocker loc(&m_updateMutex);
+ m_bufferManager.loadSet(m_uploadSet);
+ m_bufferManager.unloadSet(m_deleteSet);
+ }
+ void add(const QSet<QString> &set)
+ {
+ QMutexLocker loc(&m_updateMutex);
+ m_uploadSet.unite(set);
+ m_deleteSet.subtract(set);
+ }
+ void remove(const QSet<QString> &set)
+ {
+ QMutexLocker loc(&m_updateMutex);
+ m_uploadSet.subtract(set);
+ m_deleteSet.unite(set);
+ }
+ bool persistent() const override
+ {
+ return true;
+ }
+};
+
struct SApp;
class IAppLoadContext : public NVRefCounted
@@ -402,7 +540,6 @@ public:
struct SApp : public IApplication
{
-
NVScopedRefCounted<Q3DStudio::IRuntimeFactoryCore> m_CoreFactory;
NVScopedRefCounted<Q3DStudio::IRuntimeFactory> m_RuntimeFactory;
@@ -425,6 +562,7 @@ struct SApp : public IApplication
// the name of the file without extension.
eastl::string m_Filename;
Q3DSVariantConfig m_variantConfig;
+ QScopedPointer<STextureUploadRenderTask> m_uploadRenderTask;
qt3ds::foundation::NVScopedReleasable<IRuntimeMetaData> m_MetaData;
nvvector<eastl::pair<SBehaviorAsset, bool>> m_Behaviors;
@@ -461,6 +599,9 @@ struct SApp : public IApplication
DataInputMap m_dataInputDefs;
+ SSlideResourceCounter m_resourceCounter;
+ QSet<QString> m_createSet;
+
QT3DSI32 mRefCount;
SApp(Q3DStudio::IRuntimeFactoryCore &inFactory, const char8_t *inAppDir)
: m_CoreFactory(inFactory)
@@ -495,9 +636,9 @@ struct SApp : public IApplication
, m_ThisFrameStartTime(0)
, m_MillisecondsSinceLastFrame(0)
, m_DirtyCountdown(5)
+ , m_visitor(nullptr)
, m_createSuccessful(false)
, mRefCount(0)
- , m_visitor(nullptr)
{
m_AudioPlayer.SetApplication(*this);
eastl::string tempStr(inAppDir);
@@ -563,6 +704,21 @@ struct SApp : public IApplication
}
return m_PresentationBuffer;
}
+ QVector<CPresentation *> getPresentations()
+ {
+ QVector<CPresentation *> presentations;
+ if (m_PresentationBuffer.empty()) {
+ for (QT3DSU32 idx = 0, end = m_OrderedAssets.size(); idx < end; ++idx) {
+ SAssetValue &theAsset = *m_OrderedAssets[idx].second;
+ if (theAsset.getType() == AssetValueTypes::Presentation) {
+ SPresentationAsset &thePresAsset = *theAsset.getDataPtr<SPresentationAsset>();
+ if (thePresAsset.m_Presentation)
+ presentations.push_back(thePresAsset.m_Presentation);
+ }
+ }
+ }
+ return presentations;
+ }
void addRef() override { atomicIncrement(&mRefCount); }
@@ -895,6 +1051,49 @@ struct SApp : public IApplication
// Generalized save/load
////////////////////////////////////////////////////////////////////////////////
+ void loadComponentSlideResources(TElement *component, CPresentation *presentation, int index,
+ const QString slideName)
+ {
+ if (m_RuntimeFactory->GetQt3DSRenderContext().GetBufferManager()
+ .isReloadableResourcesEnabled()) {
+ auto &slidesystem = presentation->GetSlideSystem();
+ SSlideKey key;
+ key.m_Component = component;
+ key.m_Index = index;
+ slidesystem.setUnloadSlide(key, false);
+ const QString completeName = presentation->GetName() + QLatin1Char(':')
+ + QString::fromUtf8(key.m_Component->m_Name) + QLatin1Char(':') + slideName;
+ qCInfo(PERF_INFO) << "Load component slide resources: " << completeName;
+ m_resourceCounter.handleLoadSlide(completeName, key, slidesystem);
+ if (m_uploadRenderTask)
+ m_uploadRenderTask->add(m_resourceCounter.createSet);
+ else
+ m_createSet.unite(m_resourceCounter.createSet);
+ }
+ }
+
+ void unloadComponentSlideResources(TElement *component, CPresentation *presentation, int index,
+ const QString slideName)
+ {
+ if (m_RuntimeFactory->GetQt3DSRenderContext().GetBufferManager()
+ .isReloadableResourcesEnabled()) {
+ auto &slidesystem = presentation->GetSlideSystem();
+ SSlideKey key;
+ key.m_Component = component;
+ key.m_Index = index;
+ slidesystem.setUnloadSlide(key, true);
+ if (!slidesystem.isActiveSlide(key)) {
+ const QString completeName = presentation->GetName() + QLatin1Char(':')
+ + QString::fromUtf8(key.m_Component->m_Name) + QLatin1Char(':') + slideName;
+ qCInfo(PERF_INFO) << "Unload component slide resources: " << completeName;
+ m_resourceCounter.handleUnloadSlide(completeName, key, slidesystem);
+
+ if (m_uploadRenderTask)
+ m_uploadRenderTask->remove(m_resourceCounter.deleteSet);
+ }
+ }
+ }
+
bool LoadUIP(SPresentationAsset &inAsset,
NVConstDataRef<SElementAttributeReference> inExternalReferences)
{
@@ -939,6 +1138,12 @@ struct SApp : public IApplication
if (inAsset.m_Id.IsValid())
newScene->RegisterOffscreenRenderer(inAsset.m_Id);
+
+ QVector<TElement *> components;
+ thePresentation->GetRoot()->findComponents(components);
+ for (auto &component : qAsConst(components))
+ loadComponentSlideResources(component, thePresentation, 0, "Master");
+
return true;
}
}
@@ -1087,7 +1292,7 @@ struct SApp : public IApplication
}
};
- virtual bool BeginLoad(const QString &sourcePath, const QStringList &variantList) override
+ bool BeginLoad(const QString &sourcePath, const QStringList &variantList) override
{
SStackPerfTimer __loadTimer(m_CoreFactory->GetPerfTimer(), "Application: Begin Load");
eastl::string directory;
@@ -1198,6 +1403,82 @@ struct SApp : public IApplication
return m_createSuccessful;
}
+ bool presentationComponentSlide(const QString &elementPath,
+ Q3DStudio::CPresentation *&presentation,
+ TElement *&component,
+ QString &slideName,
+ int &index)
+ {
+ presentation = GetPrimaryPresentation();
+ slideName = elementPath;
+ QString componentName;
+ if (elementPath.contains(QLatin1Char(':'))) {
+ // presentation : component : slide
+ QStringList splits = elementPath.split(QLatin1Char(':'));
+ if (splits.size() == 3) {
+ presentation = GetPresentationById(qPrintable(splits[0]));
+ componentName = splits[1];
+ slideName = splits[2];
+ } else {
+ componentName = splits[0];
+ slideName = splits[1];
+ }
+ // else assume main presentation and component:slide
+ }
+ component = presentation->GetRoot();
+ if (!componentName.isNull() && componentName != component->m_Name)
+ component = component->FindChild(CHash::HashString(qPrintable(componentName)));
+ if (!component) {
+ qCWarning(WARNING) << "Could not find slide: " << elementPath;
+ return false;
+ }
+ ISlideSystem &s = presentation->GetSlideSystem();
+ index = s.FindSlide(*component, qPrintable(slideName));
+ return true;
+ }
+
+ void preloadSlide(const QString &slide) override
+ {
+ CPresentation *pres = nullptr;
+ TElement *component = nullptr;
+ QString slideName;
+ int index;
+ if (presentationComponentSlide(slide, pres, component, slideName, index))
+ loadComponentSlideResources(component, pres, index, slideName);
+ }
+
+ void unloadSlide(const QString &slide) override
+ {
+ CPresentation *pres = nullptr;
+ TElement *component = nullptr;
+ QString slideName;
+ int index;
+ if (presentationComponentSlide(slide, pres, component, slideName, index))
+ unloadComponentSlideResources(component, pres, index, slideName);
+ }
+
+ void setDelayedLoading(bool enable)
+ {
+ m_RuntimeFactory->GetQt3DSRenderContext().GetBufferManager()
+ .enableReloadableResources(enable);
+ }
+
+ void ComponentSlideEntered(Q3DStudio::CPresentation *presentation,
+ Q3DStudio::TElement *component,
+ const QString &elementPath, int slideIndex,
+ const QString &slideName) override
+ {
+ loadComponentSlideResources(component, presentation, slideIndex, slideName);
+ }
+
+ void ComponentSlideExited(Q3DStudio::CPresentation *presentation,
+ Q3DStudio::TElement *component,
+ const QString &elementPath, int slideIndex,
+ const QString &slideName) override
+ {
+ unloadComponentSlideResources(component, presentation, slideIndex, slideName);
+ }
+
// will force loading to end if endLoad hasn't been called yet. Will fire off loading
// of resources that need to be uploaded to opengl. Maintains reference to runtime factory
IApplication &CreateApplication(Q3DStudio::CInputEngine &inInputEngine,
@@ -1275,6 +1556,12 @@ struct SApp : public IApplication
m_AudioPlayer.SetPlayer(inAudioPlayer);
+ m_uploadRenderTask.reset(new STextureUploadRenderTask(
+ m_RuntimeFactory->GetQt3DSRenderContext().GetBufferManager()));
+ m_uploadRenderTask->add(m_createSet);
+ m_RuntimeFactory->GetQt3DSRenderContext().GetRenderList()
+ .AddRenderTask(*m_uploadRenderTask);
+ m_createSet.clear();
return *this;
}
@@ -1567,7 +1854,7 @@ CAppStr &CAppStr::operator=(const CAppStr &inOther)
return *this;
}
-IApplicationCore &IApplicationCore::CreateApplicationCore(Q3DStudio::IRuntimeFactoryCore &inFactory,
+IApplication &IApplication::CreateApplicationCore(Q3DStudio::IRuntimeFactoryCore &inFactory,
const char8_t *inApplicationDirectory)
{
return *QT3DS_NEW(inFactory.GetFoundation().getAllocator(), SApp)(inFactory,
@@ -1575,7 +1862,7 @@ IApplicationCore &IApplicationCore::CreateApplicationCore(Q3DStudio::IRuntimeFac
}
// Checks if the event is one that can cause picking
-bool IApplicationCore::isPickingEvent(TEventCommandHash event)
+bool IApplication::isPickingEvent(TEventCommandHash event)
{
return (event == ON_MOUSEDOWN
|| event == ON_MOUSEUP
diff --git a/src/Runtime/Source/runtime/Qt3DSApplication.h b/src/Runtime/Source/runtime/Qt3DSApplication.h
index 2e7eabad..972c2ad0 100644
--- a/src/Runtime/Source/runtime/Qt3DSApplication.h
+++ b/src/Runtime/Source/runtime/Qt3DSApplication.h
@@ -85,61 +85,6 @@ public:
virtual void Run() = 0;
};
-class QT3DS_AUTOTEST_EXPORT IApplicationCore : public NVRefCounted
-{
-public:
- // threadsafe call.
- virtual void QueueForMainThread(IAppRunnable &inRunnable) = 0;
-
- // The directory that contains the executable and the root resource path
- virtual CRegisteredString GetApplicationDirectory() const = 0;
- // Directory that contained the UIA file.
- virtual CRegisteredString GetProjectDirectory() const = 0;
- // Directory where we will copy shared object files to before we load them.
- // This is specifically for android and the case where the place where the project exists
- // is not always the place where we can load the project.
- virtual CRegisteredString GetDllDir() const = 0;
- virtual void SetDllDir(const char *inDllDir) = 0;
- virtual Q3DStudio::THashValue HashString(const char *inStr) = 0;
- virtual const char *ReverseHash(Q3DStudio::THashValue theValue) = 0;
-
- virtual Q3DStudio::IRuntimeMetaData &GetMetaData() = 0;
- // Element handles are unique across all presentations.
- virtual Q3DStudio::TElement *GetElementByHandle(Q3DStudio::UINT32 inHandle) = 0;
- // Passing in NULL gets you zero as the return handle.
- virtual Q3DStudio::UINT32 GetHandleForElement(Q3DStudio::TElement *inElement) = 0;
-
- virtual Q3DStudio::IRuntimeFactoryCore &GetRuntimeFactoryCore() = 0;
- virtual void HideFPS(bool flag) = 0;
-
- virtual IActivityZoneManager &GetActivityZoneManager() = 0;
- virtual IElementAllocator &GetElementAllocator() = 0;
-
- // nonblocking call to begin loading, loads uia file alone and returns.
- 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.
- // Runs any queued runnables.
- virtual bool HasCompletedLoading() = 0;
-
- virtual void setAssetVisitor(qt3ds::Qt3DSAssetVisitor *) = 0;
-
- // will force loading to end if endLoad hasn't been called yet. Will fire off loading
- // of resources that need to be uploaded to opengl. Maintains reference to runtime factory
- virtual IApplication &CreateApplication(Q3DStudio::CInputEngine &inInputEngine,
- Q3DStudio::IAudioPlayer *inAudioPlayer,
- Q3DStudio::IRuntimeFactory &inFactory) = 0;
-
- // maintains reference to runtime factory core. AppDir is where the executable is located;
- // the system will expect res directory
- // next to executable.
- static IApplicationCore &CreateApplicationCore(Q3DStudio::IRuntimeFactoryCore &inFactory,
- const char8_t *inApplicationDirectory);
- static bool isPickingEvent(Q3DStudio::TEventCommandHash event);
-};
-
struct DataInputControlledAttribute
{
QByteArray elementPath;
@@ -176,7 +121,7 @@ struct DataInputDef
typedef QMap<QString, DataInputDef> DataInputMap;
-class IApplication : public IApplicationCore
+class QT3DS_AUTOTEST_EXPORT IApplication : public NVRefCounted
{
public:
virtual Q3DStudio::IRuntimeFactory &GetRuntimeFactory() const = 0;
@@ -223,6 +168,69 @@ public:
virtual float dataInputMin(const QString &name) const = 0;
virtual void setPresentationId(const QString &id) = 0;
+
+ virtual void preloadSlide(const QString &slide) = 0;
+ virtual void unloadSlide(const QString &slide) = 0;
+ virtual void setDelayedLoading(bool enable) = 0;
+
+ // threadsafe call.
+ virtual void QueueForMainThread(IAppRunnable &inRunnable) = 0;
+
+ // The directory that contains the executable and the root resource path
+ virtual CRegisteredString GetApplicationDirectory() const = 0;
+ // Directory that contained the UIA file.
+ virtual CRegisteredString GetProjectDirectory() const = 0;
+ // Directory where we will copy shared object files to before we load them.
+ // This is specifically for android and the case where the place where the project exists
+ // is not always the place where we can load the project.
+ virtual CRegisteredString GetDllDir() const = 0;
+ virtual void SetDllDir(const char *inDllDir) = 0;
+ virtual Q3DStudio::THashValue HashString(const char *inStr) = 0;
+ virtual const char *ReverseHash(Q3DStudio::THashValue theValue) = 0;
+
+ virtual Q3DStudio::IRuntimeMetaData &GetMetaData() = 0;
+ // Element handles are unique across all presentations.
+ virtual Q3DStudio::TElement *GetElementByHandle(Q3DStudio::UINT32 inHandle) = 0;
+ // Passing in NULL gets you zero as the return handle.
+ virtual Q3DStudio::UINT32 GetHandleForElement(Q3DStudio::TElement *inElement) = 0;
+
+ virtual Q3DStudio::IRuntimeFactoryCore &GetRuntimeFactoryCore() = 0;
+ virtual void HideFPS(bool flag) = 0;
+
+ virtual IActivityZoneManager &GetActivityZoneManager() = 0;
+ virtual IElementAllocator &GetElementAllocator() = 0;
+
+ // nonblocking call to begin loading, loads uia file alone and returns.
+ 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.
+ // Runs any queued runnables.
+ virtual bool HasCompletedLoading() = 0;
+
+ virtual void setAssetVisitor(qt3ds::Qt3DSAssetVisitor *) = 0;
+
+ virtual void ComponentSlideEntered(Q3DStudio::CPresentation *presentation,
+ Q3DStudio::TElement *component,
+ const QString &elementPath, int slideIndex,
+ const QString &slideName) = 0;
+ virtual void ComponentSlideExited(Q3DStudio::CPresentation *presentation,
+ Q3DStudio::TElement *component,
+ const QString &elementPath, int slideIndex,
+ const QString &slideName) = 0;
+
+ // will force loading to end if endLoad hasn't been called yet. Will fire off loading
+ // of resources that need to be uploaded to opengl. Maintains reference to runtime factory
+ virtual IApplication &CreateApplication(Q3DStudio::CInputEngine &inInputEngine,
+ Q3DStudio::IAudioPlayer *inAudioPlayer,
+ Q3DStudio::IRuntimeFactory &inFactory) = 0;
+
+ // maintains reference to runtime factory core. AppDir is where the executable is located;
+ // the system will expect res directory
+ // next to executable.
+ static IApplication &CreateApplicationCore(Q3DStudio::IRuntimeFactoryCore &inFactory,
+ const char8_t *inApplicationDirectory);
+ static bool isPickingEvent(Q3DStudio::TEventCommandHash event);
};
}
}
diff --git a/src/Runtime/Source/runtime/Qt3DSComponentManager.cpp b/src/Runtime/Source/runtime/Qt3DSComponentManager.cpp
index 2cfb2311..d7ce0b6a 100644
--- a/src/Runtime/Source/runtime/Qt3DSComponentManager.cpp
+++ b/src/Runtime/Source/runtime/Qt3DSComponentManager.cpp
@@ -106,6 +106,10 @@ void CComponentManager::GotoSlideIndex(TElement *inComponent,
theEvent.m_IsEvent = true;
m_Presentation.ProcessEvent(theEvent);
+ m_Presentation.GetApplication().ComponentSlideExited(&m_Presentation, inComponent,
+ elementPath, theCurrentSlideIndex,
+ GetCurrentSlideName(inComponent));
+
// Signal previous slide change
m_Presentation.signalProxy()->SigSlideExited(elementPath, theCurrentSlideIndex,
GetCurrentSlideName(inComponent));
@@ -182,6 +186,9 @@ void CComponentManager::GotoSlideIndex(TElement *inComponent,
if (theZone)
theZone->OnSlideChange(*inComponent);
+ m_Presentation.GetApplication().ComponentSlideEntered(&m_Presentation, inComponent,
+ elementPath, theGotoSlideData.m_Slide,
+ GetCurrentSlideName(inComponent));
// Signal current slide change
m_Presentation.signalProxy()->SigSlideEntered(elementPath, GetCurrentSlide(inComponent),
GetCurrentSlideName(inComponent));
diff --git a/src/Runtime/Source/runtime/Qt3DSElementSystem.h b/src/Runtime/Source/runtime/Qt3DSElementSystem.h
index b9355c55..12ebebd9 100644
--- a/src/Runtime/Source/runtime/Qt3DSElementSystem.h
+++ b/src/Runtime/Source/runtime/Qt3DSElementSystem.h
@@ -508,6 +508,16 @@ namespace runtime {
return ta && ua && inParentActive;
}
+ void findComponents(QVector<SElement *> &components)
+ {
+ if (IsComponent())
+ components.push_back(this);
+ SElement *child = m_Child;
+ while (child) {
+ child->findComponents(components);
+ child = child->m_Sibling;
+ }
+ }
};
struct SGetElementNodeDirtyIndex
diff --git a/src/Runtime/Source/runtime/Qt3DSIScene.h b/src/Runtime/Source/runtime/Qt3DSIScene.h
index 8872b93f..3f80f85f 100644
--- a/src/Runtime/Source/runtime/Qt3DSIScene.h
+++ b/src/Runtime/Source/runtime/Qt3DSIScene.h
@@ -156,10 +156,6 @@ public: // Base Interface
virtual void ScreenToPosition(TElement &inElement, qt3ds::QT3DSVec3 &inScreen,
qt3ds::QT3DSVec3 &outPos) = 0;
- // This is the best place for now...
- virtual void GetImageInfoFromRenderEngine(TElement *inElement, INT32 &ioWidth,
- INT32 &ioHeight) = 0;
-
virtual qt3ds::foundation::CRegisteredString RegisterStr(const char *inStr) = 0;
virtual Q3DStudio::INT32
diff --git a/src/Runtime/Source/runtime/Qt3DSIScriptBridge.h b/src/Runtime/Source/runtime/Qt3DSIScriptBridge.h
index af322319..4be6fe16 100644
--- a/src/Runtime/Source/runtime/Qt3DSIScriptBridge.h
+++ b/src/Runtime/Source/runtime/Qt3DSIScriptBridge.h
@@ -41,7 +41,6 @@
namespace qt3ds {
namespace runtime {
class IApplication;
- class IApplicationCore;
}
}
namespace qt3ds {
@@ -130,7 +129,7 @@ public: // thread
virtual void DisableMultithreadedAccess() = 0;
public: // Settings
- virtual void SetApplicationCore(qt3ds::runtime::IApplicationCore &inApplication) = 0;
+ virtual void SetApplicationCore(qt3ds::runtime::IApplication &inApplication) = 0;
virtual void SetApplication(qt3ds::runtime::IApplication &inApplication) = 0;
public: // Scripts
diff --git a/src/Runtime/Source/runtime/Qt3DSLogicSystem.cpp b/src/Runtime/Source/runtime/Qt3DSLogicSystem.cpp
index 1aec08f1..4a8341b4 100644
--- a/src/Runtime/Source/runtime/Qt3DSLogicSystem.cpp
+++ b/src/Runtime/Source/runtime/Qt3DSLogicSystem.cpp
@@ -221,7 +221,7 @@ struct SLogicSystem : public ILogicSystem
listIter != listEnd; ++listIter)
if (listIter->m_Id == inActionIndex) {
listIter->m_Active = inActive;
- if (IApplicationCore::isPickingEvent(logicIter->first.m_CommandHash)) {
+ if (IApplication::isPickingEvent(logicIter->first.m_CommandHash)) {
SElement *theElement = inElemAllocator.FindElementByHandle(
logicIter->first.m_ElementHandle);
if (theElement && inActive)
diff --git a/src/Runtime/Source/runtime/Qt3DSPresentation.cpp b/src/Runtime/Source/runtime/Qt3DSPresentation.cpp
index 68691a99..a4302ad5 100644
--- a/src/Runtime/Source/runtime/Qt3DSPresentation.cpp
+++ b/src/Runtime/Source/runtime/Qt3DSPresentation.cpp
@@ -125,7 +125,7 @@ void CPresentation::RegisterEventCallback(TElement *inElement, const TEventComma
m_EventCallbacks.RegisterCallback(inElement, inEventHash, inCallback, inContextData);
inElement->SetFlag(ELEMENTFLAG_REGISTEREDFOREVENTCALLBACK, true);
- if (qt3ds::runtime::IApplicationCore::isPickingEvent(inEventHash))
+ if (qt3ds::runtime::IApplication::isPickingEvent(inEventHash))
inElement->SetFlag(ELEMENTFLAG_PICKENABLED, true);
}
@@ -149,7 +149,7 @@ BOOL CPresentation::UnregisterEventCallback(TElement *inElement,
if (theLast)
inElement->SetFlag(ELEMENTFLAG_REGISTEREDFOREVENTCALLBACK, false);
- if (qt3ds::runtime::IApplicationCore::isPickingEvent(inEventHash))
+ if (qt3ds::runtime::IApplication::isPickingEvent(inEventHash))
inElement->SetFlag(ELEMENTFLAG_PICKENABLED, false);
return theResult;
diff --git a/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp b/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp
index 1c8d5c31..0898df70 100644
--- a/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp
+++ b/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp
@@ -85,7 +85,6 @@ namespace Q3DStudio {
#define Q3DStudio_LOG_EVENT(S)
#endif
-using qt3ds::runtime::IApplicationCore;
using qt3ds::runtime::IApplication;
using namespace qt3ds;
@@ -362,7 +361,7 @@ class CQmlEngineImpl : public CQmlEngine
private:
qt3ds::NVFoundationBase &m_Foundation;
IApplication *m_Application;
- IApplicationCore *m_ApplicationCore;
+ IApplication *m_ApplicationCore;
qt3ds::foundation::Mutex m_PreloadMutex;
qt3ds::foundation::Mutex *m_MultithreadedMutex;
@@ -385,7 +384,7 @@ public:
void EnableMultithreadedAccess() override;
void DisableMultithreadedAccess() override;
- void SetApplicationCore(qt3ds::runtime::IApplicationCore &inApplication) override;
+ void SetApplicationCore(qt3ds::runtime::IApplication &inApplication) override;
void SetApplication(qt3ds::runtime::IApplication &inApplication) override;
qt3ds::runtime::IApplication *GetApplication() override;
void Initialize() override;
@@ -492,7 +491,7 @@ void CQmlEngineImpl::DisableMultithreadedAccess()
m_MultithreadedMutex = NULL;
}
-void CQmlEngineImpl::SetApplicationCore(qt3ds::runtime::IApplicationCore &inApplication)
+void CQmlEngineImpl::SetApplicationCore(runtime::IApplication &inApplication)
{
QML_ENGINE_MULTITHREAD_PROTECT_METHOD;
m_ApplicationCore = &inApplication;
diff --git a/src/Runtime/Source/runtime/Qt3DSRuntimeFactory.h b/src/Runtime/Source/runtime/Qt3DSRuntimeFactory.h
index 4c6de842..fb46240c 100644
--- a/src/Runtime/Source/runtime/Qt3DSRuntimeFactory.h
+++ b/src/Runtime/Source/runtime/Qt3DSRuntimeFactory.h
@@ -44,7 +44,6 @@ namespace render {
namespace qt3ds {
namespace runtime {
class IApplication;
- class IApplicationCore;
}
}
@@ -90,8 +89,8 @@ public:
virtual qt3ds::foundation::IStringTable &GetStringTable() = 0;
virtual void AddSearchPath(const char8_t *inFile) = 0;
virtual void SetDllDir(const char *inDir) = 0;
- virtual qt3ds::runtime::IApplicationCore *GetApplicationCore() = 0;
- virtual void SetApplicationCore(qt3ds::runtime::IApplicationCore *app) = 0;
+ virtual qt3ds::runtime::IApplication *GetApplicationCore() = 0;
+ virtual void SetApplicationCore(qt3ds::runtime::IApplication *app) = 0;
};
class IRuntimeFactory : public IRuntimeFactoryCore
diff --git a/src/Runtime/Source/runtime/Qt3DSSlideSystem.cpp b/src/Runtime/Source/runtime/Qt3DSSlideSystem.cpp
index e7cc0983..524422f4 100644
--- a/src/Runtime/Source/runtime/Qt3DSSlideSystem.cpp
+++ b/src/Runtime/Source/runtime/Qt3DSSlideSystem.cpp
@@ -72,7 +72,7 @@ struct SSlideAttributeNode
SSlideAttributeNode *m_NextNode;
SSlideAttributeNode()
- : m_NextNode(NULL)
+ : m_NextNode(nullptr)
{
}
};
@@ -93,8 +93,8 @@ struct SSlideElement
: m_ElementHandle(0)
, m_AttributeCount(0)
, m_Active(false)
- , m_NextElement(NULL)
- , m_AttributeNodes(NULL)
+ , m_NextElement(nullptr)
+ , m_AttributeNodes(nullptr)
{
}
};
@@ -107,7 +107,7 @@ struct SSlideAnimActionNode
SSlideAnimAction m_Data[AnimActionCount];
SSlideAnimActionNode *m_NextNode;
SSlideAnimActionNode()
- : m_NextNode(NULL)
+ : m_NextNode(nullptr)
{
}
};
@@ -128,17 +128,22 @@ struct SSlide
QT3DSU32 m_AnimActionCount;
SSlideElement *m_FirstElement;
SSlideAnimActionNode *m_FirstAnimActionNode;
+ QVector<QString> m_sourcePaths;
+ bool m_activeSlide;
+ bool m_unloadSlide;
SSlide()
- : m_NextSlide(NULL)
+ : m_NextSlide(nullptr)
, m_PlayMode(PlayMode::StopAtEnd)
, m_PlayThroughTo(0xFF)
, m_Paused(false)
, m_StartTime(0)
, m_EndTime(0)
, m_AnimActionCount(0)
- , m_FirstElement(NULL)
- , m_FirstAnimActionNode(NULL)
+ , m_FirstElement(nullptr)
+ , m_FirstAnimActionNode(nullptr)
+ , m_activeSlide(false)
+ , m_unloadSlide(false)
{
}
@@ -187,8 +192,8 @@ struct SSlideSystem : public ISlideSystem
, m_SlidePool(ForwardingAllocator(inFnd.getAllocator(), "m_SlidePool"))
, m_SlideElements(ForwardingAllocator(inFnd.getAllocator(), "m_SlideElements"))
, m_Slides(inFnd.getAllocator(), "m_Slides")
- , m_CurrentSlide(NULL)
- , m_CurrentSlideElement(NULL)
+ , m_CurrentSlide(nullptr)
+ , m_CurrentSlideElement(nullptr)
, m_RefCount(0)
{
}
@@ -209,14 +214,14 @@ struct SSlideSystem : public ISlideSystem
QT3DSU32 inMinTime, QT3DSU32 inMaxTime) override
{
eastl::pair<TComponentSlideHash::iterator, bool> inserter =
- m_Slides.insert(eastl::make_pair(&inComponent, (SSlide *)NULL));
+ m_Slides.insert(eastl::make_pair(&inComponent, (SSlide *)nullptr));
SSlide *newSlide = m_SlidePool.construct(__FILE__, __LINE__);
QT3DSU32 slideIndex = 0;
- if (inserter.first->second == NULL) {
+ if (inserter.first->second == nullptr) {
inserter.first->second = newSlide;
} else {
- SSlide *theSlide = NULL;
- for (theSlide = inserter.first->second; theSlide->m_NextSlide != NULL;
+ SSlide *theSlide = nullptr;
+ for (theSlide = inserter.first->second; theSlide->m_NextSlide != nullptr;
theSlide = theSlide->m_NextSlide) {
++slideIndex;
}
@@ -225,7 +230,7 @@ struct SSlideSystem : public ISlideSystem
m_CurrentSlide = newSlide;
newSlide->Initialize(m_StringTable.RegisterStr(inName), inPlayMode, inPlayThroughTo,
inPaused, inMinTime, inMaxTime);
- m_CurrentSlideElement = NULL;
+ m_CurrentSlideElement = nullptr;
if (inComponent.IsComponent()) {
SComponent &theComponent = static_cast<SComponent &>(inComponent);
theComponent.m_SlideCount++;
@@ -233,21 +238,35 @@ struct SSlideSystem : public ISlideSystem
return slideIndex;
}
+ void AddSourcePath(const char8_t *path) override
+ {
+ if (m_CurrentSlide)
+ m_CurrentSlide->m_sourcePaths.push_back(QString::fromUtf8(path));
+ }
+
+ QVector<QString> GetSourcePaths(SSlideKey inKey) override
+ {
+ auto slide = FindSlide(inKey);
+ if (slide)
+ return slide->m_sourcePaths;
+ return {};
+ }
+
void SetSlideMaxTime(QT3DSU32 inMaxTime) override
{
- if (m_CurrentSlide != NULL)
+ if (m_CurrentSlide != nullptr)
m_CurrentSlide->m_EndTime = inMaxTime;
}
void AddSlideElement(element::SElement &inElement, bool inActive) override
{
- if (m_CurrentSlide != NULL) {
+ if (m_CurrentSlide != nullptr) {
SSlideElement *lastSlideElement = m_CurrentSlideElement;
m_CurrentSlideElement = m_SlideElements.construct(__FILE__, __LINE__);
m_CurrentSlideElement->m_Active = inActive;
m_CurrentSlideElement->m_ElementHandle = inElement.GetHandle();
- if (lastSlideElement == NULL) {
- QT3DS_ASSERT(m_CurrentSlide->m_FirstElement == NULL);
+ if (lastSlideElement == nullptr) {
+ QT3DS_ASSERT(m_CurrentSlide->m_FirstElement == nullptr);
m_CurrentSlide->m_FirstElement = m_CurrentSlideElement;
} else {
lastSlideElement->m_NextElement = m_CurrentSlideElement;
@@ -259,7 +278,7 @@ struct SSlideSystem : public ISlideSystem
}
void AddSlideAttribute(Q3DStudio::SAttributeKey inKey, Q3DStudio::UVariant inValue) override
{
- if (m_CurrentSlideElement != NULL) {
+ if (m_CurrentSlideElement != nullptr) {
SElement *theElement =
m_ElementSystem.FindElementByHandle(m_CurrentSlideElement->m_ElementHandle);
@@ -278,7 +297,7 @@ struct SSlideSystem : public ISlideSystem
SSlideAnimAction *AddSlideAnimAction(bool inAnimation, QT3DSI32 inId, bool inActive) override
{
- if (m_CurrentSlide != NULL) {
+ if (m_CurrentSlide != nullptr) {
SSlideAnimAction &theAnimAction = TSlideAnimActionNodeList::Create(
m_CurrentSlide->m_FirstAnimActionNode, m_CurrentSlide->m_AnimActionCount,
m_AnimActionPool);
@@ -286,14 +305,29 @@ struct SSlideSystem : public ISlideSystem
&theAnimAction;
}
- return NULL;
+ return nullptr;
}
const SSlide *FindSlide(SSlideKey inKey) const
{
TComponentSlideHash::const_iterator iter = m_Slides.find(inKey.m_Component);
if (iter == m_Slides.end())
- return NULL;
+ return nullptr;
+
+ SSlide *theSlide = iter->second;
+ for (QT3DSU32 idx = inKey.m_Index; idx; --idx) {
+ if (theSlide)
+ theSlide = theSlide->m_NextSlide;
+ }
+
+ return theSlide;
+ }
+
+ SSlide *FindSlide(SSlideKey inKey)
+ {
+ TComponentSlideHash::const_iterator iter = m_Slides.find(inKey.m_Component);
+ if (iter == m_Slides.end())
+ return nullptr;
SSlide *theSlide = iter->second;
for (QT3DSU32 idx = inKey.m_Index; idx; --idx) {
@@ -417,17 +451,17 @@ struct SSlideSystem : public ISlideSystem
void InitializeDynamicKeys(SSlideKey inKey, IAnimationSystem &inAnimationSystem) const override
{
const SSlide *theSlide = FindSlide(inKey);
- if (theSlide != NULL) {
+ if (theSlide != nullptr) {
IterateSlideAnimActions(*theSlide, SDynamicKeyOperator(inAnimationSystem));
}
}
void ExecuteSlide(SSlideKey inKey, IAnimationSystem &inAnimationSystem,
- ILogicSystem &inLogicManager) const override
+ ILogicSystem &inLogicManager) override
{
- const SSlide *theSlide = FindSlide(inKey);
+ SSlide *theSlide = FindSlide(inKey);
- if (theSlide == NULL) {
+ if (theSlide == nullptr) {
QT3DS_ASSERT(false);
return;
}
@@ -458,22 +492,23 @@ struct SSlideSystem : public ISlideSystem
theComponent.SetPlayThrough(theSlide->m_PlayMode == PlayMode::PlayThroughTo);
}
-
+ theSlide->m_activeSlide = true;
IterateSlideElementAttributes(*theSlide, SElementOperator(false), m_ElementSystem);
IterateSlideAnimActions(*theSlide, SExecuteAnimActionOperator(
m_ElementSystem, inAnimationSystem, inLogicManager));
}
void RollbackSlide(SSlideKey inKey, IAnimationSystem &inAnimationSystem,
- ILogicSystem &inLogicManager) const override
+ ILogicSystem &inLogicManager) override
{
- const SSlide *theSlide = FindSlide(inKey);
+ SSlide *theSlide = FindSlide(inKey);
- if (theSlide == NULL) {
+ if (theSlide == nullptr) {
QT3DS_ASSERT(false);
return;
}
+ theSlide->m_activeSlide = false;
IterateSlideElementAttributes(*theSlide, SElementOperator(true), m_ElementSystem);
IterateSlideAnimActions(
*theSlide,
@@ -531,6 +566,30 @@ struct SSlideSystem : public ISlideSystem
QT3DS_ASSERT(false);
return 0xFF;
}
+
+ bool isActiveSlide(SSlideKey inKey) const override
+ {
+ const SSlide *theSlide = FindSlide(inKey);
+ return theSlide->m_activeSlide;
+ }
+
+ void setUnloadSlide(SSlideKey inKey, bool unload) override
+ {
+ SSlide *theSlide = FindSlide(inKey);
+ theSlide->m_unloadSlide = unload;
+ }
+
+ bool isUnloadSlideSet(SSlideKey inKey) const override
+ {
+ const SSlide *theSlide = FindSlide(inKey);
+ return theSlide->m_unloadSlide;
+ }
+
+ void setIsActiveSlide(SSlideKey inKey, bool active) override
+ {
+ SSlide *theSlide = FindSlide(inKey);
+ theSlide->m_activeSlide = active;
+ }
};
}
diff --git a/src/Runtime/Source/runtime/Qt3DSSlideSystem.h b/src/Runtime/Source/runtime/Qt3DSSlideSystem.h
index de2ddbbc..becc057f 100644
--- a/src/Runtime/Source/runtime/Qt3DSSlideSystem.h
+++ b/src/Runtime/Source/runtime/Qt3DSSlideSystem.h
@@ -130,14 +130,20 @@ namespace runtime {
Q3DStudio::UVariant inValue) = 0;
virtual SSlideAnimAction *AddSlideAnimAction(bool inAnimation, QT3DSI32 inIndex,
bool inActive) = 0;
+ virtual void AddSourcePath(const char8_t *path) = 0;
+ virtual QVector<QString> GetSourcePaths(SSlideKey inKey) = 0;
+ virtual void setIsActiveSlide(SSlideKey inKey, bool active) = 0;
+ virtual bool isActiveSlide(SSlideKey inKey) const = 0;
+ virtual void setUnloadSlide(SSlideKey inKey, bool unload) = 0;
+ virtual bool isUnloadSlideSet(SSlideKey inKey) const = 0;
// Using the dataset
virtual void InitializeDynamicKeys(SSlideKey inKey,
IAnimationSystem &inAnimationSystem) const = 0;
virtual void ExecuteSlide(SSlideKey inKey, IAnimationSystem &inAnimationSystem,
- ILogicSystem &inLogicManager) const = 0;
+ ILogicSystem &inLogicManager) = 0;
virtual void RollbackSlide(SSlideKey inKey, IAnimationSystem &inAnimationSystem,
- ILogicSystem &inLogicManager) const = 0;
+ ILogicSystem &inLogicManager) = 0;
virtual QT3DSU8 FindSlide(element::SElement &inComponent,
const char8_t *inSlideName) const = 0;
virtual QT3DSU8 FindSlide(element::SElement &inComponent, QT3DSU32 inSlideHashName) const = 0;
diff --git a/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.cpp b/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.cpp
index 3c940805..207059fc 100644
--- a/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.cpp
+++ b/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.cpp
@@ -126,7 +126,8 @@ struct SRenderContextCore : public IQt3DSRenderContextCore
IRenderPluginManagerCore &GetRenderPluginCore() override { return *m_RenderPluginManagerCore; }
IPathManagerCore &GetPathManagerCore() override { return *m_PathManagerCore; }
IQt3DSRenderContext &CreateRenderContext(NVRenderContext &inContext,
- const char8_t *inPrimitivesDirectory) override;
+ const char8_t *inPrimitivesDirectory,
+ bool delayedLoading) override;
void SetTextRendererCore(ITextRendererCore &inRenderer) override { m_TextRenderer = inRenderer; }
ITextRendererCore *GetTextRendererCore() override { return m_TextRenderer.mPtr; }
void setDistanceFieldRenderer(ITextRendererCore &inRenderer) override
@@ -263,7 +264,7 @@ struct SRenderContext : public IQt3DSRenderContext
bool m_AuthoringMode;
SRenderContext(NVRenderContext &ctx, IQt3DSRenderContextCore &inCore,
- const char8_t *inApplicationDirectory)
+ const char8_t *inApplicationDirectory, bool delayedLoading)
: m_RenderContext(ctx)
, m_CoreContext(inCore)
, m_StringTable(ctx.GetStringTable())
@@ -288,6 +289,7 @@ struct SRenderContext : public IQt3DSRenderContext
, m_FPS(qMakePair(0.0, 0))
, m_AuthoringMode(false)
{
+ m_BufferManager->enableReloadableResources(delayedLoading);
m_OffscreenRenderManager = IOffscreenRenderManager::CreateOffscreenRenderManager(
ctx.GetAllocator(), *m_StringTable, *m_ResourceManager, *this);
m_Renderer = IQt3DSRenderer::CreateRenderer(*this);
@@ -827,10 +829,12 @@ struct SRenderContext : public IQt3DSRenderContext
};
IQt3DSRenderContext &SRenderContextCore::CreateRenderContext(NVRenderContext &inContext,
- const char8_t *inPrimitivesDirectory)
+ const char8_t *inPrimitivesDirectory,
+ bool delayedLoading)
{
return *QT3DS_NEW(m_Foundation.getAllocator(), SRenderContext)(inContext, *this,
- inPrimitivesDirectory);
+ inPrimitivesDirectory,
+ delayedLoading);
}
}
diff --git a/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.h b/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.h
index 012864ba..2fcd1e0b 100644
--- a/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.h
+++ b/src/Runtime/Source/runtimerender/Qt3DSRenderContextCore.h
@@ -77,7 +77,8 @@ namespace render {
virtual ITextRendererCore *GetOnscreenTextRendererCore() = 0;
// The render context maintains a reference to this object.
virtual IQt3DSRenderContext &CreateRenderContext(NVRenderContext &inContext,
- const char8_t *inPrimitivesDirectory) = 0;
+ const char8_t *inPrimitivesDirectory,
+ bool delayedLoading) = 0;
static IQt3DSRenderContextCore &Create(NVFoundationBase &fnd, IStringTable &strt);
};
diff --git a/src/Runtime/Source/runtimerender/Qt3DSRenderImageTextureData.h b/src/Runtime/Source/runtimerender/Qt3DSRenderImageTextureData.h
index d3698032..aaa73d7e 100644
--- a/src/Runtime/Source/runtimerender/Qt3DSRenderImageTextureData.h
+++ b/src/Runtime/Source/runtimerender/Qt3DSRenderImageTextureData.h
@@ -33,6 +33,9 @@
#include "Qt3DSRender.h"
#include "foundation/Qt3DSFlags.h"
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qvector.h>
+
namespace qt3ds {
namespace render {
@@ -85,9 +88,16 @@ namespace render {
Qt3DSRenderPrefilterTexture *m_BSDFMipMap;
SImageTextureData()
- : m_Texture(NULL)
- , m_BSDFMipMap(NULL)
+ : m_Texture(nullptr)
+ , m_BSDFMipMap(nullptr)
+ {
+ }
+
+ SImageTextureData(const SImageTextureData& data)
+ : m_Texture(data.m_Texture), m_TextureFlags(data.m_TextureFlags)
+ , m_BSDFMipMap(data.m_BSDFMipMap)
{
+
}
bool operator!=(const SImageTextureData &inOther)
@@ -96,7 +106,33 @@ namespace render {
|| m_BSDFMipMap != inOther.m_BSDFMipMap;
}
};
+
+ struct IReloadableCallback
+ {
+ virtual ~IReloadableCallback() {}
+ virtual void onLoad() = 0;
+ virtual void onUnload() = 0;
+ };
+
+ struct SImage;
+ struct SReloadableImageTextureData : public SImageTextureData
+ {
+ QString m_path;
+ bool m_loaded;
+ bool m_scanTransparency;
+ bool m_bsdfMipmap;
+ bool m_initialized;
+ QVector<SImage *> m_callbacks;
+
+ SReloadableImageTextureData()
+ : SImageTextureData()
+ , m_loaded(false), m_scanTransparency(false), m_bsdfMipmap(false), m_initialized(false)
+ {
+ }
+ };
+
+ typedef QSharedPointer<SReloadableImageTextureData> ReloadableTexturePtr;
}
}
-#endif \ No newline at end of file
+#endif
diff --git a/src/Runtime/Source/runtimerender/Qt3DSRenderRenderList.cpp b/src/Runtime/Source/runtimerender/Qt3DSRenderRenderList.cpp
index 118c855d..05a7b2c4 100644
--- a/src/Runtime/Source/runtimerender/Qt3DSRenderRenderList.cpp
+++ b/src/Runtime/Source/runtimerender/Qt3DSRenderRenderList.cpp
@@ -45,6 +45,7 @@ struct SRenderList : public IRenderList
NVFoundationBase &m_Foundation;
TTaskList m_Tasks;
+ TTaskList m_PersistentTasks;
QT3DSU32 m_NextTaskId;
QT3DSI32 mRefCount;
bool m_ScissorEnabled;
@@ -54,6 +55,7 @@ struct SRenderList : public IRenderList
SRenderList(NVFoundationBase &fnd)
: m_Foundation(fnd)
, m_Tasks(fnd.getAllocator(), "m_Tasks")
+ , m_PersistentTasks(fnd.getAllocator(), "m_PersistentTasks")
, m_NextTaskId(1)
, mRefCount(0)
, m_ScissorEnabled(false)
@@ -71,8 +73,14 @@ struct SRenderList : public IRenderList
QT3DSU32 AddRenderTask(IRenderTask &inTask) override
{
QT3DSU32 taskId = m_NextTaskId;
- ++m_NextTaskId;
- m_Tasks.push_back(eastl::make_pair(taskId, &inTask));
+ if (inTask.persistent()) {
+ m_PersistentTasks.push_back(eastl::make_pair(0, &inTask));
+ taskId = 0;
+ } else {
+ QT3DSU32 taskId = m_NextTaskId;
+ ++m_NextTaskId;
+ m_Tasks.push_back(eastl::make_pair(taskId, &inTask));
+ }
return taskId;
}
@@ -89,9 +97,15 @@ struct SRenderList : public IRenderList
// before rendering to the main render target.
void RunRenderTasks() override
{
+ for (TTaskList::reverse_iterator iter = m_PersistentTasks.rbegin(),
+ end = m_PersistentTasks.rend(); iter != end;
+ ++iter) {
+ iter->second->Run();
+ }
for (TTaskList::reverse_iterator iter = m_Tasks.rbegin(), end = m_Tasks.rend(); iter != end;
- ++iter)
+ ++iter) {
iter->second->Run();
+ }
BeginFrame();
}
diff --git a/src/Runtime/Source/runtimerender/Qt3DSRenderRenderList.h b/src/Runtime/Source/runtimerender/Qt3DSRenderRenderList.h
index c498c7ee..957c3d78 100644
--- a/src/Runtime/Source/runtimerender/Qt3DSRenderRenderList.h
+++ b/src/Runtime/Source/runtimerender/Qt3DSRenderRenderList.h
@@ -42,6 +42,10 @@ namespace render {
public:
virtual ~IRenderTask() {}
virtual void Run() = 0;
+ virtual bool persistent() const
+ {
+ return false;
+ }
};
/**
diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.cpp
index eaa98c77..1cbd6015 100644
--- a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.cpp
+++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.cpp
@@ -38,9 +38,9 @@ using namespace qt3ds::render;
SImage::SImage()
: SGraphObject(GraphObjectTypes::Image)
- , m_RenderPlugin(NULL)
- , m_LastFrameOffscreenRenderer(NULL)
- , m_Parent(NULL)
+ , m_RenderPlugin(nullptr)
+ , m_LastFrameOffscreenRenderer(nullptr)
+ , m_Parent(nullptr)
, m_Scale(1, 1)
, m_Pivot(0, 0)
, m_Rotation(0)
@@ -84,7 +84,7 @@ bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager
}
}
- if (newImage.m_Texture == NULL) {
+ if (newImage.m_Texture == nullptr) {
if (m_OffscreenRendererId.IsValid()) {
SOffscreenRenderResult theResult =
inRenderManager.GetRenderedItem(m_OffscreenRendererId);
@@ -92,10 +92,26 @@ bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager
}
}
- if (newImage.m_Texture == NULL) {
- m_LastFrameOffscreenRenderer = NULL;
- newImage = inBufferManager.LoadRenderImage(m_ImagePath, false, forIbl);
- replaceTexture = newImage.m_Texture != m_TextureData.m_Texture;
+ if (newImage.m_Texture == nullptr) {
+ m_LastFrameOffscreenRenderer = nullptr;
+ if (m_ImagePath.IsValid()) {
+ if (!m_LoadedTextureData
+ || m_LoadedTextureData->m_path != QString::fromUtf8(m_ImagePath.c_str())) {
+ if (m_LoadedTextureData)
+ m_LoadedTextureData->m_callbacks.removeOne(this);
+ m_LoadedTextureData = inBufferManager.CreateReloadableImage(m_ImagePath, false,
+ forIbl);
+ m_LoadedTextureData->m_callbacks.push_back(this);
+ }
+ if (m_LoadedTextureData) {
+ if (m_LoadedTextureData->m_loaded) {
+ newImage.m_Texture = m_LoadedTextureData->m_Texture;
+ newImage.m_TextureFlags = m_LoadedTextureData->m_TextureFlags;
+ newImage.m_BSDFMipMap = m_LoadedTextureData->m_BSDFMipMap;
+ }
+ replaceTexture = m_TextureData.m_Texture != newImage.m_Texture;
+ }
+ }
}
if (replaceTexture) {
diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.h
index 47993e73..9b71d3f1 100644
--- a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.h
+++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.h
@@ -67,6 +67,7 @@ namespace render {
SGraphObject *m_Parent;
SImageTextureData m_TextureData;
+ ReloadableTexturePtr m_LoadedTextureData;
NodeFlags m_Flags; // only dirty, transform dirty, and active apply
diff --git a/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp b/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
index 37ca281f..15cf7323 100644
--- a/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
+++ b/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
@@ -45,6 +45,7 @@
#include "foundation/Qt3DSFoundation.h"
#include "Qt3DSRenderInputStreamFactory.h"
#include "Qt3DSRenderImageScaler.h"
+#include "Qt3DSRenderImage.h"
#include "Qt3DSTextRenderer.h"
#include "foundation/Qt3DSPerfTimer.h"
#include "foundation/Qt3DSMutex.h"
@@ -76,13 +77,13 @@ struct SImageEntry : public SImageTextureData
{
bool m_Loaded;
SImageEntry()
- : m_Loaded(false)
+ : SImageTextureData(), m_Loaded(false)
{
}
- ~SImageEntry()
+ SImageEntry(const SImageEntry &entry)
+ : SImageTextureData(entry), m_Loaded(entry.m_Loaded)
{
- if (m_BSDFMipMap)
- m_BSDFMipMap->release();
+
}
};
@@ -117,6 +118,10 @@ struct SBufferManager : public IBufferManager
SPrimitiveEntry m_PrimitiveNames[5];
nvvector<qt3ds::render::NVRenderVertexBufferEntry> m_EntryBuffer;
bool m_GPUSupportsDXT;
+ bool m_reloadableResources;
+
+ QHash<QString, ReloadableTexturePtr> m_reloadableTextures;
+
static const char8_t *GetPrimitivesDirectory() { return "res//primitives"; }
SBufferManager(NVRenderContext &ctx, IStringTable &strTable,
@@ -135,6 +140,7 @@ struct SBufferManager : public IBufferManager
, m_MeshMap(ctx.GetAllocator(), "SBufferManager::m_MeshMap")
, m_EntryBuffer(ctx.GetAllocator(), "SBufferManager::m_EntryBuffer")
, m_GPUSupportsDXT(ctx.AreDXTImagesSupported())
+ , m_reloadableResources(false)
{
}
virtual ~SBufferManager() { Clear(); }
@@ -210,6 +216,15 @@ struct SBufferManager : public IBufferManager
return inSourcePath;
}
+ CRegisteredString getImagePath(const QString &path)
+ {
+ TAliasImageMap::iterator theAliasIter
+ = m_AliasImageMap.find(m_StrTable->RegisterStr(qPrintable(path)));
+ if (theAliasIter != m_AliasImageMap.end())
+ return theAliasIter->second;
+ return m_StrTable->RegisterStr(qPrintable(path));
+ }
+
static inline int wrapMod(int a, int base)
{
int ret = a % base;
@@ -232,6 +247,177 @@ struct SBufferManager : public IBufferManager
sY = wrapMod(sY, height);
}
+ template <typename V, typename C>
+ void iterateAll(const V &vv, C c)
+ {
+ for (const auto x : vv)
+ c(x);
+ }
+
+ void loadTextureImage(SReloadableImageTextureData &data)
+ {
+ CRegisteredString imagePath = getImagePath(data.m_path);
+ TImageMap::iterator theIter = m_ImageMap.find(imagePath);
+ if ((theIter == m_ImageMap.end() || theIter->second.m_Loaded == false)
+ && imagePath.IsValid()) {
+ NVScopedReleasable<SLoadedTexture> theLoadedImage;
+ SImageTextureData textureData;
+
+ doImageLoad(imagePath, theLoadedImage);
+
+ if (theLoadedImage) {
+ textureData = LoadRenderImage(imagePath, *theLoadedImage, data.m_scanTransparency,
+ data.m_bsdfMipmap);
+ data.m_Texture = textureData.m_Texture;
+ data.m_TextureFlags = textureData.m_TextureFlags;
+ data.m_BSDFMipMap = textureData.m_BSDFMipMap;
+ data.m_loaded = true;
+ iterateAll(data.m_callbacks, [](SImage *img){ img->m_Flags.SetDirty(true); });
+ } else {
+ // We want to make sure that bad path fails once and doesn't fail over and over
+ // again which could slow down the system quite a bit.
+ pair<TImageMap::iterator, bool> theImage =
+ m_ImageMap.insert(make_pair(imagePath, SImageEntry()));
+ theImage.first->second.m_Loaded = true;
+ qCWarning(WARNING, "Failed to load image: %s", imagePath.c_str());
+ theIter = theImage.first;
+ }
+ } else {
+ SImageEntry textureData = theIter->second;
+ if (textureData.m_Loaded) {
+ data.m_Texture = textureData.m_Texture;
+ data.m_TextureFlags = textureData.m_TextureFlags;
+ data.m_BSDFMipMap = textureData.m_BSDFMipMap;
+ data.m_loaded = true;
+ iterateAll(data.m_callbacks, [](SImage *img){ img->m_Flags.SetDirty(true); });
+ }
+ }
+ }
+
+ void unloadTextureImage(SReloadableImageTextureData &data)
+ {
+ CRegisteredString r = m_StrTable->RegisterStr(qPrintable(data.m_path));
+ data.m_loaded = false;
+ data.m_Texture = nullptr;
+ data.m_BSDFMipMap = nullptr;
+ data.m_TextureFlags = {};
+ iterateAll(data.m_callbacks, [](SImage *img){ img->m_Flags.SetDirty(true); });
+ InvalidateBuffer(r);
+ }
+
+ void loadSet(const QSet<QString> &imageSet) override
+ {
+ for (const auto &x : imageSet) {
+ if (!m_reloadableTextures.contains(x)) {
+ auto img = CreateReloadableImage(m_StrTable->RegisterStr(qPrintable(x)), false,
+ false);
+ img->m_initialized = false;
+ loadTextureImage(*m_reloadableTextures[x]);
+ } else if (!m_reloadableTextures[x]->m_loaded) {
+ loadTextureImage(*m_reloadableTextures[x]);
+ }
+ }
+ }
+
+ void unloadSet(const QSet<QString> &imageSet) override
+ {
+ for (const auto &x : imageSet) {
+ if (m_reloadableTextures.contains(x)) {
+ if (m_reloadableTextures[x]->m_loaded)
+ unloadTextureImage(*m_reloadableTextures[x]);
+ }
+ }
+ }
+
+ virtual ReloadableTexturePtr CreateReloadableImage(CRegisteredString inSourcePath,
+ bool inForceScanForTransparency,
+ bool inBsdfMipmaps) override
+ {
+ QString path = QString::fromLatin1(inSourcePath.c_str());
+ const bool inserted = m_reloadableTextures.contains(path);
+ if (!inserted || (inserted && m_reloadableTextures[path]->m_initialized == false)) {
+ if (!inserted)
+ m_reloadableTextures.insert(path, ReloadableTexturePtr::create());
+ m_reloadableTextures[path]->m_path = path;
+ m_reloadableTextures[path]->m_scanTransparency = inForceScanForTransparency;
+ m_reloadableTextures[path]->m_bsdfMipmap = inBsdfMipmaps;
+ m_reloadableTextures[path]->m_initialized = true;
+
+ if (!m_reloadableResources)
+ loadTextureImage(*m_reloadableTextures[path]);
+
+ CRegisteredString imagePath = getImagePath(path);
+ TImageMap::iterator theIter = m_ImageMap.find(imagePath);
+ if (theIter != m_ImageMap.end()) {
+ SImageEntry textureData = theIter->second;
+ if (textureData.m_Loaded) {
+ m_reloadableTextures[path]->m_Texture = textureData.m_Texture;
+ m_reloadableTextures[path]->m_TextureFlags = textureData.m_TextureFlags;
+ m_reloadableTextures[path]->m_BSDFMipMap = textureData.m_BSDFMipMap;
+ m_reloadableTextures[path]->m_loaded = true;
+ }
+ }
+ }
+ return m_reloadableTextures[path];
+ }
+
+ void doImageLoad(CRegisteredString inImagePath,
+ NVScopedReleasable<SLoadedTexture> &theLoadedImage)
+ {
+ SStackPerfTimer __perfTimer(m_PerfTimer, "Image Decompression");
+ theLoadedImage = SLoadedTexture::Load(
+ inImagePath.c_str(), m_Context->GetFoundation(), *m_InputStreamFactory,
+ true, m_Context->GetRenderContextType());
+ // Hackish solution to custom materials not finding their textures if they are used
+ // in sub-presentations.
+ if (!theLoadedImage) {
+ if (QDir(inImagePath.c_str()).isRelative()) {
+ QString searchPath = inImagePath.c_str();
+ if (searchPath.startsWith(QLatin1String("./")))
+ searchPath.prepend(QLatin1Char('.'));
+ int loops = 0;
+ while (!theLoadedImage && ++loops <= 3) {
+ theLoadedImage = SLoadedTexture::Load(
+ searchPath.toUtf8(), m_Context->GetFoundation(),
+ *m_InputStreamFactory, true,
+ m_Context->GetRenderContextType());
+ searchPath.prepend(QLatin1String("../"));
+ }
+ } else {
+ // Some textures, for example environment maps for custom materials,
+ // have absolute path at this point. It points to the wrong place with
+ // the new project structure, so we need to split it up and construct
+ // the new absolute path here.
+ QString wholePath = inImagePath.c_str();
+ QStringList splitPath = wholePath.split(QLatin1String("../"));
+ if (splitPath.size() > 1) {
+ QString searchPath = splitPath.at(0) + splitPath.at(1);
+ int loops = 0;
+ while (!theLoadedImage && ++loops <= 3) {
+ theLoadedImage = SLoadedTexture::Load(
+ searchPath.toUtf8(), m_Context->GetFoundation(),
+ *m_InputStreamFactory, true,
+ m_Context->GetRenderContextType());
+ searchPath = splitPath.at(0);
+ for (int i = 0; i < loops; i++)
+ searchPath.append(QLatin1String("../"));
+ searchPath.append(splitPath.at(1));
+ }
+ }
+ }
+ }
+ }
+
+ void enableReloadableResources(bool enable) override
+ {
+ m_reloadableResources = enable;
+ }
+
+ bool isReloadableResourcesEnabled() const override
+ {
+ return m_reloadableResources;
+ }
+
SImageTextureData LoadRenderImage(CRegisteredString inImagePath,
SLoadedTexture &inLoadedImage,
bool inForceScanForTransparency, bool inBsdfMipmaps) override
@@ -336,51 +522,8 @@ struct SBufferManager : public IBufferManager
TImageMap::iterator theIter = m_ImageMap.find(inImagePath);
if (theIter == m_ImageMap.end() && inImagePath.IsValid()) {
NVScopedReleasable<SLoadedTexture> theLoadedImage;
- {
- SStackPerfTimer __perfTimer(m_PerfTimer, "Image Decompression");
- theLoadedImage = SLoadedTexture::Load(
- inImagePath.c_str(), m_Context->GetFoundation(), *m_InputStreamFactory,
- true, m_Context->GetRenderContextType());
- // Hackish solution to custom materials not finding their textures if they are used
- // in sub-presentations. Note: Runtime 1 is going to be removed in Qt 3D Studio 2.x,
- // so this should be ok.
- if (!theLoadedImage) {
- if (QDir(inImagePath.c_str()).isRelative()) {
- QString searchPath = inImagePath.c_str();
- if (searchPath.startsWith(QLatin1String("./")))
- searchPath.prepend(QLatin1String("."));
- int loops = 0;
- while (!theLoadedImage && ++loops <= 3) {
- theLoadedImage = SLoadedTexture::Load(
- searchPath.toUtf8(), m_Context->GetFoundation(),
- *m_InputStreamFactory, true,
- m_Context->GetRenderContextType());
- searchPath.prepend(QLatin1String("../"));
- }
- } else {
- // Some textures, for example environment maps for custom materials,
- // have absolute path at this point. It points to the wrong place with
- // the new project structure, so we need to split it up and construct
- // the new absolute path here.
- QString wholePath = inImagePath.c_str();
- QStringList splitPath = wholePath.split(QLatin1String("../"));
- if (splitPath.size() > 1) {
- QString searchPath = splitPath.at(0) + splitPath.at(1);
- int loops = 0;
- while (!theLoadedImage && ++loops <= 3) {
- theLoadedImage = SLoadedTexture::Load(
- searchPath.toUtf8(), m_Context->GetFoundation(),
- *m_InputStreamFactory, true,
- m_Context->GetRenderContextType());
- searchPath = splitPath.at(0);
- for (int i = 0; i < loops; i++)
- searchPath.append(QLatin1String("../"));
- searchPath.append(splitPath.at(1));
- }
- }
- }
- }
- }
+
+ doImageLoad(inImagePath, theLoadedImage);
if (theLoadedImage) {
return LoadRenderImage(inImagePath, *theLoadedImage, inForceScanForTransparency,
@@ -862,6 +1005,8 @@ struct SBufferManager : public IBufferManager
{
if (inEntry.m_Texture)
inEntry.m_Texture->release();
+ if (inEntry.m_BSDFMipMap)
+ inEntry.m_BSDFMipMap->release();
}
void Clear() override
{
@@ -916,5 +1061,5 @@ IBufferManager &IBufferManager::Create(NVRenderContext &inRenderContext, IString
IInputStreamFactory &inFactory, IPerfTimer &inPerfTimer)
{
return *QT3DS_NEW(inRenderContext.GetAllocator(), SBufferManager)(inRenderContext, inStrTable,
- inFactory, inPerfTimer);
+ inFactory, inPerfTimer);
}
diff --git a/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h b/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
index cd9e3d33..d595c902 100644
--- a/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
+++ b/src/Runtime/Source/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
@@ -83,6 +83,16 @@ namespace render {
virtual SImageTextureData LoadRenderImage(CRegisteredString inSourcePath,
bool inForceScanForTransparency = false,
bool inBsdfMipmaps = false) = 0;
+
+ virtual ReloadableTexturePtr CreateReloadableImage(CRegisteredString inSourcePath,
+ bool inForceScanForTransparency = false,
+ bool inBsdfMipmaps = false) = 0;
+ virtual void enableReloadableResources(bool enable) = 0;
+ virtual bool isReloadableResourcesEnabled() const = 0;
+
+ virtual void loadSet(const QSet<QString> &imageSet) = 0;
+ virtual void unloadSet(const QSet<QString> &imageSet) = 0;
+
virtual SRenderMesh *LoadMesh(CRegisteredString inSourcePath) = 0;
virtual SRenderMesh *CreateMesh(const char *inSourcePath, QT3DSU8 *inVertData,
diff --git a/src/Runtime/Source/uipparser/Qt3DSUIPParser.h b/src/Runtime/Source/uipparser/Qt3DSUIPParser.h
index 857d403c..c3b4611b 100644
--- a/src/Runtime/Source/uipparser/Qt3DSUIPParser.h
+++ b/src/Runtime/Source/uipparser/Qt3DSUIPParser.h
@@ -143,6 +143,8 @@ public: // Parse UIP file
// mesh files (and possibly font files).
virtual NVConstDataRef<eastl::string> GetSourcePaths() const = 0;
+ virtual QVector<QString> GetSlideSourcePaths() const = 0;
+
// Creation function
static IUIPParser &Create(const QString &inFileName, IRuntimeMetaData &inMetaData,
qt3ds::render::IInputStreamFactory &inStreamFactory,
diff --git a/src/Runtime/Source/uipparser/Qt3DSUIPParserImpl.cpp b/src/Runtime/Source/uipparser/Qt3DSUIPParserImpl.cpp
index 746d5e58..2ddffe3f 100644
--- a/src/Runtime/Source/uipparser/Qt3DSUIPParserImpl.cpp
+++ b/src/Runtime/Source/uipparser/Qt3DSUIPParserImpl.cpp
@@ -2089,8 +2089,11 @@ BOOL CUIPParserImpl::LoadSlideElementAttrs(IPresentation &inPresentation, bool,
++theRef;
bool isSet = AreEqual(inReader.GetNarrowElementName(), "Set");
const char8_t *sourcepath;
- if (inReader.UnregisteredAtt("sourcepath", sourcepath))
+ if (inReader.UnregisteredAtt("sourcepath", sourcepath)) {
AddSourcePath(sourcepath);
+ theBuilder.AddSourcePath(sourcepath);
+ m_slideSourcePaths.push_back(QString::fromLatin1(sourcepath));
+ }
// We don't force set attributes when a given component has a set command within one of its
// child states. This happens in the case of actions (but nothing else).
diff --git a/src/Runtime/Source/uipparser/Qt3DSUIPParserImpl.h b/src/Runtime/Source/uipparser/Qt3DSUIPParserImpl.h
index 9d96b681..fd921161 100644
--- a/src/Runtime/Source/uipparser/Qt3DSUIPParserImpl.h
+++ b/src/Runtime/Source/uipparser/Qt3DSUIPParserImpl.h
@@ -429,6 +429,8 @@ protected:
TStringSet m_SourcePathSet;
TStringVector m_SourcePathList;
+ QVector<QString> m_slideSourcePaths;
+
struct SElementRefCache
{
SElementData *m_Element;
@@ -534,6 +536,10 @@ public: // Parse UIP file
{
return NVConstDataRef<eastl::string>(m_SourcePathList.data(), m_SourcePathList.size());
}
+ QVector<QString> GetSlideSourcePaths() const override
+ {
+ return m_slideSourcePaths;
+ }
protected: // Operation
BOOL LoadProjectSettings(IPresentation &inPresentation, qt3dsdm::IDOMReader &inReader);
diff --git a/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp b/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp
index 24d768e9..ccf0a911 100644
--- a/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp
+++ b/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp
@@ -301,9 +301,10 @@ 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)
+ int offscreenID, const QString &source,
+ const QStringList &variantList,
+ bool delayedLoading,
+ qt3ds::Qt3DSAssetVisitor *assetVisitor)
{
bool hasValidPresentationFile = !source.isEmpty();
@@ -339,7 +340,7 @@ bool Q3DSViewerApp::InitializeApp(int winWidth, int winHeight, const QSurfaceFor
return false;
}
- bool success = m_Impl.m_view->InitializeGraphics(format);
+ bool success = m_Impl.m_view->InitializeGraphics(format, delayedLoading);
if (!success) {
m_Impl.m_error = QObject::tr("Viewer launch failure! Failed to load: '%1'").arg(source);
m_Impl.m_error.append("\n");
@@ -458,6 +459,27 @@ QString Q3DSViewerApp::error()
return error;
}
+void Q3DSViewerApp::setDelayedLoading(bool enable)
+{
+ if (!m_Impl.m_view)
+ return;
+ m_Impl.m_view->setDelayedLoading(enable);
+}
+
+void Q3DSViewerApp::preloadSlide(const QString &slide)
+{
+ if (!m_Impl.m_view)
+ return;
+ m_Impl.m_view->preloadSlide(slide);
+}
+
+void Q3DSViewerApp::unloadSlide(const QString &slide)
+{
+ if (!m_Impl.m_view)
+ return;
+ m_Impl.m_view->unloadSlide(slide);
+}
+
void Q3DSViewerApp::Resize(int width, int height)
{
QSize oldSize = m_Impl.m_WindowSystem->GetWindowDimensions();
diff --git a/src/Runtime/Source/viewer/Qt3DSViewerApp.h b/src/Runtime/Source/viewer/Qt3DSViewerApp.h
index 65dcda0a..38447579 100644
--- a/src/Runtime/Source/viewer/Qt3DSViewerApp.h
+++ b/src/Runtime/Source/viewer/Qt3DSViewerApp.h
@@ -116,6 +116,7 @@ public:
bool InitializeApp(int winWidth, int winHeight, const QSurfaceFormat& format,
int offscreenID, const QString &source,
const QStringList &variantList,
+ bool delayedLoading,
qt3ds::Qt3DSAssetVisitor *assetVisitor = nullptr);
bool IsInitialised(void);
@@ -359,6 +360,9 @@ public:
QString error();
void setPresentationId(const QString &id);
+ void preloadSlide(const QString &slide);
+ void unloadSlide(const QString &slide);
+ void setDelayedLoading(bool enable);
private:
/*
diff --git a/src/Runtime/qt3d-runtime b/src/Runtime/qt3d-runtime
-Subproject 228b1c7ce76a134e4d2e67809ef8b86f371a15e
+Subproject 5e0bfe934b9930b7e41d457b4f88fce91342a0e
diff --git a/src/Viewer/qmlviewer/Qt3DSRenderer.cpp b/src/Viewer/qmlviewer/Qt3DSRenderer.cpp
index e62d1267..3fe817a9 100644
--- a/src/Viewer/qmlviewer/Qt3DSRenderer.cpp
+++ b/src/Viewer/qmlviewer/Qt3DSRenderer.cpp
@@ -95,6 +95,7 @@ void Q3DSRenderer::synchronize(QQuickFramebufferObject *inView)
// processCommands, as both are needed for init
m_presentation->setVariantList(m_commands.m_variantList);
m_presentation->setSource(m_commands.m_source);
+ m_presentation->setDelayedLoading(m_commands.m_delayedLoading);
m_initialized = false;
m_initializationFailure = false;
m_error.clear();
@@ -183,6 +184,7 @@ bool Q3DSRenderer::initializeRuntime(QOpenGLFramebufferObject *inFbo)
QOpenGLContext::currentContext()->format(),
inFbo->handle(), localSource,
m_presentation->variantList(),
+ m_presentation->delayedLoading(),
m_visitor)) {
m_error = m_runtime->error();
releaseRuntime();
@@ -268,6 +270,8 @@ void Q3DSRenderer::processCommands()
m_settings->setMatteColor(m_commands.m_matteColor);
if (m_commands.m_showRenderStatsChanged)
m_settings->setShowRenderStats(m_commands.m_showRenderStats);
+ if (m_commands.m_delayedLoadingChanged)
+ this->m_runtime->setDelayedLoading(m_commands.m_delayedLoading);
if (m_commands.m_globalAnimationTimeChanged)
m_presentation->setGlobalAnimationTime(m_commands.m_globalAnimationTime);
@@ -352,6 +356,12 @@ void Q3DSRenderer::processCommands()
Q_EMIT requestResponse(cmd.m_elementPath, cmd.m_commandType, requestData);
break;
}
+ case CommandType_PreloadSlide:
+ m_runtime->preloadSlide(cmd.m_elementPath);
+ break;
+ case CommandType_UnloadSlide:
+ m_runtime->unloadSlide(cmd.m_elementPath);
+ break;
default:
qWarning() << __FUNCTION__ << "Unrecognized CommandType in command list!";
}
diff --git a/src/Viewer/studio3d/q3dscommandqueue.cpp b/src/Viewer/studio3d/q3dscommandqueue.cpp
index eba5a545..2bc540af 100644
--- a/src/Viewer/studio3d/q3dscommandqueue.cpp
+++ b/src/Viewer/studio3d/q3dscommandqueue.cpp
@@ -50,11 +50,13 @@ CommandQueue::CommandQueue()
, m_sourceChanged(false)
, m_variantListChanged(false)
, m_globalAnimationTimeChanged(false)
+ , m_delayedLoadingChanged(false)
, m_visible(false)
, m_scaleMode(Q3DSViewerSettings::ScaleModeCenter)
, m_shadeMode(Q3DSViewerSettings::ShadeModeShaded)
, m_showRenderStats(false)
, m_matteColor(Qt::black)
+ , m_delayedLoading(false)
, m_size(0)
{
qRegisterMetaType<CommandType>();
@@ -165,6 +167,7 @@ void CommandQueue::copyCommands(const CommandQueue &fromQueue)
m_variantListChanged = m_variantListChanged || fromQueue.m_variantListChanged;
m_globalAnimationTimeChanged
= m_globalAnimationTimeChanged || fromQueue.m_globalAnimationTimeChanged;
+ m_delayedLoadingChanged = m_delayedLoadingChanged || fromQueue.m_delayedLoadingChanged;
if (fromQueue.m_visibleChanged)
m_visible = fromQueue.m_visible;
@@ -182,6 +185,8 @@ void CommandQueue::copyCommands(const CommandQueue &fromQueue)
m_variantList = fromQueue.m_variantList;
if (fromQueue.m_globalAnimationTimeChanged)
m_globalAnimationTime = fromQueue.m_globalAnimationTime;
+ if (fromQueue.m_delayedLoadingChanged)
+ m_delayedLoading = fromQueue.m_delayedLoading;
// Pending queue may be synchronized multiple times between queue processing, so let's append
// to the existing queue rather than clearing it.
@@ -221,6 +226,8 @@ void CommandQueue::copyCommands(const CommandQueue &fromQueue)
source.m_intValues[2], source.m_intValues[3]);
break;
case CommandType_RequestSlideInfo:
+ case CommandType_UnloadSlide:
+ case CommandType_PreloadSlide:
queueRequest(source.m_elementPath, source.m_commandType);
break;
case CommandType_RequestDataInputs:
@@ -244,6 +251,7 @@ void CommandQueue::clear()
m_sourceChanged = false;
m_variantListChanged = false;
m_globalAnimationTimeChanged = false;
+ m_delayedLoadingChanged = false;
// We do not clear the actual queued commands, those will be reused the next frame
// To avoid a lot of unnecessary reallocations.
diff --git a/src/Viewer/studio3d/q3dscommandqueue_p.h b/src/Viewer/studio3d/q3dscommandqueue_p.h
index 46b77d08..27612bfb 100644
--- a/src/Viewer/studio3d/q3dscommandqueue_p.h
+++ b/src/Viewer/studio3d/q3dscommandqueue_p.h
@@ -69,7 +69,9 @@ enum CommandType {
CommandType_SetGlobalAnimationTime,
CommandType_SetDataInputValue,
CommandType_RequestSlideInfo,
- CommandType_RequestDataInputs
+ CommandType_RequestDataInputs,
+ CommandType_PreloadSlide,
+ CommandType_UnloadSlide
};
class Q_STUDIO3D_EXPORT ElementCommand
@@ -124,6 +126,7 @@ public:
bool m_sourceChanged;
bool m_variantListChanged;
bool m_globalAnimationTimeChanged;
+ bool m_delayedLoadingChanged;
bool m_visible;
Q3DSViewerSettings::ScaleMode m_scaleMode;
@@ -133,6 +136,7 @@ public:
QUrl m_source;
QStringList m_variantList;
qint64 m_globalAnimationTime;
+ bool m_delayedLoading;
void clear();
int size() const { return m_size; }
diff --git a/src/Viewer/studio3d/q3dspresentation.cpp b/src/Viewer/studio3d/q3dspresentation.cpp
index d0d93e4f..f4235456 100644
--- a/src/Viewer/studio3d/q3dspresentation.cpp
+++ b/src/Viewer/studio3d/q3dspresentation.cpp
@@ -129,6 +129,35 @@ void Q3DSPresentation::setVariantList(const QStringList &variantList)
}
}
+bool Q3DSPresentation::delayedLoading() const
+{
+ return d_ptr->m_delayedLoading;
+}
+
+void Q3DSPresentation::setDelayedLoading(bool enable)
+{
+ if (d_ptr->m_delayedLoading != enable) {
+ d_ptr->setDelayedLoading(enable);
+ Q_EMIT delayedLoadingChanged(enable);
+ }
+}
+
+void Q3DSPresentation::preloadSlide(const QString &elementPath)
+{
+ if (d_ptr->m_viewerApp)
+ d_ptr->m_viewerApp->preloadSlide(elementPath);
+ else if (d_ptr->m_commandQueue)
+ d_ptr->m_commandQueue->queueRequest(elementPath, CommandType_PreloadSlide);
+}
+
+void Q3DSPresentation::unloadSlide(const QString &elementPath)
+{
+ if (d_ptr->m_viewerApp)
+ d_ptr->m_viewerApp->unloadSlide(elementPath);
+ else if (d_ptr->m_commandQueue)
+ d_ptr->m_commandQueue->queueRequest(elementPath, CommandType_UnloadSlide);
+}
+
void Q3DSPresentation::goToSlide(const QString &elementPath, unsigned int index)
{
if (d_ptr->m_viewerApp) {
@@ -330,6 +359,7 @@ Q3DSPresentationPrivate::Q3DSPresentationPrivate(Q3DSPresentation *q)
, m_viewerApp(nullptr)
, m_commandQueue(nullptr)
, m_streamProxy(nullptr)
+ , m_delayedLoading(false)
{
}
@@ -410,11 +440,21 @@ void Q3DSPresentationPrivate::setCommandQueue(CommandQueue *queue)
di->d_ptr->setCommandQueue(queue);
if (m_commandQueue) {
- setSource(m_source);
+ setDelayedLoading(m_delayedLoading);
setVariantList(m_variantList);
// Queue a request ASAP for datainputs defined in UIA file so that
// getDataInputs has up-to-date info at the earliest.
m_commandQueue->queueRequest({}, CommandType_RequestDataInputs);
+ setSource(m_source);
+ }
+}
+
+void Q3DSPresentationPrivate::setDelayedLoading(bool enable)
+{
+ m_delayedLoading = enable;
+ if (m_commandQueue) {
+ m_commandQueue->m_delayedLoading = enable;
+ m_commandQueue->m_delayedLoadingChanged = true;
}
}
diff --git a/src/Viewer/studio3d/q3dspresentation.h b/src/Viewer/studio3d/q3dspresentation.h
index 38625583..34809613 100644
--- a/src/Viewer/studio3d/q3dspresentation.h
+++ b/src/Viewer/studio3d/q3dspresentation.h
@@ -49,6 +49,7 @@ class Q_STUDIO3D_EXPORT Q3DSPresentation : public QObject
Q_DECLARE_PRIVATE(Q3DSPresentation)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(QStringList variantList READ variantList WRITE setVariantList NOTIFY variantListChanged)
+ Q_PROPERTY(bool delayedLoading READ delayedLoading WRITE setDelayedLoading NOTIFY delayedLoadingChanged)
public:
explicit Q3DSPresentation(QObject *parent = nullptr);
@@ -68,6 +69,12 @@ public:
Q_INVOKABLE QVariantList getDataInputs() const;
QVector<Q3DSDataInput *> dataInputs() const;
+ bool delayedLoading() const;
+ void setDelayedLoading(bool enable);
+
+ Q_INVOKABLE void preloadSlide(const QString &elementPath);
+ Q_INVOKABLE void unloadSlide(const QString &elementPath);
+
// Input event handlers
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
@@ -100,6 +107,7 @@ Q_SIGNALS:
// and datainputs are available through dataInputs() / getDataInputs().
void dataInputsReady();
void customSignalEmitted(const QString &elementPath, const QString &name);
+ void delayedLoadingChanged(bool enable);
private:
Q_DISABLE_COPY(Q3DSPresentation)
diff --git a/src/Viewer/studio3d/q3dspresentation_p.h b/src/Viewer/studio3d/q3dspresentation_p.h
index 7ae7b945..c82e27a7 100644
--- a/src/Viewer/studio3d/q3dspresentation_p.h
+++ b/src/Viewer/studio3d/q3dspresentation_p.h
@@ -69,6 +69,7 @@ public:
void setVariantList(const QStringList &variantList);
void setViewerApp(Q3DSViewer::Q3DSViewerApp *app, bool connectApp = true);
void setCommandQueue(CommandQueue *queue);
+ void setDelayedLoading(bool enable);
void registerElement(Q3DSElement *element);
void unregisterElement(Q3DSElement *element);
@@ -101,6 +102,7 @@ private:
QUrl m_source;
QStringList m_variantList;
ViewerQmlStreamProxy *m_streamProxy;
+ bool m_delayedLoading;
};
QT_END_NAMESPACE