summaryrefslogtreecommitdiffstats
path: root/src/Runtime
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2019-05-03 17:32:41 +0300
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2019-05-14 12:02:22 +0000
commit0a82b82de3ad7796cf91a355017a24ace2c830b4 (patch)
tree431464639e01b1e8313b420c33dbdcc7fbd4683b /src/Runtime
parentd34ae2ca1590c063e26bd294c26accd9e8b605a1 (diff)
Add material creation to runtime C++ API
Materials can only be created into the material container, animatable materials are not supported. Elements using new created materials should not be created before Q3DSPresentation::materialCreated signal is received. Task-number: QT3DS-3377 Change-Id: I782f09094d5f7151d7e1dab28b76fbbfdfcb6066 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Jari Karppinen <jari.karppinen@qt.io> Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
Diffstat (limited to 'src/Runtime')
-rw-r--r--src/Runtime/Qt3DSRuntimeStatic/Qt3DSRuntimeStatic.pro2
-rw-r--r--src/Runtime/Source/engine/Qt3DSRuntimeView.cpp16
-rw-r--r--src/Runtime/Source/engine/Qt3DSRuntimeView.h2
-rw-r--r--src/Runtime/Source/runtime/Qt3DSApplication.cpp4
-rw-r--r--src/Runtime/Source/runtime/Qt3DSIScriptBridge.h6
-rw-r--r--src/Runtime/Source/runtime/Qt3DSPresentation.cpp80
-rw-r--r--src/Runtime/Source/runtime/Qt3DSPresentation.h58
-rw-r--r--src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp590
-rw-r--r--src/Runtime/Source/runtime/q3dsmaterialdefinitionparser.cpp138
-rw-r--r--src/Runtime/Source/runtime/q3dsmaterialdefinitionparser.h49
-rw-r--r--src/Runtime/Source/uipparser/Qt3DSIPresentation.h42
-rw-r--r--src/Runtime/Source/viewer/Qt3DSViewerApp.cpp10
-rw-r--r--src/Runtime/Source/viewer/Qt3DSViewerApp.h2
13 files changed, 814 insertions, 185 deletions
diff --git a/src/Runtime/Qt3DSRuntimeStatic/Qt3DSRuntimeStatic.pro b/src/Runtime/Qt3DSRuntimeStatic/Qt3DSRuntimeStatic.pro
index 9d5d2a01..1a76455a 100644
--- a/src/Runtime/Qt3DSRuntimeStatic/Qt3DSRuntimeStatic.pro
+++ b/src/Runtime/Qt3DSRuntimeStatic/Qt3DSRuntimeStatic.pro
@@ -57,6 +57,7 @@ SOURCES += \
../Source/runtime/Qt3DSSlideSystem.cpp \
../Source/runtime/Qt3DSTimePolicy.cpp \
../Source/runtime/q3dsvariantconfig.cpp \
+ ../Source/runtime/q3dsmaterialdefinitionparser.cpp \
../Source/runtimerender/graphobjects/Qt3DSRenderCamera.cpp \
../Source/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.cpp \
../Source/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp \
@@ -258,6 +259,7 @@ HEADERS += \
../Source/runtime/Qt3DSIText.h \
../Source/runtime/Qt3DSKernelTypes.h \
../Source/runtime/q3dsvariantconfig_p.h \
+ ../Source/runtime/q3dsmaterialdefinitionparser.h \
../Source/runtimerender/graphobjects/Qt3DSRenderCamera.h \
../Source/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h \
../Source/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.h \
diff --git a/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp b/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp
index 5e6506b3..5d6b0a6c 100644
--- a/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp
+++ b/src/Runtime/Source/engine/Qt3DSRuntimeView.cpp
@@ -218,6 +218,7 @@ public:
void createElement(const QString &parentElementPath, const QString &slideName,
const QHash<QString, QVariant> &properties) override;
void deleteElement(const QString &elementPath) override;
+ void createMaterial(const QString &elementPath, const QString &materialDefinition) override;
void SetAttribute(const char *elementPath, const char *attributeName,
const char *value) override;
bool GetAttribute(const char *elementPath, const char *attributeName, void *value) override;
@@ -309,6 +310,8 @@ bool CRuntimeView::InitializeGraphics(const QSurfaceFormat &format, bool delayed
signalProxy(), &QRuntimeViewSignalProxy::SigSlideExited);
QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigCustomSignal,
signalProxy(), &QRuntimeViewSignalProxy::SigCustomSignal);
+ QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigMaterialCreated,
+ signalProxy(), &QRuntimeViewSignalProxy::SigMaterialCreated);
m_TimeProvider.Reset();
return true;
@@ -636,6 +639,19 @@ void CRuntimeView::deleteElement(const QString &elementPath)
}
}
+void CRuntimeView::createMaterial(const QString &elementPath, const QString &materialDefinition)
+{
+ if (m_Application) {
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+ theBridgeEngine.createMaterial(
+ elementPath, materialDefinition,
+ &m_RuntimeFactory->GetQt3DSRenderContext().GetCustomMaterialSystem(),
+ &m_RuntimeFactory->GetQt3DSRenderContext().GetDynamicObjectSystem(),
+ &m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer());
+ }
+}
+
void CRuntimeView::SetAttribute(const char *elementPath, const char *attributeName,
const char *value)
{
diff --git a/src/Runtime/Source/engine/Qt3DSRuntimeView.h b/src/Runtime/Source/engine/Qt3DSRuntimeView.h
index 0bd63010..ec136525 100644
--- a/src/Runtime/Source/engine/Qt3DSRuntimeView.h
+++ b/src/Runtime/Source/engine/Qt3DSRuntimeView.h
@@ -55,6 +55,7 @@ Q_SIGNALS:
void SigSlideEntered(const QString &elementPath, unsigned int index, const QString &name);
void SigSlideExited(const QString &elementPath, unsigned int index, const QString &name);
void SigCustomSignal(const QString &elementPath, const QString &name);
+ void SigMaterialCreated(const QString &name);
};
namespace qt3ds {
@@ -192,6 +193,7 @@ public:
virtual void createElement(const QString &parentElementPath, const QString &slideName,
const QHash<QString, QVariant> &properties) = 0;
virtual void deleteElement(const QString &elementPath) = 0;
+ virtual void createMaterial(const QString &elementPath, const QString &materialDefinition) = 0;
virtual void SetAttribute(const char *elementPath, const char *attributeName,
const char *value) = 0;
virtual bool GetAttribute(const char *elementPath, const char *attributeName, void *value) = 0;
diff --git a/src/Runtime/Source/runtime/Qt3DSApplication.cpp b/src/Runtime/Source/runtime/Qt3DSApplication.cpp
index 830f4573..07ca8e4c 100644
--- a/src/Runtime/Source/runtime/Qt3DSApplication.cpp
+++ b/src/Runtime/Source/runtime/Qt3DSApplication.cpp
@@ -1092,7 +1092,9 @@ struct SApp : public IApplication
if (theStream) {
theStream = NULL;
CPresentation *thePresentation
- = Q3DStudio_new(CPresentation) CPresentation(inAsset.m_Id.c_str(), this);
+ = Q3DStudio_new(CPresentation) CPresentation(inAsset.m_Id.c_str(),
+ GetProjectDirectory().c_str(),
+ this);
inAsset.m_Presentation = thePresentation;
thePresentation->SetFilePath(theFile.c_str());
NVScopedReleasable<IUIPParser> theUIPParser(IUIPParser::Create(
diff --git a/src/Runtime/Source/runtime/Qt3DSIScriptBridge.h b/src/Runtime/Source/runtime/Qt3DSIScriptBridge.h
index 8f8925d8..8edced36 100644
--- a/src/Runtime/Source/runtime/Qt3DSIScriptBridge.h
+++ b/src/Runtime/Source/runtime/Qt3DSIScriptBridge.h
@@ -53,6 +53,8 @@ namespace qt3ds {
namespace render {
class IThreadPool;
class IQt3DSRenderer;
+ class ICustomMaterialSystem;
+ class IDynamicObjectSystem;
}
}
@@ -164,6 +166,10 @@ public: // Elements
qt3ds::render::IQt3DSRenderer *renderer) = 0;
virtual void deleteElement(const QString &elementPath,
qt3ds::render::IQt3DSRenderer *renderer) = 0;
+ virtual void createMaterial(const QString &elementPath, const QString &materialDefinition,
+ qt3ds::render::ICustomMaterialSystem *customMaterialSystem,
+ qt3ds::render::IDynamicObjectSystem *dynamicObjectSystem,
+ qt3ds::render::IQt3DSRenderer *renderer) = 0;
public: // Components
virtual void GotoSlide(const char *component, const char *slideName,
diff --git a/src/Runtime/Source/runtime/Qt3DSPresentation.cpp b/src/Runtime/Source/runtime/Qt3DSPresentation.cpp
index a4302ad5..ea01878c 100644
--- a/src/Runtime/Source/runtime/Qt3DSPresentation.cpp
+++ b/src/Runtime/Source/runtime/Qt3DSPresentation.cpp
@@ -28,9 +28,6 @@
**
****************************************************************************/
-//==============================================================================
-// Includes
-//==============================================================================
#include "Qt3DSPresentation.h"
#include "Qt3DSCommandEventTypes.h"
#include "Qt3DSIScriptBridge.h"
@@ -47,34 +44,28 @@
#include "Qt3DSLogicSystem.h"
#include "Qt3DSParametersSystem.h"
-//==============================================================================
-// Namespace
-//==============================================================================
+#include <QtCore/qfileinfo.h>
+
namespace Q3DStudio {
-//==============================================================================
-// Constants
-//==============================================================================
-/// Maximum number of Event/Command that can be queued in an Update cycle
+// Maximum number of Event/Command that can be queued in an Update cycle
const INT32 Q3DStudio_EVENTCOMMANDQUEUECAPACITY = 512;
-/// Limit to prevent infinite loop during queue processing
+// Limit to prevent infinite loop during queue processing
const INT32 Q3DStudio_MAXEVENTCOMMANDLOOPCOUNT = Q3DStudio_EVENTCOMMANDQUEUECAPACITY * 10;
#ifdef WIN32
#pragma warning(push)
#pragma warning(disable : 4355)
#endif
-//==============================================================================
-/**
- * Constructor
- */
-CPresentation::CPresentation(const CHAR *inName, qt3ds::runtime::IApplication *inApplication)
+
+CPresentation::CPresentation(const QString &inName, const QString &projectPath,
+ qt3ds::runtime::IApplication *inApplication)
: m_Name(inName)
, m_Application(inApplication)
- , m_Scene(NULL)
- , m_ActivityZone(NULL)
- , m_RootElement(NULL)
+ , m_Scene(nullptr)
+ , m_ActivityZone(nullptr)
+ , m_RootElement(nullptr)
, m_EventCommandQueue(Q3DStudio_EVENTCOMMANDQUEUECAPACITY, "EventCommandQueue")
, m_IsProcessingEventCommandQueue(false)
, m_ComponentManager(*this)
@@ -85,6 +76,7 @@ CPresentation::CPresentation(const CHAR *inName, qt3ds::runtime::IApplication *i
, m_OffsetInvalid(true)
, m_Active(true)
{
+ m_projectPath = QFileInfo(projectPath).absoluteFilePath();
m_Size.m_Width = 0;
m_Size.m_Height = 0;
m_Size.m_ScaleMode = SCALEMODE_UNKNOWN;
@@ -103,15 +95,10 @@ CPresentation::CPresentation(const CHAR *inName, qt3ds::runtime::IApplication *i
#pragma warning(pop)
#endif
-//==============================================================================
-/**
- * Destructor
- */
CPresentation::~CPresentation()
{
}
-//==============================================================================
/**
* Registers an element for notification when events fired on it.
* @param inElement target element to monitor
@@ -129,7 +116,6 @@ void CPresentation::RegisterEventCallback(TElement *inElement, const TEventComma
inElement->SetFlag(ELEMENTFLAG_PICKENABLED, true);
}
-//==============================================================================
/**
* Unregisters a previously registered event callback.
* @param inElement target element to monitor
@@ -183,7 +169,6 @@ void CPresentation::PreUpdate(const TTimeUnit inGlobalTime)
ProcessEventCommandQueue();
}
-//==============================================================================
/**
* Update the presentation to the current time. This will start triggering the
* various stages of the presentation frame rhythm
@@ -230,7 +215,6 @@ void CPresentation::PostUpdate(const TTimeUnit inGlobalTime)
m_PreviousGlobalTime = inGlobalTime;
}
-//==============================================================================
/**
* Process the Event/Command queue completely
* PostEventCommand is the method that will add new Event/Command to the queue.
@@ -288,7 +272,6 @@ BOOL CPresentation::ProcessEventCommandQueue()
return theResult;
}
-//==============================================================================
/**
* Pass incoming event to event consumers immediately
* @param ioEvent the incoming event
@@ -318,7 +301,6 @@ void CPresentation::ProcessEvent(SEventCommand &ioEvent, INT32 &ioEventCount)
}
}
-//==============================================================================
/**
* Handle event bubbling
* @param ioEvent the incoming event
@@ -330,7 +312,7 @@ void CPresentation::ProcessEventBubbling(SEventCommand &ioEvent, INT32 &ioEventC
// Check for onGroupedMouseOver/Out
// arg1 = the original onMouseOut model and arg2 = the original onMouseOver model
if (ioEvent.m_Type == ON_MOUSEOUT) {
- // If original onMouseOver model is NULL or not a descendent, fire onGroupedMouseOut
+ // If original onMouseOver model is nullptr or not a descendent, fire onGroupedMouseOut
TElement *theMouseOverModel = static_cast<TElement *>(ioEvent.m_Arg2.m_VoidPointer);
if (!theMouseOverModel || !ioEvent.m_Target->IsDescendent(*theMouseOverModel)) {
SEventCommand theEvent = ioEvent;
@@ -345,7 +327,7 @@ void CPresentation::ProcessEventBubbling(SEventCommand &ioEvent, INT32 &ioEventC
ioEvent.m_Arg2.m_VoidPointer = ioEvent.m_Target;
}
} else if (ioEvent.m_Type == ON_MOUSEOVER) {
- // If original onMouseOut model is NULL or not a descendent, fire onGroupedMouseOver
+ // If original onMouseOut model is nullptr or not a descendent, fire onGroupedMouseOver
TElement *theMouseOutModel = static_cast<TElement *>(ioEvent.m_Arg1.m_VoidPointer);
if (!theMouseOutModel || !ioEvent.m_Target->IsDescendent(*theMouseOutModel)) {
SEventCommand theEvent = ioEvent;
@@ -379,7 +361,6 @@ void CPresentation::ProcessEventBubbling(SEventCommand &ioEvent, INT32 &ioEventC
}
}
-//==============================================================================
/**
* Execute command immediately
* @param inCommand incoming command structure
@@ -454,7 +435,6 @@ void CPresentation::ProcessCommand(const SEventCommand &inCommand)
}
}
-//==============================================================================
/**
* Put an Event in the queue to be processed later during the Event/Command
* processing stage in Update
@@ -472,7 +452,6 @@ void CPresentation::FireEvent(const SEventCommand &inEvent)
theEventCommand.m_IsEvent = true;
}
-//==============================================================================
/**
* Put an Event in the queue to be processed later during the Event/Command
* processing stage in Update See ProcessEventCommandQueue for more
@@ -508,7 +487,6 @@ void CPresentation::FireEvent(const TEventCommandHash inEventType, TElement *inT
m_EventCommandQueue.NewEntry() = theEvent;
}
-//==============================================================================
/**
* Put a Command in the queue to be processed later during the Event/Command
* processing stage in Update. See ProcessEventCommandQueue for more information
@@ -564,7 +542,7 @@ void CPresentation::ProcessEvent(SEventCommand &inEvent)
INT32 theEventProcessedCount = 0;
ProcessEvent(inEvent, theEventProcessedCount);
}
-//==============================================================================
+
/**
* This method is triggered after the presentation is streamed in. At this point,
* all the stores will be loaded up.
@@ -574,7 +552,6 @@ void CPresentation::OnPresentationLoaded()
m_FrameData.Reserve(1000 /*m_ElementManager.GetElementCount( )*/);
}
-//==============================================================================
/**
* Set the full path for this presentation. This can be used by anyone who
* knows the presentation to form relative paths.
@@ -582,20 +559,26 @@ void CPresentation::OnPresentationLoaded()
*/
void CPresentation::SetFilePath(const CHAR *inPath)
{
- m_FilePath = inPath;
+ m_FilePath = QFileInfo(inPath).absoluteFilePath();
}
-//==============================================================================
/**
* Gets the full file path for this presentation. This can be used by anyone who
* knows the presentation to form relative correct paths.
*/
-QString CPresentation::GetFilePath()
+QString CPresentation::GetFilePath() const
{
return m_FilePath;
}
-//==============================================================================
+/**
+ * Gets the absolute file path for the project that owns this presentation.
+ */
+QString CPresentation::getProjectPath() const
+{
+ return m_projectPath;
+}
+
/**
* Gets the pause state
* @return true if the presentation is paused, false if otherwise
@@ -605,7 +588,6 @@ BOOL CPresentation::GetPause() const
return m_Paused;
}
-//==============================================================================
/**
* Sets the pause state
* @param inPause set true to pause, set false if otherwise
@@ -615,7 +597,6 @@ void CPresentation::SetPause(const BOOL inPause)
m_Paused = inPause ? true : false;
}
-//==============================================================================
/**
* Simple manager access: Scene
*/
@@ -645,7 +626,6 @@ bool CPresentation::GetActive() const
return m_Active;
}
-//==============================================================================
/**
* Simple manager access: Scene
*/
@@ -654,7 +634,6 @@ IScene *CPresentation::GetScene() const
return m_Scene;
}
-//==============================================================================
/**
* Simple manager access: Script Bridge Qml
*/
@@ -663,10 +642,9 @@ IScriptBridge *CPresentation::GetScriptBridgeQml()
if (m_Application)
return &m_Application->GetRuntimeFactoryCore().GetScriptEngineQml();
- return NULL;
+ return nullptr;
}
-//==============================================================================
/**
* Simple manager access: Component Manager
*/
@@ -675,7 +653,6 @@ IComponentManager &CPresentation::GetComponentManager()
return m_ComponentManager;
}
-//==============================================================================
/**
* Simple manager access: Slide Manager
*/
@@ -684,7 +661,6 @@ ISlideSystem &CPresentation::GetSlideSystem()
return *m_SlideSystem;
}
-//==============================================================================
/**
* Simple manager access: Animation Manager
*/
@@ -693,7 +669,6 @@ qt3ds::runtime::IAnimationSystem &CPresentation::GetAnimationSystem()
return *m_AnimationSystem;
}
-//==============================================================================
/**
* Simple manager access: Logic Manager
*/
@@ -702,7 +677,6 @@ ILogicSystem &CPresentation::GetLogicSystem()
return *m_LogicSystem;
}
-//==============================================================================
/**
* Simple manager access: Params Manager
*/
@@ -736,7 +710,6 @@ qt3ds::foundation::IStringTable &CPresentation::GetStringTable()
return GetApplication().GetRuntimeFactoryCore().GetStringTable();
}
-//==============================================================================
/**
* Current frame data stores traversal lists for use later
*/
@@ -750,7 +723,6 @@ void CPresentation::SetLoadedBuffer(qt3ds::render::ILoadedBuffer &inBuffer)
m_LoadedBuffer = inBuffer;
}
-//==============================================================================
/**
* Retrieve the name of the presentation. This is actually the file path.
* @return the name of this presentation
@@ -760,7 +732,6 @@ const QByteArray CPresentation::GetName() const
return m_Name.toLatin1();
}
-//==============================================================================
/**
* Retrieve the size of the presentation in Studio
* @return the size of this presentation
@@ -770,7 +741,6 @@ SPresentationSize CPresentation::GetSize() const
return m_Size;
}
-//==============================================================================
/**
* Set the size of the presentation as reflected in Studio
* @param inSize size of presentation ( width, height, scale mode ) in Studio
diff --git a/src/Runtime/Source/runtime/Qt3DSPresentation.h b/src/Runtime/Source/runtime/Qt3DSPresentation.h
index d813b418..5e3145fd 100644
--- a/src/Runtime/Source/runtime/Qt3DSPresentation.h
+++ b/src/Runtime/Source/runtime/Qt3DSPresentation.h
@@ -30,9 +30,6 @@
#pragma once
-//==============================================================================
-// Includes
-//==============================================================================
#include "RuntimePrefix.h"
#include "Qt3DSIPresentation.h"
#include "Qt3DSPresentationFrameData.h"
@@ -53,6 +50,7 @@ Q_SIGNALS:
void SigSlideEntered(const QString &elementPath, unsigned int index, const QString &name);
void SigSlideExited(const QString &elementPath, unsigned int index, const QString &name);
void SigCustomSignal(const QString &elementPath, const QString &name);
+ void SigMaterialCreated(const QString &name);
};
namespace qt3ds {
@@ -68,45 +66,40 @@ namespace render {
}
}
-//==============================================================================
-// Namespace
-//==============================================================================
namespace Q3DStudio {
-//==============================================================================
+
/**
* Intelligent representation of a Studio presentation.
*/
class CPresentation : public IPresentation
{
- //==============================================================================
- // Fields
- //==============================================================================
protected:
- QString m_Name; ///< Name of ths presentation
- QString m_FilePath; ///< The full path from which this presentation was loaded
- qt3ds::runtime::IApplication *m_Application; ///< Runtime object
- IScene *m_Scene; ///< Connection to the associated scene (render) for this presentation
- qt3ds::runtime::IActivityZone *m_ActivityZone; ///< Controls element active status.
+ QString m_Name; // Name of this presentation
+ QString m_FilePath; // Absolute path to this presentation
+ QString m_projectPath; // Absolute path to the project root
+ qt3ds::runtime::IApplication *m_Application; // Runtime object
+ IScene *m_Scene; // Connection to the associated scene (render) for this presentation
+ qt3ds::runtime::IActivityZone *m_ActivityZone; // Controls element active status
TElement *m_RootElement;
- CPresentationFrameData m_FrameData; ///< Storage of data of the current frame
- CCircularArray<SEventCommand> m_EventCommandQueue; ///< The Event/Command integrated queue
+ CPresentationFrameData m_FrameData; // Storage of data of the current frame
+ CCircularArray<SEventCommand> m_EventCommandQueue; // The Event/Command integrated queue
bool m_IsProcessingEventCommandQueue;
- CEventCallbacks m_EventCallbacks; ///< Handles event callbacks on registered elements
- SPresentationSize m_Size; ///< Native width, height and mode exported from Studio
+ CEventCallbacks m_EventCallbacks; // Handles event callbacks on registered elements
+ SPresentationSize m_Size; // Native width, height and mode exported from Studio
qt3ds::foundation::NVScopedRefCounted<qt3ds::render::ILoadedBuffer>
- m_LoadedBuffer; ///< Reference to loaded data when loading from binary.
+ m_LoadedBuffer; // Reference to loaded data when loading from binary
CComponentManager m_ComponentManager;
qt3ds::foundation::NVScopedRefCounted<ISlideSystem>
- m_SlideSystem; ///< Container and factory of all logics
+ m_SlideSystem; // Container and factory of all slides
qt3ds::foundation::NVScopedRefCounted<ILogicSystem>
- m_LogicSystem; ///< Container and factory of all logics
+ m_LogicSystem; // Container and factory of all logics
qt3ds::foundation::NVScopedRefCounted<IAnimationSystem>
- m_AnimationSystem; ///< Container and factory of all animation tracks
+ m_AnimationSystem; // Container and factory of all animation tracks
qt3ds::foundation::NVScopedRefCounted<IParametersSystem>
- m_ParametersSystem; ///< Container and factory of all custom actions
+ m_ParametersSystem; // Container and factory of all custom actions
TTimeUnit m_Offset;
TTimeUnit m_LocalTime;
@@ -118,12 +111,10 @@ protected:
typedef eastl::hash_map<TElement *, qt3ds::foundation::CRegisteredString> TElemStringMap;
TElemStringMap m_ElementPathMap;
- //==============================================================================
- // Methods
- //==============================================================================
public: // Construction
- CPresentation(const CHAR *inName, qt3ds::runtime::IApplication *inRuntime);
- virtual ~CPresentation();
+ CPresentation(const QString &inName, const QString &projectPath,
+ qt3ds::runtime::IApplication *inRuntime);
+ virtual ~CPresentation() override;
public: // Execution
void Initialize();
@@ -153,11 +144,11 @@ public: // Bridge Control
public: // Commands and Events
void FireEvent(const SEventCommand &inEvent);
void FireEvent(const TEventCommandHash inEventType, TElement *inTarget,
- const UVariant *inArg1 = NULL, const UVariant *inArg2 = NULL,
+ const UVariant *inArg1 = nullptr, const UVariant *inArg2 = nullptr,
const EAttributeType inType1 = ATTRIBUTETYPE_NONE,
const EAttributeType inType2 = ATTRIBUTETYPE_NONE) override;
void FireCommand(const TEventCommandHash inCommandType, TElement *inTarget,
- const UVariant *inArg1 = NULL, const UVariant *inArg2 = NULL,
+ const UVariant *inArg1 = nullptr, const UVariant *inArg2 = nullptr,
const EAttributeType inType1 = ATTRIBUTETYPE_NONE,
const EAttributeType inType2 = ATTRIBUTETYPE_NONE) override;
void FlushEventCommandQueue(void) override;
@@ -213,9 +204,10 @@ public: // Configuration access
void SetUpdateLock(const BOOL inLockUpdate);
void SetVCAA(const BOOL inVCAA);
-public: // Full file path
+public: // Full file paths
void SetFilePath(const CHAR *inPath) override;
- QString GetFilePath() override;
+ QString GetFilePath() const override;
+ QString getProjectPath() const override;
private: // Disabled Copy Construction
CPresentation(CPresentation &);
diff --git a/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp b/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp
index e4aed96e..4825c7ef 100644
--- a/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp
+++ b/src/Runtime/Source/runtime/Qt3DSQmlEngine.cpp
@@ -70,6 +70,13 @@
#include "Qt3DSRenderRuntimeBindingImpl.h"
#include "Qt3DSRenderBufferManager.h" // TODO: Needed for adding meshes dynamically (QT3DS-3378)
#include "Qt3DSRenderer.h"
+#include "q3dsmaterialdefinitionparser.h"
+#include "Qt3DSRenderCustomMaterialSystem.h"
+#include "Qt3DSRenderDynamicObjectSystem.h"
+#include "Qt3DSRenderMaterialHelpers.h"
+#include "Qt3DSRenderUIPLoader.h"
+#include "Qt3DSDMMetaData.h"
+#include "Qt3DSRenderUIPSharedTranslation.h"
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcontext.h>
@@ -357,8 +364,10 @@ struct SEmitSignalData : public NVRefCounted
class CQmlEngineImpl : public CQmlEngine
{
- typedef NVScopedRefCounted<SEmitSignalData> TEmitSignalPtr;
- typedef eastl::list<TEmitSignalPtr, ForwardingAllocator> TEmitSignalQueue;
+ using TEmitSignalPtr = NVScopedRefCounted<SEmitSignalData>;
+ using TEmitSignalQueue = eastl::list<TEmitSignalPtr, ForwardingAllocator>;
+ using TPropertyDescAndValueList = eastl::vector<qt3ds::runtime::element::TPropertyDescAndValue>;
+ using TPropertyDesc = qt3ds::runtime::element::SPropertyDesc;
static const int MAX_ACTION_QUEUE_SIZE = 100;
@@ -423,7 +432,10 @@ public:
qt3ds::render::IQt3DSRenderer *renderer) override;
void deleteElement(const QString &elementPath,
qt3ds::render::IQt3DSRenderer *renderer) override;
- //void createMaterial() override; // TODO (QT3DS-3377)
+ void createMaterial(const QString &elementPath, const QString &materialDefinition,
+ qt3ds::render::ICustomMaterialSystem *customMaterialSystem,
+ IDynamicObjectSystem *dynamicObjectSystem,
+ qt3ds::render::IQt3DSRenderer *renderer) override;
//void createMesh() override; // TODO (QT3DS-3378)
void GotoSlide(const char *component, const char *slideName,
@@ -473,6 +485,39 @@ private:
// find out which datainputs are used in the expression
QVector<QString> resolveDependentDatainputs(const QString &expression,
const QString &controllerName);
+
+ // Methods to add element attributes to list for element creation
+ void addStringAttribute(qt3ds::foundation::IStringTable &strTable,
+ TPropertyDescAndValueList &list,
+ const QString &inAttName, const QString &inValue);
+ void addIntAttribute(qt3ds::foundation::IStringTable &strTable,
+ TPropertyDescAndValueList &list,
+ const QString &inAttName, int inValue);
+ void addBoolAttribute(qt3ds::foundation::IStringTable &strTable,
+ TPropertyDescAndValueList &list,
+ const QString &inAttName, bool inValue);
+ void addFloatAttribute(qt3ds::foundation::IStringTable &strTable,
+ TPropertyDescAndValueList &list,
+ const QString &inAttName, float inValue);
+ void addFloat2Attribute(qt3ds::foundation::IStringTable &strTable,
+ TPropertyDescAndValueList &list,
+ const QStringList &inAttNames, const QVector2D &inValue);
+ void addFloat3Attribute(qt3ds::foundation::IStringTable &strTable,
+ TPropertyDescAndValueList &list,
+ const QStringList &inAttNames, const QVector3D &inValue);
+ void addFloat4Attribute(qt3ds::foundation::IStringTable &strTable,
+ TPropertyDescAndValueList &list,
+ const QStringList &inAttNames, const QVector4D &inValue);
+ void addElementRefAttribute(qt3ds::foundation::IStringTable &strTable,
+ TPropertyDescAndValueList &list,
+ const QString &inAttName, TElement *element);
+ template <typename TDataType>
+ void setDynamicObjectProperty(qt3ds::render::SDynamicObject &material,
+ const qt3ds::render::dynamic::SPropertyDefinition &propDesc,
+ const TDataType &propValue);
+ QVector2D parseFloat2Property(const QString &propValue);
+ QVector3D parseFloat3Property(const QString &propValue);
+ QVector4D parseFloat4Property(const QString &propValue);
};
CQmlEngineImpl::CQmlEngineImpl(NVFoundationBase &fnd, ITimeProvider &)
@@ -868,8 +913,7 @@ void CQmlEngineImpl::SetDataInputValue(
}
}
-using TPropertyDescAndValueList = eastl::vector<qt3ds::runtime::element::TPropertyDescAndValue>;
-using TPropertyDesc = qt3ds::runtime::element::SPropertyDesc;
+static int _idCounter = 0;
void CQmlEngineImpl::createElement(const QString &parentElementPath, const QString &slideName,
const QHash<QString, QVariant> &properties,
@@ -898,8 +942,7 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri
IPresentation *presentation = parentElement->GetBelongedPresentation();
- static int idCounter = 0;
- ++idCounter;
+ ++_idCounter;
// Resolve slide
QByteArray theSlideName = slideName.toUtf8();
@@ -921,7 +964,7 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri
refMatName = QStringLiteral("/") + refMatName;
if (newElementName.isEmpty())
- newElementName = QStringLiteral("NewElement_%1").arg(idCounter);
+ newElementName = QStringLiteral("NewElement_%1").arg(_idCounter);
QByteArray newElementNameBa = newElementName.toUtf8();
// Make sure the name is not duplicate
@@ -941,52 +984,6 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri
const CRegisteredString elementSubType;
TPropertyDescAndValueList elementProperties;
- // Set properties
- auto addStringAttribute = [&strTable](TPropertyDescAndValueList &list,
- const QString &inAttName, const QString &inValue) {
- QByteArray valueBa = inValue.toUtf8();
- qt3ds::foundation::CStringHandle strHandle = strTable.GetHandle(valueBa.constData());
- UVariant theValue;
- theValue.m_StringHandle = strHandle.handle();
- const CRegisteredString attStr = strTable.RegisterStr(inAttName);
- list.push_back(
- eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_STRING), theValue));
- };
- auto addIntAttribute = [&strTable](TPropertyDescAndValueList &list, const QString &inAttName,
- int inValue) {
- UVariant theValue;
- theValue.m_INT32 = inValue;
- const CRegisteredString attStr = strTable.RegisterStr(inAttName);
- list.push_back(
- eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_INT32), theValue));
- };
- auto addBoolAttribute = [&strTable](TPropertyDescAndValueList &list,
- const QString &inAttName, bool inValue) {
- UVariant theValue;
- theValue.m_INT32 = int(inValue);
- const CRegisteredString attStr = strTable.RegisterStr(inAttName);
- list.push_back(
- eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_BOOL), theValue));
- };
- auto addFloatAttribute = [&strTable](TPropertyDescAndValueList &list, const QString &inAttName,
- float inValue) {
- UVariant theValue;
- theValue.m_FLOAT = inValue;
- const CRegisteredString attStr = strTable.RegisterStr(inAttName);
- list.push_back(
- eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_FLOAT), theValue));
- };
- auto addFloat3Attribute = [&strTable](TPropertyDescAndValueList &list,
- const QStringList &inAttNames, const QVector3D &inValue) {
- for (int i = 0; i < 3; ++i) {
- UVariant theValue;
- theValue.m_FLOAT = inValue[i];
- const CRegisteredString attStr = strTable.RegisterStr(inAttNames.at(i));
- list.push_back(
- eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_FLOAT), theValue));
- }
- };
-
// Set default values for missing mandatory properties
const QString sourcePathPropName = QStringLiteral("sourcepath");
const QString startTimePropName = QStringLiteral("starttime");
@@ -995,18 +992,20 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri
Q3DStudio::UVariant attValue;
bool eyeBall = true;
theProperties.value(QStringLiteral("eyeball"), true).toBool();
- if (!theProperties.contains(sourcePathPropName))
- addStringAttribute(elementProperties, sourcePathPropName, QStringLiteral("#Cube"));
+ if (!theProperties.contains(sourcePathPropName)) {
+ addStringAttribute(strTable, elementProperties, sourcePathPropName,
+ QStringLiteral("#Cube"));
+ }
if (!theProperties.contains(startTimePropName)) {
parentElement->GetAttribute(Q3DStudio::ATTRIBUTE_STARTTIME, attValue);
- addIntAttribute(elementProperties, startTimePropName, int(attValue.m_INT32));
+ addIntAttribute(strTable, elementProperties, startTimePropName, int(attValue.m_INT32));
}
if (!theProperties.contains(endTimePropName)) {
parentElement->GetAttribute(Q3DStudio::ATTRIBUTE_ENDTIME, attValue);
- addIntAttribute(elementProperties, endTimePropName, int(attValue.m_INT32));
+ addIntAttribute(strTable, elementProperties, endTimePropName, int(attValue.m_INT32));
}
if (!theProperties.contains(eyeBallPropName))
- addBoolAttribute(elementProperties, eyeBallPropName, true);
+ addBoolAttribute(strTable, elementProperties, eyeBallPropName, true);
else
eyeBall = theProperties.value(QStringLiteral("eyeball")).toBool();
@@ -1015,16 +1014,16 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri
it.next();
switch (it.value().type()) {
case QVariant::Double:
- addFloatAttribute(elementProperties, it.key(), it.value().toFloat());
+ addFloatAttribute(strTable, elementProperties, it.key(), it.value().toFloat());
break;
case QVariant::Bool:
- addBoolAttribute(elementProperties, it.key(), it.value().toBool());
+ addBoolAttribute(strTable, elementProperties, it.key(), it.value().toBool());
break;
case QVariant::Int:
- addIntAttribute(elementProperties, it.key(), it.value().toInt());
+ addIntAttribute(strTable, elementProperties, it.key(), it.value().toInt());
break;
case QVariant::String:
- addStringAttribute(elementProperties, it.key(), it.value().toString());
+ addStringAttribute(strTable, elementProperties, it.key(), it.value().toString());
break;
case QVariant::Vector3D: {
QVector3D vec = it.value().value<QVector3D>();
@@ -1039,7 +1038,7 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri
atts << (it.key() + QLatin1String(".x"))
<< (it.key() + QLatin1String(".y"))
<< (it.key() + QLatin1String(".z"));
- addFloat3Attribute(elementProperties, atts, vec);
+ addFloat3Attribute(strTable, elementProperties, atts, vec);
break;
}
default:
@@ -1131,7 +1130,7 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri
NVAllocatorCallback &allocator = presentation->GetScene()->allocator();
qt3ds::render::SModel *newObject = QT3DS_NEW(allocator, qt3ds::render::SModel)();
newObject->m_Id = strTable.RegisterStr((QByteArrayLiteral("_newObject_")
- + QByteArray::number(idCounter)).constData());
+ + QByteArray::number(_idCounter)).constData());
parentObject.AddChild(*newObject);
qt3ds::render::Qt3DSTranslator::CreateTranslatorForElement(newElem, *newObject, allocator);
@@ -1140,7 +1139,7 @@ void CQmlEngineImpl::createElement(const QString &parentElementPath, const QStri
qt3ds::render::SReferencedMaterial *newMaterial
= QT3DS_NEW(allocator, qt3ds::render::SReferencedMaterial)();
newMaterial->m_Id = strTable.RegisterStr((QByteArrayLiteral("_newMaterial_")
- + QByteArray::number(idCounter)).constData());
+ + QByteArray::number(_idCounter)).constData());
newMaterial->m_ReferencedMaterial = referencedMaterial;
newObject->AddMaterial(*newMaterial);
@@ -1236,6 +1235,336 @@ void CQmlEngineImpl::deleteElement(const QString &elementPath,
m_Application->GetElementAllocator().ReleaseElement(*element, true);
}
+/**
+ Creates material into material container of the presentation that owns the specified element.
+ The materialDefinition parameter can contain a .materialdef file path or
+ the entire material definition in the .materialdef format.
+*/
+void CQmlEngineImpl::createMaterial(const QString &elementPath,
+ const QString &materialDefinition,
+ ICustomMaterialSystem *customMaterialSystem,
+ IDynamicObjectSystem *dynamicObjectSystem,
+ qt3ds::render::IQt3DSRenderer *renderer)
+{
+ QByteArray thePath = elementPath.toUtf8();
+ TElement *element = getTarget(thePath.constData());
+
+ if (!element) {
+ qWarning() << __FUNCTION__ << "Invalid element:" << elementPath;
+ return;
+ }
+
+ CPresentation *presentation = static_cast<CPresentation *>(element->GetBelongedPresentation());
+ QString presPath = QFileInfo(presentation->GetFilePath()).absolutePath();
+ QString projPath = presentation->getProjectPath();
+
+ QString materialName;
+ QMap<QString, QString> materialProps;
+ QMap<QString, QMap<QString, QString>> textureProps;
+
+ Q3DSMaterialDefinitionParser::getMaterialInfo(materialDefinition,
+ projPath, presPath,
+ materialName, materialProps, textureProps);
+
+ // We don't care about the path parameter
+ const QString pathStr = QStringLiteral("path");
+ if (materialProps.contains(pathStr))
+ materialProps.remove(pathStr);
+
+ // Find material container
+ auto &strTable = presentation->GetStringTable();
+ NVAllocatorCallback &allocator = presentation->GetScene()->allocator();
+ TElement *rootElement = presentation->GetRoot();
+ const auto containerName = strTable.RegisterStr("__Container");
+ TElement *container = rootElement->FindChild(CHash::HashString(containerName.c_str()));
+ if (container) {
+ // Check that the material doesn't already exist in container
+ TElement *firstChild = nullptr;
+ TElement *nextChild = container->GetChild();
+ firstChild = nextChild;
+ while (nextChild) {
+ QString childName = QString::fromUtf8(nextChild->m_Name);
+ if (childName == materialName) {
+ qWarning() << __FUNCTION__ << "Material already exists in material container";
+ return;
+ }
+ nextChild = nextChild->GetSibling();
+ }
+ } else {
+ // TODO: Create a material container if it doesn't exist (QT3DS-3412)
+ qWarning() << __FUNCTION__ << "Presentation has no material container";
+ return;
+ }
+
+ // Create material element in the container based on the material definition
+ auto &metaData = m_Application->GetMetaData();
+ const auto matName = strTable.RegisterStr(materialName);
+ const bool isCustomMaterial
+ = materialProps.value(QStringLiteral("type")) == QLatin1String("CustomMaterial");
+ CRegisteredString matType;
+ CRegisteredString matClass;
+ QHash<QString, qt3ds::render::dynamic::SPropertyDefinition> dynPropDefs;
+
+ if (isCustomMaterial) {
+ CRegisteredString sourcePath
+ = strTable.RegisterStr(materialProps.value(QStringLiteral("sourcepath")).toUtf8());
+ matType = strTable.RegisterStr("CustomMaterial");
+ matClass = sourcePath; // Create just one class per shader
+ if (sourcePath.IsValid()) {
+ Option<qt3dsdm::SMetaDataCustomMaterial> matMetaData =
+ metaData.GetMaterialMetaDataBySourcePath(sourcePath.c_str());
+ if (!matMetaData.hasValue()) {
+ metaData.LoadMaterialXMLFile(matType.c_str(), matClass.c_str(), matName.c_str(),
+ sourcePath.c_str());
+ matMetaData = metaData.GetMaterialMetaDataBySourcePath(sourcePath.c_str());
+ }
+ if (matMetaData.hasValue()) {
+ qt3ds::render::IUIPLoader::CreateMaterialClassFromMetaMaterial(
+ matClass, m_Foundation, *customMaterialSystem, matMetaData,
+ strTable);
+ NVConstDataRef<qt3ds::render::dynamic::SPropertyDefinition> customProperties;
+ customProperties = dynamicObjectSystem->GetProperties(matClass);
+ for (QT3DSU32 i = 0, end = customProperties.size(); i < end; ++i) {
+ QString propName = QString::fromUtf8(customProperties[i].m_Name.c_str());
+ if (materialProps.contains(propName))
+ dynPropDefs.insert(propName, customProperties[i]);
+ }
+ } else {
+ qWarning() << __FUNCTION__
+ << "Could not resolve material properties for CustomMaterial:"
+ << materialName;
+ }
+ } else {
+ qWarning() << __FUNCTION__
+ << "Missing sourcepath from material definition of a CustomMaterial:"
+ << materialName;
+ }
+ } else {
+ matType = strTable.RegisterStr("Material");
+ }
+
+ auto createElementPropsFromDefProps = [&](const QMap<QString, QString> &defProps,
+ TPropertyDescAndValueList &elementProps,
+ const CRegisteredString &elementType) -> bool {
+ QMapIterator<QString, QString> propIter(defProps);
+ while (propIter.hasNext()) {
+ propIter.next();
+ if (dynPropDefs.contains(propIter.key()))
+ continue; // Dynamic properties are added directly to graph objects later
+
+ auto propName = strTable.RegisterStr(propIter.key());
+ ERuntimeDataModelDataType dataType;
+ ERuntimeAdditionalMetaDataType additionalType;
+ dataType = metaData.GetPropertyType(elementType, propName);
+ additionalType = metaData.GetAdditionalType(elementType, propName);
+
+ switch (dataType) {
+ case ERuntimeDataModelDataTypeLong: {
+ addIntAttribute(strTable, elementProps, propIter.key(),
+ propIter.value().toInt());
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat: {
+ addFloatAttribute(strTable, elementProps, propIter.key(),
+ propIter.value().toFloat());
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat2: {
+ QVector2D vec = parseFloat2Property(propIter.value());
+ QStringList atts;
+ atts << (propIter.key() + QLatin1String(".x"))
+ << (propIter.key() + QLatin1String(".y"));
+ addFloat2Attribute(strTable, elementProps, atts, vec);
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat3: {
+ QVector3D vec = parseFloat3Property(propIter.value());
+ if (additionalType == ERuntimeAdditionalMetaDataTypeRotation) {
+ vec.setX(qDegreesToRadians(vec.x()));
+ vec.setY(qDegreesToRadians(vec.y()));
+ vec.setZ(qDegreesToRadians(vec.z()));
+ }
+ QStringList atts;
+ atts << (propIter.key() + QLatin1String(".x"))
+ << (propIter.key() + QLatin1String(".y"))
+ << (propIter.key() + QLatin1String(".z"));
+ addFloat3Attribute(strTable, elementProps, atts, vec);
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat4: {
+ QVector4D vec = parseFloat4Property(propIter.value());
+ QStringList atts;
+ if (additionalType == ERuntimeAdditionalMetaDataTypeColor) {
+ atts << (propIter.key() + QLatin1String(".r"))
+ << (propIter.key() + QLatin1String(".g"))
+ << (propIter.key() + QLatin1String(".b"))
+ << (propIter.key() + QLatin1String(".a"));
+ } else {
+ atts << (propIter.key() + QLatin1String(".x"))
+ << (propIter.key() + QLatin1String(".y"))
+ << (propIter.key() + QLatin1String(".z"))
+ << (propIter.key() + QLatin1String(".w"));
+ }
+ addFloat4Attribute(strTable, elementProps, atts, vec);
+ break;
+ }
+ case ERuntimeDataModelDataTypeBool: {
+ bool boolValue = propIter.value().compare(QLatin1String("true"),
+ Qt::CaseInsensitive) == 0;
+ addBoolAttribute(strTable, elementProps, propIter.key(), boolValue);
+ break;
+ }
+ case ERuntimeDataModelDataTypeStringRef:
+ case ERuntimeDataModelDataTypeString: {
+ addStringAttribute(strTable, elementProps, propIter.key(), propIter.value());
+ break;
+ }
+ case ERuntimeDataModelDataTypeLong4: {
+ if (additionalType == ERuntimeAdditionalMetaDataTypeImage) {
+ // Insert placeholder for now, will be patched later
+ addElementRefAttribute(strTable, elementProps, propIter.key(), nullptr);
+ }
+ break;
+ }
+ default:
+ qWarning() << __FUNCTION__
+ << "Unsupported material property type for property:"
+ << propIter.key();
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ return true;
+ };
+
+ TPropertyDescAndValueList elementProps;
+ bool success = createElementPropsFromDefProps(materialProps, elementProps, matType);
+ if (!success)
+ return; // createElementPropsFromDefProps already prints a warning
+
+ TElement &newMatElem = m_Application->GetElementAllocator().CreateElement(
+ matName, matType, matClass,
+ toConstDataRef(elementProps.data(), QT3DSU32(elementProps.size())),
+ presentation, container, false);
+ newMatElem.SetActive(true);
+
+ // Create image elements
+ CRegisteredString imageType = strTable.RegisterStr("Image");
+ QMapIterator<QString, QMap<QString, QString>> texIter(textureProps);
+ QHash<QString, TElement *> imageElementMap;
+ while (texIter.hasNext()) {
+ texIter.next();
+ elementProps.clear();
+ success = createElementPropsFromDefProps(texIter.value(), elementProps, imageType);
+ if (!success) {
+ m_Application->GetElementAllocator().ReleaseElement(newMatElem, true);
+ return; // createElementPropsFromDefProps already prints a warning
+ }
+ CRegisteredString imageName = strTable.RegisterStr(texIter.key());
+
+ TElement &newImageElem = m_Application->GetElementAllocator().CreateElement(
+ imageName, imageType, CRegisteredString(),
+ toConstDataRef(elementProps.data(), QT3DSU32(elementProps.size())),
+ presentation, &newMatElem, false);
+ imageElementMap.insert(texIter.key(), &newImageElem);
+ newImageElem.SetActive(true);
+ }
+
+ // Create render object for the material
+ qt3ds::render::SGraphObject *newMaterial = nullptr;
+ CRegisteredString newMatId = strTable.RegisterStr(
+ (QByteArrayLiteral("_newMaterial_") + QByteArray::number(++_idCounter))
+ .constData());
+ if (isCustomMaterial) {
+ newMaterial = customMaterialSystem->CreateCustomMaterial(matClass, allocator);
+ newMaterial->m_Id = newMatId;
+ auto dynObj = static_cast<qt3ds::render::SDynamicObject *>(newMaterial);
+
+ QHashIterator<QString, qt3ds::render::dynamic::SPropertyDefinition>
+ dynPropIter(dynPropDefs);
+ while (dynPropIter.hasNext()) {
+ dynPropIter.next();
+ QByteArray propValStr = materialProps.value(dynPropIter.key()).toUtf8();
+ const auto propDesc = dynPropIter.value();
+ switch (propDesc.m_DataType) {
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool: {
+ bool boolValue = propValStr.compare(QByteArrayLiteral("true"),
+ Qt::CaseInsensitive) == 0;
+ setDynamicObjectProperty(*dynObj, propDesc, boolValue);
+ break;
+ }
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSF32:
+ setDynamicObjectProperty(*dynObj, propDesc, propValStr.toFloat());
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSI32:
+ if (!propDesc.m_IsEnumProperty) {
+ setDynamicObjectProperty(*dynObj, propDesc, propValStr.toInt());
+ } else {
+ const NVConstDataRef<CRegisteredString> &enumNames = propDesc.m_EnumValueNames;
+ for (QT3DSU32 i = 0, end = enumNames.size(); i < end; ++i) {
+ if (propValStr.compare(enumNames[i].c_str()) == 0) {
+ setDynamicObjectProperty(*dynObj, propDesc, i);
+ break;
+ }
+ }
+ }
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec2:
+ setDynamicObjectProperty(*dynObj, propDesc, parseFloat2Property(propValStr));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec3:
+ setDynamicObjectProperty(*dynObj, propDesc, parseFloat3Property(propValStr));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4:
+ setDynamicObjectProperty(*dynObj, propDesc, parseFloat4Property(propValStr));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr:
+ case qt3ds::render::NVRenderShaderDataTypes::NVRenderImage2DPtr: {
+ CRegisteredString regStr;
+ regStr = strTable.RegisterStr(propValStr);
+ setDynamicObjectProperty(*dynObj, propDesc, regStr);
+ break;
+ }
+ default:
+ qWarning() << __FUNCTION__
+ << "Unsupported custom material property type '" << propDesc.m_DataType
+ << "' for property:"
+ << dynPropIter.key();
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ } else {
+ newMaterial = QT3DS_NEW(allocator, qt3ds::render::SDefaultMaterial)();
+ newMaterial->m_Id = newMatId;
+
+ // Update element refs for image elements and create graph objects & translators
+ QHashIterator<QString, TElement *> imageIter(imageElementMap);
+ while (imageIter.hasNext()) {
+ imageIter.next();
+ TElement *imageElem = imageIter.value();
+ UVariant *propValue = newMatElem.FindPropertyValue(imageElem->m_Name);
+ if (propValue) {
+ propValue->m_ElementHandle = imageIter.value()->GetHandle();
+
+ qt3ds::render::SImage *newImageObj = QT3DS_NEW(allocator, qt3ds::render::SImage)();
+ newImageObj->m_Id
+ = strTable.RegisterStr((QByteArrayLiteral("_newImage_")
+ + QByteArray::number(++_idCounter)).constData());
+ qt3ds::render::Qt3DSTranslator::CreateTranslatorForElement(*imageElem,
+ *newImageObj, allocator);
+ }
+ }
+ }
+
+ qt3ds::render::Qt3DSTranslator::CreateTranslatorForElement(newMatElem, *newMaterial, allocator);
+
+ // Notify presentation asynchronously to give renderer time to initialize the materials properly
+ QTimer::singleShot(0, [materialName, presentation]() {
+ presentation->signalProxy()->SigMaterialCreated(materialName);
+ });
+}
+
void CQmlEngineImpl::GotoSlide(const char *component, const char *slideName,
const SScriptEngineGotoSlideArgs &inArgs)
{
@@ -1777,6 +2106,134 @@ QVector<QString> CQmlEngineImpl::resolveDependentDatainputs(const QString &expre
return ret;
}
+void CQmlEngineImpl::addStringAttribute(IStringTable &strTable,
+ CQmlEngineImpl::TPropertyDescAndValueList &list,
+ const QString &inAttName, const QString &inValue)
+{
+ QByteArray valueBa = inValue.toUtf8();
+ qt3ds::foundation::CStringHandle strHandle = strTable.GetHandle(valueBa.constData());
+ UVariant theValue;
+ theValue.m_StringHandle = strHandle.handle();
+ const CRegisteredString attStr = strTable.RegisterStr(inAttName);
+ list.push_back(eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_STRING), theValue));
+}
+
+void CQmlEngineImpl::addIntAttribute(IStringTable &strTable,
+ CQmlEngineImpl::TPropertyDescAndValueList &list,
+ const QString &inAttName, int inValue)
+{
+ UVariant theValue;
+ theValue.m_INT32 = inValue;
+ const CRegisteredString attStr = strTable.RegisterStr(inAttName);
+ list.push_back(eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_INT32), theValue));
+}
+
+void CQmlEngineImpl::addBoolAttribute(IStringTable &strTable,
+ CQmlEngineImpl::TPropertyDescAndValueList &list,
+ const QString &inAttName, bool inValue)
+{
+ UVariant theValue;
+ theValue.m_INT32 = int(inValue);
+ const CRegisteredString attStr = strTable.RegisterStr(inAttName);
+ list.push_back(eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_BOOL), theValue));
+}
+
+void CQmlEngineImpl::addFloatAttribute(IStringTable &strTable,
+ CQmlEngineImpl::TPropertyDescAndValueList &list,
+ const QString &inAttName, float inValue)
+{
+ UVariant theValue;
+ theValue.m_FLOAT = inValue;
+ const CRegisteredString attStr = strTable.RegisterStr(inAttName);
+ list.push_back(eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_FLOAT), theValue));
+}
+
+void CQmlEngineImpl::addFloat2Attribute(IStringTable &strTable,
+ CQmlEngineImpl::TPropertyDescAndValueList &list,
+ const QStringList &inAttNames, const QVector2D &inValue)
+{
+ for (int i = 0; i < 2; ++i) {
+ UVariant theValue;
+ theValue.m_FLOAT = inValue[i];
+ const CRegisteredString attStr = strTable.RegisterStr(inAttNames.at(i));
+ list.push_back(eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_FLOAT), theValue));
+ }
+}
+
+void CQmlEngineImpl::addFloat3Attribute(IStringTable &strTable,
+ CQmlEngineImpl::TPropertyDescAndValueList &list,
+ const QStringList &inAttNames, const QVector3D &inValue)
+{
+ for (int i = 0; i < 3; ++i) {
+ UVariant theValue;
+ theValue.m_FLOAT = inValue[i];
+ const CRegisteredString attStr = strTable.RegisterStr(inAttNames.at(i));
+ list.push_back(eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_FLOAT), theValue));
+ }
+}
+
+void CQmlEngineImpl::addFloat4Attribute(IStringTable &strTable,
+ CQmlEngineImpl::TPropertyDescAndValueList &list,
+ const QStringList &inAttNames, const QVector4D &inValue)
+{
+ for (int i = 0; i < 4; ++i) {
+ UVariant theValue;
+ theValue.m_FLOAT = inValue[i];
+ const CRegisteredString attStr = strTable.RegisterStr(inAttNames.at(i));
+ list.push_back(eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_FLOAT), theValue));
+ }
+}
+
+void CQmlEngineImpl::addElementRefAttribute(IStringTable &strTable,
+ CQmlEngineImpl::TPropertyDescAndValueList &list,
+ const QString &inAttName, TElement *element)
+{
+ UVariant theValue;
+ if (element) {
+ theValue.m_ElementHandle = element->GetHandle();
+ QT3DS_ASSERT(theValue.m_ElementHandle);
+ } else {
+ theValue.m_ElementHandle = 0;
+ }
+ const CRegisteredString attStr = strTable.RegisterStr(inAttName);
+ list.push_back(eastl::make_pair(TPropertyDesc(attStr, ATTRIBUTETYPE_ELEMENTREF), theValue));
+}
+
+QVector2D CQmlEngineImpl::parseFloat2Property(const QString &propValue)
+{
+ QVector<QStringRef> values = propValue.splitRef(QLatin1Char(' '));
+ QVector2D retVal;
+ for (int i = 0; i < values.size() && i < 2; ++i)
+ retVal[i] = values[i].toFloat();
+ return retVal;
+}
+
+QVector3D CQmlEngineImpl::parseFloat3Property(const QString &propValue)
+{
+ QVector<QStringRef> values = propValue.splitRef(QLatin1Char(' '));
+ QVector3D retVal;
+ for (int i = 0; i < values.size() && i < 3; ++i)
+ retVal[i] = values[i].toFloat();
+ return retVal;
+}
+
+QVector4D CQmlEngineImpl::parseFloat4Property(const QString &propValue)
+{
+ QVector<QStringRef> values = propValue.splitRef(QLatin1Char(' '));
+ QVector4D retVal;
+ for (int i = 0; i < values.size() && i < 4; ++i)
+ retVal[i] = values[i].toFloat();
+ return retVal;
+}
+
+template<typename TDataType>
+void CQmlEngineImpl::setDynamicObjectProperty(qt3ds::render::SDynamicObject &material,
+ const dynamic::SPropertyDefinition &propDesc,
+ const TDataType &propValue)
+{
+ memCopy(material.GetDataSectionBegin() + propDesc.m_Offset, &propValue, sizeof(TDataType));
+}
+
/**
* @brief Create QML engine
*
@@ -1789,4 +2246,5 @@ CQmlEngine *CQmlEngine::Create(qt3ds::NVFoundationBase &inFoundation, ITimeProvi
{
return QT3DS_NEW(inFoundation.getAllocator(), CQmlEngineImpl)(inFoundation, inTimeProvider);
}
+
}
diff --git a/src/Runtime/Source/runtime/q3dsmaterialdefinitionparser.cpp b/src/Runtime/Source/runtime/q3dsmaterialdefinitionparser.cpp
new file mode 100644
index 00000000..913a24ec
--- /dev/null
+++ b/src/Runtime/Source/runtime/q3dsmaterialdefinitionparser.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dsmaterialdefinitionparser.h"
+
+#include <QtCore/qfile.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qxmlstream.h>
+#include <QtCore/qtextstream.h>
+#include <QtCore/qdebug.h>
+
+namespace Q3DStudio {
+
+void Q3DSMaterialDefinitionParser::getMaterialInfo(const QString &materialDefinition,
+ const QString &projPath, const QString &presPath,
+ QString &outName, QMap<QString, QString> &outValues,
+ QMap<QString, QMap<QString, QString>> &outTextureValues)
+{
+ // materialDefinition can be the .materialdef file name or its content
+ QString matDef;
+ if (materialDefinition.endsWith(QLatin1String(".materialdef"), Qt::CaseInsensitive)) {
+ QFile file(materialDefinition);
+ if (!file.open(QFile::Text | QFile::ReadOnly)) {
+ qWarning() << __FUNCTION__ << "Failed to open material definition file:"
+ << file.errorString();
+ return;
+ }
+ QTextStream stream(&file);
+ matDef = stream.readAll();
+ } else {
+ matDef = materialDefinition;
+ }
+
+ QXmlStreamReader reader(matDef);
+ reader.setNamespaceProcessing(false);
+
+ const QDir docDir(presPath);
+ const QDir projDir(projPath);
+ QString textureName;
+ QString propertyName;
+ QString propertyType;
+ QString propertyValue;
+ QMap<QString, QString> textureProperties;
+
+ const QString matDataVersion = QStringLiteral("1.0");
+ const QString sourcePathStr = QStringLiteral("sourcepath");
+ const QString nameStr = QStringLiteral("name");
+ const QString typeStr = QStringLiteral("type");
+ const QString versionStr = QStringLiteral("version");
+
+ while (!reader.atEnd()) {
+ reader.readNext();
+ if (reader.tokenType() == QXmlStreamReader::StartElement) {
+ if (reader.name() == QLatin1String("TextureData")) {
+ textureName = reader.attributes().value(nameStr).toString();
+ textureProperties.clear();
+ } else if (reader.name() == QLatin1String("Property")) {
+ propertyName = reader.attributes().value(nameStr).toString();
+ propertyType = reader.attributes().value(typeStr).toString();
+ propertyValue.clear();
+ } else if (reader.name() == QLatin1String("MaterialData")) {
+ QString version = reader.attributes().value(versionStr).toString();
+ if (version != matDataVersion) {
+ qWarning() << __FUNCTION__ << "Invalid MaterialData version; expected '"
+ << matDataVersion << "', got '" << version << "'";
+ outName.clear();
+ outValues.clear();
+ outTextureValues.clear();
+ return;
+ }
+ }
+ } else if (reader.tokenType() == QXmlStreamReader::EndElement) {
+ if (reader.name() == QLatin1String("TextureData")) {
+ outTextureValues[textureName] = textureProperties;
+ textureName.clear();
+ } else if (reader.name() == QLatin1String("Property")) {
+ if (textureName.isEmpty()) {
+ outValues[propertyName] = propertyValue;
+ if (propertyName == nameStr)
+ outName = propertyValue;
+ } else {
+ textureProperties[propertyName] = propertyValue;
+ }
+ propertyName.clear();
+ propertyType.clear();
+ }
+ } else if (reader.tokenType() == QXmlStreamReader::Characters) {
+ if (!propertyName.isEmpty()) {
+ propertyValue = reader.text().toString();
+ if (propertyName == sourcePathStr) {
+ // Check that the referenced file exists
+ const auto absSourcePath = projDir.absoluteFilePath(propertyValue);
+ if (!QFileInfo(absSourcePath).exists()) {
+ qWarning() << __FUNCTION__ << "Referenced file doesn't exist:"
+ << propertyValue;
+ outName.clear();
+ outValues.clear();
+ outTextureValues.clear();
+ return;
+ }
+ }
+ if (!propertyValue.isEmpty() && (propertyType == QLatin1String("Texture")
+ || propertyName == sourcePathStr)) {
+ propertyValue = docDir.relativeFilePath(
+ projDir.absoluteFilePath(propertyValue));
+ }
+ }
+ }
+ }
+}
+
+}
diff --git a/src/Runtime/Source/runtime/q3dsmaterialdefinitionparser.h b/src/Runtime/Source/runtime/q3dsmaterialdefinitionparser.h
new file mode 100644
index 00000000..f6d98bbf
--- /dev/null
+++ b/src/Runtime/Source/runtime/q3dsmaterialdefinitionparser.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSMATERIALDEFINITIONPARSER_H
+#define Q3DSMATERIALDEFINITIONPARSER_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qmap.h>
+
+namespace Q3DStudio {
+
+class Q3DSMaterialDefinitionParser
+{
+public:
+ static void getMaterialInfo(const QString &materialDefinition,
+ const QString &projPath, const QString &presPath,
+ QString &outName, QMap<QString, QString> &outValues,
+ QMap<QString, QMap<QString, QString>> &outTextureValues);
+};
+
+}
+
+#endif
diff --git a/src/Runtime/Source/uipparser/Qt3DSIPresentation.h b/src/Runtime/Source/uipparser/Qt3DSIPresentation.h
index 00f3d15a..a9d36446 100644
--- a/src/Runtime/Source/uipparser/Qt3DSIPresentation.h
+++ b/src/Runtime/Source/uipparser/Qt3DSIPresentation.h
@@ -30,9 +30,6 @@
#pragma once
-//==============================================================================
-// Includes
-//==============================================================================
#include "Qt3DSEventCallbacks.h"
namespace qt3ds {
@@ -52,14 +49,8 @@ namespace foundation {
}
}
-//==============================================================================
-// Namespace
-//==============================================================================
namespace Q3DStudio {
-//==============================================================================
-// Forwards
-//==============================================================================
class IComponentManager;
class IEventManager;
class IScene;
@@ -71,20 +62,14 @@ using qt3ds::runtime::IAnimationSystem;
using qt3ds::runtime::ILogicSystem;
using qt3ds::runtime::IParametersSystem;
-//==============================================================================
-// Enumeration
-//==============================================================================
-/// Method used to translate from presentation size to window size
+// Method used to translate from presentation size to window size
enum EScaleMode {
- SCALEMODE_FREE, ///< Free scaling mode
- SCALEMODE_EXACT, ///< Fixed presentation size
- SCALEMODE_ASPECT, ///< Maintain aspect ratio
- SCALEMODE_UNKNOWN, ///< ERROR! - Uninitialized scale mode
+ SCALEMODE_FREE, // Free scaling mode
+ SCALEMODE_EXACT, // Fixed presentation size
+ SCALEMODE_ASPECT, // Maintain aspect ratio
+ SCALEMODE_UNKNOWN, // ERROR! - Uninitialized scale mode
};
-//==============================================================================
-// Structs
-//==============================================================================
struct SPresentationSize
{
SPresentationSize()
@@ -93,22 +78,18 @@ struct SPresentationSize
, m_ScaleMode(0)
{
}
- UINT16 m_Width; ///< Native width of the presentation
- UINT16 m_Height; ///< Native height of the presentation
- UINT8 m_ScaleMode; ///< Presentation to window scale method
+ UINT16 m_Width; // Native width of the presentation
+ UINT16 m_Height; // Native height of the presentation
+ UINT8 m_ScaleMode; // Presentation to window scale method
UINT8 m_Padding[3];
};
-//==============================================================================
/**
* @interface IPresentation
* Base interface of the presentation.
*/
class IPresentation
{
- //==============================================================================
- // Methods
- //==============================================================================
public: // Construction
IPresentation() {}
virtual ~IPresentation() {}
@@ -127,11 +108,11 @@ public: // Bridge Control
public: // Commands and Events
virtual void FireEvent(const TEventCommandHash inEventType, TElement *inTarget,
- const UVariant *inArg1 = NULL, const UVariant *inArg2 = NULL,
+ const UVariant *inArg1 = nullptr, const UVariant *inArg2 = nullptr,
const EAttributeType inType1 = ATTRIBUTETYPE_NONE,
const EAttributeType inType2 = ATTRIBUTETYPE_NONE) = 0;
virtual void FireCommand(const TEventCommandHash inEventType, TElement *inTarget,
- const UVariant *inArg1 = NULL, const UVariant *inArg2 = NULL,
+ const UVariant *inArg1 = nullptr, const UVariant *inArg2 = nullptr,
const EAttributeType inType1 = ATTRIBUTETYPE_NONE,
const EAttributeType inType2 = ATTRIBUTETYPE_NONE) = 0;
virtual void FlushEventCommandQueue(void) = 0;
@@ -153,7 +134,8 @@ public: // Hooks and callbacks
public: // Full file path
virtual void SetFilePath(const CHAR *inPath) = 0;
- virtual QString GetFilePath() = 0;
+ virtual QString GetFilePath() const = 0;
+ virtual QString getProjectPath() const = 0;
virtual TElement *GetRoot() = 0;
virtual void SetRoot(TElement &inRoot) = 0;
diff --git a/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp b/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp
index 8bf7eb80..fadd680c 100644
--- a/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp
+++ b/src/Runtime/Source/viewer/Qt3DSViewerApp.cpp
@@ -357,6 +357,8 @@ bool Q3DSViewerApp::InitializeApp(int winWidth, int winHeight, const QSurfaceFor
&QRuntimeViewSignalProxy::SigSlideExited, this, &Q3DSViewerApp::SigSlideExited);
connect(m_Impl.m_view->signalProxy(),
&QRuntimeViewSignalProxy::SigCustomSignal, this, &Q3DSViewerApp::SigCustomSignal);
+ connect(m_Impl.m_view->signalProxy(), &QRuntimeViewSignalProxy::SigMaterialCreated, this,
+ &Q3DSViewerApp::SigMaterialCreated);
Resize(winWidth, winHeight);
@@ -811,6 +813,14 @@ void Q3DSViewerApp::deleteElement(const QString &elementPath)
m_Impl.m_view->deleteElement(elementPath);
}
+void Q3DSViewerApp::createMaterial(const QString &elementPath, const QString &materialDefinition)
+{
+ if (!m_Impl.m_view)
+ return;
+
+ m_Impl.m_view->createMaterial(elementPath, materialDefinition);
+}
+
Q3DSViewerApp &Q3DSViewerApp::Create(void *glContext, Q3DStudio::IAudioPlayer *inAudioPlayer,
QElapsedTimer *startupTimer)
{
diff --git a/src/Runtime/Source/viewer/Qt3DSViewerApp.h b/src/Runtime/Source/viewer/Qt3DSViewerApp.h
index d2d9b93e..5cd52bca 100644
--- a/src/Runtime/Source/viewer/Qt3DSViewerApp.h
+++ b/src/Runtime/Source/viewer/Qt3DSViewerApp.h
@@ -362,6 +362,7 @@ public:
void createElement(const QString &parentElementPath, const QString &slideName,
const QHash<QString, QVariant> &properties);
void deleteElement(const QString &elementPath);
+ void createMaterial(const QString &elementPath, const QString &materialDefinition);
QString error();
@@ -403,6 +404,7 @@ Q_SIGNALS:
void SigSlideEntered(const QString &elementPath, unsigned int index, const QString &name);
void SigSlideExited(const QString &elementPath, unsigned int index, const QString &name);
void SigCustomSignal(const QString &elementPath, const QString &name);
+ void SigMaterialCreated(const QString &name);
void SigPresentationReady();
};